编程语言
首页 > 编程语言> > python-旋转游戏蒙特卡洛

python-旋转游戏蒙特卡洛

作者:互联网

问题:

这是一个蒙特卡洛(Monte Carlo)挑战的小问题,请考虑以下游戏,该游戏使用两个微调盘.假设播放器根据以下规则旋转磁盘上的一个或另一个指针:

>如果玩家旋转指针i并将其停在区域p_ {ij}的区域中,则他将从磁盘i移至磁盘j(i和j为1或2);
>如果指针停在x_i区域内,则游戏结束;否则,游戏结束.
>如果游戏在x_1区域结束,则玩家获胜,但如果指针在x_2区域停止,则玩家输.

从磁盘1开始,播放器获胜的概率是多少?假设每个磁盘的面积为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情况下再次打开磁盘

问题来自名为Digital Dice(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))

这实际上写在《数字骰子》书的附录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#会在指针2< p_22,而不是指针< p_11.我们可以通过添加额外的标志丢失来解决它,这将为您提供正确的答案.

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)

标签:montecarlo,python
来源: https://codeday.me/bug/20191210/2104593.html