Skip to content

Commit

Permalink
Merge pull request #50 from OpenDebates/tau-option
Browse files Browse the repository at this point in the history
Implement additive dynamics factor 'tau'.
  • Loading branch information
vivekjoshy committed Mar 18, 2022
2 parents 9e2dbe8 + 25d4d5a commit ce66f8f
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 6 deletions.
4 changes: 4 additions & 0 deletions changes/50.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
``tau`` (defaults to 0): Additive dynamics factor, which keeps a player's rating from getting stuck at a level. Normally, a player's sigma will only decrease as we gain more information about their performance. This option will put some pressure on this back up. This default will change to be sigma/100 with v3, to be more congruent with TrueSkill, but higher may make your rating system more exciting.

``prevent_sigma_increase`` (defaults to false): for a tau > 0, it is possible that a player could play someone with a low enough rating that even if they win, their ordinal rating will still go down slightly. If your players have no agency in matchmaking, it is not desirable to have a situation where a player goes down on the leaderboard even though they win.

38 changes: 32 additions & 6 deletions openskill/rate.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import copy
import itertools
import math
from functools import reduce
Expand Down Expand Up @@ -142,9 +143,20 @@ def rate(teams: List[List[Rating]], **options) -> List[List[Rating]]:
:param teams: A list of teams, where teams are lists of :class:`~openskill.rate.Rating` objects.
:param rank: A list of :class:`~int` where the lower values represent the winners.
:param score: A list of :class:`~int` where higher values represent the winners.
:param tau: A :class:`~float` that modifies the additive dynamics factor.
:param prevent_sigma_increase: A :class:`~bool` that prevents sigma from ever increasing.
:param options: Pass in a set of custom values for constants defined in the Weng-Lin paper.
:return: Returns a list of :class:`~openskill.rate.Rating` objects.
"""
original_teams = copy.deepcopy(teams)
if "tau" in options:
tau_squared = options["tau"] * options["tau"]
for team_index, team in enumerate(teams):
for player_index, player in enumerate(team):
teams[team_index][player_index].sigma = math.sqrt(
player.sigma * player.sigma + tau_squared
)

if "rank" in options:
rank = options["rank"]
else:
Expand All @@ -166,25 +178,39 @@ def rate(teams: List[List[Rating]], **options) -> List[List[Rating]]:
else:
model = PlackettLuce(teams, team_rating=team_rating, **options)

processed_result = []
if rank and tenet:
result = model.calculate()
result, old_tenet = unwind(tenet, result)
final_result = []
for item in result:
team = []
for player in item:
team.append(create_rating(player))
final_result.append(team)
return final_result
processed_result.append(team)
else:
result = model.calculate()
final_result = []
for item in result:
team = []
for player in item:
team.append(create_rating(player))
final_result.append(team)
return final_result
processed_result.append(team)

final_result = processed_result

if options.get("tau"):
if options.get("prevent_sigma_increase"):
final_result = []
for team_index, team in enumerate(processed_result):
final_team = []
for player_index, player in enumerate(team):
player_original = original_teams[team_index][player_index]
if player.sigma <= player_original.sigma:
sigma = player.sigma
else:
sigma = player_original.sigma
final_team.append(Rating(mu=player.mu, sigma=sigma))
final_result.append(final_team)
return final_result


def predict_win(teams: List[List[Rating]], **options) -> List[Union[int, float]]:
Expand Down
31 changes: 31 additions & 0 deletions tests/test_rate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from openskill import Rating, rate


def test_rate():

# Accepts a tau term
a = Rating(sigma=3)
b = Rating(sigma=3)
[[winner], [loser]] = rate([[a], [b]], tau=0.3)
assert [[winner], [loser]] == [
[Rating(mu=25.624880438870754, sigma=2.9879993738476953)],
[Rating(mu=24.375119561129246, sigma=2.9879993738476953)],
]

# Prevents sigma from rising
a = Rating(mu=40, sigma=3)
b = Rating(mu=-20, sigma=3)
[[winner], [loser]] = rate([[a], [b]], tau=0.3, prevent_sigma_increase=True)
assert [[winner], [loser]] == [
[Rating(mu=40.00032667136128, sigma=3)],
[Rating(mu=-20.000326671361275, sigma=3)],
]

# Ensures sigma decreases
a = Rating()
b = Rating()
[[winner], [loser]] = rate([[a], [b]], tau=0.3, prevent_sigma_increase=True)
assert [[winner], [loser]] == [
[Rating(mu=27.6372798316677, sigma=8.070625245679999)],
[Rating(mu=22.3627201683323, sigma=8.070625245679999)],
]

0 comments on commit ce66f8f

Please sign in to comment.