Nach der letzten Artikelserie zum Thema Computergrafik (keine Angst – die vorgebrachten Themenwünsche habe ich weiter auf dem Radar) geht es mit der neuen Artikelserie in einen gänzlich anderen Themenbereich. Wie bereits im letzten Artikel angedeutet, möchte ich mich etwas mit der Frage beschäftigen, wie die Informatik eingesetzt werden kann, um wissenschaftliche Theorien zu überprüfen. Das Mittel der Wahl ist hier die Simulation – und die soll uns auch in einigen (etwas loser verteilten) Artikeln beschäftigen. Wir wollen uns dabei nicht nur auf verbale Beschreibungen beschränken, sondern die ein oder andere Simulation auch tatsächlich einmal programmieren – und los geht es.

In der Presse ist des Öfteren zu lesen, dass diese oder jene Theorie mit Computersimulationen überprüft wurde – insbesondere im Bereich der Klimawissenschaften hört man oft davon. Das liegt nun aber natürlich nicht daran, dass hier Simulationen besonders oft zum Einsatz kommen, sondern eher daran, dass die Presse über diesen Bereich tendenziell öfter berichtet – aber das ist ein anderes Thema und soll hier nicht zur Debatte stehen. Fakt ist, dass in sehr vielen Bereichen der Wissenschaft Computersimulationen zum Einsatz kommen; das ist übrigens nicht nur auf die technischeren Bereiche beschränkt – prinzipiell lässt sich fast alles simulieren, was einigermaßen mathematisch beschrieben werden kann.

Damit wären wir dann auch schon beim Kernpunkt einer jeden Simulation: der mathematischen Beschreibung. Alle Simulationen folgen weitgehend dem gleichen Schema. Zuerst wird die zu untersuchende Problematik mit Hilfe eines formalen (in der Regel mathematischen) Modells beschrieben. Das Modell umfasst dabei zum einen eine Beschreibung des Zustands der Welt (mit Welt ist damit die Problemumgebung gemeint) und zum anderen Regeln, nach welchen sich dieser Zustand ändern kann. Die Begriffe “Zustand” und “Regel” sind hierbei sehr weit gefasst und können – je nach Problem – vollkommen unterschiedliche Dinge beschreiben, aber das werden wir im Verlauf der Artikelserie noch sehen.

Im Anschluss an die Definition des Modells wird der Ausgangszustand definiert; das ist der Zustand der Welt, mit welchem die Simulation beginnen soll. Der Ausgangszustand kann dabei entweder fest gewählt sein, wenn er nämlich eine bestimmte Hypothese darstellen soll, die mit Hilfe eines (genau definierten) Modells untersucht werden soll (wenn etwa untersucht werden soll, wie sich eine bestimmte Verteilung von Individuen einer Population langfristig auf die Entwicklung innerhalb der Population auswirkt); oder er wird (mehr oder weniger) zufällig gewürfelt, wenn der Fokus der Simulation eher auf dem Modell liegt und der Ausgangszustand nicht so wichtig ist (die Simulation von Teilchen in Physiksimulationen ist hierfür ein Beispiel).

Sind Modell und Ausgangszustand bestimmt, kann die eigentliche Simulation beginnen. Die besteht nun darin, dass die im Modell definierten Regeln ausgehend vom Ausgangszustand immer wieder auf den Zustand angewendet werden – es wird also eine (meist zeitliche) Entwicklung des Zustandes simuliert. Die Simulation wird nach einer festgelegten Anzahl von Regelanwendungen (man spricht mitunter auch von Runden) abgebrochen – oder wenn ein vorher definierter Zielzustand erreicht wurde.

Das ist bisher zwar alles wunderbar abstrakt und unkompliziert, aber die eigentliche Frage bleibt noch offen: wie wird eine derartige Simulation tatsächlich umgesetzt? Das könnte nun auch wieder an konkreten Beispielen rein verbal beschrieben werden, aber das wäre langweilig. Wir wollen daher an dieser Stelle ganz konkret werden und eine Simulation auch selber einmal programmieren. Für dieses erste Beispiel werde ich die Programmiersprache JavaScript wählen, da sie sich einfach im Browser ausführen lässt und die Beschreibungen damit sehr einfach nachvollzogen werden können. Wer mit dem Programmieren allgemein noch nicht vertraut ist, dem empfehle ich die entsprechende Artikelserie (Punkt: Programmierung); ein kurzer Ausflug in die Artikelserien zum Thema Web-Programmierung (Punkt: Web) kann dabei auch nicht schaden. 1

1 Wer den hier aufgeführten Code ausprobieren möchte, der erstellt einfach eine neue Datei auf seinem Computer, welche die Dateiendung “.html” trägt (also z.B. “test.html”). Diese Datei muss dann in einem Texteditor (Microsoft Word ist kein Texteditor) geöffnet werden; die hier beschriebenen Inhalte werden dann einfach in die Datei kopiert (Speichern nicht vergessen) und diese dann per Doppelklick im Standardbrowser geöffnet.

