Monty Hall Problem — An empirical proof
By: Madhushan Buwaneswaran
Tags: Statistics, Simulation, Mathematics, Python, Probability

Monty Hall problem is a mathematical brain teaser dealing with probabilistic decision making. It originated from a TV show hosted by Monty Hall in 1963. It is a very good example of how probabilistic scenarios may seem simple but yet at times can be difficult to wrap our minds around them.

Scenario…

The problem is simple, you go to Monty’s game show “Let’s make a deal”. There are 3 doors in front of you. Behind 1 of those doors, there is a car and behind the remaining two doors are goats! If you select the door behind which the car is there, you drive it home. The host asks you to select a door, you pick one. Then comes the fun part. After you picked a door, the host will open one of the two remaining doors to always reveal a goat. Now he would ask you, are you going to switch your selection or are you staying with your original choice? This is where the dilemma kicks in.

On the surface, it seems there is no clear advantage in staying with your original decision or switching it. Since there are now two unopened doors, we see it as a 50–50 choice. But in fact, if you ponder enough you will see that there is a clear advantage of changing your decision when the host asks you whether you wanna switch!!!

The key reason this is not a 50–50 scenario is that the host, who opens one of the remaining doors after you made your initial choice, has the information that you don’t — which door has the car behind it. And he never opens the door which has the car behind it. If we incorporate this piece of information into calculating the probabilities, we end up with the number that you have a 2/3 probability of winning if you switch.

Explanation

There are a lot of good explanations using multiple methodologies on the internet. (I find this, that and the other one to be interesting.) But personally, I feel, in probability, anything can be simply and intuitively explained using a tree diagram.

Figure 1 — Tree diagram showing the probabilities associated with the Monty Hall Problem (Diagram by the Author)

When you are asked to make your first choice, there is an equal probability that the car is behind any one of the three doors. So you have a 1/3 chance of guessing it correctly. This implies that 2/3 of the times your guesses are wrong. So now comes the host and he opens a door to reveal a goat. At this point his choice of opening a door is not random. It is governed by your previous choice, since he has a rule not to reveal the car when opening the door.

Let’s first consider the case where your first choice is correct. Then the remaining two doors have goats behind them. In this scenario, the host can open any of those two doors. So now if you change your initial choice you will definitely loose regardless of the host’s choice of door. But remember this happens only 1/3 of the times because your initial choice is only correct that many times.

Now consider the case when your initial choice is wrong. You choose a door behind which a goat is there. Now out of the two remaining doors, one has the car behind it, and one has a goat behind it. Now the host cannot open a door randomly. He cannot open the door with the car behind it. So he is forced to open the door with the other goat behind it. At this point, if you change your initial choice, you’ll definitely win. If we look back to initial probabilities, we can realize that this is the most likely scenario, since 2/3 of the times our initial guess is wrong. So you should always make the switch! Statistically, if you play this game infinitely many times you will win in 2/3 of the games you play, if you always make the switch.

I was discussing this with one of my friends and he was like, “yeah that seems understandable but it is still a bit dizzy to get a feel for this explanation”. So I thought, “Hey let’s simulate it and get the same number!”. That way, seeing empirical proof would be more convincing!

The Pythonic way!

So let’s get to the fun part! I created the whole program with number of doors as configurable, so that if someone wants to simulate scenarios with more doors (as explained here), it can be done.

First, let’s look at the Contestant class. It has one constructor parameter switch . This parameter defines the response of the contestant when asked “Do you wanna switch?”. By changing this parameter when instantiating the contestant object, we can simulate a contestant who always switches and a contestant who never switches.

The Contestant class has two methods. The first one is select_door() . This is used to make the initial choice. When given the number of doors ( door_count ) as input, it selects and returns one door ( selection ) with a random uniform probability. Next method is wanna_switch() . This method is to be invoked when the host opens all remaining doors, presents one alternative door, and asks the contestant if she/he wants to change her/his decision? It takes one input: the new_door . If the contestant’s attribute switch is False , this method returns the old selection (sticking with the original decision). If the contestant’s attribute switch is true, it returns the new_door (changing the original choice).

Next we have the Host class. It takes one constructor parameter door_count . During instantiation the Host class randomly ‘places’ the imaginary car behind one of the doors by setting the private attribute _car_index . I have made the _car_index , door_counts attributes of the Host class, since the host has knowledge of these.

The Host class has three methods. The first one is present_doors() , which is used to show the doors to the contestant by returning the door_count . The next method is eliminate_others_and_present_one_door() . This method takes the contestant’s first selection ( contestant_selection ) as an input and returns an alternative_door as output, to ask the contestant whether she/he wants to switch? If the contestant's first selection is the door with the car behind it, it randomly returns another door as alternative_door . If the contestant’s first choice is not the door with the car behind it, this method returns the _car_index (door with the car behind it) as alternative_door . (This returning of alternative_door is analogous to opening all other doors and revealing goats behind them.) The final method is reveal_if_winner() . It takes the contestant’s final_selection as the input and returns if the contestant has won or not.

Putting everything together we can simulate one iteration of the competition using the snippet shown below.

However to get the actual probability of winning we need to simulate this infinitely many times (which is impossible). Hence I have simulated this for 1 million times and used the resulting number as a proxy to actual probability. As we increase the number of iterations, we can see in fig. 2, that the empirical probability is converging towards the (expected) actual probability.

Figure 2 — Plot showing the convergence of empirical win probabilities towards the theoretical probabilities with more iterations (Diagram by the author)

I have simulated two contestants: one who always changes her/his decision and one who always sticks with the original decision. From the above results, we can clearly see, that if we switch our decision when asked, we have a better chance of driving the imaginary car home.

Safe driving… 😁

In case if you want to access the full code (I don’t know why someone would want that), it can be found here.

References

“Numberphile” explanation video — https://www.youtube.com/watch?v=4Lb-6rxZxx0

“The Infographics Show” explanation video — https://www.youtube.com/watch?v=hdo4CZC76fA