From df74a5c15f78990dd71ce7fe06ebe50c0aab5125 Mon Sep 17 00:00:00 2001 From: xiaowuc1 Date: Fri, 28 Feb 2025 14:03:14 -0800 Subject: [PATCH] add perf_ceiling in rating computation --- judge/ratings.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/judge/ratings.py b/judge/ratings.py index 05e8d1d59b..e60c8ad458 100644 --- a/judge/ratings.py +++ b/judge/ratings.py @@ -1,5 +1,5 @@ from bisect import bisect -from math import pi, sqrt, tanh +from math import inf, pi, sqrt, tanh from operator import attrgetter, itemgetter from django.db import transaction @@ -19,6 +19,7 @@ VAR_LIM = (sqrt(VAR_PER_CONTEST**2 + 4 * BETA2 * VAR_PER_CONTEST) - VAR_PER_CONTEST) / 2 SD_LIM = sqrt(VAR_LIM) TANH_C = sqrt(3) / pi +PERF_CEILING_INCREMENT = 400 def tie_ranker(iterable, key=attrgetter('points')): @@ -77,17 +78,19 @@ def get_var(times_ranked, cache=[VAR_INIT]): return cache[times_ranked] -def recalculate_ratings(ranking, old_mean, times_ranked, historical_p): +def recalculate_ratings(ranking, old_mean, times_ranked, historical_p, perf_ceiling): n = len(ranking) new_p = [0.] * n new_mean = [0.] * n + updated_bounds = [VALID_RANGE[0], min(VALID_RANGE[1], perf_ceiling)] + # Note: pre-multiply delta by TANH_C to improve efficiency. delta = [TANH_C * sqrt(get_var(t) + VAR_PER_CONTEST + BETA2) for t in times_ranked] p_tanh_terms = [(m, d, 1) for m, d in zip(old_mean, delta)] # Calculate performance at index i. - def solve_idx(i, bounds=VALID_RANGE): + def solve_idx(i, bounds): r = ranking[i] y_tg = 0 for d, s in zip(delta, ranking): @@ -111,8 +114,8 @@ def divconq(i, j): new_mean = list(old_mean) else: # Calculate performance. - solve_idx(0) - solve_idx(n - 1) + solve_idx(0, updated_bounds) + solve_idx(n - 1, updated_bounds) divconq(0, n - 1) # Calculate mean. @@ -160,6 +163,9 @@ def rate_contest(contest): users = users.exclude(last_rating__lt=contest.rating_floor) if contest.rating_ceiling is not None: users = users.exclude(last_rating__gt=contest.rating_ceiling) + perf_ceiling = contest.rating_ceiling + PERF_CEILING_INCREMENT + else: + perf_ceiling = inf users = list(users) participation_ids = list(map(itemgetter('id'), users)) @@ -176,7 +182,7 @@ def rate_contest(contest): idx = user_id_to_idx[h['user_id']] historical_p[idx].append(h['performance']) - rating, mean, performance = recalculate_ratings(ranking, old_mean, times_ranked, historical_p) + rating, mean, performance = recalculate_ratings(ranking, old_mean, times_ranked, historical_p, perf_ceiling) now = timezone.now() ratings = [Rating(user_id=i, contest=contest, rating=r, mean=m, performance=perf,