Skip to content

Commit

Permalink
Make style updates conditional
Browse files Browse the repository at this point in the history
If there are no style pages in the first place, don't bother including
style terms in the climber base updates, and don't update the style
ratings on each iteration.

This optimization halves the number of calls to get_bt_derivatives.
This corresponds to a time saving of approximately 35%.
  • Loading branch information
p00ya committed May 14, 2022
1 parent 9f66588 commit 8dbefa8
Showing 1 changed file with 22 additions and 10 deletions.
32 changes: 22 additions & 10 deletions climbing_ratings/whole_history_rating.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ class WholeHistoryRating:
__slots__ = (
"_bases",
"_styles",
"_has_styles",
"_route_ratings",
"_route_var",
"_route_ascents",
Expand Down Expand Up @@ -257,6 +258,7 @@ def __init__(
hparams.style_prior_variance,
hparams.style_wiener_variance,
)
self._has_styles = len(style_pages) > 0
self._route_ratings: _Array = np.array(routes_rating)
self._route_var = np.empty_like(self._route_ratings)
self._route_ascents = _make_route_ascents(
Expand All @@ -277,6 +279,7 @@ def __copy__(self) -> "WholeHistoryRating":
whr: WholeHistoryRating = self.__class__.__new__(self.__class__)
whr._bases = copy.copy(self._bases)
whr._styles = copy.copy(self._styles)
whr._has_styles = self._has_styles
whr._route_ratings = self._route_ratings.copy()
whr._route_var = self._route_var.copy()
whr._route_ascents = self._route_ascents
Expand Down Expand Up @@ -316,20 +319,21 @@ def route_var(self) -> _Array:
return self._route_var

def __get_page_bt_derivatives(
self, pages: "_PageModel", aux_pages: "_PageModel"
self, pages: "_PageModel", aux_pages: Optional["_PageModel"]
) -> Tuple[_Array, _Array]:
"""Gets the Bradley-Terry terms for page/style-page ratings.
Gets the first and second derivative of the Bradley-Terry model with
respect to the player's natural rating. Auxilliary ratings allow the
respect to the player's natural rating. Auxiliary ratings allow the
player to be modeled with either base-ratings or style-ratings.
Parameters
----------
pages
A slicing of ascents for the player's ratings.
aux_pages
A slicing of ascents for the auxilliary ratings.
An optional slicing of ascents for the auxiliary ratings. None is
equivalent to auxiliary ratings of 0 for all pages.
Returns
-------
Expand All @@ -342,9 +346,11 @@ def __get_page_bt_derivatives(
num_ascents = len(ascents.adversary)

page_ratings = expand_to_slices(ratings, ascents.slices, num_ascents)
page_ratings += expand_to_slices_sparse(
aux_pages.ratings, aux_pages.ascents.slices, num_ascents
)

if aux_pages is not None:
page_ratings += expand_to_slices_sparse(
aux_pages.ratings, aux_pages.ascents.slices, num_ascents
)

route_ratings = self.route_ratings[ascents.adversary]

Expand All @@ -356,7 +362,10 @@ def __get_page_bt_derivatives(
)

def __update_page_ratings(
self, pages: "_PageModel", aux_pages: "_PageModel", only_variance: bool
self,
pages: "_PageModel",
aux_pages: Optional["_PageModel"],
only_variance: bool,
) -> None:
"""Update the ratings of all pages.
Expand All @@ -365,7 +374,8 @@ def __update_page_ratings(
pages
Pages of the player to update.
aux_pages
Auxilliary pages for the player.
Optional auxiliary pages for the player. None is equivalent to an
auxiliary rating of 0 for all pages.
only_variance
If true, only updates the page variance and covariance.
The ratings estimates are left unchanged.
Expand Down Expand Up @@ -402,7 +412,8 @@ def update_base_ratings(self, only_variance: bool = False) -> None:
If true, only updates the base variance and covariance.
The ratings estimates are left unchanged.
"""
self.__update_page_ratings(self._bases, self._styles, only_variance)
styles = self._styles if self._has_styles else None
self.__update_page_ratings(self._bases, styles, only_variance)

def update_style_ratings(self, only_variance: bool = False) -> None:
"""Update the ratings of all style pages.
Expand Down Expand Up @@ -462,7 +473,8 @@ def update_ratings(self) -> None:
# the routes.
self.update_base_ratings()
self.update_route_ratings()
self.update_style_ratings()
if self._has_styles:
self.update_style_ratings()

def update_covariance(self) -> None:
"""Update covariance estimates for all routes and pages."""
Expand Down

0 comments on commit 8dbefa8

Please sign in to comment.