# Think Bayes solutions: Chapter 2

This notebook presents solutions to exercises in Think Bayes.

``````

In [1]:

from __future__ import print_function, division

from thinkbayes2 import Hist, Pmf

% matplotlib inline

``````

Exercise 2.1 In Section 2.3 I said that the solution to the cookie problem generalizes to the case where we draw multiple cookies with replacement.

But in the more likely scenario where we eat the cookies we draw, the likelihood of each draw depends on the previous draws.

Modify the solution in this chapter to handle selection without replacement. Hint: add instance variables to Cookie to represent the hypothetical state of the bowls, and modify Likelihood accordingly. You might want to define a Bowl object.

Solution Here's the original solution from the book:

``````

In [2]:

pmf = Pmf()
pmf.Set('Bowl 1', 0.5)
pmf.Set('Bowl 2', 0.5)

pmf.Mult('Bowl 1', 0.75)
pmf.Mult('Bowl 2', 0.5)

pmf.Normalize()

pmf.Print()

``````
``````

Bowl 1 0.6000000000000001
Bowl 2 0.4

``````

We could write it more concisely like this:

``````

In [3]:

pmf = Pmf(['Bowl 1', 'Bowl 2'])

pmf['Bowl 1'] *= 0.75
pmf['Bowl 2'] *= 0.5

pmf.Normalize()
pmf.Print()

``````
``````

Bowl 1 0.6000000000000001
Bowl 2 0.4

``````

And we can do a second update, with a chocolate cookie, like this:

``````

In [4]:

pmf['Bowl 1'] *= 0.25
pmf['Bowl 2'] *= 0.5

pmf.Normalize()
pmf.Print()

``````
``````

Bowl 1 0.4285714285714286
Bowl 2 0.5714285714285714

``````

Now let's solve the version of the problem where we don't replace the cookies.

We'll need an object to keep track of the number of cookies in each bowl. I'll use a Hist object, defined in thinkbayes2:

``````

In [5]:

bowl1 = Hist(dict(vanilla=30, chocolate=10))
bowl2 = Hist(dict(vanilla=20, chocolate=20))

bowl1.Print()

``````
``````

chocolate 10
vanilla 30

``````

Now I'll make a Pmf that contains the two bowls, giving them equal probability.

``````

In [6]:

pmf = Pmf([bowl1, bowl2])
pmf.Print()

``````
``````

Hist({'vanilla': 30, 'chocolate': 10}) 0.5
Hist({'vanilla': 20, 'chocolate': 20}) 0.5

``````

Here's a likelihood function that takes `hypo`, which is one of the Hist objects that represents a bowl, and `data`, which is either `'vanilla'` or `'chocolate'`.

`likelihood` computes the likelihood of the data under the hypothesis, and as a side effect, it removes one of the cookies from `hypo`

``````

In [7]:

def likelihood(hypo, data):
like = hypo[data] / hypo.Total()
if like:
hypo[data] -= 1
return like

``````

Now for the update. We have to loop through the hypotheses and compute the likelihood of the data under each hypothesis.

``````

In [8]:

def update(pmf, data):
for hypo in pmf:
pmf[hypo] *= likelihood(hypo, data)
return pmf.Normalize()

``````

Here's the first update. The posterior probabilities are the same as what we got before, but notice that the number of cookies in each Hist has been updated.

``````

In [9]:

update(pmf, 'vanilla')
pmf.Print()

``````
``````

Hist({'vanilla': 29, 'chocolate': 10}) 0.6
Hist({'vanilla': 19, 'chocolate': 20}) 0.4

``````

So when we update again with a chocolate cookies, we get different likelihoods, and different posteriors.

``````

In [10]:

update(pmf, 'chocolate')
pmf.Print()

``````
``````

Hist({'vanilla': 29, 'chocolate': 9}) 0.428571428571
Hist({'vanilla': 19, 'chocolate': 19}) 0.571428571429

``````

If we get 10 more chocolate cookies, that eliminates Bowl 1 completely

``````

In [11]:

for i in range(10):
update(pmf, 'chocolate')
print(pmf[bowl1])

``````
``````

0.26213592233
0.136363636364
0.0610465116279
0.0238005289006
0.00806142034549
0.0023166023166
0.000535554894377
8.92990028278e-05
8.11875025371e-06
0.0

``````
``````

In [ ]:

``````
``````

In [ ]:

``````
``````

In [ ]:

``````
``````

In [ ]:

``````
``````

In [ ]:

``````
``````

In [ ]:

``````