Zu Anfang jeder Simulation steht natürlich die Problembeschreibung. Für das Beispiel habe ich das Ziegenproblem ausgewählt, da es zum einen relativ leicht verständlich und zum anderen auch sehr leicht zu simulieren ist. Eigentlich wäre es zwar kein üblicher Kandidat für eine Simulation, aber die Prinzipien lassen sich daran sehr gut veranschaulichen.

Der Kern des Ziegenproblems ist der folgende: in einer Spielshow hat ein Kandidat die Wahl zwischen drei verschiedenen Toren. Hinter einem Tor befindet sich der eigentliche Preis, hinter den anderen beiden Toren jeweils eine Ziege (daher der Name des Problems) als Nicht-Preis. Der Kandidat wählt eines der Tore, woraufhin der Moderator des Spiels eines der anderen Tore öffnet, hinter dem sich eine Ziege befindet. Anschließend wird der Kandidat vor die Wahl gestellt: möchte er bei seinem gewählten Tor bleiben oder zum noch verschlossenen Tor wechseln. Die Frage ist: was ist die beste Strategie, um die Gewinnchancen zu maximieren? Sollte das Tor gewechselt werden oder eher nicht? (Das eigentliche Problem ist etwas komplexer als hier beschrieben, soll aber für die Simulation nicht weiter von Interesse sein; bei Interesse kann im entsprechenden Wikipedia-Artikel nachgelesen werden, und falls nach der Lektüre die Frage aufkommt: wir betrachten allein den Fall des ausgeglichenen Moderators).

Bildlich dargestellt also:

(Quelle: Wikipedia)

Die intuitive Antwort bei dieser Frage ist meist: es ist egal, ob man wechselt oder nicht. Zum Zeitpunkt der Frage sind noch 2 Tore geschlossen – hinter einem davon befindet sich eine Ziege, hinter dem anderen der Preis. Egal, welches Tor man wählt, man hat eine Chance von 50%, den Preis zu gewinnen. Richtig? Falsch. Es kann mathematisch gezeigt werden, dass es günstiger ist, das gewählte Tor in jedem Fall zu wechseln, da die Gewinnchancen damit auf 2/3, also etwa 66% steigen. Wer am mathematischen Beweis dafür interessiert ist, möge in der Wikipedia lesen – wir wollen dieses Problem hier aber per Simulation lösen.

Das Modell der Simulation ist denkbar einfach: der Zustand der Welt besteht aus den Informationen darüber, hinter welchem Tor sich der Preis befindet, welches Tor durch den Kandidaten initial gewählt wurde und theoretisch auch noch, welches Tor durch den Moderator geöffnet wurde (diese Information können wir sogar verwerfen – dazu gleich mehr). Die Regeln der Simulation sind ebenso einfach: haben wir durch unsere Wahl (Tor wechseln oder nicht wechseln) das Tor mit dem Preis erwischt, erhalten wir einen (imaginären) Punkt. Führen wir diesen Versuch n mal aus und zählen dabei, wie oft der Wechsel des Tores (bzw. der Nicht-Wechsel) zum Erfolg geführt hat, erhalten wir damit eine Einschätzung der Gewinnchancen. Je öfter wir den Versuch wiederholen, desto genauer wird natürlich die Abschätzung. Mit diesen sehr einfachen Grundlagen können wir das Problem auch schon simulieren.

Da das Problem mit Hilfe von JavaScript und HTML simuliert werden soll, müssen vorher noch einige technische Details geklärt werden; so benötigen wir ein Eingabefeld für die Anzahl der Versuche und Ausgabefelder für die gemessenen Ergebnisse; zusätzlich noch einige Hilfsfunktionen. Der folgende Code baut diese Testumgebung auf; für die eigentliche Simulation ist er nicht erforderlich, soll hier aber der Vollständigkeit halber aufgeführt werden (wer sich nicht dafür interessiert, kann ihn also einfach überspringen):

<script type=”text/javascript”>
<!–
function getRandom( min, max ) {
  var r;

  do {
     r = Math.random();
  } while( r == 1.0 );

  return min + parseInt( r * ( max-min+1 ) );
}

function getTries() {
  var tries = parseInt( document.form.tries.value, 10 );

  if ( isNaN( tries ) ) {
     alert(“Bitte eine Zahl eingeben.”);
     document.form.tries.focus();
     return 0;
  }

  return tries;
}

// Hier folgt gleich die eigentliche Funktion “run”.
//–>
</script>

<form name=”form” action=””>
  <table border=”0″ cellpadding=”0″ cellspacing=”4″>
     <tr>
        <td align=”right”>Anzahl Versuche: </td>
        <td><input name=”tries” type=”text” size=”12″
                maxlength=”8″></td>
     </tr>
     <tr>
        <td><input type=”button” value=”Simulieren”
                onclick=”run()”></td>
     </tr>
     <tr>
        <td align=”right”>Nicht wechseln:</td>
        <td><input name=”stay” type=”text” size=”12″
                maxlength=”12″ readonly></td>
     </tr>
     <tr>
        <td align=”right”>Immer wechseln:</td>
        <td><input name=”switch” type=”text” size=”12″
                maxlength=”12″ readonly></td>
     </tr>
  </table>
</form>

Der Code tut nichts weiter als im unteren HTML-Teil ein Formular mit einem Eingabe-Feld, einem Button und 2 Ausgabefeldern zu definieren; mit dem Button wird die noch zu implementierende Funktion run verknüpft. Im oberen JavaScript-Teil werden zwei Funktionen getRandom und getTries definiert. Erstere liefert eine Zufallszahl im Bereich der angegebenen Werte, die zweite liest die eingegebene Anzahl von Versuchen aus dem Eingabefeld aus (und vermeldet eine Fehlermeldung, wenn dabei etwas schiefging).

Der eigentlich interessante Code erfolgt nun in der Methode run, die wir hier implementieren:

function run() {

Als erstes wollen wir in einer Variable tries die Anzahl der durchzuführenden Versuche speichern:

  var tries = getTries();

Sicherheitshalber fahren wir mit der Simulation nur fort, wenn die Anzahl der Versuche größer als 0 ist (die Methode getTries liefert auch 0 zurück, wenn die Eingabe fehlerhaft ist):

  if ( tries > 0 ) {

Als nächstes wollen wir zwei Variablen anlegen, welche zählen, ob ein Wechsel des Tores bzw. der Nicht-Wechsel zum Erfolg geführt hat:

     var stay = 0;
     var sw = 0;

Und als nächstes folgt auch schon die eigentliche Simulation. So oft, wie angegeben, wollen wir das tun, was es zu tun gilt (die Variable i läuft dabei von 0 bis tries, bedingt also so viele Schleifendurchläufe, wie erwünscht):

     for ( var i = 0; i < tries; ++i ) {

Das besondere an dieser Simulation ist, dass sich der Zustand der Welt in jedem Durchlauf neu ergibt und nicht aus dem letzten Lauf übernommen wird. Der Zustand besteht aus der Position des Tores mit dem Preis und aus unserem gewählten Tor – wir benötigen dafür also 2 Variablen, die wir zufällig bestimmen. Die möglichen Werte 0, 1 und 2 stehen dabei für die drei zur Verfügung stehenden Tore:

        var winPos = getRandom( 0, 2 );
        var tryPos = getRandom( 0, 2 );

Als nächstes folgt die Auswahl der Strategie und damit entweder der Wechsel des Tores oder das Verbleiben beim bisherigen. Um Rechenzeit und Programmieraufwand zu sparen, erledigen wir beide Schritte mit einem mal und legen dabei die folgende Überlegung zugrunde:

Wir wissen, dass der Moderator immer ein Tor öffnet, hinter dem sich kein Preis befindet. Nach Bestimmung des Gewinntores und der eigenen initialen Wahl kann also das durch den Moderator geöffnete Tor vernachlässigt werden; welches genau das ist (0, 1 oder 2), spielt dabei auch keine Rolle, denn nach dem Öffnen sind lediglich 2 Tore übrig – das selbst gewählte und das andere, wobei sich hinter einem von beiden der Preis befindet. Die Entscheidung beschränkt sich hierdurch auf lediglich 2 Alternativen: soll gewechselt werden oder nicht.

Weiterhin wissen wir: wechseln wir das gewählte Tor nicht und hatten von Anfang an das richtige Tor gewählt, so ist das als Erfolg zu verbuchen (da wir ja den Preis bekommen). Wechseln wir dagegen, obwohl wir initial das Tor mit dem Preis gewählt hatten, so haben wir einen Misserfolg. Umgekehrt gilt: wechseln wir nicht, obwohl wir nicht das Tor mit dem Preis gewählt haben, ist dies ein Misserfolg; ein Wechsel beim initial falschen Tor führt dagegen zu einem Erfolg. Zusammengefasst: beim Nichtwechseln haben wir Erfolg, wenn wir initial das richtige Tor gewählt hatten, beim Wechsel haben wir Erfolg, wenn das initial gewählte Tor nicht das richtige wahr. Entsprechend können wir dann auch die Erfolge zählen: ein Erfolg fürs Nichtwechseln, wenn gewähltes Tor und Gewinntor übereinstimmen, ein Erfolg fürs Wechseln, wenn dies gerade nicht der Fall ist. Als Code lässt sich das folgendermaßen ausdrücken:

        if ( tryPos == winPos )
          ++stay;
        if ( tryPos != winPos )
          ++sw;
      }

Fehlt nur noch, die erhaltenen Ergebnisse auszugeben:

      document.form.stay.value = ( stay/tries*100 ).toFixed( 5 ) + “%”;
      document.form.switch.value = ( sw/tries*100 ).toFixed( 5 ) + “%”;
    }
  }

