Simple-Switching-2

 Author Sean Submission date 2016-08-26 20:30:02.650279 Rating 7444 Matches played 415 Win rate 74.46

Use rpsrunner.py to play unranked matches on your computer.

Source code:

if not input:

import math
import random
import collections

log = math.log
exp = math.exp

gamma = random.gammavariate

third = 1.0 / 3

thirds = [third for _ in xrange(3)]

log_third = log(third)

nmodels = 20
models = range(nmodels)
log_nmodels = log(nmodels)
log_nmodelsm1 = log(nmodels - 1.0)
log_weights = [-log_nmodels for _ in models]

if y > x:
x, y = y, x
d = y - x
if d < -60:
return x
return x + log(1.0 + exp(d))

class ContextTree:
def __init__(self):
self.counts = [0, 0, 0]
self.children = [None, None, None]
def update(self, history, input):
l = len(history)
i = 0
while i < nmodels - 1:
self.counts[input] += 1
if i >= l:
return
x = history[i]
if self.children[x] is None:
self.children[x] = ContextTree()
self = self.children[x]
i += 1
def path(self, history):
l = len(history)
i = 0
while i < nmodels - 1:
yield self.counts
if i >= l:
return
x = history[i]
if self.children[x] is None:
return
self = self.children[x]
i += 1

def cond_probs(path):
yield thirds
i = 0
for counts in path:
rt = 1.0 / (sum(counts) + 3.0)
yield [(n + 1.0) * rt for n in counts]
i += 1
while i < nmodels - 1:
yield thirds
i += 1

def sample_probs(path):
yield thirds
i = 0
for counts in path:
counts1 = [gamma(n + 1, 1) for n in counts]
rt = 1.0 / (sum(counts1) + 3.0)
yield [n * rt for n in counts1]
i += 1
while i < nmodels - 1:
counts1 = [gamma(1, 1) for _ in names]
rt = 1.0 / (sum(counts1) + 3.0)
yield [n * rt for n in counts1]
i += 1

names = ["R", "P", "S"]
R, P, S = range(3)
index = dict(zip(names, range(3)))
beat = (P, S, R)
beaten = (S, R, P)

model = ContextTree()
history = collections.deque([])
output = random.choice(names)

cond_ps = [thirds for _ in models]

rnd = 1.0

else:

rnd += 1

alpha = 1.0 / rnd

k = (1 - alpha) * (nmodels - 1) - 1

alpha = log(alpha)

k = log(k)

inp = index[input]
out = index[output]

log_inp_ps = [log(ps[inp]) for ps in cond_ps]

r = float("-infinity")
for w, p in zip(log_weights, log_inp_ps):
r = log_add(r, w + p)

for i, (w, p) in enumerate(zip(log_weights, log_inp_ps)):
log_weights[i] = log_add(alpha + r, k + w + p) - log_nmodelsm1

model.update(history, inp)

history.appendleft(inp)
history.appendleft(out)

path = list(model.path(history))

cond_ps = list(cond_probs(path))

sampled_ps = list(sample_probs(path))

log_cond_ps = [float("-infinity") for _ in names]

for i, (w, ps) in enumerate(zip(log_weights, sampled_ps)):
for j, p in enumerate(ps):
log_cond_ps[j] = log_add(log_cond_ps[j], w + log(p))

log_p0 = min(log_cond_ps)

weighted_cond_ps = [0 for _ in names]

for j, log_p in enumerate(log_cond_ps):
weighted_cond_ps[j] = exp(log_p - log_p0)

scores = [0, 0, 0]

for i, p in enumerate(weighted_cond_ps):
scores[beat[i]] += p
scores[beaten[i]] -= p
print(scores)
output = names[scores.index(max(scores))]