More Monty Hall

Just having some fun with the Monty Hall problem. The question comes down to as a contestant do you switch or not. The code below computes the probabilities of winning if you switch or say with your original guess.

image


import pandas as pd
import numpy as np
import arviz as az


import io
data_string1="""door,prize,monty,stay,switch
0,0,1,0,2
0,0,2,0,1
0,1,2,0,1
0,2,1,0,2
1,0,2,1,0
1,1,0,1,2
1,1,2,1,0
1,2,0,1,2
2,0,1,2,0
2,1,0,2,1
2,2,0,2,1
2,2,1,2,0"""

data=pd.read_csv(io.StringIO(data_string1),sep=",")
LU=np.zeros((3,3,3,2)).astype(np.float64)

LU[data["door"],data["prize"],data["monty"],0]=data["stay"]
LU[data["door"],data["prize"],data["monty"],1]=data["switch"]

P_MONTY=np.array([[[0.,0.5,0.5],[0.,0.,1.],[0.,1.,0.]],
          [[0.,0.,1],[0.5,0.,0.5],[1.,0.,0.]],
          [[0.,1.0,0.],[1.,0.,0.],[0.5,0.5,0.]]])

with pm.Model() as monty:

    p_monty=pm.ConstantData("p_monty",P_MONTY)
    lu=pm.ConstantData("lu",LU)
 
    prize = pm.Categorical("prize", np.ones(3)/3)
    door = pm.Categorical("door", np.ones(3)/3)
    monty=pm.Categorical("monty", p_monty[door,prize])
  
    stay=lu[door,prize,monty,0]
    switch=lu[door,prize,monty,1]
    
    win_stay=pm.Deterministic("win_stay",pm.math.eq(prize,stay))
    win_switch=pm.Deterministic("win_switch",pm.math.eq(prize,switch))

    idata=pm.sample(10000)
1 Like

I would have liked a better way to do lookups rather than making a four dimensional array with cells that never get referenced.

Monty hall was the last example of my talk sometime ago: Automatic probability.ipynb · GitHub

It’s a bit out of context, but that means you cam wrap that generative code inside a CustomDist and PyMC figures out the logp form you.

More down to earth, Austin had an example for a talk he did as well: A Modern Introduction to Probabilistic Programming with PyMC | Austin Rochford

Thanks. I will look at using a CustomDist. I wanted to focus on if you switch or not and did not want to just do it for a specific choice that the contestant might start with. The array that I used to figure out what door you choose if you switch or stay does not make much sense. Since if you stay you already know the door, and if you switch it means you choose door that is different than what either Monty chose or you chose before.

Better version

with pm.Model() as monty:

    p_monty=pm.ConstantData("p_monty",P_MONTY)
    lu=pm.ConstantData("lu",np.array([2,1,0]))
 
    prize = pm.Categorical("prize", np.ones(3)/3)
    door = pm.Categorical("door", np.ones(3)/3)
    monty=pm.Categorical("monty", p_monty[door,prize])
    
    switch=pm.Deterministic("switch",lu[door+monty-1])
    
    win_stay=pm.Deterministic("win_stay",pm.math.eq(prize,door))
    win_switch=pm.Deterministic("win_switch",pm.math.eq(prize,switch))

    idata=pm.sample(100000)
1 Like