#!/usr/bin/env python # coding: utf-8 # In[75]: import math import numpy as np import pandas as pd # ### Initial conditions # In[82]: initial_rating = 400 k = 100 things = ['Malted Milk','Rich Tea','Hobnob','Digestive'] # ### Elo Algos # In[135]: def expected_win(r1, r2): """ Expected probability of player 1 beating player 2 if player 1 has rating 1 (r1) and player 2 has rating 2 (r2) """ return 1.0 / (1 + math.pow(10, (r2-r1)/400)) def update_rating(R, k, P, d): """ d = 1 = WIN d = 0 = LOSS """ return R + k*(d-P) # In[84]: def elo(Ra, Rb, k, d): """ d = 1 when player A wins d = 0 when player B wins """ Pa = expected_win(Ra, Rb) Pb = expected_win(Rb, Ra) # update if A wins if d == 1: Ra = update_rating(Ra, k, Pa, d) Rb = update_rating(Rb, k, Pb, d-1) # update if B wins elif d == 0: Ra = update_rating(Ra, k, Pa, d) Rb = update_rating(Rb, k, Pb, d+1) return Pa, Pb, Ra, Rb # In[85]: def elo_sequence(things, initial_rating, k, results): """ Initialises score dictionary, and runs through sequence of pairwise results, returning final dictionary of Elo rankings """ dic_scores = {i:initial_rating for i in things} for result in results: winner, loser = result Ra, Rb = dic_scores[winner], dic_scores[loser] _, _, newRa, newRb = elo(Ra, Rb, k, 1) dic_scores[winner], dic_scores[loser] = newRa, newRb return dic_scores # ### Mean Elo # In[136]: def mElo(things, initial_rating, k, results, numEpochs): """ Randomises the sequence of the pairwise comparisons, running the Elo sequence in a random sequence for a number of epochs Returns the mean Elo ratings over the randomised epoch sequences """ lst_outcomes = [] for i in np.arange(numEpochs): np.random.shuffle(results) lst_outcomes.append(elo_sequence(things, initial_rating, k, results)) return pd.DataFrame(lst_outcomes).mean().sort_values(ascending=False) # ### Pairwise Outcomes from Christian's Taste Test # # > **Format** (Winner, Loser) # In[137]: results = np.array([('Malted Milk','Rich Tea'),('Malted Milk','Digestive'),('Malted Milk','Hobnob')\ ,('Hobnob','Rich Tea'),('Hobnob','Digestive'),('Digestive','Rich Tea')]) # In[138]: jenResults = np.array([('Rich Tea','Malted Milk'),('Digestive','Malted Milk'),('Hobnob','Malted Milk')\ ,('Hobnob','Rich Tea'),('Hobnob','Digestive'),('Digestive','Rich Tea')]) # In[149]: mElo(things, initial_rating, k, jenResults, 1000) # In[ ]: