Von Ziegen und Schlangen -- Simulation des Ziegenproblems in Python
| Das Ziegenproblem ist ein bekanntes Statistikproblem, dessen Lösung die Menschen stets zu verblüffen vermag. Dieser Artikel stellt eine in Python implementierte Simulation des Spiels vor. |
Das Ziegenproblem
In einer Spielshow im Fernsehen soll ein Kandidat eines von drei Toren auswählen.
Hinter einem Tor ist ein Gewinn (ein Auto) versteckt, hinter den anderen beiden
Toren befinden sich jeweils eine Niete (eine Ziege).
Der Kandidat wählt (zufällig) ein Tor aus. Dieses wird jedoch noch nicht geöffnet.
Der Moderator kennt die Belegung der Tore. Er läßt nun eines der beiden anderen
Tore öffnen. Hinter diesem befindet sich eine Ziege.
Als nächstes bietet der Moderator dem Kandidaten an, seine Entscheindung zu
überdenken. Er kann bei seiner ursprünglichen Wahl bleiben, oder zum
anderen noch verschlossenen Tor wechseln.
Was soll er tun?
Die Lösung
Wenn dieses Problem diskutiert wird, hält sich die Meinung, daß es egal sei, ob der Kandidat wechselt oder nicht, was einer 50-50-Chance gleich kommt, erstaunlich lange. Tatsächlich aber, ist es nicht so. Die Wahrscheinlichkeit das Auto zu gewinnen liegt im Falle des Wechselns bei 2/3 und im Falle des Nicht-Wechselns bei 1/3.
Warum?
Die Erklärung
Der Kandidat hat (nur) die Wahl zwischen links und rechts (siehe Abbildung 1).

Abbildung 1: Wahrscheinlichkeitsverteilung a) vor und b) nach dem Öffnen von Tor 3
Die Wahrscheinlichkeit, dass der Preis hinter einem der Tore (1,2 oder 3) liegt ist 1/3. D.h. die Wahrscheinlichkeit den Preis auf der linken Seite zu finden (also hinter Tor 1) ist 1/3 und auf der rechten Seite 2/3 (Tor 2 und 3). Dies ändert sich im Verlauf des Spiel nicht. Die Summe der Wahrscheinlichkeit ist stets gleich 1. Auch dies ändert sich nicht.
Wird nun eines der beiden Tore (z.B. Tor 3, ohne Beschränkung der Allgemeinheit) geöffnet und eine
Niete preisgegeben, dann ist die Wahrscheinlichkeit hier einen Auto zu gewinnen gleich 0. Nun
liegt die Wahrscheinlichkeit von 2/3 auf dem zweiten noch nicht geöffneten Tor (Tor 2).
Die Wahrscheinlichkeit von Tor 1 ist nach wie vor 1/3. Auch die Wahrscheinlichkeit von Tor 2 UND Tor 3 ist
immernoch 2/3.
Also ist das Wechseln zur rechten Seite stets besser (in diesem Fall zu Tor 2).
Die Verallgemeinerung
Angenommen man hat N Tore statt nur 3. Man wählt ein Tor aus. Die Wahrscheinlichkeit für einen
Preis liegt bei 1/N, was bei großen N sehr klein wird.
Bei z.B. N=1000 Toren auf Anhieb das mit dem Preis zu wählen ist offensichtlich fast nicht
möglich. Bei N=3 ist dies nicht so offensichtlich (für den "gesunden Menschenverstand").
Nun werden N-2 Tore mit Nieten dahinter
geöffnet. Also bei 1000 Toren 998 Stück. Das Wechseln bringt eine Wahrscheinlickeit von N-1/N, was offensichtlich für große N
gegen 1 strebt (hier 999/1000=99,9%). Das verbleibende Tor verbirgt also fast mit Sicherheit den Preis.
Das Programm
Wer es theoretisch nicht recht glauben mag, der macht gern ein Experiment, um der Sache empirisch auf den Grund zu gehen. Ein einziges Experiment ist aber nicht sehr aussagekräftig. Es ist besser mehrere, n Experimente unter den gleichen Bedingungen durchzuführen. Dabei sollen N Tore betrachtet werden. Außerdem entscheiden wir, dass wir entweder immer oder nie das ursprünglich gewählte Tor wechseln wollen (mit switch=1 oder 0). Eine Implementierung in Python [1] (zonk.py.gz) ist nachfolgend dargestellt.
| Monte-Carlo-Simulation des Ziegenproblems |
1 #!/usr/bin/python
2 #
3 # Simulation des Ziegenproblems
4 #
5
6 import random
7
8 N=3 # Anzahl Tore (N)
9 n=100 # Anzahl Experimente (n)
10 switch=0 # 0=nie, 1=immer
11 won=lost=0 # Anzahl gewonnener/verlorener Spiele
12
13 for i in range(1,n+1): # führe n Experimente aus
14 print "Experiment Nr.%(i)d/%(n)d" % vars()
15 door_list=range(N)
16 print " door_list:",door_list
17 # Tor ohne Ziege
18 door_without_goat_behind=random.choice(door_list)
19 print " door_without_goat_behind:",door_without_goat_behind
20 # Kandidat wählt zufällig 1 Tor
21 door_picked_by_candidate=random.choice(door_list)
22 print " door_picked_by_candidate:",door_picked_by_candidate
23 door_list.remove(door_picked_by_candidate)
24 try: door_list.remove(door_without_goat_behind)
25 except ValueError: pass
26 print " door_list:",door_list
27 # Moderator öffnet N-2 Tore hinter denen je eine Ziege steht
28 for j in range(N-2):
29 door_opened_by_presenter=random.choice(door_list)
30 door_list.remove(door_opened_by_presenter)
31 print " door_opened_by_presenter:",door_opened_by_presenter
32 # Die Liste ist leer, wenn der Kandidat ein Tor mit Ziege wählte.
33 if len(door_list)==0: door_list.append(door_without_goat_behind)
34 print " door_list:",door_list
35 # Kandidat darf sich umentscheiden
36 if switch: final_choice=door_list[0]
37 else: final_choice=door_picked_by_candidate
38 # Auswertung
39 if final_choice==door_without_goat_behind: won+=1
40 else: lost+=1
41 # theoretische Wahrscheinlichkeit
42 if switch: w_win,w_lost=(N-1)/float(N),1/float(N)
43 else: w_win,w_lost=1/float(N),(N-1)/float(N)
44 # relative Häufigkeit im Experiment
45 h_win,h_lost=won/float(n),lost/float(n)
46
47 print "Ergebnis:"
48 print "Experimente: %(n)d, Tore: %(N)d, switch: %(switch)d" % vars()
49 print "gewonnen: %(won)d, hg=%(h_win)0.4f, wg=%(w_win)0.4f" % vars()
50 print "verloren: %(lost)d, hv=%(h_lost)0.4f, wv=%(w_lost)0.4f" % vars()
|
Alle problemrelevanten Parameter sind in Zeile 8, 9 und 10 einzustellen.
Die Tore werden in einer Liste gehalten (Zeile 15). Listen sind Datentypen (Objekte), die
Python standardmäßig zu Verfügung stellt.
In Zeile 18 wird der Preis
hinter einem zufällig gewählten Tor versteckt. Dann wählt der Kandidat
zufällig ein Tor aus (Zeile 21). Als nächstes wird das Tor, das der
Kandidat gewählt hat aus der Torliste entfernt (Zeile 23).
Dies kann bereits das Tor mit dem Preis dahinter sein.
Als nächstes wird das Tor mit dem Preis dahinter ebenfalls aus der Torliste entfernt.
Falls der Kandidat mit seiner Wahl schon richtig lag, würde das Tor
nicht mehr in der Liste sein und das Entfernen einen Fehler auslösen. Glücklicherweise kann Python
ggf. auftretende Exceptions fangen (Zeile 24 und 25). Nun öffnet der Moderator
alle außer 2 Tore (Zeile 29). Diese werden ebenfalls aus der Torliste entfernt (Zeile 30).
Wenn der Kandidat richtig lag, dann ist die Liste jetzt leer. Ist dies der Fall,
so wird das vom Kandiaten bereits gewählte Tor (mit dem Preis) wieder zur Liste
hinzugefügt (Zeile 33). Nun entscheidet sich der Kandidat, ob
er das gewählte Tor behält (Zeile 37) oder ob er das andere nimmt (Zeile 36).
Abschließend findet eine Auswertung statt. Hierbei steht "h" für relative Häufigkeiten (experimentell),
"w" für Wahrscheinlichkeiten (theoretisch), "g" für gewonnen und "v" für verloren.
Experimente
Durch sukzessive Änderung der Parameter bekommt man schnell die verschiedenen Situationen in den Griff:
Ergebnis: Experimente: 100000, Tore: 3, switch: 0 gewonnen: 33384, hg=0.3338, wg=0.3333 verloren: 66616, hv=0.6662, wv=0.6667
Ergebnis: Experimente: 100000, Tore: 3, switch: 1 gewonnen: 66635, hg=0.6663, wg=0.6667 verloren: 33365, hv=0.3337, wv=0.3333
Ergebnis: Experimente: 10000, Tore: 1000, switch: 0 gewonnen: 8, hg=0.0008, wg=0.0010 verloren: 9992, hv=0.9992, wv=0.9990
Ergebnis: Experimente: 10000, Tore: 1000, switch: 1 gewonnen: 9986, hg=0.9986, wg=0.9990 verloren: 14, hv=0.0014, wv=0.0010Das Wechseln des Tors ist offensichlich besser für den Kandidaten.
Links und Literaturhinweise:
- [1] Python: http://www.python.org
- [2] Das Ziegenproblem ausgegooglet
- [3] Gero von Randow: Das Ziegenproblem - Denken in Wahrscheinlichkeiten. Rowohlt, Reinbek 1992.
- [4] A. K. Dewdney: 200 Prozent von nichts - Die geheimen Tricks der Statistik und andere Schwindeleien mit Zahlen. Birkhäuser, 1994
Anmerkungen zu diesem Artikel
| [3] | Widerspruch | J/Psi | 31-10-2006 |
Eigene Anmerkung eintragen