📚 The CoCalc Library - books, templates and other resources
License: OTHER
"""This file contains code for use with "Think Bayes",1by Allen B. Downey, available from greenteapress.com23Copyright 2013 Allen B. Downey4License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html5"""67import csv8import numpy9import thinkbayes10import thinkplot1112import matplotlib.pyplot as pyplot131415FORMATS = ['png', 'pdf', 'eps']161718def ReadData(filename='showcases.2011.csv'):19"""Reads a CSV file of data.2021Args:22filename: string filename2324Returns: sequence of (price1 price2 bid1 bid2 diff1 diff2) tuples25"""26fp = open(filename)27reader = csv.reader(fp)28res = []2930for t in reader:31_heading = t[0]32data = t[1:]33try:34data = [int(x) for x in data]35# print heading, data[0], len(data)36res.append(data)37except ValueError:38pass3940fp.close()41return zip(*res)424344class Price(thinkbayes.Suite):45"""Represents hypotheses about the price of a showcase."""4647def __init__(self, pmf, player, name=''):48"""Constructs the suite.4950pmf: prior distribution of price51player: Player object52name: string53"""54thinkbayes.Suite.__init__(self, pmf, name=name)55self.player = player5657def Likelihood(self, data, hypo):58"""Computes the likelihood of the data under the hypothesis.5960hypo: actual price61data: the contestant's guess62"""63price = hypo64guess = data6566error = price - guess67like = self.player.ErrorDensity(error)6869return like707172class GainCalculator(object):73"""Encapsulates computation of expected gain."""7475def __init__(self, player, opponent):76"""Constructs the calculator.7778player: Player79opponent: Player80"""81self.player = player82self.opponent = opponent8384def ExpectedGains(self, low=0, high=75000, n=101):85"""Computes expected gains for a range of bids.8687low: low bid88high: high bid89n: number of bids to evaluates9091returns: tuple (sequence of bids, sequence of gains)9293"""94bids = numpy.linspace(low, high, n)9596gains = [self.ExpectedGain(bid) for bid in bids]9798return bids, gains99100def ExpectedGain(self, bid):101"""Computes the expected return of a given bid.102103bid: your bid104"""105suite = self.player.posterior106total = 0107for price, prob in sorted(suite.Items()):108gain = self.Gain(bid, price)109total += prob * gain110return total111112def Gain(self, bid, price):113"""Computes the return of a bid, given the actual price.114115bid: number116price: actual price117"""118# if you overbid, you get nothing119if bid > price:120return 0121122# otherwise compute the probability of winning123diff = price - bid124prob = self.ProbWin(diff)125126# if you are within 250 dollars, you win both showcases127if diff <= 250:128return 2 * price * prob129else:130return price * prob131132def ProbWin(self, diff):133"""Computes the probability of winning for a given diff.134135diff: how much your bid was off by136"""137prob = (self.opponent.ProbOverbid() +138self.opponent.ProbWorseThan(diff))139return prob140141142class Player(object):143"""Represents a player on The Price is Right."""144145n = 101146price_xs = numpy.linspace(0, 75000, n)147148def __init__(self, prices, bids, diffs):149"""Construct the Player.150151prices: sequence of prices152bids: sequence of bids153diffs: sequence of underness (negative means over)154"""155self.pdf_price = thinkbayes.EstimatedPdf(prices)156self.cdf_diff = thinkbayes.MakeCdfFromList(diffs)157158mu = 0159sigma = numpy.std(diffs)160self.pdf_error = thinkbayes.GaussianPdf(mu, sigma)161162def ErrorDensity(self, error):163"""Density of the given error in the distribution of error.164165error: how much the bid is under the actual price166"""167return self.pdf_error.Density(error)168169def PmfPrice(self):170"""Returns a new Pmf of prices.171172A discrete version of the estimated Pdf.173"""174return self.pdf_price.MakePmf(self.price_xs)175176def CdfDiff(self):177"""Returns a reference to the Cdf of differences (underness).178"""179return self.cdf_diff180181def ProbOverbid(self):182"""Returns the probability this player overbids.183"""184return self.cdf_diff.Prob(-1)185186def ProbWorseThan(self, diff):187"""Probability this player's diff is greater than the given diff.188189diff: how much the oppenent is off by (always positive)190"""191return 1 - self.cdf_diff.Prob(diff)192193def MakeBeliefs(self, guess):194"""Makes a posterior distribution based on estimated price.195196Sets attributes prior and posterior.197198guess: what the player thinks the showcase is worth199"""200pmf = self.PmfPrice()201self.prior = Price(pmf, self, name='prior')202self.posterior = self.prior.Copy(name='posterior')203self.posterior.Update(guess)204205def OptimalBid(self, guess, opponent):206"""Computes the bid that maximizes expected return.207208guess: what the player thinks the showcase is worth209opponent: Player210211Returns: (optimal bid, expected gain)212"""213self.MakeBeliefs(guess)214calc = GainCalculator(self, opponent)215bids, gains = calc.ExpectedGains()216gain, bid = max(zip(gains, bids))217return bid, gain218219def PlotBeliefs(self, root):220"""Plots prior and posterior beliefs.221222root: string filename root for saved figure223"""224thinkplot.Clf()225thinkplot.PrePlot(num=2)226thinkplot.Pmfs([self.prior, self.posterior])227thinkplot.Save(root=root,228xlabel='price ($)',229ylabel='PMF',230formats=FORMATS)231232233def MakePlots(player1, player2):234"""Generates two plots.235236price1 shows the priors for the two players237price2 shows the distribution of diff for the two players238"""239240# plot the prior distribution of price for both players241thinkplot.Clf()242thinkplot.PrePlot(num=2)243pmf1 = player1.PmfPrice()244pmf1.name = 'showcase 1'245pmf2 = player2.PmfPrice()246pmf2.name = 'showcase 2'247thinkplot.Pmfs([pmf1, pmf2])248thinkplot.Save(root='price1',249xlabel='price ($)',250ylabel='PDF',251formats=FORMATS)252253# plot the historical distribution of underness for both players254thinkplot.Clf()255thinkplot.PrePlot(num=2)256cdf1 = player1.CdfDiff()257cdf1.name = 'player 1'258cdf2 = player2.CdfDiff()259cdf2.name = 'player 2'260261print 'Player median', cdf1.Percentile(50)262print 'Player median', cdf2.Percentile(50)263264print 'Player 1 overbids', player1.ProbOverbid()265print 'Player 2 overbids', player2.ProbOverbid()266267thinkplot.Cdfs([cdf1, cdf2])268thinkplot.Save(root='price2',269xlabel='diff ($)',270ylabel='CDF',271formats=FORMATS)272273274def MakePlayers():275"""Reads data and makes player objects."""276data = ReadData(filename='showcases.2011.csv')277data += ReadData(filename='showcases.2012.csv')278279cols = zip(*data)280price1, price2, bid1, bid2, diff1, diff2 = cols281282# print list(sorted(price1))283# print len(price1)284285player1 = Player(price1, bid1, diff1)286player2 = Player(price2, bid2, diff2)287288return player1, player2289290291def PlotExpectedGains(guess1=20000, guess2=40000):292"""Plots expected gains as a function of bid.293294guess1: player1's estimate of the price of showcase 1295guess2: player2's estimate of the price of showcase 2296"""297player1, player2 = MakePlayers()298MakePlots(player1, player2)299300player1.MakeBeliefs(guess1)301player2.MakeBeliefs(guess2)302303print 'Player 1 prior mle', player1.prior.MaximumLikelihood()304print 'Player 2 prior mle', player2.prior.MaximumLikelihood()305print 'Player 1 mean', player1.posterior.Mean()306print 'Player 2 mean', player2.posterior.Mean()307print 'Player 1 mle', player1.posterior.MaximumLikelihood()308print 'Player 2 mle', player2.posterior.MaximumLikelihood()309310player1.PlotBeliefs('price3')311player2.PlotBeliefs('price4')312313calc1 = GainCalculator(player1, player2)314calc2 = GainCalculator(player2, player1)315316thinkplot.Clf()317thinkplot.PrePlot(num=2)318319bids, gains = calc1.ExpectedGains()320thinkplot.Plot(bids, gains, label='Player 1')321print 'Player 1 optimal bid', max(zip(gains, bids))322323bids, gains = calc2.ExpectedGains()324thinkplot.Plot(bids, gains, label='Player 2')325print 'Player 2 optimal bid', max(zip(gains, bids))326327thinkplot.Save(root='price5',328xlabel='bid ($)',329ylabel='expected gain ($)',330formats=FORMATS)331332333def PlotOptimalBid():334"""Plots optimal bid vs estimated price.335"""336player1, player2 = MakePlayers()337guesses = numpy.linspace(15000, 60000, 21)338339res = []340for guess in guesses:341player1.MakeBeliefs(guess)342343mean = player1.posterior.Mean()344mle = player1.posterior.MaximumLikelihood()345346calc = GainCalculator(player1, player2)347bids, gains = calc.ExpectedGains()348gain, bid = max(zip(gains, bids))349350res.append((guess, mean, mle, gain, bid))351352guesses, means, _mles, gains, bids = zip(*res)353354thinkplot.PrePlot(num=3)355pyplot.plot([15000, 60000], [15000, 60000], color='gray')356thinkplot.Plot(guesses, means, label='mean')357#thinkplot.Plot(guesses, mles, label='MLE')358thinkplot.Plot(guesses, bids, label='bid')359thinkplot.Plot(guesses, gains, label='gain')360thinkplot.Save(root='price6',361xlabel='guessed price ($)',362formats=FORMATS)363364365def TestCode(calc):366"""Check some intermediate results.367368calc: GainCalculator369"""370# test ProbWin371for diff in [0, 100, 1000, 10000, 20000]:372print diff, calc.ProbWin(diff)373374375# test Return376price = 20000377for bid in [17000, 18000, 19000, 19500, 19800, 20001]:378print bid, calc.Gain(bid, price)379380381382def main():383PlotExpectedGains()384PlotOptimalBid()385386387388if __name__ == '__main__':389main()390391392