[PYTHON] Do you understand the Monty Hall problem?

I don't know if it fits my intuition or not, so the Monty Hall problem has become a staple of probability quiz questions. But do you really understand?

Monty Hall problem

There are three doors, A, B and C. Only one of the three doors is a hit and the other two are off. The game is played in the following procedure.

  1. Player chooses one of three doors
  2. The moderator, Monty, opens one door that the player did not choose to liven up the game. Monty knows the answer in advance and always opens the door off
  3. Moderator Monty asks the player, "Now you can change to the remaining one door. Do you want to change it? Do you want to change it?"

Question: Should the player change the door or not? More specifically, by changing the door, the probability of winning is increased, decreased, or unchanged.

Answer: Players should change the door. Since the player chose one of the three doors, the odds of winning the chosen door are 1/3. Also, the probability that one of the unselected doors will be a hit is 2/3. And Monty opened one of the doors he didn't choose. Therefore, the probability that the remaining door will be a hit is 2/3. In other words, by changing the door, the probability of winning will increase from 1/3 to 2/3.

Monty Hall problem in the event of a gust of wind

But what if Monty didn't open it, but a gust of wind opened the door? The gust is an accident, not the purpose of exciting the game, so it is possible to open the door of your choice or the door you hit. We also assume that the probabilities of opening any door are the same.

  1. Player chooses one of three doors
  2. When the moderator Monty tried to liven up the game, a gust of wind blew and one of the doors opened.
  3. If the door selected by the player in 1 opens, or if the winning door opens, the game will be canceled because it cannot be continued.
  4. If the door that the player didn't choose opens and it's off, the game continues and Monty regains his temper and asks the player, "Now I can change to the remaining one door. You can. Do you want to change it? Would you like to change it? "

Question: Should the player change the door or not? More specifically, by changing the door, the probability of winning is increased, decreased, or unchanged.

Answer: The odds of winning are the same whether you change the door or not. e? If you change it, the probability is 2/3? What the hell are you talking about?

Did you understand

Someone who somehow understands the Monty Hall problem may not be convinced by the consequences of a gust of wind. Whether it was Monty who opened it or a gust of wind, the conclusion was the same because the door on the outskirts that the player did not choose opened. Didn't you think so?

Flying Monty Python

Here, you can talk about probability theory in a mess. However, as you all know, [Monty is Python](https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%B3%E3%83%86%E3%82%A3 % E3% 83% BB% E3% 83% 91% E3% 82% A4% E3% 82% BD% E3% 83% B3). Here, I would like you to forcibly convince yourself by actually simulating the Monty Hall problem and the gust Monty Hall problem in Python.

Ordinary Monty Hall problem


import random

N = 100000
first_choice_is_atari = 0
second_choice_is_atari = 0
for _ in range(N):
    #Any one is correct
    atari = random.choice(["A", "B", "C"])

    #First, choose one
    first_choice = random.choice(["A", "B", "C"])

    #Monty opens something that is neither a hit nor a chosen one
    monty_opened = random.choice(list({"A", "B", "C"}.difference(atari).difference(first_choice)))                  
                                                                                                                    
    #Then there's only one thing you haven't opened yet and haven't chosen.?                                                  
    second_choice_candidates = list({"A", "B", "C"}.difference(first_choice).difference(monty_opened))              
    assert len(second_choice_candidates) == 1                                                                       
    #If you want to change, you can change
    second_choice = second_choice_candidates[0]                                                                     
                                                                                                                    
    if first_choice == atari:                                                                                       
        first_choice_is_atari += 1
    elif second_choice == atari:
        second_choice_is_atari += 1
    else:
        raise ValueError("Unreachable")
#Probability of winning if not changed,Probability of winning when changed
print(first_choice_is_atari / N, second_choice_is_atari / N)

I wrote it in a simple and easy-to-understand manner without considering efficiency. It's not accurate because it uses random numbers, but no matter how many times you run it, it should be about 1/3 if you don't change it, and 2/3 if you change it.

Gust Monty Hall Problem


import random

