这是一个好的还是坏的“蒙提霍尔”模拟?为什么?
昨天在课堂上,我试着给朋友解释蒙提霍尔问题,结果我们用Python写了个代码来证明如果你总是换选择,你会赢2/3的机会。我们写出了这个:
import random as r
#iterations = int(raw_input("How many iterations? >> "))
iterations = 100000
doors = ["goat", "goat", "car"]
wins = 0.0
losses = 0.0
for i in range(iterations):
n = r.randrange(0,3)
choice = doors[n]
if n == 0:
#print "You chose door 1."
#print "Monty opens door 2. There is a goat behind this door."
#print "You swapped to door 3."
wins += 1
#print "You won a " + doors[2] + "\n"
elif n == 1:
#print "You chose door 2."
#print "Monty opens door 1. There is a goat behind this door."
#print "You swapped to door 3."
wins += 1
#print "You won a " + doors[2] + "\n"
elif n == 2:
#print "You chose door 3."
#print "Monty opens door 2. There is a goat behind this door."
#print "You swapped to door 1."
losses += 1
#print "You won a " + doors[0] + "\n"
else:
print "You screwed up"
percentage = (wins/iterations) * 100
print "Wins: " + str(wins)
print "Losses: " + str(losses)
print "You won " + str(percentage) + "% of the time"
我朋友觉得这个方法不错(而且是个很好的模拟),但我对此有些怀疑和担心。这个模拟真的够随机吗?
我觉得问题在于,所有的选择都是固定写死的。
这个模拟对于蒙提霍尔问题来说是好还是坏?为什么?
你能想出一个更好的版本吗?
15 个回答
2
我喜欢这样的东西。
#!/usr/bin/python
import random
CAR = 1
GOAT = 0
def one_trial( doors, switch=False ):
"""One trial of the Monty Hall contest."""
random.shuffle( doors )
first_choice = doors.pop( )
if switch==False:
return first_choice
elif doors.__contains__(CAR):
return CAR
else:
return GOAT
def n_trials( switch=False, n=10 ):
"""Play the game N times and return some stats."""
wins = 0
for n in xrange(n):
doors = [CAR, GOAT, GOAT]
wins += one_trial( doors, switch=switch )
print "won:", wins, "lost:", (n-wins), "avg:", (float(wins)/float(n))
if __name__=="__main__":
import sys
n_trials( switch=eval(sys.argv[1]), n=int(sys.argv[2]) )
$ ./montyhall.py True 10000
won: 6744 lost: 3255 avg: 0.674467446745
2
你提到所有的选择都是写死在代码里的。但如果你仔细看看,就会发现你认为的“选择”其实根本不是选择。蒙提的决定是没有损失的一般性,因为他总是选择有山羊的那扇门。你换门的决定总是由蒙提的选择来决定,而蒙提的“选择”实际上并不算选择,所以你的选择也不算选择。你的模拟结果是正确的。
38
你的解决方案很好,但如果你想更严格地模拟这个问题(而且想要更高质量的Python代码;-),可以试试:
import random
iterations = 100000
doors = ["goat"] * 2 + ["car"]
change_wins = 0
change_loses = 0
for i in xrange(iterations):
random.shuffle(doors)
# you pick door n:
n = random.randrange(3)
# monty picks door k, k!=n and doors[k]!="car"
sequence = range(3)
random.shuffle(sequence)
for k in sequence:
if k == n or doors[k] == "car":
continue
# now if you change, you lose iff doors[n]=="car"
if doors[n] == "car":
change_loses += 1
else:
change_wins += 1
print "Changing has %s wins and %s losses" % (change_wins, change_loses)
perc = (100.0 * change_wins) / (change_wins + change_loses)
print "IOW, by changing you win %.1f%% of the time" % perc
一个典型的输出结果是:
Changing has 66721 wins and 33279 losses
IOW, by changing you win 66.7% of the time