Спин-игра Монте-Карло - PullRequest
3 голосов
/ 21 мая 2019

Проблема:

Вот небольшая проблема Монте-Карло, рассмотрим следующую игру, в которой используются два вращающихся диска. Предположим, игрок крутит один или другой указатель на дисках в соответствии со следующими правилами:

  1. если игрок вращает указатель i и останавливается в области с областью p_{ij}, он перемещается с диска i на диск j (i и j равны 1 или 2) ;

  2. если указатель останавливается в области с областью x_i, игра заканчивается;

  3. , если игра заканчивается в области с областью 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 случаев

enter image description here

Вопрос из книги «Цифровые кости» (Пол Дж. Нахим) Страница 27-29 (Theres a pdf)

1 Ответ

2 голосов
/ 21 мая 2019

Я проанализировал проблему математически и обнаружил, что решение на самом деле:

(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 # 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)
...