(self)
| 874 | ax.set_title( |
| 875 | f"Elo Distribution ({self.bootstrap_type} bootstrap, {self.n_bootstrap} samples)", |
| 876 | fontproperties=FONT_BOLD, |
| 877 | fontsize=16, |
| 878 | ) |
| 879 | ax.grid(True, axis="y", alpha=0.3) |
| 880 | legend = ax.legend(prop=FONT_BOLD, fontsize=12) |
| 881 | legend.set_frame_on(False) |
| 882 | |
| 883 | plt.tight_layout() |
| 884 | self._save_plot(output_dir, f"{self.game}_elo_violin_{self.bootstrap_type}") |
| 885 | plt.close() |
| 886 | |
| 887 | def run(self) -> dict: |
| 888 | game = self.game |
| 889 | assert game in self.builder.win_matrix, f"Game '{game}' not found in win matrix" |
| 890 | |
| 891 | baseline_res = self._fit_on_matrix(self.builder.win_matrix[game]) |
| 892 | baseline_elos = self._elos_from_result(baseline_res) |
| 893 | baseline_ranking = self._ranking_from_elos(baseline_elos) |
| 894 | players = baseline_ranking |
| 895 | n = len(players) |
| 896 | topks = list(range(1, n + 1)) if self.topks is None else [k for k in self.topks if k <= n] |
| 897 | |
| 898 | rank_samples: dict[str, list[int]] = {p: [] for p in players} |
| 899 | elo_samples: dict[str, list[float]] = {p: [] for p in players} |
| 900 | tau_vals: list[float] = [] |
| 901 | rho_vals: list[float] = [] |
| 902 | footrule_vals: list[float] = [] |
| 903 | topk_overlap: dict[int, list[float]] = {k: [] for k in topks} |
| 904 | top1_match = 0 |
| 905 | pair_agree = 0 |
| 906 | total_pairs = n * (n - 1) // 2 |
| 907 | |
| 908 | base_pos = self._positions(baseline_ranking) |
| 909 | |
| 910 | rng = np.random.default_rng(42) |
| 911 | baseline_fitter = BradleyTerryFitter( |
| 912 | self.builder.win_matrix[game], regularization=self.regularization, compute_uncertainties=False |
| 913 | ) |
| 914 | for _ in tqdm(range(self.n_bootstrap), desc="Bootstrap samples"): |
| 915 | if self.bootstrap_type == "nonparametric": |
| 916 | boot = self.builder.get_nonparametric_bootstrap(rng=rng) |
| 917 | res = self._fit_on_matrix(boot[game]) |
| 918 | else: |
| 919 | baseline_fitter.fit() |
| 920 | boot_matrix = baseline_fitter.get_parametric_bootstrap(rng=rng) |
| 921 | res = self._fit_on_matrix(boot_matrix) |
| 922 | elos = self._elos_from_result(res) |
| 923 | ranking = self._ranking_from_elos(elos) |
| 924 | pos = self._positions(ranking) |
| 925 | |
| 926 | for p in players: |
| 927 | rank_samples[p].append(pos[p] + 1) |
| 928 | elo_samples[p].append(elos[p]) |
| 929 | |
| 930 | base_rank_arr = np.array([base_pos[p] + 1 for p in players]) |
| 931 | boot_rank_arr = np.array([pos[p] + 1 for p in players]) |
| 932 | tau = kendalltau(base_rank_arr, boot_rank_arr, variant="b").correlation |
| 933 | rho = spearmanr(base_rank_arr, boot_rank_arr).correlation |
nothing calls this directly
no test coverage detected