Problem:
Here’s a little Monte Carlo challenge problem, Consider the following game, which uses the two spinner disks. Suppose a player spins one or the other of the pointers on the disks according to the following rules:
if the player spins pointer i and it stops in the region with area p_{ij}
, he moves from disk i
to disk j
(i
and j
are either 1 or 2);
if a pointer stops in the region with area x_i
, the game ends;
if the game ends in the region with area x_1
, the player wins, but if the pointer stops in the region with area x_2
the player loses.
What is the probability the player, starting with disk 1, wins? Assume the area of each disk is one, so that x_1+p_{11}+p_{12} =1
, as well as that x_2+p_{21}+p_{22} =1
Run your code for the case of p_{11} =0.2
, p_{12} =0.4
, p_{21} =0.3
, and 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)
The correct answer is 0.5821 however I am getting 0.7141465. Where am I doing wrong ?
I edited my code, in this case it turns the disk again for p_22
and p_11
cases
The question is from the book called Digital Dice (Paul J. Nahim) Page 27-29 (Theres a pdf )
I have analyzed the problem mathematically and found out that the solution is actually:
(1 - p_11 - p_12) * (1 - p_22) / ((1 - p_11) * (1 - p_22) - p_12 * p_21)
(which is actually not correct in some corner cases (e.g. p_22 = 1
))
This is actually written in Appendix 6 of the Digital Dice book, so I won't prove it.
With your numbers it gives the answer of 0.65
and that is correct. Your code changed a lot and now it gives the output of 1.0
instead of what is written in the question. Here I corrected the first version of your code:
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))
Now about your current code. It is wrong now because break # loses
breaks from the loop while pointer2 < p_22
, not from the loop while pointer < p_11
. We can fix it by adding extra flag lost
and that will give you correct answer.
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)