<jupyter_start><jupyter_text><NAME>, 3 Oct 2015, revised Oct-Feb 2016  Probability, Paradox, and the Reasonable Person PrincipleIn [another notebook](http://nbviewer.jupyter.org/url/norvig.com/ipython/Probability.ipynb), I introduced the basics of probability theory. I'll duplicate the code we developed there:<jupyter_code>from fractions import Fraction

class ProbDist(dict):
    "A Probability Distribution; an {outcome: probability} mapping."
    def __init__(self, mapping=(), **kwargs):
        self.update(mapping, **kwargs)
        # Make probabilities sum to 1.0; assert no negative probabilities
        total = sum(self.values())
        for outcome in self:
            self[outcome] = self[outcome] / total
            assert self[outcome] >= 0
            
def P(event, space): 
    """The probability of an event, given a sample space of equiprobable outcomes. 
    event: a collection of outcomes, or a predicate that is true of outcomes in the event. 
    space: a set of outcomes or a probability distribution of {outcome: frequency}."""
    if is_predicate(event):
        event = such_that(event, space)
    if isinstance(space, ProbDist):
        return sum(space[o] for o in space if o in event)
    else:
        return Fraction(len(event & space), len(space))
    
def such_that(predicate, space): 
    """The outcomes in the sample space for which the predicate is true.
    If space is a set, return a subset {outcome,...};
    if space is a ProbDist, return a ProbDist {outcome: frequency,...};
    in both cases only with outcomes where predicate(element) is true."""
    if isinstance(space, ProbDist):
        return ProbDist({o:space[o] for o in space if predicate(o)})
    else:
        return {o for o in space if predicate(o)}
    
is_predicate = callable

def cross(A, B):
    "The set of ways of concatenating one item from collection A with one from B."
    return {a + b 
            for a in A for b in B}

def joint(A, B, sep=''):
    """The joint distribution of two independent probability distributions. 
    Result is all entries of the form {a+sep+b: P(a)*P(b)}"""
    return ProbDist({a + sep + b: A[a] * B[b]
                    for a in A
                    for b in B})<jupyter_output><empty_output><jupyter_text>In this notebook we use this code to show how to solve some particularly perplexing paradoxical probability problems. Child ParadoxesIn 1959, [<NAME>]() [posed](https://en.wikipedia.org/wiki/Boy_or_Girl_paradox) these two problems:- **Child Problem 1.** <NAME> has two children. The older child is a boy. What is theprobability that both children are boys?- **Child Problem 2.** Mr. Smith has two children. At least one of them is a boy. What isthe probability that both children are boys? Then in 2006, Mike & <NAME> came up with a variant, which <NAME> introduced to Gardner fans in 2010:- **Child Problem 3.** I have two children. At least one of them is a boy born on Tuesday. What isthe probability that both children are boys? Problems 2 and 3 are considered *paradoxes* because they have surprising answers that peopleargue about. (Assume the probability of a boy is exactly 1/2, and is independent of any siblings.)![<NAME>](https://upload.wikimedia.org/wikipedia/commons/0/04/Martin_Gardner.jpeg)<NAME>  Child Problem 1: Older child is a boy. What is the probability both are boys?We use `'BG'` to denote the outcome in which the older child is a boy and the younger a girl. The sample space, `S`, of equi-probable outcomes is:<jupyter_code>S = {'BG', 'BB', 'GB', 'GG'}<jupyter_output><empty_output><jupyter_text>Let's define predicates for the conditions of having two boys, and of the older child being a boy:<jupyter_code>def two_boys(outcome): return outcome.count('B') == 2

def older_is_a_boy(outcome): return outcome.startswith('B')<jupyter_output><empty_output><jupyter_text>Now we can answer Problem 1:<jupyter_code>P(two_boys, such_that(older_is_a_boy, S))<jupyter_output><empty_output><jupyter_text>You're probably thinking that was a lot of mechanism just to get the obvious answer. But in the next problems, what is obvious becomes less obvious. Child Problem 2: At least one is a boy. What is the probability both are boys? Implementing this problem and finding the answer is easy:<jupyter_code>def at_least_one_boy(outcome): return 'B' in outcome
P(two_boys, such_that(at_least_one_boy, S))<jupyter_output><empty_output><jupyter_text>Understanding the answer is tougher. Some people think the answer should be 1/2. Can we justify the answer 1/3?  We can see there are three equiprobable outcomes in which there is at least one boy:<jupyter_code>such_that(at_least_one_boy, S)<jupyter_output><empty_output><jupyter_text>Of those three outcomes, only one has two boys, so the answer of 1/3 is indeed justified. But some people *still* think the answer should be 1/2.Their reasoning is *"If one child is a boy, then there are two equiprobable outcomes for the other child, so the probability that the other child is a boy, and thus that there are two boys, is 1/2."* When two methods of reasoning give two different answers, we have a [paradox](https://en.wikipedia.org/wiki/Paradox). Here are three responses to a paradox:1. The very fundamentals of mathematics must be incomplete, and this problem reveals it!!!2. I'm right, and anyone who disagrees with me is an idiot!!!3. I have the right answer for one interpretation of the problem, and you have the right answerfor a different interpretation of the problem.If you're [<NAME>](https://en.wikipedia.org/wiki/Russell%27s_paradox) or [<NAME>](https://en.wikipedia.org/wiki/Cantor%27s_paradox), you might very well uncover a fundamental flaw in mathematics; for the rest of us, I recommend Response 3. When I believe the answer is 1/3, and I hear someone say the answer is 1/2, my response is not *"You're wrong!"*, rather it is *"How interesting! You must have a different interpretation of the problem; I should try to discover what your interpretation is, and why your answer is correct for your interpretation."* The first step is to be more precise in *my* wording of the experiment:- **Child Experiment 2a.** <NAME> is chosen at random from families with two children. He is asked if at least one of his children is a boy. He replies "yes."The next step is to envision another possible interpretation of the experiment:- **Child Experiment 2b.** <NAME> is chosen at random from families with two children. He is observed at a time when he is accompanied by one of his children, chosen at random. The child is observed to be a boy.  Experiment 2b needs a different sample space, which we will call `S2b`.  It consists of 8 outcomes, not just 4; for each of the 4 outcomes in `S`, we have a choice of observing either the older child or the younger child.  We will use the notation `'GB/g?'` to mean that the older child is a girl, the younger a boy, the older child was observed to be a girl, and the younger was not observed. The sample space is therefore:<jupyter_code>S2b = {'BB/b?', 'BB/?b', 
       'BG/b?', 'BG/?g', 
       'GB/g?', 'GB/?b', 
       'GG/g?', 'GG/?g'}<jupyter_output><empty_output><jupyter_text>Now we can figure out the subset of this sample space in which we observe <NAME> with a boy:<jupyter_code>def observed_boy(outcome): return 'b' in outcome

such_that(observed_boy, S2b)<jupyter_output><empty_output><jupyter_text>And finally we can determine the probability that he has two boys, given that we observed him with a boy:<jupyter_code>P(two_boys, such_that(observed_boy, S2b))<jupyter_output><empty_output><jupyter_text>The paradox is resolved. Two reasonable people can have different interpretations of the problem, and can each reason flawlessly to reach different conclusions, 1/3 or 1/2. Which interpretation of the problem is "better?"  We could debate that, or we could just agree to use unambiguous wording (that is, use the language of Experiment 2a or Experiment 2b, not the ambiguous language of Problem 2).  The Reasonable Person PrincipleIt is an unfortunate fact of human nature that we often assume the other person is an idiot. As [<NAME> puts it](https://www.youtube.com/watch?v=XWPCE2tTLZQ) *"Have you ever noticed when you're driving that anybody driving slower than you is an idiot, and anyone going faster than you is a maniac?"*<NAME>The opposite assumption&mdash;that other people are more likely to be **reasonable** rather than **idiots** is known as the **[reasonable person principle](http://www.cs.cmu.edu/~weigand/staff/)**. It is a guiding principle at Carnegie Mellon University's School of Computer Science, and is a principle I try to live by as well.Now let's return to an even more paradoxical problem. Child Problem 3. One is a boy born on Tuesday. What's the probability  both are boys?Most people can not imagine how the boy's birth-day-of-week could be relevant, and feel the answer should be the same as Problem 2.  But to be sure, we need to clearly describe the experiment, define the sample space, and calculate.  First:- **Child Experiment 3a.** A parent is chosen at random from families with two children. She is asked if at least one of her children is a boy born on Tuesday. She replies "yes."Next we'll define a sample space. We'll use the notation "`G1B3`" to mean the older child is a girl born on the first day of the week (Sunday) and the younger a boy born on the third day of the week (Tuesday). We'll call the resulting sample space `S3`.<jupyter_code>sexesdays = cross('BG', '1234567')
S3 = cross(sexesdays, sexesdays)
len(S3)<jupyter_output><empty_output><jupyter_text>That's too many to print, but we can sample them:<jupyter_code>import random
random.sample(S3, 8)<jupyter_output><empty_output><jupyter_text>We determine below that the probability of having at least one boy is 3/4, both in `S3` (where we keep track of the birth day of week) and in `S` (where we don't):<jupyter_code>P(at_least_one_boy, S3)
P(at_least_one_boy, S)<jupyter_output><empty_output><jupyter_text>The probability of two boys is 1/4 in either sample space:<jupyter_code>P(two_boys, S3)
P(two_boys, S)<jupyter_output><empty_output><jupyter_text>And the probability of two boys given at least one boy is 1/3 in either sample space:<jupyter_code>P(two_boys, such_that(at_least_one_boy, S3))
P(two_boys, such_that(at_least_one_boy, S))<jupyter_output><empty_output><jupyter_text>We will define a predicate for the event of at least one boy born on Tuesday:<jupyter_code>def at_least_one_boy_tues(outcome): return 'B3' in outcome<jupyter_output><empty_output><jupyter_text>We are now ready to answer Problem 3:<jupyter_code>P(two_boys, such_that(at_least_one_boy_tues, S3))<jupyter_output><empty_output><jupyter_text>13/27? How many saw that coming? 13/27 is quite different from 1/3, but rather close to 1/2. So "at least one boy born on Tuesday" is quite different from "at least one boy." Are you surprised? Do you accept the answer, or do you think we did something wrong? Are there other interpretations of the experiment that lead to other answers?Here is one alternative interpretation: - **Child Experiment 3b.** A parent is chosen at random from families with two children. She is observed at a time when she is accompanied by one of her children, chosen at random. The child is observed to be a boy who reports that his birth day is Tuesday.We can represent outcomes in this sample space with the notation `G1B3/??b3`, meaning the older child is a girl born on Sunday, the younger a boy born on Tuesday, the older was not observed, and the younger was.<jupyter_code>def observed_boy_tues(outcome): return 'b3' in outcome

S3b = {children + '/' + observation
       for children in S3
       for observation in (children[:2].lower()+'??', '??'+children[-2:].lower())}                        
random.sample(S3b, 5)<jupyter_output><empty_output><jupyter_text>Now we can answer this version of  Child Problem 3:<jupyter_code>P(two_boys, such_that(observed_boy_tues, S3b))<jupyter_output><empty_output><jupyter_text>So with the wording of Child Experiment 3b, the answer is the same as 2b.Still confused? Let's build a visualization tool to make things more concrete. VisualizationWe'll display the results as a two dimensional grid of outcomes. An outcome will be colored white if it does not satisfy the condition stated in the problem; green if the outcome contains two boys; and yellow if it does satisfy the condition, but does not have two boys. Every cell in a row has the same older child, and every cell in a column has the same younger child. Here's the code to display a table:<jupyter_code>from IPython.display import HTML

def Pgrid(space, n, event, condition):
    """Display sample space in a grid, color-coded: green if event and condition is true; 
    yellow if only condition is true; white otherwise."""
    # n is the number of characters that make up the older child.
    olders = sorted(set(outcome[:n] for outcome in space))
    return HTML('<table>' +
                cat(row(older, space, event, condition) for older in olders) +
                '</table>' + 
                '<tt>P({} | {}) = {}</tt>'.format(
                event.__name__, condition.__name__, 
                P(event, such_that(condition, space))))

def row(older, space, event, condition):
    "Display a row where an older child is paired with each of the possible younger children."
    thisrow = sorted(outcome for outcome in space if outcome.startswith(older))
    return '<tr>' + cat(cell(outcome, event, condition) for outcome in thisrow) + '</tr>'

def cell(outcome, event, condition): 
    "Display outcome in appropriate color."
    color = ('lightgreen' if event(outcome) and condition(outcome) else
             'yellow' if condition(outcome) else
             'white')
    return '<td style="background-color: {}">{}</td>'.format(color, outcome)    

cat = ''.join<jupyter_output><empty_output><jupyter_text>We can use this visualization tool to see that in Child Problem 1, there is one outcome with two boys (green) out of a total of two outcomes where the older is a boy (green and yellow) so the probability of two boys given that the older is a boy is 1/2.<jupyter_code># Child Problem 1
Pgrid(S, 1, two_boys, older_is_a_boy)<jupyter_output><empty_output><jupyter_text>For Child Problem 2, we see the probability of two boys (green) given at least one boy (green and yellow)  is 1/3.<jupyter_code># Child Problem 2
Pgrid(S, 1, two_boys, at_least_one_boy)<jupyter_output><empty_output><jupyter_text>The answer is still 1/3 when we consider the day of the week of each birth.<jupyter_code># Child Problem 2, with days of week enumerated
Pgrid(S3, 2, two_boys, at_least_one_boy)<jupyter_output><empty_output><jupyter_text>Now for the paradox of Child Problem 3:<jupyter_code># Child Problem 3
Pgrid(S3, 2, two_boys, at_least_one_boy_tues)<jupyter_output><empty_output><jupyter_text>We see there are 27 relevant outcomes, of which 13 are green. So 13/27 really does seem to be the right answer. This picture also gives us a way to think about why the answer is not 1/3. Think of the yellow-plus-green area as a horizontal stripe and a vertical stripe, with an overlap. Each stripe is half yellow and half green, so if there were no overlap at all, the probability of green would be 1/2.  When each stripe takes up half the sample space and the overlap is maximal, the probability is 1/3. And in the Problem 3 table, where the overlap is small, the probability is close to 1/2 (but slightly smaller).One way to look at it is that if I tell you very specific information (such as a boy born on Tuesday), it is unlikely that this applies to both children, so we have smaller overlap and a probability closer to 1/2, but if I give you broad information (a boy), this is more likely to apply to either child, resulting in a larger overlap, and a probability closer to 1/3.You can read some more discussions of the problem by (in alphabetical order) [<NAME>](https://www.newscientist.com/article/dn18950-magic-numbers-a-meeting-of-mathemagical-tricksters?full=true),[<NAME>](http://www.cut-the-knot.org/Probability/BearBornOnTuesday.shtml),[<NAME>](http://andrewgelman.com/2010/05/27/hype_about_cond/),[<NAME>](https://web.viu.ca/bigelow2/Problem%201127%20Solution.pdf),[<NAME>](https://www.sciencenews.org/article/when-intuition-and-math-probably-look-wrong),[<NAME>](https://www.maa.org/external_archive/devlin/devlin_05_10.html),[<NAME>](http://mathsci.ucd.ie/~plynch/Publications/BIMS-TwoChildParadox.pdf),[<NAME>](http://arxiv.org/pdf/1102.0173v1.pdf),and[<NAME> &amp; <NAME>](http://www.aamt.edu.au/Journals/Sample-articles/amt70_2_taylor.pdf).  The Sleeping Beauty ParadoxThe [Sleeping Beauty Paradox](https://en.wikipedia.org/wiki/Sleeping_Beauty_problem) is another tricky one:>Sleeping Beauty volunteers to undergo the following experiment and is told all of the following details: On Sunday she will be put to sleep. Then a fair coin will be tossed,to determine which experimental procedure to undertake:- Heads: Beauty will be awakened and interviewed on Monday only.- Tails: Beauty will be awakened and interviewed on Monday and Tuesday only.>In all cases she is put back to sleep with an amnesia-inducing drug that makes her forget that awakening and sleep until the next one. In any case, she will be awakened on Wednesday without interview and the experiment ends. Any time Beauty is awakened and interviewed, she is asked, "What is your belief now for the proposition that the coin landed heads?"What should Sleeping Beauty say when she is interviewed?  First, she should define the sample space.  She could use the notation `'heads/Monday/interviewed'` to mean the outcome where the coin flip was heads, it is Monday, and she is interviewed. So there are 4 equiprobable outcomes:<jupyter_code>B = {'heads/Monday/interviewed', 'heads/Tuesday/sleep',
     'tails/Monday/interviewed', 'tails/Tuesday/interviewed'}<jupyter_output><empty_output><jupyter_text>At this point, you're probably expecting me to define predicates, like this:    def heads(outcome): return 'heads' in outcome    def interviewed(outcome): return 'interviewed' in outcome    We've seen a lot of predicates like this. I think it is time to heed the "[don't repeat yourself](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)" principle, so I will define a predicate-defining function, `T`. Think of "`T`" for "it is true that":<jupyter_code>def T(property):
    "Return a predicate that is true of all outcomes that have 'property' as a substring."
    return lambda outcome: property in outcome<jupyter_output><empty_output><jupyter_text>Now we can get the answer:<jupyter_code>heads = T("heads")
interviewed = T("interviewed")

P(heads, such_that(interviewed, B))<jupyter_output><empty_output><jupyter_text>Note: I could have done that in one line: `P(T("heads"), such_that(T("interviewed"), B))`This problem is considered a paradox because there are people who argue that the answer should be 1/2, not 1/3. I admit I'm having difficulty coming up with a sample space that supports the "halfer" position. I do know of a question that has the answer 1/2:<jupyter_code>P(heads, B)<jupyter_output><empty_output><jupyter_text>But that seems like the wrong question; we want the probability of heads given that Sleeping Beauty was interviewed, not the unconditional probability of heads.The "halfers" argue that before Sleeping Beauty goes to sleep, her unconditional probability for heads should be 1/2. When she is interviewed, she doesn't know anything more than before she went to sleep, so nothing has changed, so the probability of heads should still be 1/2. I find two flaws with this argument. First, if you want to convince me, show me a sample space; don't just make philosophical arguments. (Although a philosophical argument can be employed to help you define the right sample space.) Second, while I agree that before she goes to sleep, Beauty's *unconditional* probability for heads should be 1/2, I would say that both before she goes to sleep and when she is awakened, her *conditional* probability of heads *given that she is being interviewed* should be 1/3, as shown by the sample space.  The Monty Hall Paradox[This](https://en.wikipedia.org/wiki/Monty_Hall_problem) is one of the most famous probability paradoxes. It can be stated as follows:> Suppose you're on a game show, and you're given the choice of three doors: Behind one door is a car; behind the others, goats. You pick a door, say No. 1, and the host, who knows what's behind the doors, opens another door, say No. 3, which has a goat. He then says to you, "Do you want to switch your choice to door No. 2?" Is it to your advantage to switch your choice?Monty HallMuch has been written about this problem, but to solve it all we have to do is be careful about how we understand the problem, and about defining our sample space.  I will define outcomes of the form `'Car1/Lo/Pick1/Open2'`, which means:* `Car1`: The producers of the show randomly placed the car behind door 1.* `Lo`: The host randomly commits to the strategy of opening the lowest-numbered allowable door. A door is allowable if it does not contain the car and was not picked by the contestant. Alternatively, the host could have chosen to open the highest-numbered allowable door (`Hi`).* `Pick1`: The contestant picks door 1.  Our sample space will only consider cases where the contestant picks door 1, but by symmetry, the same arguments could be used if the contestant picked door 2 or 3.* `Open2`: After hearing the contestant's choice, and following the strategy, the host opens a door; in this case door 2.We can see that the sample space has 6 equiprobable outcomes involving `Pick1`:<jupyter_code>M = {'Car1/Lo/Pick1/Open2', 'Car1/Hi/Pick1/Open3',
     'Car2/Lo/Pick1/Open3', 'Car2/Hi/Pick1/Open3',
     'Car3/Lo/Pick1/Open2', 'Car3/Hi/Pick1/Open2'}<jupyter_output><empty_output><jupyter_text>Now, assuming the contestant picks door 1 and the host opens door 3, we can ask:- What are the possible outcomes remaining?- What is the probability that the car is behind door 1? - Or door 2?<jupyter_code>such_that(T("Open3"), M)
P(T("Car1"), such_that(T("Open3"), M))
P(T("Car2"), such_that(T("Open3"), M))<jupyter_output><empty_output><jupyter_text>We see that the strategy of **switching** from door 1 to door 2 will win the car 2/3 of the time, whereas the strategy of **sticking** with the original pick wins the car only 1/3 of the time. So if you like cars more than goats, you should switch. But don't feel bad if you got this one wrong; it turns out that Monty Hall himself, who opened many doors while hosting *Let's Make a Deal* for 13 years, didn't know the answer either, as revealed in this letter from Monty to Prof. <NAME>, when Denenberg asked for permission to use the problem in his textbook: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. [<NAME>](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:<jupyter_code>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'}<jupyter_output><empty_output><jupyter_text>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:<jupyter_code>P(T("Car1"), such_that(T("Open3/Goat"), M2))
P(T("Car2"), such_that(T("Open3/Goat"), M2))
P(T("Car3"), such_that(T("Open3/Goat"), M2))<jupyter_output><empty_output><jupyter_text>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 ProblemSome people might be more convinced by a simulation than by a probability argument. Here is code for a simulation:<jupyter_code>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)<jupyter_output><empty_output><jupyter_text>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:<jupyter_code>from collections import Counter

Counter(monty('switch') for _ in range(10 ** 5))
Counter(monty('stick') for _ in range(10 ** 5))<jupyter_output><empty_output><jupyter_text>Reasoning with Probability DistributionsSo 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: 135138Let's implement that:<jupyter_code>DK = ProbDist(GG=121801, GB=126840,
              BG=127123, BB=135138)
DK<jupyter_output><empty_output><jupyter_text>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:<jupyter_code># Child Problem 1 in DK
P(two_boys, such_that(older_is_a_boy, DK))
# Child Problem 2 in DK
P(two_boys, such_that(at_least_one_boy, DK))<jupyter_output><empty_output><jupyter_text>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&times;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`).<jupyter_code>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<jupyter_output><empty_output><jupyter_text>Let's check out these last two probability distributions:<jupyter_code>child
S4<jupyter_output><empty_output><jupyter_text>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%.<jupyter_code># Child Problem 4
boy_born_on_leap_day = T("BL")

P(two_boys, such_that(boy_born_on_leap_day, S4))<jupyter_output><empty_output><jupyter_text>The St. Petersburg ParadoxThe [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 [<NAME>](), the nephew of <NAME> (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 &times; 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 ResourcesThe 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.<jupyter_code>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)<jupyter_output><empty_output><jupyter_text>Let's try with the casino limited to 100 million dollars:<jupyter_code>StP = st_pete(limit=10**8)
StP<jupyter_output><empty_output><jupyter_text>Now we define the function `EV` to compute the [expected value](https://en.wikipedia.org/wiki/Expected_value) of a probability distribution:<jupyter_code>def EV(P):
    "The expected value of a probability distribution."
    return sum(P[v] * v 
               for v in P)
EV(StP)<jupyter_output><empty_output><jupyter_text>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 <NAME>.  Response 2: Value of Money<NAME> 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-p8qlyAIViKWICh0XAAz5v=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.<jupyter_code>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)<jupyter_output><empty_output><jupyter_text>A table and a plot will give a feel for the `util` function. Notice the characterisitc concave-down shape of the plot.<jupyter_code>for d in range(2, 10):
    m = 10 ** d
    print('{:15,d} $ = {:10,d} util'.format(m, int(util(m))))
%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.')<jupyter_output>Y axis is util(x); x axis is in thousands of dollars.<jupyter_text>Now I will define the function `EU`, which computes the [expected utility](http://wiki.lesswrong.com/wiki/Expected_utility) of the game:<jupyter_code>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)
EU(StP, util)<jupyter_output><empty_output><jupyter_text>That says we should pay up to $13.10 to play the game, which sounds more reasonable than $27.49. Understanding St. Petersburg  through SimulationBefore I plunk down my $13, I'd like to understand the game better. I'll write a simulation of the game:<jupyter_code>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<jupyter_output><empty_output><jupyter_text>I will run the simulation 100,000 times (with a random seed specified for reproducability) and make the results into a probability distribution:<jupyter_code>random.seed(123456)

results = ProbDist(Counter(simulate_st_pete() for _ in range(100000)))
results<jupyter_output><empty_output><jupyter_text>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:<jupyter_code>EU(results, util), EV(results)<jupyter_output><empty_output><jupyter_text>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:<jupyter_code>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))))<jupyter_output><empty_output><jupyter_text>Let's do ten repetitions of plotting the running averages of 100,000 rounds:<jupyter_code>random.seed('running')

for i in range(10):
    plot_running_averages(simulate_st_pete, 100000);<jupyter_output><empty_output><jupyter_text>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 ParadoxThe [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, [<NAME>](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:<jupyter_code>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()<jupyter_output><empty_output><jupyter_text>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:<jupyter_code>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)<jupyter_output>R  33.0
B  33.0
RY 66.0
BY 66.0<jupyter_text>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**:<jupyter_code>compare(all_urns[:33] + 2 * all_urns[33:])<jupyter_output>R  33.0
B  38.554455445544555
RY 60.445544554455445
BY 66.0<jupyter_text>If we believe the first half of the list (with fewer black balls) is twice as likely, we get this:<jupyter_code>compare(2 * all_urns[:33] + all_urns[33:])<jupyter_output>R  33.0
B  27.39
RY 71.61
BY 66.0<jupyter_text>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 ParadoxThis has nothing to do with the TV show. D'oh! In 1951, statistician [<NAME>](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:<jupyter_code># 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']<jupyter_output><empty_output><jupyter_text>Let's compare probabilities of success:<jupyter_code>[success(case) for case in A]
[success(case) for case in B]<jupyter_output><empty_output><jupyter_text>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:<jupyter_code>success(A[0] + A[1])
success(B[0] + B[1])<jupyter_output><empty_output><jupyter_text>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, <NAME> and <NAME>, 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):<jupyter_code>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']
[BA(year) for year in Jeter]
[BA(year) for year in Justice]<jupyter_output><empty_output><jupyter_text>So Justice had a higher batting average than Jeter for both 1995 and 1996.  Let's check overall:<jupyter_code>BA(Jeter[0] + Jeter[1])
BA(Justice[0] + Justice[1])<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08948061513737919, 'fraction_numerical': 0.018949623909113228, 'mean_word_length': 4.530675225280829, 'pattern_counts': {'":': 1, '<': 273, '<?xml version=': 0, '>': 288, 'https://': 20, 'lorem ipsum': 0, 'www.': 8, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '58', 'dir': 'jupyter-structured-clean-dedup', 'id': '479791', 'license': 'MIT', 'n_tokens_mistral': 13940, 'n_tokens_neox': 12909, 'n_words': 6172, 'path': 'ipynb/ProbabilityParadox.ipynb', 'repo_name': 'filmy33/pytudes', 'size': '45049'}