Skip to content

Instantly share code, notes, and snippets.

@axs
Created February 21, 2015 20:28
Show Gist options
  • Save axs/b39f8dd4a992cc70494a to your computer and use it in GitHub Desktop.
Save axs/b39f8dd4a992cc70494a to your computer and use it in GitHub Desktop.
"""
microsoft TrueSkill algorithm for rankings
"""
from __future__ import print_function
import math
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 true_skill(winner, loser):
muw, sigmaw = winner
mul, sigmal = loser
c = (2*beta**2 + sigmaw**2 + sigmal**2)**.5
t = (muw - mul) / c
e = epsilon / c
sigmaw_new = (sigmaw**2 * (1 - (sigmaw**2) / (c**2)*Wwin(t, e)) + gamma**2)**.5
sigmal_new = (sigmal**2 * (1 - (sigmal**2) / (c**2)*Wwin(t, e)) + gamma**2)**.5
muw_new = (muw + sigmaw**2/c * Vwin(t,e))
mul_new = (mul - sigmal**2/c * Vwin(t,e))
winner = muw_new, sigmaw_new
loser = mul_new, sigmal_new
return winner, loser
def update(squads, winner, loser):
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)
def rank(squads, squad):
return squads[squad][0] - 3*squads[squad][1]
def main(argv):
games = [
("BARNEY", "STONE") , ("MIXIL", "KANE") , ("KANE", "CUTLER") , ("JOHNSONE", "HUXTABLE") , #day 1
("EDISON", "ALI") , ("SHARP", "STEVENS") , ("GALAVANT", "LEVY") , ("BARNEY", "ELROY") , #day 2
("MIXIL", "BARNEY") , ("MIXIL", "JOHNSONE") , ("JOHNSONE", "MIXIL") , ("MIXIL", "JOHNSONE") , #day 3
("JOHNSONE", "GALAVANT") , ("SALLY", "LEVY") , ("EDISON", "ROSE") , ("POE", "CHEECH") , #day 4
("COSTANZA", "HUXTABLE") , ("STONE", "SHARP") , ("KANE", "MIXIL") , ("STEVENS", "KATZ") , #day 5
("POE", "COSTANZA") , ("KANE", "STONE") , ("BARNEY", "JETSON") , ("JOHNSONE", "ROBERTSON"), #day 6
("POE", "EDISON"), ("NACHE", "KANE") , ("NACHE", "STEVENS") , ("BARNEY", "HO") , #day 7
("JOHNSONE", "CUTLER") , ("POE", "NACHE") , ("BARNEY", "JOHNSONE") , ("ELROY", "MARCUS") , #day 8
("ROSE", "ELROY") , ("POE", "BARNEY") , ("JOHNSONE", "LEVY") , ("JOHNSONE", "POE") , #day 9
("LEVY", "ROSE") , ("ELROY", "SHARP"), ("CHEECH", "MIXIL"), ("MIXIL", "ROSE") , #day 10
("SHARP", "HO") , ("JETSON", "MIXIL") , ("ROSE", "ELROY") , ("ROSE", "JETSON") , #day 11
("ROSE", "GALAVANT"), ("EDISON", "ROSE") , ("EDISON", "NACHE") , ("NACHE", "STONE") , #day 12
("JETSON", "STEVENS") , ("KANE", "SHARP") , ("KANE", "COSTANZA") , ("NACHE", "KANE") ] #day 13
squads = {}
for winner, loser in games:
update(squads, winner, loser)
for squad in sorted(squads, key=lambda squad: rank(squads, squad),reverse=True):
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment