#!/usr/bin/env python # coding: utf-8 # # Appendix: An interactive Jupyter notebook session to accompany: "Penney's game odds from no-arbitrage" by Miller, J.B. (2019) # # # # see https://github.com/joshua-benjamin-miller/penneysgame for .ipynb and .py files. # # # # This interactive notebook explores an algorithm that solves a generalized version of Penney's pattern-matching game for a q-sided die ($q\geq 3$), with potentially unequal probabilities. # # The solution implements a generalized version of Conway's leading number algorithm , and cross-validates it via simulation. # # References # 1. Miller, J.B. (2019) "Penney's game odds from no-arbitrage", OSF [PDF Download](https://osf.io/47u5a/) # 2. Li, Shuo-Yen Robert. (1980) A martingale approach to the study of occurrence of sequence patterns in repeated experiments." _the Annals of Probability_, 8(6) 1171-1176. [PDF Download](https://projecteuclid.org/euclid.aop/1176994578) # 3. Guibas, L. J. & Odlyzko, A. M. (1981), "String overlaps, pattern matching, and nontransitive games", # _Journal of Combinatorial Theory, Series A_ 30(2), 183--208. [PDF Download](https://core.ac.uk/download/pdf/81142890.pdf) # 2. # ### Third party modules and directory check # In[1]: import time import os #for benchmarking import numpy as np #in case we need to update user-defined code e.g. importlib.reload(diffP) import importlib # In[32]: current_dir=os.getcwd() print(current_dir) for file in os.listdir(current_dir): if file[-3:]=='.py': print(file) # ### Desciption of code in "conway.py" # In[2]: import conway #The programs live here importlib.reload(conway) #help(conway) print('Locked and loaded') # ## Inspect functions # ### Let's test the generalized Conway leading number # # note: In the speccial case of a fair coin flip, this is $2\times \text{Conway Leading Number}$ # # Conway leading number is an (asymmetric) measure of overlap between two patterns A and B. # # AB measures how the leading numbers of B overlap with the trailing numbers of A, as B is shifted to the right (assuming B is not a subpattern of A) # # Here is the function: # In[6]: help(conway.payoff_to_B_bettors_if_A_occurs_first) # If A=THH comes first, how much does a player who, on each trial, initiates a asequence of bets on characters according to B=HHH, get paid? # # The players that arrive at time T-1 and time T walk out with \$4 and \$2 respectively, for a total of \$6 # # In[17]: distribution={'H':.5, 'T':.5} A = "THH" B = "HHH" print(conway.payoff_to_B_bets_if_A_occurs_first(A, B, distribution)) # ### Let's test the generalized Conway leading number algorithm # # Here is the function: # In[18]: help(conway.oddsAB) # What are the odds that that pattern A=HTH precedes pattern B=TTH? # # In the case that A occurs before B, i.e we compare the trailing characters of $A\cdot$ # * $AA=8+0+2=10$ (the $A$-bets initiated at $T-2$ and $T$ are winners) # * $AB=0+0+0=0$ (the $B$-bets never win) # # In the case that B occurs before A, i.e we compare the trailing characters of $B\cdot$ # * $BB=8+0+0=8$ (the $B$-bet inititiated at $T-2$ is a winner) # * $BA=0+0+2=2$ (the $A$-bet initiated at $T$ is a winner) # # so odds against $A$ occuring before $B$ are ${AA-AB}:{BB-BA} = 10:6$, or $5:3$ # # this translates to a probability that $A$ occurs first equal to $3/8$ # # Let's check this below: # In[19]: distribution={'H':.5, 'T':.5} A = "HTH" B = "TTH" print('odds against A = [chances against, chances in favor] = ',conway.oddsAB(A, B, distribution)) print('probability A occurs before B = ', conway.probAB(A, B, distribution)) # ## Cross-Validating the code. # # # ### Replicating original Penney's Game odds (patterns of length 3) # # Let's create the table, the probability the row pattern comes before the column pattern, and cross-validate with table from Gardner # # In[97]: from fractions import Fraction pH = .5 pT = 1-pH distribution={'H':pH, 'T':pT} k = 3 #initialize the globals within the module conway.list_pattern=['-']*k conway.patterns = [] #build the patterns help(conway.all_patterns) conway.all_patterns(k,distribution) patterns = conway.patterns print("all patterns of length",k,"= ",patterns) row = 0 print("-" * 70) print("", end='\t') print(*patterns, sep='\t') while row < 8: col = 0 print(patterns[row],end='\t') while col <= 7: r='\t' if col ==7: r='\n' if patterns[row]==patterns[col]: print('', end=r) else: o=conway.oddsAB(patterns[row],patterns[col], distribution) F = Fraction(int(o[1]),int(o[0]+o[1])) N = F.numerator D = F.denominator print(N,"/",D,end=r) col += 1 row += 1 print("-" * 70) # Gardner's table (they match): # # # drawing # ### Cross-validate the odds function by simulation # # here is the simulation function: # In[11]: help(conway.simulate_winrates_penney_game) # Cross-validate the simple case # In[258]: distribution={'H':.5, 'T':.5} A = "HTH" B = "TTH" p = conway.probAB(A,B,distribution) wait = conway.expected_waiting_time(A,B,distribution) N=10000 np.random.seed(0) prop, average_n_flips= conway.simulate_winrates_penney_game(A,B,distribution,N) print('Pr(A