Dorian’s Math

PRACTICE / PROBABILITY STATISTICS

Conditional probability in Python

Comparisons, predicates, the Monty Hall problem, and updating on evidence, in the CS61A style.

Single choice

What would Python display? Comparing a list

What would Python display?

>>> child1 = [1, 2, 1]
>>> child1 == 1
Your answer

Choose one answer.

Hints
1

Python’s == compares the whole left value with the whole right value.

2

Is a list ever equal to a number?

Reference solution

False. Python compares the list [1, 2, 1] as a whole with the number 1, and they are not equal. Nothing is compared entry by entry, unlike R, where child1 == 1 gives TRUE FALSE TRUE. Write [c == 1 for c in child1] to get [True, False, True].

Source: Adapted from Blitzstein & Hwang, Introduction to Probability, Chapter 2 and §2.10 (R), rewritten in Python · Original exercise; the book's R examples are paraphrased, not copied

Fill in the blank

What would Python display? Counting with and

What would Python display?

>>> pairs = [(1, 1), (1, 2), (2, 1), (1, 1)]
>>> sum([c1 == 1 and c2 == 1 for c1, c2 in pairs])
Your answer

Use an integer, decimal, or fraction such as 1/2. An exact value is expected.

Hints
1

The comprehension is [True, False, False, True].

2

sum counts each True as 1.

Reference solution

2. Only the first and last pairs have both children equal to 1, so the list is [True, False, False, True], and its sum is 2. This is nABn_{AB} for AA = both girls.

Source: Adapted from Blitzstein & Hwang, Introduction to Probability, Chapter 2 and §2.10 (R), rewritten in Python · Original exercise; the book's R examples are paraphrased, not copied

Python

Estimate a conditional probability

Complete conditional_frequency(outcomes, a, b). a and b are predicates, functions that take one outcome and return True or False. Return nAB/nBn_{AB}/n_B: the number of outcomes where both hold, divided by the number where b holds. Return None if b never holds.

Your answer

Python function exercise. Tab moves focus; use the indent buttons for selected lines.

Public tests

1. Elder child is a girl

>>> families = [(1, 1), (1, 2), (2, 1), (2, 2)]
>>> both_girls = lambda f: f == (1, 1)
>>> conditional_frequency(families, both_girls, lambda f: f[0] == 1)
0.5

2. At least one girl

>>> families = [(1, 1), (1, 2), (2, 1), (2, 2)]
>>> both_girls = lambda f: f == (1, 1)
>>> round(conditional_frequency(families, both_girls, lambda f: 1 in f), 3)
0.333

3. B never happens

>>> families = [(1, 1), (1, 2), (2, 1), (2, 2)]
>>> both_girls = lambda f: f == (1, 1)
>>> conditional_frequency(families, both_girls, lambda f: False) is None
True

4. Other outcomes

>>> rolls = [1, 2, 3, 4, 5, 6]
>>> conditional_frequency(rolls, lambda r: r == 6, lambda r: r % 2 == 0)
0.3333333333333333
Hints
1

Count nBn_B with sum(1 for o in outcomes if b(o)).

2

Count nABn_{AB} the same way, requiring a(o) and b(o).

3

Check for nB=0n_B = 0 before dividing.

Reference solution
def conditional_frequency(outcomes, a, b):
    n_b = sum(1 for o in outcomes if b(o))
    n_ab = sum(1 for o in outcomes if a(o) and b(o))
    return None if n_b == 0 else n_ab / n_b

The function knows nothing about children or dice. It only calls the predicates it is given, which is what lets one definition answer every question in the note.

Source: Adapted from Blitzstein & Hwang, Introduction to Probability, Chapter 2 and §2.10 (R), rewritten in Python · Original exercise; the book's R examples are paraphrased, not copied

Python

Which door does Monty open?

Complete monty_opens(chosen, car) for doors 1, 2, and 3. Monty never opens the player’s door or the car’s door. When two doors are allowed (the player picked the car), return the lower-numbered one, so the result is always predictable.

