X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=bayeswf.cpp;h=48d52325620c0542b4f61553e2d0d075d906371c;hb=b48d3244dd4ed5f61e4e1e1d21bca88e918ccff9;hp=f518edd7ca2987f9ae3c6551be9a0deaa1613706;hpb=fc8d9feb8f0b81581b24d779e3f7c3ee45290eb8;p=wloh diff --git a/bayeswf.cpp b/bayeswf.cpp index f518edd..48d5232 100644 --- a/bayeswf.cpp +++ b/bayeswf.cpp @@ -112,6 +112,42 @@ void update_sigma(float *mu, float *sigma, int player_num, const vector & 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; @@ -247,6 +283,7 @@ int main(int argc, char **argv) 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); @@ -263,6 +300,7 @@ int main(int argc, char **argv) } } 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); }