#!/usr/bin/env python # coding: utf-8 #
#
# If you were Denenberg, how would you answer Monty, in non-mathematical terms? I would try something like this:
#
# > When the contestant makes her initial pick, she has 1/3 chance of picking the car, and there is a 2/3 chance the car is behind one of the other doors. That's still true after you open a door, but now the 2/3 chance for *either* other door becomes concentrated as 2/3 behind *one* other door, so the contestant should switch.
#
# But that type of argument was not persuasive to everyone. [Marilyn vos Savant](http://marilynvossavant.com/game-show-problem/) reports that many of her readers (including, she is pleased to point out, many Ph.D.s) still insist the answer is that it doesn't matter if the contestant switches; the odds are 1/2 either way. Let's try to discover what problem and what sample space those people are dealing with. Perhaps they are reasoning like this:
#
# They define outcomes of the form `'Car1/Pick1/Open2/Goat'`, which means:
# * `Car1`: First the car is randomly placed behind door 1.
# * `Pick1`: The contestant picks door 1.
# * `Open2`: The host opens one of the two other doors at random (so the host might open the door with the car).
# * `Goat`: We observe there is a goat behind the opened door.
#
# Under this interpretation, the sample space of all outcomes involving `Pick1` is:
# In[37]:
M2 = {'Car1/Pick1/Open2/Goat', 'Car1/Pick1/Open3/Goat',
'Car2/Pick1/Open2/Car', 'Car2/Pick1/Open3/Goat',
'Car3/Pick1/Open2/Goat', 'Car3/Pick1/Open3/Car'}
# And we can calculate the probability of the car being behind each door, given that the contestant picks door 1 and the host opens door 3 to reveal a goat:
# In[38]:
P(T("Car1"), such_that(T("Open3/Goat"), M2))
# In[39]:
P(T("Car2"), such_that(T("Open3/Goat"), M2))
# In[40]:
P(T("Car3"), such_that(T("Open3/Goat"), M2))
# So we see that under this interpretation it doesn't matter if you switch or not.
#
# Is this a valid interpretation? I agree that the wording of the problem can be seen as being ambiguous. However, this interpretation has a serious problem: in all the history of *Let's Make a Deal*, it was never the case that the host opened up a door with the grand prize. This strongly suggests (but does not prove) that `M` is the correct sample space, not `M2`
# # Simulating the Monty Hall Problem
#
# Some people might be more convinced by a simulation than by a probability argument. Here is code for a simulation:
# In[41]:
import random
def monty(strategy):
"""Simulate this sequence of events:
1. The host randomly chooses a door for the 'car'
2. The contestant randomly makes a 'pick' of one of the doors
3. The host randomly selects a non-car, non-pick door to be 'opened.'
4. If strategy == 'switch', contestant changes 'pick' to the other unopened door
5. Return true if the pick is the door with the car."""
doors = (1, 2, 3)
car = random.choice(doors)
pick = random.choice(doors)
opened = random.choice([d for d in doors if d != car and d != pick])
if strategy == 'switch':
pick = next(d for d in doors if d != pick and d != opened)
return (pick == car)
# We can confirm that the contestant wins about 2/3 of the time with the `switch` strategy, and only wins about 1/3 of the time with the `stick` strategy:
# In[42]:
from collections import Counter
Counter(monty('switch') for _ in range(10 ** 5))
# In[43]:
Counter(monty('stick') for _ in range(10 ** 5))
# # Reasoning with Probability Distributions
#
# So far, we have made the assumption that every outcome in a sample space is equally likely. In real life, the probability of a child being a girl is not exactly 1/2. As mentioned in the [previous notebook](http://nbviewer.jupyter.org/url/norvig.com/ipython/Probability.ipynb), an [article](http://people.kzoo.edu/barth/math105/moreboys.pdf) gives the following counts for two-child families in Denmark:
#
# GG: 121801 GB: 126840
# BG: 127123 BB: 135138
#
# Let's implement that:
# In[44]:
DK = ProbDist(GG=121801, GB=126840,
BG=127123, BB=135138)
DK
# Now let's try the first two Child Problems with the probability distribution `DK`. Since boys are slightly more probable than girls, we expect a little over 1/2 for Problem 1, and a little over 1/3 for problem 2:
# In[45]:
# Child Problem 1 in DK
P(two_boys, such_that(older_is_a_boy, DK))
# In[46]:
# Child Problem 2 in DK
P(two_boys, such_that(at_least_one_boy, DK))
# It all looks good. Now let's leave Denmark behind and try a new problem:
#
# ### Child Problem 4. One is a boy born on Feb. 29. What is the probability both are boys?
#
# * **Child Problem 4.** I have two children. At least one of them is a boy born on leap day, February 29. What is the probability that both children are boys? Assume that 51.5% of births are boys and that birth days are distributed evenly across the 4×365 + 1 days in a 4-year cycle.
#
# We will use the notation `GLBN` to mean an older girl born on leap day (`L`) and a younger boy born on a non-leap day (`N`).
# In[47]:
sexes = ProbDist(B=51.5, G=48.5) # Probability distribution over sexes
days = ProbDist(L=1, N=4*365) # Probability distribution over Leap days and Non-leap days
child = joint(sexes, days) # Probability distribution for one child family
S4 = joint(child, child) # Probability distribution for two-child family
# Let's check out these last two probability distributions:
# In[48]:
child
# In[49]:
S4
# Now we can solve the problem. Since "boy born on a leap day" applies to so few children, we expect the probability of two boys to be just ever so slightly below the baseline rate for boys, 51.5%.
# In[50]:
# Child Problem 4
boy_born_on_leap_day = T("BL")
P(two_boys, such_that(boy_born_on_leap_day, S4))
# # The St. Petersburg Paradox
#
# The [St. Petersburg paradox](https://en.wikipedia.org/wiki/St._Petersburg_paradox) from 1713, named for the home town of the [Bernoullis](http://www.storyofmathematics.com/18th_bernoulli.html), and introduced by [Daniel Bernoulli](), the nephew of Jacob Bernoulli (the urn guy):
#
# > *A casino offers a game of chance for a single player in which a fair coin is tossed at each stage. The pot starts at 2 dollars and is doubled every time a head appears. The first time a tail appears, the game ends and the player wins whatever is in the pot. Thus the player wins 2 dollars if a tail appears on the first toss, 4 dollars if a head appears on the first toss and a tail on the second, etc. What is the expected value of this game to the player?*
#
# To calculate the expected value, we see there is a 1/2 chance of a tail on the first toss (yielding a pot of $2) and if not that, a 1/2 × 1/2 = 1/4 chance of a tail on the second toss (yielding a pot of $4), and so on. So in total, the expected value is:
#
# 2 * (1/2) + 4 * (1/4) + 8 * (1/8) + ... = 1 + 1 + 1 + ... = ∞
#
# The expected value is infinite! But anyone playing the game would not expect to win an infinite amount; thus the paradox.
#
# ## Response 1: Limited Resources
#
# The first major response to the paradox is that the casino's resources are limited. Once you break their bank, they can't pay out any more, and thus the expected return is finite. Let's consider the case where the bank has a limit to their resources, and create a probability distribution for the problem. We keep doubling the pot and halving the probability of winning the amount in the pot (half because you get the pot on a tail but not a head), until we reach the limit.
# In[51]:
def st_pete(limit):
"Return the probability distribution for the St. Petersburg Paradox with a limited bank."
P = {} # The probability distribution
pot = 2 # Amount of money in the pot
pr = 1/2. # Probability that you end up with the amount in pot
while pot < limit:
P[pot] = pr
pot = pot * 2
pr = pr / 2
P[limit] = pr * 2 # pr * 2 because you get limit for heads or tails
return ProbDist(P)
# Let's try with the casino limited to 100 million dollars:
# In[52]:
StP = st_pete(limit=10**8)
StP
# Now we define the function `EV` to compute the [expected value](https://en.wikipedia.org/wiki/Expected_value) of a probability distribution:
# In[53]:
def EV(P):
"The expected value of a probability distribution."
return sum(P[v] * v
for v in P)
# In[54]:
EV(StP)
# This says that for a casino with a bankroll of 100 million dollars, if you want to maximize your expected value, you should be willing to pay up to $27.49 to play the game. Would you pay that much? I wouldn't, and neither would Daniel Bernoulli.
#
# ## Response 2: Value of Money
#
# Daniel Bernoulli came up with a second response to the paradox based on the idea that if you have a lot of money, then additional money becomes less valuable to you. If I had nothing, and I won $1000, I would be very happy. But if I already had a million dollars and I won $1000, it would be less valuable. How much less valuable? Bernoulli proposed, and [experiments confirm](https://books.google.com/books?id=1oEa-BiARWUC&pg=PA205&lpg=PA205&dq=mr+beard+oil+wildcatter+value+of+money+utility&source=bl&ots=cBDIX-rkTz&sig=GHB8-inorWrU39vA8JYV_sCtqB8&hl=en&sa=X&ved=0CCAQ6AEwAGoVChMI5fu-p8qlyAIViKWICh0XAAz5#v=onepage&q=mr%20beard%20oil%20wildcatter%20value%20of%20money%20utility&f=false), that *the value of money is roughly logarithmic.* That is, rational bettors don't try to maximize their expected monetary value, they try to maximize their *expected utility*: the amount of "happiness" that the money is worth.
# I'll write the function `util` to describe what a dollar amount is worth to a hypothetical gambler. `util` says that a dollar is worth a dollar, until the amount is "enough" money. After that point, each additional dollar is worth half as much (only brings half as much happiness). Value keeps accumulating at this rate until we reach the next threshold of "enough," when the utility of additional dollars is halfed again. The exact details of `util` are not critical; what matters is that overall money becomes less valuable after we have won a lot of it.
# In[55]:
def util(dollars, enough=1000):
"The value of money: only half as valuable after you already have enough."
if dollars < enough:
return dollars
else:
additional = dollars-enough
return enough + util(additional / 2, enough * 2)
# A table and a plot will give a feel for the `util` function. Notice the characterisitc concave-down shape of the plot.
# In[56]:
for d in range(2, 10):
m = 10 ** d
print('{:15,d} $ = {:10,d} util'.format(m, int(util(m))))
# In[57]:
get_ipython().run_line_magic('matplotlib', 'inline')
import matplotlib.pyplot as plt
plt.plot([util(x) for x in range(1000, 10000000, 1000)])
print('Y axis is util(x); x axis is in thousands of dollars.')
# Now I will define the function `EU`, which computes the [expected utility](http://wiki.lesswrong.com/wiki/Expected_utility) of the game:
# In[58]:
def EU(P, U):
"The expected utility of a probability distribution, given a utility function."
return sum(P[e] * U(e)
for e in P)
# In[59]:
EU(StP, util)
# That says we should pay up to $13.10 to play the game, which sounds more reasonable than $27.49.
#
# # Understanding St. Petersburg through Simulation
#
# Before I plunk down my $13, I'd like to understand the game better. I'll write a simulation of the game:
# In[60]:
def flip(): return random.choice(('head', 'tail'))
def simulate_st_pete(limit=10**9):
"Simulate one round of the St. Petersburg game, and return the payoff."
pot = 2
while flip() == 'head':
pot = pot * 2
if pot > limit:
return limit
return pot
# I will run the simulation 100,000 times (with a random seed specified for reproducability) and make the results into a probability distribution:
# In[61]:
random.seed(123456)
results = ProbDist(Counter(simulate_st_pete() for _ in range(100000)))
results
# The results are about what you would expect: about half the pots are 2, a quarter are 4, an eighth are 8, and higher pots are more and more unlikely. Let's check expected utility and expected value:
# In[62]:
EU(results, util), EV(results)
# These are not too far off from the theoretial values.
#
# To see better how things unfold, I will define a function to plot the running average of repeated rounds:
# In[63]:
def running_averages(iterable):
"For each element in the iterable, yield the mean of all elements seen so far."
total, n = 0, 0
for x in iterable:
total, n = total + x, n + 1
yield total / n
def plot_running_averages(fn, n):
"Plot the running average of calling the function n times."
plt.plot(list(running_averages(fn() for _ in range(n))))
# Let's do ten repetitions of plotting the running averages of 100,000 rounds:
# In[64]:
random.seed('running')
for i in range(10):
plot_running_averages(simulate_st_pete, 100000);
# What can we see from this? Nine of the 10 repetitions have a final expected value payoff (after 100,000 rounds) between 10 and 35. So a price around $13 still seems reasonable. One outlier has an average payoff just over 100, so if you are feeling lucky you might be willing to pay more than $13.
#
# # The Ellsburg Paradox
#
# The [Ellsburg Paradox](https://en.wikipedia.org/wiki/Ellsberg_paradox) has it all: an urn problem; a paradox; a conclusion that can only be resolved through psychology, not mathematics alone; and a colorful history with an inventor, [Daniel Ellsburg](https://en.wikipedia.org/wiki/Daniel_Ellsberg), who went on to become the releaser of the [Pentagon Papers](https://en.wikipedia.org/wiki/Pentagon_Papers). The paradox is as follows:
#
# > An urn contains 33 red balls and 66 other balls that are either black or yellow. You don't know the mix of black and yellow, just that they total 66. A single ball is drawn at random. You are asked which of these two gambles you would prefer:
# - **R**: Win 100 for a red ball.
# - **B**: Win 100 for a black ball.
#
# > Separately, you are also asked which of these two gambles you prefer:
# - **RY**: Win 100 for a red or yellow ball.
# - **BY**: Win 100 for a black or yellow ball.
#
# Many people reason as follows:
# - **R**: I win 1/3 of the time
# - **B**: I win somewhere between 0 and 2/3 of the time, but I'm not sure of the probability.
# - **RY**: I win at least 1/3 of the time and maybe up to 100% of the time; I'm not sure.
# - **BY**: I win 2/3 of the time.
# - Overall, I prefer the relative certainty of **R** over **B** and of **BY** over **RY**.
#
# The paradox is that, from an expected utility point of view, that reasoning is inconsistent, no matter what the mix of black and yellow balls is (or no matter what you believe the mix might be). **RY** and **BY** are just the same gambles as **R** and **B**, but with an additional 100 for a yellow ball. So if you prefer **R** over **B**, you should prefer **RY** over **BY** (and if you prefer **B** over **R** you should prefer **BY** over **RY**), for any possible mix of black and yellow balls.
#
# Let's demonstrate. For each possible number of black balls (on the *x* axis), we'll plot the expected value of each of the four gambles; **R** as a solid red line, **B** as a solid black line, **RY** as a dotted red line, and **BY** as a dotted black line:
# In[65]:
def ellsburg():
show('R', 'r')
show('B', 'k')
show('RY', 'r:')
show('BY', 'k:')
plt.xlabel('Number of black balls')
plt.ylabel('Expected value of each gamble')
blacks = list(range(67))
all_urns = [Counter(R=33, B=b, Y=66-b) for b in blacks]
def show(colors, line):
scores = [score(colors, urn) for urn in all_urns]
plt.plot(blacks, scores, line)
def score(colors, urn): return sum(urn[c] for c in colors)
ellsburg()
# We see that for any number of black balls up to 33, the solid red line is above the solid black line, which means **R** is better than **B**. The two gambles are equal with 33 black balls, and from there on, **B** is better than **R**.
#
# Similarly, up to 33 black balls, the dashed red line is above the dashed black line, so **RY** is better than **BY**. They are equal at 33, and after that, **BY** is better than **RY**. So in summary, **R** > **B** if and only if **RY** > **BY**.
#
# It is pretty clear that this holds for every possible mix of black and yellow balls, taken one at a time. But what if you believe that the mix might be one of several possibilities? For example, if we assume that any number of black balls from 0 to 66 is equally likely, then we can use a function, `expected_score` to give the expected return for a gamble (as specified by the colors in the gamble), averaged over a collection of possible urns, each with a different black/yellow mix:
# In[66]:
def expected_score(colors, urns):
return sum(score(colors, urn) for urn in urns) / len(urns)
def compare(urns):
for colors in ('R', 'B', 'RY', 'BY'):
print(colors.ljust(2), expected_score(colors, urns))
compare(all_urns)
# This says that **B** and **R** have an equal expected return, as do **BY** and **RY**.
#
# Now imagine that you believe that any mix is possible, but that a majority of black balls is more likely, in particular that the urns in the second half of the list of `all_urns` are twice as likely as those in the first half. Then we will see that **B** > **R** and **BY** > **RY**:
# In[67]:
compare(all_urns[:33] + 2 * all_urns[33:])
# If we believe the first half of the list (with fewer black balls) is twice as likely, we get this:
# In[68]:
compare(2 * all_urns[:33] + all_urns[33:])
# This time the preferences are reversed for both gambles, **R** > **B** and **RY** > **BY**.
# So why do many people prefer **R** > **B** and **BY** > **RY**? One explanation is *risk aversion*; it feels safer to take a definite 1/3 chance of winning, rather than a gamble that might be as good as 2/3, but might be as bad as 0. This is irrational thinking (in the sense that those who follow this strategy will win less), but people are sometimes irrational.
# # Simpson's Paradox
#
# This has nothing to do with the TV show. D'oh! In 1951, statistician [Edward Simpson](https://en.wikipedia.org/wiki/Edward_H._Simpson) (who worked with Alan Turing at Bletchley Park during World War II), noted that it is possible to take a sample space in which **A** is better than **B**, and split it into two groups, such that **B** is better than **A** in both groups.
#
# For example, here is data from trials of two treatments for kidney stones, **A** and **B**, separated into two subgroups or cases: first, for small kidney stones, and second for large ones. In all cases we record the number of good and bad outcomes of the treatment:
# In[69]:
# Good and bad outcomes for kidney stone treatments A and B,
# each in two cases: [small_stones, large_stones]
A = [Counter(good=81, bad=6), Counter(good=192, bad=71)]
B = [Counter(good=234, bad=36), Counter(good=55, bad=25)]
def success(case): return ProbDist(case)['good']
# Let's compare probabilities of success:
# In[70]:
[success(case) for case in A]
# In[71]:
[success(case) for case in B]
# We see that for small stones, **A** is better, 93% to 87%, and for large stones, **A** is also better, 75% to 69%. So **A** is better no matter what, right?
#
# Not so fast.
#
# We can add up `Counter`s to get the overall success rate for **A** and **B**, over all cases:
# In[72]:
success(A[0] + A[1])
# In[73]:
success(B[0] + B[1])
# Overall, **B** is more successful, 83% to 78%, even though **A** is better in both cases. So if you had kidney stones, and you want the highest chance of success, which treatment would you prefer? If you knew you had small stones (or large stones), the evidence supports **A**. But if the size was unknown, does that mean you should prefer **B**? Analysts agree that the answer is no, you should stick with **A**. The only reason why **B** has a higher overall success rate is that doctors choose to do **B** more often on the easier, small stone cases, and reserve **A** for the harder, large stone cases. **A** is better, but it has a lower overall percentage because it is given the difficult patients.
#
# Here's another example, showing the batting averages for two baseball players, Derek Jeter and David Justice, for the years 1995 and 1996 (I should say that Justice is considered a very good player, but Jeter is considered even better, a sure-bet future Hall of Fame player):
# In[74]:
Jeter = [Counter(hit=12, out=36), Counter(hit=183, out=399)]
Justice = [Counter(hit=104, out=307), Counter(hit=45, out=95)]
def BA(case): "Batting average"; return ProbDist(case)['hit']
# In[75]:
[BA(year) for year in Jeter]
# In[76]:
[BA(year) for year in Justice]
# So Justice had a higher batting average than Jeter for both 1995 and 1996. Let's check overall:
# In[77]:
BA(Jeter[0] + Jeter[1])
# In[78]:
BA(Justice[0] + Justice[1])
# Overall, Jeter had a significantly higher batting average. How did Jeter manage to do worse both years, then? Because in 1995, Jeter was injured for much of the year, and his low batting average was over a small number of at-bats. In 1996, Jeter was healthy, but Justice was injured for much of the year; however he managed a high average in his few at-bats.
#
# For the kidney stone data, we trust the individual cases, not the overall, because there are biases that lead to patients being assigned to one treatment or the other. For the batting average data, we trust the overall numbers, because there are no such biases, and because larger numbers lead to a closer approximation to a true value. The data alone can't tell you what to believe; you need the story (and the model) behind the data as well.
# # Conclusion
#
# We've seen how to manage probability paradoxes. Just be explicit about what the problem says, and then methodical about defining the sample space, and finally be careful in counting the number of outcomes in the numerator and denominator. But the bigger lesson is: treat those around you as reasonable people, and when they have different opinions, try to discover what problem they are solving.
#
# *Note*: Mohammed El-Beltagy created a very nice [translation of an earlier version of this page to Julia](http://nbviewer.ipython.org/gist/mbeltagy/3ba5f77da6382da192c3).
# .