///////////////////////////////////////////////////////////////////////////// // Compute variance with the diagonal of the Hessian ///////////////////////////////////////////////////////////////////////////// void CBradleyTerry::GetVariance(double *pdVariance) const { ConvertEloToGamma(); const double x = std::log(10.0) / 400; const double xx = x * x; for (int Player = crs.GetPlayers(); --Player >= 0;) { double Diag = 0; double PlayerGamma = pGamma[Player]; for (int j = crs.GetOpponents(Player); --j >= 0;) { const CCondensedResult &cr = crs.GetCondensedResult(Player, j); double OpponentGamma = pGamma[cr.Opponent]; double h = 0; { double d = ThetaW * PlayerGamma + ThetaD * OpponentGamma; h += (cr.w_ij + cr.d_ij) / (d * d); } { double d = ThetaD * ThetaW * PlayerGamma + OpponentGamma; h += (cr.l_ij + cr.d_ij) / (d * d); } { double d = ThetaW * OpponentGamma + ThetaD * PlayerGamma; h += (cr.w_ji + cr.d_ji) / (d * d); } { double d = ThetaD * ThetaW * OpponentGamma + PlayerGamma; h += (cr.l_ji + cr.d_ji) / (d * d); } h *= PlayerGamma * OpponentGamma * ThetaD * ThetaW; Diag -= h; } pdVariance[Player] = -1.0 / (Diag * xx); } }
///////////////////////////////////////////////////////////////////////////// // Compute the covariance matrix // This function assumes that ratings are maximum-likelihood ratings ///////////////////////////////////////////////////////////////////////////// void CBradleyTerry::ComputeCovariance() { // // Compute the truncated opposite of the Hessian // CMatrix mTruncatedHessian(crs.GetPlayers() - 1, crs.GetPlayers() - 1); { ConvertEloToGamma(); const double x = std::log(10.0) / 400; const double xx = -x * x; mTruncatedHessian.Zero(); for (int Player = crs.GetPlayers() - 1; --Player >= 0;) { double Diag = 0; double PlayerGamma = pGamma[Player]; for (int j = crs.GetOpponents(Player); --j >= 0;) { const CCondensedResult &cr = crs.GetCondensedResult(Player, j); double OpponentGamma = pGamma[cr.Opponent]; double h = 0; { double d = ThetaW * PlayerGamma + ThetaD * OpponentGamma; h += (cr.w_ij + cr.d_ij) / (d * d); } { double d = ThetaD * ThetaW * PlayerGamma + OpponentGamma; h += (cr.l_ij + cr.d_ij) / (d * d); } { double d = ThetaW * OpponentGamma + ThetaD * PlayerGamma; h += (cr.w_ji + cr.d_ji) / (d * d); } { double d = ThetaD * ThetaW * OpponentGamma + PlayerGamma; h += (cr.l_ji + cr.d_ji) / (d * d); } h *= PlayerGamma * OpponentGamma * ThetaD * ThetaW; Diag -= h; if (cr.Opponent != crs.GetPlayers() - 1) mTruncatedHessian.SetElement(Player, cr.Opponent, h * xx); } mTruncatedHessian.SetElement(Player, Player, Diag * xx); } } // // LU-Decompose it // CLUDecomposition lud(crs.GetPlayers() - 1); std::vector<int> vIndex(crs.GetPlayers() - 1); lud.Decompose(mTruncatedHessian, &vIndex[0]); // // Fill A // CMatrix mA(crs.GetPlayers(), crs.GetPlayers() - 1); { double x = -1.0 / crs.GetPlayers(); for (int i = crs.GetPlayers() * (crs.GetPlayers() - 1); --i >= 0;) mA[i] = x; for (int i = crs.GetPlayers() - 1; --i >= 0;) mA.SetElement(i, i, 1.0 + x); } // // Compute AC // CMatrix mAC(crs.GetPlayers(), crs.GetPlayers() - 1); for (int i = crs.GetPlayers(); --i >= 0;) { int Index = i * (crs.GetPlayers() - 1); lud.Solve(mTruncatedHessian, &vIndex[0], mA + Index, mAC + Index); } // // Compute the covariance // mCovariance.SetProductByTranspose(mAC, mA); }