#include <math.h>
#include <string.h>
#include <stdlib.h>
+#include <Eigen/Core>
+#include <Eigen/Eigenvalues>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
+using namespace Eigen;
-#define PRIOR_MU 1500
+#define PRIOR_MU 500
#define PRIOR_WEIGHT 1.0
#define MAX_PLAYERS 4096
#define DUMP_RAW 0
float mu[MAX_PLAYERS];
+float mu_stddev[MAX_PLAYERS];
float global_sigma = 70.0f;
float prior_sigma = 70.0f;
map<int, vector<match> > matches_for_player;
vector<match> all_matches;
-void dump_scores(const vector<string> &players, const float *mu, int num_players)
+void dump_scores(const vector<string> &players, const float *mu, const float *mu_stddev, int num_players)
{
#if 0
for (int i = 0; i < num_players; ++i) {
printf("\n");
#else
for (int i = 0; i < num_players; ++i) {
- printf("%f %s\n", mu[i], players[i].c_str());
+ printf("%f %f %s\n", mu[i], mu_stddev[i], players[i].c_str());
}
#endif
}
*
* Note that this does not depend on mu or the margin at all.
*/
-double hessian[MAX_PLAYERS][MAX_PLAYERS];
-void construct_hessian(const float *mu, const float *sigma, int num_players)
+Matrix<float, Dynamic, Dynamic> hessian;
+void construct_hessian(const float *mu, int num_players)
{
- memset(hessian, 0, sizeof(hessian));
+ hessian = Matrix<float, Dynamic, Dynamic>(num_players, num_players);
+ hessian.fill(0.0f);
+ for (int i = 0; i < num_players; ++i) {
+ hessian(i, i) += 1.0f / (prior_sigma * prior_sigma);
+ }
for (unsigned i = 0; i < all_matches.size(); ++i) {
const match &m = all_matches[i];
double sigma_sq = global_sigma * global_sigma;
float w = m.weight;
- hessian[p1][p2] -= w / sigma_sq;
- hessian[p2][p1] -= w / sigma_sq;
+ hessian(p1, p2) -= w / sigma_sq;
+ hessian(p2, p1) -= w / sigma_sq;
- hessian[p1][p1] += w / sigma_sq;
- hessian[p2][p2] += w / sigma_sq;
+ hessian(p1, p1) += w / sigma_sq;
+ hessian(p2, p2) += w / sigma_sq;
}
+}
- for (int i = 0; i < num_players; ++i) {
- for (int j = 0; j < num_players; ++j) {
- printf("%.12f ", hessian[i][j]);
+// Compute uncertainty (stddev) of mu estimates, which is sqrt((H^-1)_ii),
+// where H is the Hessian (see construct_hessian()).
+void compute_mu_uncertainty(const float *mu, const vector<string> &players)
+{
+ // FIXME: Use pseudoinverse if applicable.
+ Matrix<float, Dynamic, Dynamic> ih = hessian.inverse();
+ for (unsigned i = 0; i < players.size(); ++i) {
+ mu_stddev[i] = sqrt(ih(i, i));
+ }
+
+ for (unsigned i = 0; i < players.size(); ++i) {
+ for (unsigned j = 0; j < players.size(); ++j) {
+ printf("covariance %s %s %f\n",
+ players[i].c_str(),
+ players[j].c_str(),
+ ih(i, j));
}
- printf("\n");
}
}
sumdiff += (global_sigma - old_global_sigma) * (global_sigma - old_global_sigma);
if (sumdiff < EPSILON) {
//fprintf(stderr, "Converged after %d iterations. Stopping.\n", j);
- printf("%d -1\n", j + 1);
+ printf("%d 0 -1\n", j + 1);
break;
}
}
#if DUMP_RAW
dump_raw(mu, num_players);
#else
- dump_scores(players, mu, num_players);
+ construct_hessian(mu, num_players);
+ compute_mu_uncertainty(mu, players);
+ dump_scores(players, mu, mu_stddev, num_players);
//fprintf(stderr, "Optimal sigma: %f (two-player: %f)\n", sigma[0], sigma[0] * sqrt(2.0f));
- printf("%f -2\n", global_sigma / sqrt(2.0f));
- printf("%f -3\n", prior_sigma);
+ printf("%f 0 -2\n", global_sigma / sqrt(2.0f));
+ printf("%f 0 -3\n", prior_sigma);
float total_logl = compute_total_logl(mu, num_players);
- printf("%f -4\n", total_logl);
-
-// construct_hessian(mu, sigma, num_players);
+ printf("%f 0 -4\n", total_logl);
#endif
}