Hier noch einmal die Funktion im Ganzen:

function run() {
  var tries = getTries();

  if ( tries != 0 ) {
    var stay = 0;
    var sw = 0;

    for ( var i = 0; i < tries; ++i ) {       var winPos = getRandom( 0, 2 );       var tryPos = getRandom( 0, 2 );       if ( tryPos == winPos )         ++stay;       if ( tryPos != winPos )         ++sw;     }     document.form.stay.value = ( stay/tries*100 ).toFixed( 5 ) + "%";     document.form.switch.value = ( sw/tries*100 ).toFixed( 5 ) + "%";   } }

Damit haben wir sämtliche Funktionalität programmiert, um unsere Simulation durchzuführen. Fügt man die hier gezeigten Codeausschnitte zusammen und fügt sie in ein HTML-Dokument ein, so ergibt sich das folgende Formular, welches auch gleich mit einer Zahl gefüllt (bitte langsam vorantasten – zu große Zahlen könnten den Rechner zu stark belasten) und ausprobiert werden kann (wichtig: JavaScript muss hierzu im Browser aktiv sein):

Anzahl Versuche:
Nicht wechseln:
Immer wechseln:

Wenn eine genügend große Zahl eingegeben wird, bestätigt sich hiermit auch die eingangs getroffene Aussage, dass uns das Wechseln des Tores eine Gewinnchance von ungefähr 66% beschert.2

Wir haben hiermit also ein (zugegebenermaßen relativ unspannendes) Problem durch Simulation gelöst. Im nächsten Artikel der Reihe wollen wir ein etwas komplexeres Problem simulieren – Vorschläge hierfür können gern eingereicht werden (ansonsten habe ich schon die ein oder andere Idee).

2 Aufmerksame Leser werden natürlich völlig zu recht bemerken, dass sich das Ergebnis allein schon aus der Zählweise ergeben muss. Dies ist hier auch lediglich die abgekürzte Version der Simulation; eigentlich müsste man sie komplett ausführen, mit der Simulation des Öffnen eines Tores, einem anschließenden zufälligen Nicht-/Wechsel und der Überprüfung auf einen Gewinn – das würde aber den Rahmen eines Artikels sprengen und dabei zum gleichen Ergebnis führen (was ich auch verifiziert habe).

