旋转游戏 monte carlo
A spin game monte carlo
问题:
这里有一个小 Monte Carlo 挑战问题,考虑以下使用两个转盘的游戏。假设玩家根据以下规则旋转圆盘上的一个或另一个指针:
如果玩家旋转指针 i 并停在区域 p_{ij}
的区域,他从磁盘 i
移动到磁盘 j
(i
和 j
是 1 或 2);
如果指针停在区域x_i
的区域,则游戏结束;
若游戏结束于区域x_1
则玩家获胜,若指针停在区域x_2
则玩家输。
从圆盘 1 开始的玩家获胜的概率是多少?假设每个磁盘的面积是一个,所以x_1+p_{11}+p_{12} =1
,以及x_2+p_{21}+p_{22} =1
运行 p_{11} =0.2
、p_{12} =0.4
、p_{21} =0.3
和 p_{22} =0.35
.
情况下的代码
import random
p_11 = 0.2
p_12 = 0.4 #0.2+0.4
p_21 = 0.3
p_22 = 0.35
wins = 0
pointer = 0
pointer2 = 0
for i in range(10**7):
while pointer < p_11:
pointer2 = 0 #resetting pointer2
pointer = random.uniform(0,1)
if p_11+p_21 < pointer < 1: #area corresponding to x_1
wins += 1 #wins
pointer = 0
break
else:
pointer = 0 #resetting pointer1
while pointer2 < p_22:
pointer2 = random.uniform(0,1)
if p_22+p_21 < pointer2 < 1: #area corresponding to x_2
pointer2 = 0
break #loses
print(wins/10**7)
正确答案是 0.5821,但我得到的是 0.7141465。我哪里做错了?
我编辑了我的代码,在这种情况下它再次转动磁盘 p_22
和 p_11
个案例
问题出自《数字骰子》一书(Paul J. Nahim)第 27-29 页(有 pdf )
我已经对问题进行了数学分析,发现解决方案实际上是:
(1 - p_11 - p_12) * (1 - p_22) / ((1 - p_11) * (1 - p_22) - p_12 * p_21)
(在某些极端情况下实际上是不正确的(例如 p_22 = 1
))
这个其实是在Digital Dice这本书的附录6里面写的,就不证明了。
根据你的数字,它给出了 0.65
的答案,这是正确的。您的代码更改了很多,现在它给出了 1.0
的输出,而不是问题中所写的内容。在这里,我更正了您的代码的第一个版本:
import random
p_11 = 0.2
p_12 = 0.4
p_21 = 0.3
p_22 = 0.35
total_iterations = 10 ** 6
wins = 0
num = 0
for i in range(total_iterations):
current_disk = 1
while True:
num = random.uniform(0, 1)
if current_disk == 1:
if num < p_12:
current_disk = 2
continue
elif num > p_11 + p_12:
wins += 1 #wins
break
else:
if num < p_21:
current_disk = 1
continue
elif num > p_21 + p_22:
break
print(wins / total_iterations)
print((1 - p_11 - p_12) * (1 - p_22) / ((1 - p_11) * (1 - p_22) - p_12 * p_21))
现在关于您当前的代码。现在是错误的,因为 break # loses
从循环 while pointer2 < p_22
中断,而不是从循环 while pointer < p_11
中断。我们可以通过添加额外的标志 lost
来修复它,这会给你正确的答案。
import random
p_11 = 0.2
p_12 = 0.4 #0.2+0.4
p_21 = 0.3
p_22 = 0.35
wins = 0
pointer = 0
pointer2 = 0
for i in range(10**6):
while pointer < p_11:
pointer2 = 0 #resetting pointer2
pointer = random.uniform(0,1)
if p_11+p_21 < pointer < 1: #area corresponding to x_1
wins += 1 #wins
pointer = 0
break
else:
pointer = 0 #resetting pointer1
lost = False
while pointer2 < p_22:
pointer2 = random.uniform(0,1)
if p_22+p_21 < pointer2 < 1: #area corresponding to x_2
pointer2 = 0
lost = True
break #loses
if lost:
break
print(wins/10**6)
问题:
这里有一个小 Monte Carlo 挑战问题,考虑以下使用两个转盘的游戏。假设玩家根据以下规则旋转圆盘上的一个或另一个指针:
如果玩家旋转指针 i 并停在区域
p_{ij}
的区域,他从磁盘i
移动到磁盘j
(i
和j
是 1 或 2);如果指针停在区域
x_i
的区域,则游戏结束;若游戏结束于区域
x_1
则玩家获胜,若指针停在区域x_2
则玩家输。
从圆盘 1 开始的玩家获胜的概率是多少?假设每个磁盘的面积是一个,所以x_1+p_{11}+p_{12} =1
,以及x_2+p_{21}+p_{22} =1
运行 p_{11} =0.2
、p_{12} =0.4
、p_{21} =0.3
和 p_{22} =0.35
.
import random
p_11 = 0.2
p_12 = 0.4 #0.2+0.4
p_21 = 0.3
p_22 = 0.35
wins = 0
pointer = 0
pointer2 = 0
for i in range(10**7):
while pointer < p_11:
pointer2 = 0 #resetting pointer2
pointer = random.uniform(0,1)
if p_11+p_21 < pointer < 1: #area corresponding to x_1
wins += 1 #wins
pointer = 0
break
else:
pointer = 0 #resetting pointer1
while pointer2 < p_22:
pointer2 = random.uniform(0,1)
if p_22+p_21 < pointer2 < 1: #area corresponding to x_2
pointer2 = 0
break #loses
print(wins/10**7)
正确答案是 0.5821,但我得到的是 0.7141465。我哪里做错了?
我编辑了我的代码,在这种情况下它再次转动磁盘 p_22
和 p_11
个案例
问题出自《数字骰子》一书(Paul J. Nahim)第 27-29 页(有 pdf )
我已经对问题进行了数学分析,发现解决方案实际上是:
(1 - p_11 - p_12) * (1 - p_22) / ((1 - p_11) * (1 - p_22) - p_12 * p_21)
(在某些极端情况下实际上是不正确的(例如 p_22 = 1
))
这个其实是在Digital Dice这本书的附录6里面写的,就不证明了。
根据你的数字,它给出了 0.65
的答案,这是正确的。您的代码更改了很多,现在它给出了 1.0
的输出,而不是问题中所写的内容。在这里,我更正了您的代码的第一个版本:
import random
p_11 = 0.2
p_12 = 0.4
p_21 = 0.3
p_22 = 0.35
total_iterations = 10 ** 6
wins = 0
num = 0
for i in range(total_iterations):
current_disk = 1
while True:
num = random.uniform(0, 1)
if current_disk == 1:
if num < p_12:
current_disk = 2
continue
elif num > p_11 + p_12:
wins += 1 #wins
break
else:
if num < p_21:
current_disk = 1
continue
elif num > p_21 + p_22:
break
print(wins / total_iterations)
print((1 - p_11 - p_12) * (1 - p_22) / ((1 - p_11) * (1 - p_22) - p_12 * p_21))
现在关于您当前的代码。现在是错误的,因为 break # loses
从循环 while pointer2 < p_22
中断,而不是从循环 while pointer < p_11
中断。我们可以通过添加额外的标志 lost
来修复它,这会给你正确的答案。
import random
p_11 = 0.2
p_12 = 0.4 #0.2+0.4
p_21 = 0.3
p_22 = 0.35
wins = 0
pointer = 0
pointer2 = 0
for i in range(10**6):
while pointer < p_11:
pointer2 = 0 #resetting pointer2
pointer = random.uniform(0,1)
if p_11+p_21 < pointer < 1: #area corresponding to x_1
wins += 1 #wins
pointer = 0
break
else:
pointer = 0 #resetting pointer1
lost = False
while pointer2 < p_22:
pointer2 = random.uniform(0,1)
if p_22+p_21 < pointer2 < 1: #area corresponding to x_2
pointer2 = 0
lost = True
break #loses
if lost:
break
print(wins/10**6)