3
votes

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:

  1. 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);

  2. if a pointer stops in the region with area x_i, the game ends;

  3. 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

enter image description here

The question is from the book called Digital Dice (Paul J. Nahim) Page 27-29 (Theres a pdf )

1
Why all the downvotes? They state the problem, give relevant background, show a minimal, complete, and verifiable example, and even give the current/expected outputs. - SyntaxVoid supports Monica
These rules are really hard to understand. What is area pij? What is xi in "region with area xi"? Is that X1? or P_11?. Is it significant that (i and j are either 1 or 2)? - Mark
Correct me if I'm wrong @Rear. Disk1 Region 1 (x1): Land on this and you win. --- Disk1 Region 2 (p11): Land on this and spin disk1 again. --- Disk1 Region 3 (p12): Land on this and switch to disk 2, then spin disk 2. --- Disk2 Region 1 (x2): Land on this and you lose. --- Disk2 Region 2 (p21): Land on this and switch to disk 1, then spin disk 1. --- Disk2 Region 3 (p22): Land on this and spin disk2 again. --- - SyntaxVoid supports Monica
I'm guessing there should be a diagram? Is this a coding challenge site or homework? Are you sure P_1 and P_2 are correctly calculated? Have you tried adding up losses and see if wins + losses add up to 10**7? I don't see anything here for spins on disk 2. - Kenny Ostrom
I put a diagram and edited my post a bit. I hope this helps more..Its not homework or a coding challange site. Its just from a book that I am reading to learn monte carlo algorithm. Well I didnt get to the part for what happens if it stars from disk2. - seVenVo1d

1 Answers

2
votes

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)