Your answer

Python function exercise. Tab moves focus; use the indent buttons for selected lines.

Public tests

1. Only one door allowed

>>> monty_opens(1, 2)
3
>>> monty_opens(2, 1)
3
>>> monty_opens(3, 1)
2

2. Player picked the car

>>> monty_opens(1, 1)
2
>>> monty_opens(2, 2)
1
>>> monty_opens(3, 3)
1
Hints
1

Consider each door in (1, 2, 3) and keep the ones that are neither chosen nor car.

2

min of the allowed doors gives the lower-numbered one.

Reference solution
def monty_opens(chosen, car):
    return min(door for door in (1, 2, 3) if door != chosen and door != car)

When chosen != car, exactly one door is allowed; when they are equal, two are, and min picks the lower. In the real game Monty chooses at random in that case, which the simulation in the note adds back.

Source: Adapted from Blitzstein & Hwang, Introduction to Probability, Chapter 2 and §2.10 (R), rewritten in Python · Original exercise; the book's R examples are paraphrased, not copied

Fill in the blank

The chance of winning by switching

You pick door 1, Monty opens a door with a goat behind it, and you always switch. What is the probability that you win the car? Answer as a fraction.

Your answer

Use an integer, decimal, or fraction such as 1/2. An exact value is expected.

Hints
1

Switching wins exactly when your first pick was wrong.

2

Your first pick is wrong with probability 2/32/3.

Reference solution

2/32/3. If your first pick is the car (probability 1/31/3), switching loses. If your first pick is a goat (probability 2/32/3), Monty must open the other goat door, so the door you switch to has the car. The simulation in the note gives 0.66900.6690.

Source: Adapted from Blitzstein & Hwang, Introduction to Probability, Chapter 2 and §2.10 (R), rewritten in Python · Original exercise; the book's R examples are paraphrased, not copied

Python

Update a probability on evidence

Complete bayes_update(prior, p_evidence_if_a, p_evidence_if_not_a). Given P(A)P(A), P(E∣A)P(E\mid A), and P(E∣Ac)P(E\mid A^c), return P(A∣E)P(A\mid E) using Bayes’ rule with the law of total probability. The tests pass Fraction values so the answers are exact. Assume P(E)>0P(E)>0.

Your answer

Python function exercise. Tab moves focus; use the indent buttons for selected lines.

Public tests

1. Monday: at least one girl

>>> bayes_update(Fraction(1, 4), 1, Fraction(2, 3))
Fraction(1, 3)

2. Tuesday: the elder is a girl

>>> bayes_update(Fraction(1, 3), 1, Fraction(1, 2))
Fraction(1, 2)

3. Evidence that rules out not-A

>>> bayes_update(Fraction(1, 100), 1, 0)
Fraction(1, 1)

4. Evidence that says nothing

>>> bayes_update(Fraction(1, 5), Fraction(1, 2), Fraction(1, 2))
Fraction(1, 5)
Hints
1

The numerator is P(E∣A) P(A)P(E\mid A)\,P(A).

2

The denominator adds P(E∣Ac) (1−P(A))P(E\mid A^c)\,(1-P(A)) to the numerator.

Reference solution
def bayes_update(prior, p_evidence_if_a, p_evidence_if_not_a):
    numerator = p_evidence_if_a * prior
    return numerator / (numerator + p_evidence_if_not_a * (1 - prior))

Because the result is again a probability for AA, it can be passed straight back in as the next prior: that is sequential updating. Evidence equally likely under AA and not AA leaves the prior unchanged.

Source: Adapted from Blitzstein & Hwang, Introduction to Probability, Chapter 2 and §2.10 (R), rewritten in Python · Original exercise; the book's R examples are paraphrased, not copied

Read as Markdown ↗Read alongside: Conditional probability in Python: two children, Monty Hall, and updating on evidence