Kommentare (22)

  1. #1 Frank Wappler
    https://Im.Übrigen.bewerte.ich.das.Vorenthalten.einer.Kommentar-Vorschau.als.Missachtung.der.Leserschaft
    Oktober 4, 2012

    Marcus Frenkel schrieb (Oktober 3, 2012):
    > Die Regeln der Simulation sind ebenso einfach: haben wir durch unsere Wahl (Tor wechseln

    oder nicht wechseln) das Tor mit dem Preis erwischt, erhalten wir einen (imaginären) Punkt.

    >
    var stay = 0;
    var sw = 0;

    >
    if ( tryPos == winPos )
    ++stay;
    if ( tryPos != winPos )
    ++sw;

    Dies scheint ja (nur) den Fall zu behandeln, dass man jeweils einen (weiteren) reellen Punkt

    erhält, falls man das Tor mit dem Preis erwischt; und diesen reellen Punkt zur (schon

    vorhandenen) reellen Summe aller schon erhaltenen rellen Punkte addiert.

    Für die Summation imaginärer Punkte gilt aber doch offenbar:

    si \in {\mathbb C},

    {\rm if( \,} si == 0  {\rm \, ) \, then \,} \{
    {\rm \, \, \, \, \, if( \, Preis \, ) \,} {\rm \, then \,} si = \sqrt{ -1 } \,; \} und

    {\rm if( \,} si == \sqrt{ -1 }   {\rm \, ) \, then \,} \{
    {\rm \, \, \, \, \, if( \, Preis \, ) \,} {\rm \, then \,} \{

    {\rm \, \, \, \, \, \, \, \, \, \, } si = \sqrt{ -1 } + \sqrt{ -1 } \,;

    {\rm \, \, \, \, \, \, \, \, \, \, } si^2 = (\sqrt{ -1 } + \sqrt{ -1 })^2 \,;
    {\rm \, \, \, \, \, \, \, \, \, \, } si^2 = (\sqrt{ -1 })^2 + 2 \sqrt{ -1 } \sqrt{ -1 }     + (\sqrt{ -1 })^2 \,;
    {\rm \, \, \, \, \, \, \, \, \, \, } si^2 = (-1) + 2 \sqrt{ (-1) (-1) } + (-1) \,;
    {\rm \, \, \, \, \, \, \, \, \, \, } si^2 = (-1) + 2 \sqrt{ 1 } + (-1) \,;
    {\rm \, \, \, \, \, \, \, \, \, \, } si^2 = (-1) + 2 + (-1) \,;
    {\rm \, \, \, \, \, \, \, \, \, \, } si^2 = 0 \,;
    {\rm \, \, \, \, \, \, \, \, \, \, } si = 0 \,;
    {\rm \, \, \, \, \,} \}
    \},

    oder?

  2. #2 Marcus Frenkel
    Oktober 4, 2012

    Man muss ja nicht jedes Wort so…wörtlich nehmen. 😉

    Imaginär an den Punkten ist, dass man in der Ursprungsaufgabe natürlich keine Punkte bekommt, da man hier lediglich einen Versuch hat. Der Punkt entsteht also rein in der Simulation.

    Übrigens ist doch
    {\rm \, \, \, \, \, \, \, \, \, \, } \sqrt{ -1 } + \sqrt{ -1 } = 2 i \,;

    wenn ich mich gerade richtig erinnere?

    Und: wenn mir jemand verraten kann, wie man die Kommentar-Vorschau bei WordPress aktiviert, so mache ich das sofort. Ich habe schon danach gesucht, leider vergeblich.

  3. #3 Turi
    Oktober 4, 2012

    Es ist faszinierend: Bis 10 000 000 Versuchen war grade mal eine kleine Verzögerung von ~ 2 Sekunden zu bemerken.
    10 Millionen Runden in 2 Sekunden. Kaum vorzustellen.
    (Bei 99 999 999 Versuchen kam dann zweimal der Hinweis Javascript würde nicht mehr antworten : ), insgesamt hatte die Simulationen ~25 Sekunden gedauert)

  4. #4 Marcus Frenkel
    Oktober 4, 2012

    Na wenn man mal so rechnet…moderne Prozessoren haben eine Taktrate von ~3 GHz. Das sind 3 Milliarden Takte in der Sekunde. Auf meinem 3 GHz-Rechner brauche ich ungefähr 1 Sekunde für 10 Mio. Runde – das heißt, pro Runde werden ungefähr 300 Rechenzyklen benötigt (wenn man jetzt ganz blauäugig einfach mal davon ausgeht, dass sämtliche System-Berechnungen auf einem anderen Kern stattfinden).

    Was das ganze natürlich nicht weniger unglaublich macht. Allein die Aussage “3 Milliarden Takte in der Sekunde” – das ist doch eine ziemlich große Zahl.

  5. #5 rolak
    Oktober 4, 2012

    Grüezi – ich werde diese Serie dann zum JS-räubern nutzen 😉

    Das sieht ja interessant aus, kleiner Bildtest:

  6. #6 Frank Wappler
    https://This.game-show-hosting.recipient.of.a.star.on.Canada's.Walk.of.Fame.isn't.Howie.Mandel.
    Oktober 4, 2012

    Marcus Frenkel schrieb (#2, Oktober 4, 2012):
    > Imaginär an den Punkten ist, dass man in der Ursprungsaufgabe natürlich keine Punkte bekommt, da man hier lediglich einen Versuch hat

    Das kommt wohl (auch) darauf an, ob man für (im obigen ScienceBlog-Artikel gebrauchte) Begriffe wie “Gewinnchancen” größere Versuchs-Ensemble zugrundelegt.
    Vielleicht sind ja die Punkte, die im Programm-Code offenbar als reelle (sogar natürliche) Zahlen repräsentiert sind, zum Zweck der Simulation “virtuell” ? …

    > Übrigens ist doch
    > \sqrt{-1} + \sqrt{-1} = 2~i

    Also, um “si = 2~\sqrt{-1}” zu erhalten würde ich (auch) damit rechnen, dass

    si^2 = (2~\sqrt{-1})^2 \,;
    si^2 = 2^2~(\sqrt{-1})^2 \,;
    si^2 = 4~(-1) \,;
    si^2 = (-1) - 2 + (-1) \,;
    si^2 = (\sqrt{-1})^2 - 2~\sqrt{ 1 } + (\sqrt{-1})^2 \,;
    si^2 = (\sqrt{-1})^2 - 2~\sqrt{ (-1)~(-1) } + (\sqrt{-1})^2 \,;
    si^2 = (\sqrt{-1})^2 - 2~\sqrt{ (-1) }~\sqrt{ (-1) } + (\sqrt{-1})^2 \,;
    si^2 = (\sqrt{-1} - \sqrt{-1})^2 \,;
    si = \sqrt{-1} - \sqrt{-1}  \,.

    p.s.
    > Und: wenn mir jemand verraten kann, wie man die Kommentar-Vorschau bei WordPress aktiviert, so mache ich das sofort. Ich habe schon danach gesucht, leider vergeblich.

    Prima, danke! Und während ich dir bei der Suche so zu helfen versuche …

    https://www.google.de/search?q=wordpress+commet+preview

    https://wordpress.org/extend/plugins/live-comment-preview/

    … versuche ich mal weiter mir zur Syntax für “preformatted text” zu helfen:
    $latex si = \sqrt{-1} - \sqrt{-1} \,. $ .

  7. #7 rolak
    Oktober 4, 2012

    Wie zum Henker schiebt der Meister Wappler hier tonnenweise <img >-tags rein? Bei mir werden sie offensichtlich weggefiltert…

  8. #8 rolak
    Oktober 4, 2012

    ahso, $..$ standard-Latex

  9. #9 Marcus Frenkel
    Oktober 4, 2012

    @Frank Wappler

    Da ich leider manuell keine neuen Plugins installieren kann, hilft mir die Google-Suche da auch nur bedingt; die hatte ich auch schon bemüht. Ich habe noch einmal eine Anfrage gestellt, ob man denn blogweit eine Vorschaufunktion einrichten könnte.

  10. #10 camil7
    Oktober 4, 2012

    … und ich Weichei hab mich nur getraut, Zahlen wie 200 einzugeben, aber JavaScript in heutigen Browsern ist immer noch schneller als Rechungen direkt auf der CPU vor 30 Jahren 😉

    Kann es uebrigens sein, das der Herr Frank Wippler uns mit seinen Rechnungen ein wenig aufs Glatteis fuehren will 😉 Der Fehler liegt natuerlich darin, dass die Quadratwurzel nur fuer positive Zahlen ein eindeutiges (positives) Ergebnis hat, und nur dann Rechenregeln wie sqrt(a*b) = sqrt(a)*sqrt(b) gelten (sorry, keine schicken Formeln von mir, die Zeiten, wo ich fluessig TeX sprach, sind leider schon lange vorbei.) Mit negativen Zahlen gibt es immer zwei Loesungen sqrt(-a) = i*sqrt(a) und -i*sqrt(a), die sich prinzipiell nicht voneinander unterscheiden lassen, und weil es dann keine “ausgezeichnete” Loesung mehr gibt, bezeichnet die Wurzel nicht mehr eine eindeutige, sondern zwei moegliche Loesungen, da kann mal gerne mal eben ein Vorzeichen hervorzaubern 😉

    An den Blogautor: Danke, dass eine Fragen zur Computergraphik nicht ganz aus dem Blick verschwunden sind, aber wenn es zu kompliziert wird, kann ich auch versuchen, mich selber zur Uni-bibliothek zu schleppen; also von mit aus schreib nur etwas, wenn es Dir gerade auch wirklich in den Kram passt. (Und nur wenn es Spass macht, sowieso.)

  11. #11 Stefan W.
    Oktober 5, 2012

    Ich sehe mal wieder Grund rumzuätzen – hält sich aber in Grenzen.

    Der Kern bei der Vorstellung des Ziegenproblems ist es, den unbedarften Leser, der das Spiel nicht kennt, über den Ablauf des Spiels schlecht zu informieren – am besten im Unklaren darüber zu lassen, dass der Moderator immer eine Tür öffnet – egal ob man die richtige Tür getippt hat oder nicht.

    Was hier sprachlich aber unsauber formuliert wurde, ist:

    Der Kandidat wählt eines der Tore, woraufhin der Moderator des Spiels eines der anderen Tore öffnet, hinter dem sich eine Ziege befindet.

    Eines welcher Tore öffnet der Moderator? Eines der anderen, hinter dem sich eine Ziege befindet?

    Das kann man nicht sagen. “Eines der anderen, hinter denen sich eine Ziege befindet.” könnte man sagen – es sind ja zwei. Und es kann sich sogar hinter beiden je eine Ziege verbergen, aber gesagt werden soll, dass der Moderator entweder das eine der anderen Tore öffnet, hinter dem sich eine Ziege verbirgt, sofern die andere Ziege hinter dem vorläufig vom Kandidaten gewählten Tor ist, oder von den zwei anderen, hinter denen sich je eine Ziege verbirgt, eines auswählt.

    Gegen eine Optimierung wie hier mit Artikelumfang begründet spricht, dass der Grund eine solche Simulation zu schreiben doch der ist, dass man das Ergebnis eben nicht im Kopf herleiten will, sondern empirisch demonstrieren will – dann sollte man mit Optimierungen, in die – unter Umständen falsche Überlegungen – eingehen, vertagen, und zuerst eine gradlinige Lösung anstreben.

    “Premature optimization is the root of all evil.”

    Was noch unklar ist, ist, wieso das Spiel kein üblicher Kandidat für eine Simulation ist, und wieso diese Aussage mit einem “Eigentlich” eingeschränkt wird.

    Mein Scala-Code sähe folgendermaßen aus:

    val r = util.Random
    val tore = Vector (“Preis”, “Ziege”, “Ziege”)
    def ziegenMischen = r.shuffle (tore)
    def kandidatWaehlt : Int = r.nextInt (2)
    def tuerOeffnen (spiel: Vector[String], wahl: Int): Int = {
    val freieZiegen = spiel.zipWithIndex.filterNot (_._2 == wahl).filter (_._1 == “Ziege”)
    if (freieZiegen.size == 1) freieZiegen (0)._2
    else freieZiegen (r.nextInt (2))._2
    }
    def gewinnErmitteln (spiel: Vector[String], wahl: Int): Int = if (spiel (wahl) == “Preis”) 1 else 0
    println (
    (1 to 100).map {n =>
    val spiel = ziegenMischen
    val wahl = kandidatWaehlt
    val offeneTuer = tuerOeffnen (spiel, wahl)
    gewinnErmitteln (spiel, wahl)
    }.sum )

    So ist es komplett nicht benutzerfreundlich. Man könnte es aber animieren, wenn man wollte.

    Auch hier sieht man, dass die Funktion des Torwechselns überflüssig ist. Wenn man immer wechselt entspricht die Zahl der Gewinne den Niederlagen, wenn man nicht wechselt – tertium non datur: Entweder man wechselt, oder nicht und entweder man gewinnt, oder verliert.

    Man sieht aber auch, dass das Türöffnen sinnlos ist – für die Rechnung, nicht für das Spiel. ‘offeneTuer’ wird im späteren Verlauf überhaupt nicht benutzt.

    Was bleibt ist, dass der Kandidat eine Tür wählt, und leicht sieht man ein, dass er mit 1/3 Chance gewonnen hat, und mit 2/3 verloren. Daher ist das Ergebnis bei einem Wechsel, dass er mit 2/3 gewinnt.

    Den Scalacode testen kann man hier: https://www.simplyscala.com/ testen. Für eine Vielzahl an Sprachen gibt es hier: https://ideone.com eine Online-Testmöglichkeit.

    Und nächste Woche erklären wir dann den Unterschied zwischen Tor und Tür. 😉

  12. #12 Frank Wappler
    https://In.der.Physik.gibt.es.keine.Probleme--sondern.allenfalls.ungute.Koordinatensysteme...
    Oktober 5, 2012

    Frank Wappler schrieb (#6, Oktober 4, 2012):
    > […]
    > si^2 = (\sqrt{-1})^2 - 2~\sqrt{ (-1)~(-1) } + (\sqrt{-1})^2 \,;
    > si^2 = (\sqrt{-1})^2 - 2~\sqrt{ (-1) }~\sqrt{ (-1) } + (\sqrt{-1})^2 \,;

    Das stimmt ja (leider!?) gar nicht, auch wenn’s scheinbar selbstverständlich aussah;
    das Multiplizieren und das Radizieren sind bzgl. der komplexen Zahlen keine kompatiblen (bzw. vertauschbaren) Operatoren.
    Quantitativ (und hoffentlich stimmt das einigermaßen ):

    \langle I [ \, \sqrt, \, \times \, ] I \rangle + \langle I [ \, \sqrt, \, \times \, ] (-) \rangle + \langle (-) [ \, \sqrt, \, \times \, ] I \rangle + \langle (-) [ \, \sqrt, \, \times \, ] (-) \rangle = 2.

    p.s.
    camil7 schrieb (#10, Oktober 4, 2012):
    > das[s] der Herr Frank W[a]ppler uns mit seinen Rechnungen ein wenig aufs Glatteis fuehren will

    Dass die oben (#1, #6) gezeigten Rechnung vom gewohnten Weg abführen, war mir zwar bewußt;
    in der ersten Begeisterung darüber, hier endlich einigermaßen LaTeXten zu können, war mir das
    zugrundeliegende Glatteis aber ziemlich entgangen.
    Also: danke für die (unabhängige) Berichtigung.

    > dass die Quadratwurzel nur fuer positive Zahlen ein eindeutiges (positives) Ergebnis hat, und nur dann Rechenregeln wie sqrt(a*b) = sqrt(a)*sqrt(b) gelten

    Diese “Rechenregel” gilt ja offenbar auch dann, falls nicht beide diese Zahlen, “a” und “b“, negativ sind.

    > Mit negativen Zahlen gibt es immer zwei Loesungen sqrt(-a) = i*sqrt(a) und -i*sqrt(a), die sich prinzipiell nicht voneinander unterscheiden lassen

    Und dennoch wurden im zitierten Satz zwei “Lösungen” deutlich unterscheidbar genannt:
    i*sqrt(a)” und “-i*sqrt(a)” sollen doch offenbar nicht ein-und-die-Selbe “Lösung” sein.

  13. #13 Marcus Frenkel
    Oktober 5, 2012

    @camil7
    Keine Angst – nächster Artikel beschäftigt sich wieder mit Computergrafik. 😉

    @Frank Wappler
    Ich habe mal die Formel im ersten Beitrag korrigiert und den Korrekturkommentar gelöscht; ich hoffe, das trifft auf Zustimmung.

  14. #14 HF
    Oktober 6, 2012

    Nett gemacht. Hat das kleine Programm auf Anhieb funktioniert oder gab es Bugs in der ersten Version? Wenn man das Ergebnis nicht schon kennt, ist es schwierig, Programmierfehler in einer Simulation zu finden.

  15. #15 Marcus Frenkel
    Oktober 6, 2012

    @HF
    Es hat auf Anhieb funktioniert – aber ich hatte das Problem auch vorher schon weitaus ausführlicher in C++ gelöst; das habe ich als Grundlage für das Programm hier genutzt.

  16. #16 Dr. W
    Oktober 8, 2012

    Der Kandidat wählt eines der Tore, woraufhin der Moderator des Spiels eines der anderen Tore öffnet, hinter dem sich eine Ziege befindet.

    Wenn der Moderator immer anbietet das Tor zu wechseln und wir wissen dies, müssen wir wechseln, WEIL man sich so für zwei Tore anstatt für ein Tor entscheiden kann. (Das ist das “Problem” um das sich das Javascript -Modell und der Artikel kümmern, ein Problem, das sich mit einfacher Fallunterscheidung lösen lässt.)

    Wissen wir nicht, ob und wann genau der Moderator anbietet zu wechseln, entsteht ein wesentlich interessanteres Problem.

  17. #17 Frank Wappler
    https://Im.Übrigen.ist.dem.nichts.hinzuzufügen
    Oktober 8, 2012

    Marcus Frenkel schrieb (#15, Oktober 5, 2012):
    > Ich habe mal die Formel im ersten Beitrag korrigiert und den Korrekturkommentar gelöscht; ich hoffe, das trifft auf Zustimmung.

    Nicht ganz ungetrübte;
    denn obwohl es mir offenbar gelungen war, die fragliche “$latex $”- Formel so zu korrigieren, dass sie zumindest geparst werden konnte, wird dadurch ja nun erst ersichtlich, dass sie auf die vorliegende Weise ganz miserabel formatiert ist:
    das (#12, Oktober 5, 2012) sieht ja aus, als würden Wurzeln aus Kommas gezogen, und nicht (so wie Kommutatoren aussehen sollen), als wären zwei Operatoren (\sqrt und \times ) durch Komma getrennt.

    Um das zielführend zu verbessern, bräuchte man natürlich eine Kommentar-Vorschau; oder wenigstens eine Sandbox, die spezifisch für die Syntax der hier einzureichenden Kommenare wäre; oder wenigstens Dokumentation dieser Syntax …

  18. #18 Marcus Frenkel
    Oktober 9, 2012

    Die Kommentarvorschau ist beantragt und wohl “in Bearbeitung” – wann sie kommen wird, kann ich allerdings nicht sagen.

  19. #19 rolak
    Oktober 9, 2012

    Für Wapplers Latex-Tests wüßte ich auf anhieb nichts (außer einem -zu suchenden- blog mit Vorschau), doch fürs htmlige reicht so etwas wie WriteArea völlig aus (ist leider in der tag-Auswahl afaik nicht beschränkbar, somit ‘zu gut’).

  20. #20 Bienenstich
    Essen
    Oktober 15, 2012

    Hi,
    der ca. 66%ige wechsel Treffer passt nur wenn der Moderator auch weiss wo die Ziege steckt, falls nicht bleibt es eine 50:50 🙂

  21. #21 Stefan W.
    https://home.arcor.de/hirnstrom/beschneidung/index.html
    November 6, 2012

    Hi Bienenstich,

    Ja, die Diskussionen können viel länger geführt werden, wenn das Setting ein wenig unklar ist.

    Das erste Mal dass ich mit dem Quiz konfrontiert wurde wollte es einfach nicht in meinen Kopf, dass der Moderator immer eine Ziegentür öffnet, und zwar immer von den 2 nicht gewählten, und immer die gleiche Frage stellt. Entsprechend habe ich die ganze Nacht diskutiert – am Thema vorbei.

    Der Gegenpart hat aber das Missverständnis nicht bemerkt, weil er so begeistert war, dass ich falsch liege. 🙂

  22. #22 Dr. W
    November 16, 2012

    > der ca. 66%ige wechsel Treffer passt nur wenn der Moderator auch weiss wo die Ziege steckt, falls nicht bleibt es eine 50:50

    Wie soll der Moderator eine mit einer Ziege versehene Tür öffnen und dann das Wechseln anbieten, wenn er nicht weiß, wo das gute Tier steckt?

    50:50 ist beim Ziegenproblem übrigens nur bei einem ganz bestimmten Moderatorenverhalten möglich. Die üblichen Lösungen sind 0% (wenn der Moderator nicht kooperiert und der Kandidat wechselt), 1/3 (wenn das Spiel nicht verstanden wird und der Kandifat nie wechselt) und 2/3 (wenn der Moderator immer anbietet zu wechseln, nachdem er eine Ziege gezeigt hat – die Standardlösung, die auch im Artikel behandelt wird)

    BTW, das Ziegenproblem ist trivial, wird aber immer wieder falsch bearbeitet. Man kann es auch ohne weiteres lösen, mit Hilfe der Fallunterscheidung, wenn man von bedingten Wahrscheinlichkeiten nie etwas gehört hat.