sigma[player_num] = sqrt(sum / matches.size());
}
+/*
+ * diff(logL, sigma) = w ( (x - mu)² - sigma² ) / sigma³
+ * maximizer for sigma is given by: sum_i[ (w_i/sigma)³ ((x - mu)² - sigma²) ] = 0
+ * sum_i[ w_i ( (x - mu)² - sigma² ) ] = 0 |: sigma != 0
+ * sum_i[ w_i (x - mu)² ] = sum[ w_i sigma² ]
+ * sigma = sqrt( sum_i[ w_i (x - mu)² ] / sum[w_i] )
+ */
+void update_global_sigma(float *mu, float *sigma, int num_players)
+{
+ float nom = 0.0f, denom = 0.0f;
+ for (int i = 0; i < num_players; ++i) {
+ for (unsigned j = 0; j < matches_for_player[i].size(); ++j) {
+ const match& m = matches_for_player[i][j];
+
+ // Only count each match once.
+ if (m.other_player <= i) {
+ continue;
+ }
+
+ float mu1 = mu[i];
+ float mu2 = mu[m.other_player];
+ float mu = mu1 - mu2;
+ float x = m.margin;
+ float w = m.weight;
+
+ nom += w * ((x - mu) * (x - mu));
+ denom += w;
+ }
+ }
+
+ float best_sigma = sqrt(nom / denom) / sqrt(2.0f); // Divide evenly between the two players.
+ for (int i = 0; i < num_players; ++i) {
+ sigma[i] = best_sigma;
+ }
+}
+
void renormalize(float *mu, float *sigma, int num_players)
{
float avg = 0.0f;
update_mu(mu, sigma, i, matches_for_player[i]);
renormalize(mu, sigma, num_players);
}
+ update_global_sigma(mu, sigma, num_players);
/* for (int i = 0; i < num_players; ++i) {
update_sigma(mu, sigma, i, matches_for_player[i]);
dump_scores(players, mu, sigma, num_players);
}
}
dump_scores(players, mu, sigma, num_players);
+ fprintf(stderr, "Optimal sigma: %f (two-player: %f)\n", sigma[0], sigma[0] * sqrt(2.0f));
// construct_fim(mu, sigma, num_players);
}