1111
1212from openskill .models .common import _normalize , _unary_minus
1313from openskill .models .weng_lin .common import (
14- _ladder_pairs ,
1514 _unwind ,
1615 phi_major ,
1716 phi_major_inverse ,
@@ -281,6 +280,7 @@ def __init__(
281280 float ,
282281 ] = _gamma ,
283282 tau : float = 25.0 / 300.0 ,
283+ window_size : int = 4 ,
284284 limit_sigma : bool = False ,
285285 balance : bool = False ,
286286 ):
@@ -321,6 +321,10 @@ def __init__(
321321
322322 *Represented by:* :math:`\tau`
323323
324+ :param window_size: The sliding window size for partial pairing such
325+ that a larger window size tends to full pairing
326+ mode's accuracy.
327+
324328 :param limit_sigma: Boolean that determines whether to restrict
325329 the value of sigma from increasing.
326330
@@ -346,6 +350,7 @@ def __init__(
346350 ] = gamma
347351
348352 self .tau : float = float (tau )
353+ self .window_size : int = int (window_size )
349354 self .limit_sigma : bool = limit_sigma
350355 self .balance : bool = balance
351356
@@ -748,87 +753,83 @@ def _compute(
748753 original_teams = teams
749754 team_ratings = self ._calculate_team_ratings (teams , ranks = ranks )
750755 beta = self .beta
751- adjacent_teams = _ladder_pairs (team_ratings )
752-
756+ num_teams = len (team_ratings )
757+ window = self . window_size
753758 result = []
754- for i , (team_i , adjacent_i ) in enumerate (zip (team_ratings , adjacent_teams )):
755- omega = 0.0
756- delta = 0.0
757759
758- for q , team_q in enumerate (adjacent_i ):
760+ for i , team_i in enumerate (team_ratings ):
761+ omega_sum = 0.0
762+ delta_sum = 0.0
763+ comparisons = 0
764+
765+ start = max (0 , i - window )
766+ end = min (num_teams , i + window + 1 )
767+ for q in range (start , end ):
759768 if q == i :
760769 continue
761-
770+ team_q = team_ratings [ q ]
762771 c_iq = math .sqrt (
763772 team_i .sigma_squared + team_q .sigma_squared + (2 * beta ** 2 )
764773 )
765774 p_iq = 1 / (1 + math .exp ((team_q .mu - team_i .mu ) / c_iq ))
766- sigma_squared_to_ciq = team_i .sigma_squared / c_iq
775+ sigma_to_ciq = team_i .sigma_squared / c_iq
767776
768777 s = 0.0
769778 if team_q .rank > team_i .rank :
770- s = 1
779+ s = 1.0
771780 elif team_q .rank == team_i .rank :
772781 s = 0.5
773782
774- omega += sigma_squared_to_ciq * (s - p_iq )
775- if weights :
776- gamma_value = self .gamma (
777- c_iq ,
778- len (team_ratings ),
779- team_i .mu ,
780- team_i .sigma_squared ,
781- team_i .team ,
782- team_i .rank ,
783- weights [i ],
784- )
785- else :
786- gamma_value = self .gamma (
787- c_iq ,
788- len (team_ratings ),
789- team_i .mu ,
790- team_i .sigma_squared ,
791- team_i .team ,
792- team_i .rank ,
793- None ,
794- )
795- delta += (
796- ((gamma_value * sigma_squared_to_ciq ) / c_iq ) * p_iq * (1 - p_iq )
783+ omega_sum += sigma_to_ciq * (s - p_iq )
784+ current_weights = weights [i ] if weights else None
785+ gamma_value = self .gamma (
786+ c_iq ,
787+ num_teams ,
788+ team_i .mu ,
789+ team_i .sigma_squared ,
790+ team_i .team ,
791+ team_i .rank ,
792+ current_weights ,
797793 )
794+ delta_sum += (gamma_value * sigma_to_ciq / c_iq ) * p_iq * (1 - p_iq )
795+ comparisons += 1
798796
799- intermediate_result_per_team = []
800- for j , j_players in enumerate (team_i .team ):
801-
802- if weights :
803- weight = weights [i ][j ]
804- else :
805- weight = 1
806-
807- mu = j_players .mu
808- sigma = j_players .sigma
797+ if comparisons > 0 :
798+ omega = omega_sum / comparisons
799+ delta = delta_sum / comparisons
800+ else :
801+ omega = 0.0
802+ delta = 0.0
809803
810- if omega > 0 :
811- mu += (sigma ** 2 / team_i .sigma_squared ) * omega * weight
812- sigma *= math .sqrt (
804+ intermediate_result_per_team = []
805+ for j , player in enumerate (team_i .team ):
806+ w = weights [i ][j ] if weights else 1
807+ new_mu = player .mu
808+ new_sigma = player .sigma
809+
810+ if omega >= 0 :
811+ new_mu += (new_sigma ** 2 / team_i .sigma_squared ) * omega * w
812+ new_sigma *= math .sqrt (
813813 max (
814- 1 - (sigma ** 2 / team_i .sigma_squared ) * delta * weight ,
814+ 1 - (new_sigma ** 2 / team_i .sigma_squared ) * delta * w ,
815815 self .kappa ,
816- ),
816+ )
817817 )
818818 else :
819- mu += (sigma ** 2 / team_i .sigma_squared ) * omega / weight
820- sigma *= math .sqrt (
819+ new_mu += (new_sigma ** 2 / team_i .sigma_squared ) * omega / w
820+ new_sigma *= math .sqrt (
821821 max (
822- 1 - (sigma ** 2 / team_i .sigma_squared ) * delta / weight ,
822+ 1 - (new_sigma ** 2 / team_i .sigma_squared ) * delta / w ,
823823 self .kappa ,
824- ),
824+ )
825825 )
826826
827827 modified_player = original_teams [i ][j ]
828- modified_player .mu = mu
829- modified_player .sigma = sigma
828+ modified_player .mu = new_mu
829+ modified_player .sigma = new_sigma
830830 intermediate_result_per_team .append (modified_player )
831831 result .append (intermediate_result_per_team )
832+
832833 return result
833834
834835 def predict_win (self , teams : List [List [BradleyTerryPartRating ]]) -> List [float ]:
0 commit comments