From 1fbc1b1940669747540132f7779d257722402ebf Mon Sep 17 00:00:00 2001 From: Vivek Joshy <8206808+vivekjoshy@users.noreply.github.com> Date: Sat, 2 Nov 2024 17:29:14 +0530 Subject: [PATCH] Use 2 * beta instead of scaling by total player count. Fixes #145 Signed-off-by: Vivek Joshy <8206808+vivekjoshy@users.noreply.github.com> --- openskill/models/weng_lin/bradley_terry_full.py | 17 +++++------------ openskill/models/weng_lin/bradley_terry_part.py | 17 +++++------------ openskill/models/weng_lin/plackett_luce.py | 17 +++++------------ .../models/weng_lin/thurstone_mosteller_full.py | 16 +++++----------- .../models/weng_lin/thurstone_mosteller_part.py | 17 +++++------------ .../models/weng_lin/test_bradley_terry_full.py | 4 ++-- .../models/weng_lin/test_bradley_terry_part.py | 4 ++-- tests/models/weng_lin/test_plackett_luce.py | 4 ++-- .../weng_lin/test_thurstone_mosteller_full.py | 4 ++-- .../weng_lin/test_thurstone_mosteller_part.py | 4 ++-- 10 files changed, 35 insertions(+), 69 deletions(-) diff --git a/openskill/models/weng_lin/bradley_terry_full.py b/openskill/models/weng_lin/bradley_terry_full.py index 0ea69c1..4d1f3f9 100644 --- a/openskill/models/weng_lin/bradley_terry_full.py +++ b/openskill/models/weng_lin/bradley_terry_full.py @@ -839,7 +839,6 @@ def predict_win(self, teams: List[List[BradleyTerryFullRating]]) -> List[float]: self._check_teams(teams) n = len(teams) - total_player_count = sum(len(team) for team in teams) # 2 Player Case if n == 2: @@ -848,11 +847,7 @@ def predict_win(self, teams: List[List[BradleyTerryFullRating]]) -> List[float]: b = teams_ratings[1] result = phi_major( (a.mu - b.mu) - / math.sqrt( - total_player_count * self.beta**2 - + a.sigma_squared - + b.sigma_squared - ) + / math.sqrt(2 * self.beta**2 + a.sigma_squared + b.sigma_squared) ) return [result, 1 - result] @@ -866,8 +861,7 @@ def predict_win(self, teams: List[List[BradleyTerryFullRating]]) -> List[float]: sigma_b = pair_b_subset[0].sigma_squared pairwise_probabilities.append( phi_major( - (mu_a - mu_b) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + (mu_a - mu_b) / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) ) @@ -912,11 +906,11 @@ def predict_draw(self, teams: List[List[BradleyTerryFullRating]]) -> float: pairwise_probabilities.append( phi_major( (draw_margin - mu_a + mu_b) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) - phi_major( (mu_b - mu_a - draw_margin) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) ) @@ -936,7 +930,6 @@ def predict_rank( self._check_teams(teams) n = len(teams) - total_player_count = sum(len(team) for team in teams) team_ratings = self._calculate_team_ratings(teams) win_probabilities = [] @@ -947,7 +940,7 @@ def predict_rank( team_win_probability += phi_major( (team_i.mu - team_j.mu) / math.sqrt( - total_player_count * self.beta**2 + 2 * self.beta**2 + team_i.sigma_squared + team_j.sigma_squared ) diff --git a/openskill/models/weng_lin/bradley_terry_part.py b/openskill/models/weng_lin/bradley_terry_part.py index d7ad0e3..db105c0 100644 --- a/openskill/models/weng_lin/bradley_terry_part.py +++ b/openskill/models/weng_lin/bradley_terry_part.py @@ -847,7 +847,6 @@ def predict_win(self, teams: List[List[BradleyTerryPartRating]]) -> List[float]: self._check_teams(teams) n = len(teams) - total_player_count = sum(len(team) for team in teams) # 2 Player Case if n == 2: @@ -856,11 +855,7 @@ def predict_win(self, teams: List[List[BradleyTerryPartRating]]) -> List[float]: b = teams_ratings[1] result = phi_major( (a.mu - b.mu) - / math.sqrt( - total_player_count * self.beta**2 - + a.sigma_squared - + b.sigma_squared - ) + / math.sqrt(2 * self.beta**2 + a.sigma_squared + b.sigma_squared) ) return [result, 1 - result] @@ -874,8 +869,7 @@ def predict_win(self, teams: List[List[BradleyTerryPartRating]]) -> List[float]: sigma_b = pair_b_subset[0].sigma_squared pairwise_probabilities.append( phi_major( - (mu_a - mu_b) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + (mu_a - mu_b) / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) ) @@ -920,11 +914,11 @@ def predict_draw(self, teams: List[List[BradleyTerryPartRating]]) -> float: pairwise_probabilities.append( phi_major( (draw_margin - mu_a + mu_b) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) - phi_major( (mu_b - mu_a - draw_margin) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) ) @@ -944,7 +938,6 @@ def predict_rank( self._check_teams(teams) n = len(teams) - total_player_count = sum(len(team) for team in teams) team_ratings = self._calculate_team_ratings(teams) win_probabilities = [] @@ -955,7 +948,7 @@ def predict_rank( team_win_probability += phi_major( (team_i.mu - team_j.mu) / math.sqrt( - total_player_count * self.beta**2 + 2 * self.beta**2 + team_i.sigma_squared + team_j.sigma_squared ) diff --git a/openskill/models/weng_lin/plackett_luce.py b/openskill/models/weng_lin/plackett_luce.py index 1140b1f..ba8cc46 100644 --- a/openskill/models/weng_lin/plackett_luce.py +++ b/openskill/models/weng_lin/plackett_luce.py @@ -839,7 +839,6 @@ def predict_win(self, teams: List[List[PlackettLuceRating]]) -> List[float]: self._check_teams(teams) n = len(teams) - total_player_count = sum(len(team) for team in teams) # 2 Player Case if n == 2: @@ -848,11 +847,7 @@ def predict_win(self, teams: List[List[PlackettLuceRating]]) -> List[float]: b = teams_ratings[1] result = phi_major( (a.mu - b.mu) - / math.sqrt( - total_player_count * self.beta**2 - + a.sigma_squared - + b.sigma_squared - ) + / math.sqrt(2 * self.beta**2 + a.sigma_squared + b.sigma_squared) ) return [result, 1 - result] @@ -866,8 +861,7 @@ def predict_win(self, teams: List[List[PlackettLuceRating]]) -> List[float]: sigma_b = pair_b_subset[0].sigma_squared pairwise_probabilities.append( phi_major( - (mu_a - mu_b) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + (mu_a - mu_b) / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) ) @@ -912,11 +906,11 @@ def predict_draw(self, teams: List[List[PlackettLuceRating]]) -> float: pairwise_probabilities.append( phi_major( (draw_margin - mu_a + mu_b) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) - phi_major( (mu_b - mu_a - draw_margin) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) ) @@ -936,7 +930,6 @@ def predict_rank( self._check_teams(teams) n = len(teams) - total_player_count = sum(len(team) for team in teams) team_ratings = self._calculate_team_ratings(teams) win_probabilities = [] @@ -947,7 +940,7 @@ def predict_rank( team_win_probability += phi_major( (team_i.mu - team_j.mu) / math.sqrt( - total_player_count * self.beta**2 + 2 * self.beta**2 + team_i.sigma_squared + team_j.sigma_squared ) diff --git a/openskill/models/weng_lin/thurstone_mosteller_full.py b/openskill/models/weng_lin/thurstone_mosteller_full.py index 80f5077..8a2ce09 100644 --- a/openskill/models/weng_lin/thurstone_mosteller_full.py +++ b/openskill/models/weng_lin/thurstone_mosteller_full.py @@ -880,7 +880,6 @@ def predict_win( self._check_teams(teams) n = len(teams) - total_player_count = sum(len(team) for team in teams) # 2 Player Case if n == 2: @@ -889,11 +888,7 @@ def predict_win( b = teams_ratings[1] result = phi_major( (a.mu - b.mu) - / math.sqrt( - total_player_count * self.beta**2 - + a.sigma_squared - + b.sigma_squared - ) + / math.sqrt(2 * self.beta**2 + a.sigma_squared + b.sigma_squared) ) return [result, 1 - result] @@ -907,8 +902,7 @@ def predict_win( sigma_b = pair_b_subset[0].sigma_squared pairwise_probabilities.append( phi_major( - (mu_a - mu_b) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + (mu_a - mu_b) / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) ) @@ -953,11 +947,11 @@ def predict_draw(self, teams: List[List[ThurstoneMostellerFullRating]]) -> float pairwise_probabilities.append( phi_major( (draw_margin - mu_a + mu_b) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) - phi_major( (mu_b - mu_a - draw_margin) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) ) @@ -989,7 +983,7 @@ def predict_rank( team_win_probability += phi_major( (team_i.mu - team_j.mu) / math.sqrt( - total_player_count * self.beta**2 + 2 * self.beta**2 + team_i.sigma_squared + team_j.sigma_squared ) diff --git a/openskill/models/weng_lin/thurstone_mosteller_part.py b/openskill/models/weng_lin/thurstone_mosteller_part.py index 31a0680..724575a 100644 --- a/openskill/models/weng_lin/thurstone_mosteller_part.py +++ b/openskill/models/weng_lin/thurstone_mosteller_part.py @@ -878,7 +878,6 @@ def predict_win( self._check_teams(teams) n = len(teams) - total_player_count = sum(len(team) for team in teams) # 2 Player Case if n == 2: @@ -887,11 +886,7 @@ def predict_win( b = teams_ratings[1] result = phi_major( (a.mu - b.mu) - / math.sqrt( - total_player_count * self.beta**2 - + a.sigma_squared - + b.sigma_squared - ) + / math.sqrt(2 * self.beta**2 + a.sigma_squared + b.sigma_squared) ) return [result, 1 - result] @@ -905,8 +900,7 @@ def predict_win( sigma_b = pair_b_subset[0].sigma_squared pairwise_probabilities.append( phi_major( - (mu_a - mu_b) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + (mu_a - mu_b) / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) ) @@ -951,11 +945,11 @@ def predict_draw(self, teams: List[List[ThurstoneMostellerPartRating]]) -> float pairwise_probabilities.append( phi_major( (draw_margin - mu_a + mu_b) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) - phi_major( (mu_b - mu_a - draw_margin) - / math.sqrt(total_player_count * self.beta**2 + sigma_a + sigma_b) + / math.sqrt(2 * self.beta**2 + sigma_a + sigma_b) ) ) @@ -975,7 +969,6 @@ def predict_rank( self._check_teams(teams) n = len(teams) - total_player_count = sum(len(team) for team in teams) team_ratings = self._calculate_team_ratings(teams) win_probabilities = [] @@ -986,7 +979,7 @@ def predict_rank( team_win_probability += phi_major( (team_i.mu - team_j.mu) / math.sqrt( - total_player_count * self.beta**2 + 2 * self.beta**2 + team_i.sigma_squared + team_j.sigma_squared ) diff --git a/tests/models/weng_lin/test_bradley_terry_full.py b/tests/models/weng_lin/test_bradley_terry_full.py index c1977de..a219ed4 100644 --- a/tests/models/weng_lin/test_bradley_terry_full.py +++ b/tests/models/weng_lin/test_bradley_terry_full.py @@ -531,10 +531,10 @@ def test_predict_draw(): team_2 = [b1, b2] probability = model.predict_draw(teams=[team_1, team_2]) - assert probability == pytest.approx(0.1694772, 0.0001) + assert probability == pytest.approx(0.1919967, 0.0001) probability = model.predict_draw(teams=[team_1, team_2, [a1], [a2], [b1]]) - assert probability == pytest.approx(0.0518253, 0.0001) + assert probability == pytest.approx(0.0603735, 0.0001) probability = model.predict_draw(teams=[[b1], [b1]]) assert probability == pytest.approx(0.5) diff --git a/tests/models/weng_lin/test_bradley_terry_part.py b/tests/models/weng_lin/test_bradley_terry_part.py index 0cdb298..628699e 100644 --- a/tests/models/weng_lin/test_bradley_terry_part.py +++ b/tests/models/weng_lin/test_bradley_terry_part.py @@ -534,10 +534,10 @@ def test_predict_draw(): team_2 = [b1, b2] probability = model.predict_draw(teams=[team_1, team_2]) - assert probability == pytest.approx(0.1694772, 0.0001) + assert probability == pytest.approx(0.1919967, 0.0001) probability = model.predict_draw(teams=[team_1, team_2, [a1], [a2], [b1]]) - assert probability == pytest.approx(0.0518253, 0.0001) + assert probability == pytest.approx(0.0603735, 0.0001) probability = model.predict_draw(teams=[[b1], [b1]]) assert probability == pytest.approx(0.5) diff --git a/tests/models/weng_lin/test_plackett_luce.py b/tests/models/weng_lin/test_plackett_luce.py index 366d585..c34ded0 100644 --- a/tests/models/weng_lin/test_plackett_luce.py +++ b/tests/models/weng_lin/test_plackett_luce.py @@ -529,10 +529,10 @@ def test_predict_draw(): team_2 = [b1, b2] probability = model.predict_draw(teams=[team_1, team_2]) - assert probability == pytest.approx(0.1694772, 0.0001) + assert probability == pytest.approx(0.1919967, 0.0001) probability = model.predict_draw(teams=[team_1, team_2, [a1], [a2], [b1]]) - assert probability == pytest.approx(0.0518253, 0.0001) + assert probability == pytest.approx(0.0603735, 0.0001) probability = model.predict_draw(teams=[[b1], [b1]]) assert probability == pytest.approx(0.5) diff --git a/tests/models/weng_lin/test_thurstone_mosteller_full.py b/tests/models/weng_lin/test_thurstone_mosteller_full.py index 72a1736..3f499d0 100644 --- a/tests/models/weng_lin/test_thurstone_mosteller_full.py +++ b/tests/models/weng_lin/test_thurstone_mosteller_full.py @@ -538,10 +538,10 @@ def test_predict_draw(): team_2 = [b1, b2] probability = model.predict_draw(teams=[team_1, team_2]) - assert probability == pytest.approx(0.1694772, 0.0001) + assert probability == pytest.approx(0.1919967, 0.0001) probability = model.predict_draw(teams=[team_1, team_2, [a1], [a2], [b1]]) - assert probability == pytest.approx(0.0518253, 0.0001) + assert probability == pytest.approx(0.0603735, 0.0001) probability = model.predict_draw(teams=[[b1], [b1]]) assert probability == pytest.approx(0.5) diff --git a/tests/models/weng_lin/test_thurstone_mosteller_part.py b/tests/models/weng_lin/test_thurstone_mosteller_part.py index 3557b52..f4fc186 100644 --- a/tests/models/weng_lin/test_thurstone_mosteller_part.py +++ b/tests/models/weng_lin/test_thurstone_mosteller_part.py @@ -542,10 +542,10 @@ def test_predict_draw(): team_2 = [b1, b2] probability = model.predict_draw(teams=[team_1, team_2]) - assert probability == pytest.approx(0.1694772, 0.0001) + assert probability == pytest.approx(0.1919967, 0.0001) probability = model.predict_draw(teams=[team_1, team_2, [a1], [a2], [b1]]) - assert probability == pytest.approx(0.0518253, 0.0001) + assert probability == pytest.approx(0.0603735, 0.0001) probability = model.predict_draw(teams=[[b1], [b1]]) assert probability == pytest.approx(0.5)