Von Ziegen und Schlangen -- Simulation des Ziegenproblems in Python
| The goat problem is a well known statistical problem. But its solution still suprises. This article presents a simulation of this game written in Python. |
The goat problem
In a game show on TV the candidate is asked to choose one door out of three.
Behind one of the doors a prize (a car) is hidden, both other doors hide a loss (a goat) each.
The candidate chooses a door, but it isn't opened yet.
The show host, who knows what is behind each door, now opens one of the un-chooses doors containing a goat.
Now the candidate is offered to think about his descission.
He can stick to the door he chose or change to the other, still unopened door.
What shall he do?
The answer
If this problem is discussed it is amazing how long the opinion that changing or not would be a 50:50 chance stays alive. Suprisingly this is wrong. The chance to win the car is 2/3 in case of changing the door but only 1/3 if sticking to the firstly chosen one.
Why?
The explanation
Imagine the candidate may only choose between "left" and "right" (see figure 1).

Fig. 1: possibility factors (a) before and (b) after opening door 3
The possibility for the prize being hidden behind one of the three doors is 1/3 each. So the possibility to find it on the left side (behind door 1) is 1/3, for the right side (doors 2 and 3) it is 2/3.
This won't change during the game.
The sum of possibilities is 1.
That won't change, too.
If now one of the two doors is opened and reveals to be a loss (e.g. door 3, without loss of generality) the possibility to win the car is 0 here.
The possibility to win (2/3 as we know) is now only on the unopened door 2.
The possibility for door 1 to hide the prize is still 1/3.
You see: Changing to the right side (in that case to door 2) is better.
Generalization
Presume you have N doors instead of 3.
Choose a door.
The possibility to win is 1/N which can be really small for big N.
To pick the right door out of 1000 (for N=1000 for example) seems nearly impossible.
With N=3 this is not so easy to see (for the "common sense").
Now N-2 doors hiding losses are opened.
With 1000 doors this means 998.
Changing the door brings a possibility of N-1/N, which will gain 1 for big N (in our example 999/1000 = 99,9%).
The last door hides the prize nearly for sure.
Das programm
Those who don't belive theoretic explanations do perform tests to reveal secrets. But a single test doesn't say thta much. There have to be more, better n tests done in the sam environment. In our test N doors should be supervised. Additionally we decide whether we do always or never want to change the door (switch=1 or 0). An implementation using python (zonk.py.gz) is shown below.
| Monte-Carlo-Simulation: goat problem |
1 #!/usr/bin/python
2 #
3 # Simulating the goat problem
4 #
5
6 import random
7
8 N=3 # Number of doors (N)
9 n=100 # Number of experiments (n)
10 switch=0 # 0=never, 1=always
11 won=lost=0 # Number of won/lost games
12
13 for i in range(1,n+1): # do n tests
14 print "Experiment No.%(i)d/%(n)d" % vars()
15 door_list=range(N)
16 print " door_list:",door_list
17 # Door without goat
18 door_without_goat_behind=random.choice(door_list)
19 print " door_without_goat_behind:",door_without_goat_behind
20 # Candidate chooses door randomly
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 # Host opens N-2 doors hiding a goat each
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 # If a door hiding a goat was choosen the list is empty now
33 if len(door_list)==0: door_list.append(door_without_goat_behind)
34 print " door_list:",door_list
35 # Candidate may change
36 if switch: final_choice=door_list[0]
37 else: final_choice=door_picked_by_candidate
38 # Resulting
39 if final_choice==door_without_goat_behind: won+=1
40 else: lost+=1
41 # theoretic possibilities
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 # experimental data
45 h_win,h_lost=won/float(n),lost/float(n)
46
47 print "Result:"
48 print "Tests: %(n)d, Doors: %(N)d, switch: %(switch)d" % vars()
49 print "won: %(won)d, hg=%(h_win)0.4f, wg=%(w_win)0.4f" % vars()
50 print "lost: %(lost)d, hv=%(h_lost)0.4f, wv=%(w_lost)0.4f" % vars()
|
All needed parameters are set in lines 8-10.
The doors are administrated using a list (line 15).
Lists are data objects provided by python.
In line 18 the prize is hidden behind a randomly choosen door.
After that the candidate chooses a door randomly, too (line 21).
This door is removed from the list of doors and can, of course, be the one with the prize.
In the next step the door with the prize is removed from the list, too.
If the candidate choose the right door this one won't be on the list any more.
Luckily python is able to catch the exception that may occour (lines 24 and 25).
Now the show master opens all but 2 doors (line 29).
If the candidate chose the right door at the beginning the list is empty now.
In that case the chosen door (hiding the prize) is being added to the list again (line 33).
Now the candidate decides whether to keep (line 37) or change (line 36) the door.
At the end some statistics are given.
"h" stands for the frequency of occurrence (experimental), "w" for possibility (theoretically), "g" for won and "v" for lost.
Some tests
By simply changing the parameters several situations can be tested:
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.0010Changing the door proves obviously best for the candidate.
Links:
Talkback Area
Enter Own Comment