N = 100000
first_choice_is_atari = 0
second_choice_is_atari = 0
game_canceled = 0
for _ in range(N):
    #Any one is correct
    atari = random.choice(["A", "B", "C"])

    #Choose one
    first_choice = random.choice(["A", "B", "C"])

    #A gust of wind blows and one opens
    wind_opened = random.choice(["A", "B", "C"])

    #If the correct answer opens or the first choice opens, the game will be cancelled.
    if wind_opened == atari or wind_opened == first_choice:
        game_canceled += 1
        continue

    #If you continue the game, there's only one thing you haven't opened yet and haven't chosen.?
    second_choice_candidates = list({"A", "B", "C"}.difference(first_choice).difference(wind_opened))
    assert len(second_choice_candidates) == 1
    #If you want to change, you can change
    second_choice = second_choice_candidates[0]

    if first_choice == atari:
        first_choice_is_atari += 1
    elif second_choice == atari:
        second_choice_is_atari += 1
    else:
        raise ValueError("Unreachable")
#Probability of winning if not changed,Probability of winning when changed,Probability that the game cannot continue
print(first_choice_is_atari / N, second_choice_is_atari / N, game_canceled / N)

This is also a random number, so it's not accurate, but this time it should be around 22% with or without change.

Let's have Python do our best. This time, I will try to find out where this 22% comes from by listing all the patterns instead of random numbers.

Unravel the mystery of the gust


from itertools import product

first_choice_is_atari = 0
second_choice_is_atari = 0
game_canceled = 0

print("|Hit|First choice|Gust|result|")
print("|------|----------|----|--------|")
for atari, first_choice, wind_opened in product("ABC", repeat=3):
    if atari == wind_opened or first_choice == wind_opened:
        result = "Cancel"
        game_canceled += 1
    elif atari == first_choice:
        result = "Do not change"
        first_choice_is_atari += 1
    else:
        result = "Change"
        second_choice_is_atari += 1
    print("|     {}|         {}|   {}|{}|".format(atari, first_choice, wind_opened, result))

print("")
total = first_choice_is_atari + second_choice_is_atari + game_canceled
print(first_choice_is_atari / total, second_choice_is_atari / total, game_canceled / total)

A Markdown format table is output. If you count the case where the person who does not change wins ("do not change") and the case where the person who changes wins ("change"), you can see that there are 6 each. With or without change, there are 6 out of 27 ways in total, so 6/27 = 2/9 = 22.2222 ...%.

Hit First choice Gust result
A A A Cancel
A A B Do not change
A A C Do not change
A B A Cancel
A B B Cancel
A B C Change
A C A Cancel
A C B Change
A C C Cancel
B A A Cancel
B A B Cancel
B A C Change
B B A Do not change
B B B Cancel
B B C Do not change
B C A Change
B C B Cancel
B C C Cancel
C A A Cancel
C A B Change
C A C Cancel
C B A Change
C B B Cancel
C B C Cancel
C C A Do not change
C C B Do not change
C C C Cancel

Probability is difficult. So let's move our hands

The problem of probability is difficult. And it's even harder to get confirmation that the answer to the probability problem is really right or wrong. But that's when programming languages become a reassuring partner.

Actually, preparing a door and Mr. Monty and blowing a gust of wind until the door opens is quite a difficult task, but it is too large to simulate appropriately by allocating random numbers on a computer. If you don't have a problem, you can try it right away. Also, enumerating and counting all patterns is limited to smaller problems, but even so, the Monty Hall problem is not a problem at all.

Do it yourself before you feel like you're confused or deceived. You may see a different world.

By the way, if you have the spare capacity, why not try enumerating all the patterns to see why changing the door reduces the probability to 2/3 in the Monty Hall problem where the wind does not blow.

Recommended Posts

Do you understand the Monty Hall problem?
Solve the Monty Hall problem
Let's write a simple simulation program for the "Monty Hall problem"
Do you understand the confidence intervals correctly? What is the difference from the conviction section?
How do you make "the first three words you found"?
Which day of the week do you buy gold?
How much do you know the basics of Python?
Examine the dual problem
What you can do with the Python standard library statistics