private static function calculateNewRating(GameInfo $gameInfo, Rating $selfRating, Rating $opponentRating, $comparison) { $drawMargin = DrawMargin::getDrawMarginFromDrawProbability($gameInfo->getDrawProbability(), $gameInfo->getBeta()); $c = sqrt(square($selfRating->getStandardDeviation()) + square($opponentRating->getStandardDeviation()) + 2 * square($gameInfo->getBeta())); $winningMean = $selfRating->getMean(); $losingMean = $opponentRating->getMean(); switch ($comparison) { case PairwiseComparison::WIN: case PairwiseComparison::DRAW: // NOP break; case PairwiseComparison::LOSE: $winningMean = $opponentRating->getMean(); $losingMean = $selfRating->getMean(); break; } $meanDelta = $winningMean - $losingMean; if ($comparison != PairwiseComparison::DRAW) { // non-draw case $v = TruncatedGaussianCorrectionFunctions::vExceedsMarginScaled($meanDelta, $drawMargin, $c); $w = TruncatedGaussianCorrectionFunctions::wExceedsMarginScaled($meanDelta, $drawMargin, $c); $rankMultiplier = (int) $comparison; } else { $v = TruncatedGaussianCorrectionFunctions::vWithinMarginScaled($meanDelta, $drawMargin, $c); $w = TruncatedGaussianCorrectionFunctions::wWithinMarginScaled($meanDelta, $drawMargin, $c); $rankMultiplier = 1; } $meanMultiplier = (square($selfRating->getStandardDeviation()) + square($gameInfo->getDynamicsFactor())) / $c; $varianceWithDynamics = square($selfRating->getStandardDeviation()) + square($gameInfo->getDynamicsFactor()); $stdDevMultiplier = $varianceWithDynamics / square($c); $newMean = $selfRating->getMean() + $rankMultiplier * $meanMultiplier * $v; $newStdDev = sqrt($varianceWithDynamics * (1 - $w * $stdDevMultiplier)); return new Rating($newMean, $newStdDev); }
protected function updateMessageVariable(Message &$message, Variable &$variable) { $oldMarginal = clone $variable->getValue(); $oldMessage = clone $message->getValue(); $messageFromVariable = GaussianDistribution::divide($oldMarginal, $oldMessage); $c = $messageFromVariable->getPrecision(); $d = $messageFromVariable->getPrecisionMean(); $sqrtC = sqrt($c); $dOnSqrtC = $d / $sqrtC; $epsilonTimesSqrtC = $this->_epsilon * $sqrtC; $d = $messageFromVariable->getPrecisionMean(); $denominator = 1.0 - TruncatedGaussianCorrectionFunctions::wWithinMargin($dOnSqrtC, $epsilonTimesSqrtC); $newPrecision = $c / $denominator; $newPrecisionMean = ($d + $sqrtC * TruncatedGaussianCorrectionFunctions::vWithinMargin($dOnSqrtC, $epsilonTimesSqrtC)) / $denominator; $newMarginal = GaussianDistribution::fromPrecisionMean($newPrecisionMean, $newPrecision); $newMessage = GaussianDistribution::divide(GaussianDistribution::multiply($oldMessage, $newMarginal), $oldMarginal); // Update the message and marginal $message->setValue($newMessage); $variable->setValue($newMarginal); // Return the difference in the new marginal return GaussianDistribution::subtract($newMarginal, $oldMarginal); }
private static function updatePlayerRatings(GameInfo $gameInfo, RatingContainer &$newPlayerRatings, Team $selfTeam, Team $otherTeam, $selfToOtherTeamComparison) { $drawMargin = DrawMargin::getDrawMarginFromDrawProbability($gameInfo->getDrawProbability(), $gameInfo->getBeta()); $betaSquared = square($gameInfo->getBeta()); $tauSquared = square($gameInfo->getDynamicsFactor()); $totalPlayers = $selfTeam->count() + $otherTeam->count(); $meanGetter = function ($currentRating) { return $currentRating->getMean(); }; $selfMeanSum = sum($selfTeam->getAllRatings(), $meanGetter); $otherTeamMeanSum = sum($otherTeam->getAllRatings(), $meanGetter); $varianceGetter = function ($currentRating) { return square($currentRating->getStandardDeviation()); }; $c = sqrt(sum($selfTeam->getAllRatings(), $varianceGetter) + sum($otherTeam->getAllRatings(), $varianceGetter) + $totalPlayers * $betaSquared); $winningMean = $selfMeanSum; $losingMean = $otherTeamMeanSum; switch ($selfToOtherTeamComparison) { case PairwiseComparison::WIN: case PairwiseComparison::DRAW: // NOP break; case PairwiseComparison::LOSE: $winningMean = $otherTeamMeanSum; $losingMean = $selfMeanSum; break; } $meanDelta = $winningMean - $losingMean; if ($selfToOtherTeamComparison != PairwiseComparison::DRAW) { // non-draw case $v = TruncatedGaussianCorrectionFunctions::vExceedsMarginScaled($meanDelta, $drawMargin, $c); $w = TruncatedGaussianCorrectionFunctions::wExceedsMarginScaled($meanDelta, $drawMargin, $c); $rankMultiplier = (int) $selfToOtherTeamComparison; } else { // assume draw $v = TruncatedGaussianCorrectionFunctions::vWithinMarginScaled($meanDelta, $drawMargin, $c); $w = TruncatedGaussianCorrectionFunctions::wWithinMarginScaled($meanDelta, $drawMargin, $c); $rankMultiplier = 1; } $selfTeamAllPlayers =& $selfTeam->getAllPlayers(); foreach ($selfTeamAllPlayers as &$selfTeamCurrentPlayer) { $localSelfTeamCurrentPlayer =& $selfTeamCurrentPlayer; $previousPlayerRating = $selfTeam->getRating($localSelfTeamCurrentPlayer); $meanMultiplier = (square($previousPlayerRating->getStandardDeviation()) + $tauSquared) / $c; $stdDevMultiplier = (square($previousPlayerRating->getStandardDeviation()) + $tauSquared) / square($c); $playerMeanDelta = $rankMultiplier * $meanMultiplier * $v; $newMean = $previousPlayerRating->getMean() + $playerMeanDelta; $newStdDev = sqrt((square($previousPlayerRating->getStandardDeviation()) + $tauSquared) * (1 - $w * $stdDevMultiplier)); $newPlayerRatings->setRating($localSelfTeamCurrentPlayer, new Rating($newMean, $newStdDev)); } }