<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Think Bayes
Step3:  The Euro problem
Problem statement here.
Here's a more efficient version of the Euro class that takes the dataset in a more compact form and uses the binomial distribution (ignoring the binomial coefficient because it does not depend on x).
Step4:  If we know the coin is fair, we can evaluate the likelihood of the data directly.
Step5:  If we cheat an pretend that the alternative hypothesis is exactly the observed proportion, we can compute the likelihood of the data and the likelihood ratio, relative to the fair coin.
Step6:  Under this interpretation, the data are in favor of "biased", with K=6.  But that's a total cheat.
Suppose we think "biased" means either 0.4 or 0.6, but we're not sure which.  The total likelihood of the data is the weighted average of the two likelihoods.
Step8:  Under this interpretation, the data are in favor of "biased", but very weak.
More generally, if "biased" refers to a range of possibilities with different probabilities, the total likelihood of the data is the weighted sum
Step9:  Here's what it looks like if "biased" means "equally likely to be any value between 0 and 1".
Step11:  By that definition, the data are evidence against the biased hypothesis, with K=2.
But maybe a triangle prior is a better model of what "biased" means.
Step12:  Here's what it looks like
Step13:  By the triangle definition of "biased", the data are very weakly in favor of "fair".
Normalizing constant
We don't really need the SuiteLikelihood function, because Suite.Update already computes the total probability of the data, which is the normalizing constant.
<ASSISTANT_TASK:>
Python Code:
from __future__ import print_function, division
% matplotlib inline
import warnings
warnings.filterwarnings('ignore')
import math
import numpy as np
from thinkbayes2 import Pmf, Cdf, Suite, Joint
import thinkplot
Explanation: Think Bayes: Chapter 11
This notebook presents code and exercises from Think Bayes, second edition.
Copyright 2016 Allen B. Downey
MIT License: https://opensource.org/licenses/MIT
End of explanation
class Euro(Suite):
    Represents hypotheses about the probability of heads.
    def Likelihood(self, data, hypo):
        Computes the likelihood of the data under the hypothesis.
        hypo: integer value of x, the probability of heads (0-100)
        data: tuple of (number of heads, number of tails)
        
        x = hypo / 100.0
        heads, tails = data
        like = x**heads * (1-x)**tails
        return like
Explanation: The Euro problem
Problem statement here.
Here's a more efficient version of the Euro class that takes the dataset in a more compact form and uses the binomial distribution (ignoring the binomial coefficient because it does not depend on x).
End of explanation
data = 140, 110
suite = Euro()
like_f = suite.Likelihood(data, 50)
print('p(D|F)', like_f)
Explanation: If we know the coin is fair, we can evaluate the likelihood of the data directly.
End of explanation
actual_percent = 100.0 * 140 / 250
likelihood = suite.Likelihood(data, actual_percent)
print('p(D|B_cheat)', likelihood)
print('p(D|B_cheat) / p(D|F)', likelihood / like_f)
Explanation: If we cheat an pretend that the alternative hypothesis is exactly the observed proportion, we can compute the likelihood of the data and the likelihood ratio, relative to the fair coin.
End of explanation
like40 = suite.Likelihood(data, 40)
like60 = suite.Likelihood(data, 60)
likelihood = 0.5 * like40 + 0.5 * like60
print('p(D|B_two)', likelihood)
print('p(D|B_two) / p(D|F)', likelihood / like_f)
Explanation: Under this interpretation, the data are in favor of "biased", with K=6.  But that's a total cheat.
Suppose we think "biased" means either 0.4 or 0.6, but we're not sure which.  The total likelihood of the data is the weighted average of the two likelihoods.
End of explanation
def SuiteLikelihood(suite, data):
    Computes the weighted average of likelihoods for sub-hypotheses.
    suite: Suite that maps sub-hypotheses to probability
    data: some representation of the data
   
    returns: float likelihood
    
    total = 0
    for hypo, prob in suite.Items():
        like = suite.Likelihood(data, hypo)
        total += prob * like
    return total
Explanation: Under this interpretation, the data are in favor of "biased", but very weak.
More generally, if "biased" refers to a range of possibilities with different probabilities, the total likelihood of the data is the weighted sum:
End of explanation
b_uniform = Euro(range(0, 101))
b_uniform.Remove(50)
b_uniform.Normalize()
likelihood = SuiteLikelihood(b_uniform, data)
print('p(D|B_uniform)', likelihood)
print('p(D|B_uniform) / p(D|F)', likelihood / like_f)
Explanation: Here's what it looks like if "biased" means "equally likely to be any value between 0 and 1".
End of explanation
def TrianglePrior():
    Makes a Suite with a triangular prior.
    suite = Euro()
    for x in range(0, 51):
        suite.Set(x, x)
    for x in range(51, 101):
        suite.Set(x, 100-x) 
    suite.Normalize()
    return suite
Explanation: By that definition, the data are evidence against the biased hypothesis, with K=2.
But maybe a triangle prior is a better model of what "biased" means.
End of explanation
b_tri = TrianglePrior()
b_tri.Remove(50)
b_tri.Normalize()
likelihood = b_tri.Update(data)
print('p(D|B_tri)', likelihood)
print('p(D|B_tri) / p(D|F)', likelihood / like_f)
Explanation: Here's what it looks like:
End of explanation
likelihood = SuiteLikelihood(b_uniform, data)
likelihood
euro = Euro(b_uniform)
euro.Update(data)
likelihood = SuiteLikelihood(b_tri, data)
likelihood
euro = Euro(b_tri)
euro.Update(data)
Explanation: By the triangle definition of "biased", the data are very weakly in favor of "fair".
Normalizing constant
We don't really need the SuiteLikelihood function, because Suite.Update already computes the total probability of the data, which is the normalizing constant.
End of explanation
<END_TASK>