Skip to content

Instantly share code, notes, and snippets.

@tompaton
Created December 22, 2010 08:41
Show Gist options
  • Save tompaton/751275 to your computer and use it in GitHub Desktop.
Save tompaton/751275 to your computer and use it in GitHub Desktop.
Version of true_skill() Python algorithm that handles draws.
#!/usr/bin/env python2.6
from __future__ import print_function
import sys
from scipy.stats.distributions import norm as scipy_norm
beta = 25/6
gamma = 25/300
epsilon = 0.08
norm = scipy_norm()
def pdf(x):
return norm.pdf(x)
def cdf(x):
return norm.cdf(x)
def Vwin(t, e):
return pdf(t - e) / cdf(t - e)
def Wwin(t, e):
return Vwin(t, e) * (Vwin(t, e) + t - e)
def Vdraw(t, e):
return (pdf(-e - t) - pdf(e - t)) / (cdf(e - t) - cdf(-e - t))
def Wdraw(t, e):
return Vdraw(t, e)**2 + ((e - t)*pdf(e - t) + (e + t)*pdf(e + t)) / (cdf(e - t) - cdf(-e - t))
def true_skill(winner, loser, draw=False):
muw, sigmaw = winner
mul, sigmal = loser
c = (2*beta**2 + sigmaw**2 + sigmal**2)**.5
t = (muw - mul) / c
e = epsilon / c
if draw:
W = Wdraw
V = Vdraw
else:
W = Wwin
V = Vwin
sigmaw_new = (sigmaw**2 * (1 - (sigmaw**2) / (c**2)*W(t, e)) + gamma**2)**.5
sigmal_new = (sigmal**2 * (1 - (sigmal**2) / (c**2)*W(t, e)) + gamma**2)**.5
muw_new = (muw + sigmaw**2/c * V(t,e))
mul_new = (mul - sigmal**2/c * V(t,e))
winner = muw_new, sigmaw_new
loser = mul_new, sigmal_new
return winner, loser
def update(squads, winner, loser, draw):
winner_stats = squads.get(winner, (25, 25/3))
loser_stats = squads.get(loser, (25, 25/3))
squads[winner], squads[loser] = true_skill(winner_stats, loser_stats, draw)
def rank(squads, squad):
return squads[squad][0] - 3*squads[squad][1]
def main(argv):
games = [
("PK", "SF", False), ("RT", "XT", False), ("ACE", "BS", False), ("SRM", "GB", False), #day 1
("SysX", "XT", False), ("PK", "RT", False), ("SF", "GB", False), ("SRM", "BS", False), #day 2
("SysX", "GB", False), ("RT", "BS", False), ("SF", "SRM", False), ("XT", "ACE", False), #day 3
("SysX", "PK", False), ("RT", "SF", False), ("XT", "BS", False), ("GB", "SRM", False), #day 4
("SysX", "RT", False), ("PK", "ACE", False), ("XT", "SF", False), ("BS", "GB", False), #day 5
("SysX", "SF", False), ("RT", "GB", False), ("XT", "PK", False), ("ACE", "SRM", False), #day 6
("SysX", "ACE",False), ("RT", "SF", False), ("XT", "PK", False), ("BS", "SRM", False), #day 7
("SysX", "BS", False), ("PK", "GB", False), ("RT", "SRM", False), ("ACE", "SF", True ), #day 8
("SysX", "RT", False), ("PK", "SRM", False), ("XT", "SF", False), ("BS", "ACE", False), #day 9
("PK", "SF", False), ("XT", "SysX",False), ("SRM", "ACE",False), ("BS", "GB", False), #day 10
("SysX", "SF", False), ("PK", "RT", False), ("XT", "SRM", False), ("ACE", "GB", False), #day 11
("SysX", "SRM",False), ("PK", "BS", False), ("RT", "ACE", False), ("XT", "GB", False), #day 12
("SysX", "PK", False), ("RT", "XT", False), ("BS", "ACE", False), ("GB", "ACE", False) ] #day 13
squads = {}
for winner, loser, draw in games:
update(squads, winner, loser, draw)
for squad in sorted(squads, key=lambda squad: rank(squads, squad)):
mu = squads[squad][0]
sigma = squads[squad][1]
print("%6s R: %5.2f mu: %5.2f sigma: %5.2f" % (squad, rank(squads, squad), mu, sigma))
return 0
if __name__ == "__main__":
exit_code = main(sys.argv)
sys.exit(exit_code)
@tompaton
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment