Think Bayes
This notebook presents example code and exercise solutions for Think Bayes.
Copyright 2018 Allen B. Downey
MIT License: https://opensource.org/licenses/MIT
The Dungeons and Dragons club
Suppose there are 10 people in my Dungeons and Dragons club; on any game day, each of them has a 70% chance of showing up.
Each player has one character and each character has 6 attributes, each of which is generated by rolling and adding up 3 6-sided dice.
At the beginning of the game, I ask whose character has the lowest attribute. The wizard says, "My constitution is 5; does anyone have a lower attribute?", and no one does.
The warrior says "My strength is 16; does anyone have a higher attribute?", and no one does.
How many characters are in the party?
The prior
There are three ways to compute the prior distribution:
Simulation
Convolution
Analytic distribution
First, simulation. Here's a function that flips a coin with probability p:
We can use it to flip a coin for each member of the club.
And count the number that show up on game day.
Let's encapsulate that in a function that simulates a game day.
If we run that function many times, we get a sample from the distribution of the number of players.
The second method is convolution. Instead of flipping a coin, we can create a Pmf object that represents the distribution of outcomes from a single flip.
Here's what it looks like.
If we have two players, there are three possible outcomes:
If we have 10 players, we can get the prior distribution like this:
Now we can compare the results of simulation and convolution:
Finally, we can use an analytic distribution. The distribution we just computed is the binomial distribution, which has the following PMF:
We could evalate the right hand side in Python, or use MakeBinomialPmf:
And we can confirm that the analytic result matches what we computed by convolution.
Since two players spoke, we can eliminate the possibility of 0 or 1 players:
Likelihood
There are three components of the likelihood function:
The probability that the highest attribute is 16.
The probability that the lowest attribute is 5.
The probability that the lowest and highest attributes are held by different players.
To compute the first component, we have to compute the distribution of the maximum of attributes, where is the number of players.
Here is the distribution for a single die.
And here's the distribution for the sum of three dice.
Here's the CDF for the sum of three dice.
The Max method raises the CDF to a power. So here's the CDF for the maximum of six attributes.
If there are n players, there are 6*n attributes. Here are the distributions for the maximum attribute of n players, for a few values of n.
To check that, I'll compute the CDF for 7 players, and estimate it by simulation.
Looks good.
Now, to compute the minimum, I have to write my own function, because Cdf doesn't provide a Min function.
Now we can compute the CDF of the minimum attribute for n players, for several values of n.
And again we can check it by comparing to simulation results.
For efficiency and conciseness, it is helpful to precompute the distributions for the relevant values of n, and store them in dictionaries.
The output shows that the particular data we saw is symmetric: the chance that 16 is the maximum is the same as the chance that 5 is the minimum.
Finally, we need the probability that the minimum and maximum are held by the same person. If there are n players, there are 6*n attributes.
Let's call the player with the highest attribute Max. What is the chance that Max also has the lowest attribute? Well Max has 5 more attributes, out of a total of 6*n-1 remaining attributes.
So here's prob_same as a function of n.
The update
Here's a class that implements this likelihood function.
Here's the prior we computed above.
And here's the update based on the data in the problem statement.
Here's the posterior.
Based on the data, I am 94% sure there are between 5 and 9 players.