home   articles   archive   forum   masthead  
Published at 5.05.05
Author: Lars-Anders Schmuhl
Translator: Sebastian Kueppers
Languages: de
Printer printer-version
Support Us!
  Warning: This article needs a proof reader.

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.0010
  
Changing the door proves obviously best for the candidate.


Links:



Talkback Area




Enter Own Comment