protected function updateMessageVariable(Message $message, Variable $variable) { $oldMarginal = clone $variable->getValue(); $oldMessage = $message; $newMarginal = GaussianDistribution::fromPrecisionMean($oldMarginal->getPrecisionMean() + $this->_newMessage->getPrecisionMean() - $oldMessage->getValue()->getPrecisionMean(), $oldMarginal->getPrecision() + $this->_newMessage->getPrecision() - $oldMessage->getValue()->getPrecision()); $variable->setValue($newMarginal); $newMessage = $this->_newMessage; $message->setValue($newMessage); return GaussianDistribution::subtract($oldMarginal, $newMarginal); }
public function __construct(GameInfo &$gameInfo, array &$teams, array $teamRanks) { $this->_priorLayer = new PlayerPriorValuesToSkillsLayer($this, $teams); $this->_gameInfo = $gameInfo; $newFactory = new VariableFactory(function () { return GaussianDistribution::fromPrecisionMean(0, 0); }); $this->setVariableFactory($newFactory); $this->_layers = array($this->_priorLayer, new PlayerSkillsToPerformancesLayer($this), new PlayerPerformancesToTeamPerformancesLayer($this), new IteratedTeamDifferencesInnerLayer($this, new TeamPerformancesToTeamPerformanceDifferencesLayer($this), new TeamDifferencesComparisonLayer($this, $teamRanks))); }
public function testAbsoluteDifference() { // Verified with Ralf Herbrich's F# implementation $standardNormal = new GaussianDistribution(0, 1); $absDiff = GaussianDistribution::absoluteDifference($standardNormal, $standardNormal); $this->assertEquals(0.0, $absDiff, '', GaussianDistributionTest::ERROR_TOLERANCE); $m1s2 = new GaussianDistribution(1, 2); $m3s4 = new GaussianDistribution(3, 4); $absDiff2 = GaussianDistribution::absoluteDifference($m1s2, $m3s4); $this->assertEquals(0.4330127018922193, $absDiff2, '', GaussianDistributionTest::ERROR_TOLERANCE); }
public static function getDrawMarginFromDrawProbability($drawProbability, $beta) { // Derived from TrueSkill technical report (MSR-TR-2006-80), page 6 // draw probability = 2 * CDF(margin/(sqrt(n1+n2)*beta)) -1 // implies // // margin = inversecdf((draw probability + 1)/2) * sqrt(n1+n2) * beta // n1 and n2 are the number of players on each team $margin = GaussianDistribution::inverseCumulativeTo(0.5 * ($drawProbability + 1), 0, 1) * sqrt(1 + 1) * $beta; return $margin; }
private function updateHelper(Message $message1, Message $message2, Variable $variable1, Variable $variable2) { $message1Value = clone $message1->getValue(); $message2Value = clone $message2->getValue(); $marginal1 = clone $variable1->getValue(); $marginal2 = clone $variable2->getValue(); $a = $this->_precision / ($this->_precision + $marginal2->getPrecision() - $message2Value->getPrecision()); $newMessage = GaussianDistribution::fromPrecisionMean($a * ($marginal2->getPrecisionMean() - $message2Value->getPrecisionMean()), $a * ($marginal2->getPrecision() - $message2Value->getPrecision())); $oldMarginalWithoutMessage = GaussianDistribution::divide($marginal1, $message1Value); $newMarginal = GaussianDistribution::multiply($oldMarginalWithoutMessage, $newMessage); // Update the message and marginal $message1->setValue($newMessage); $variable1->setValue($newMarginal); // Return the difference in the new marginal return GaussianDistribution::subtract($newMarginal, $marginal1); }
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); }
public function createVariableToMessageBinding(Variable $variable) { $newDistribution = GaussianDistribution::fromPrecisionMean(0, 0); $binding = parent::createVariableToMessageBindingWithMessage($variable, new Message($newDistribution, sprintf("message from %s to %s", $this, $variable))); return $binding; }
public function getPlayerWinProbability(GameInfo $gameInfo, $playerRating, $opponentRating) { $ratingDifference = $playerRating - $opponentRating; // See equation 1.1 in the TrueSkill paper return GaussianDistribution::cumulativeTo($ratingDifference / (sqrt(2) * $gameInfo->getBeta())); }
private function updateHelper(array $weights, array $weightsSquared, array $messages, array $variables) { // Potentially look at http://mathworld.wolfram.com/NormalSumDistribution.html for clues as // to what it's doing $message0 = clone $messages[0]->getValue(); $marginal0 = clone $variables[0]->getValue(); // The math works out so that 1/newPrecision = sum of a_i^2 /marginalsWithoutMessages[i] $inverseOfNewPrecisionSum = 0.0; $anotherInverseOfNewPrecisionSum = 0.0; $weightedMeanSum = 0.0; $anotherWeightedMeanSum = 0.0; $weightsSquaredLength = count($weightsSquared); for ($i = 0; $i < $weightsSquaredLength; $i++) { // These flow directly from the paper $inverseOfNewPrecisionSum += $weightsSquared[$i] / ($variables[$i + 1]->getValue()->getPrecision() - $messages[$i + 1]->getValue()->getPrecision()); $diff = GaussianDistribution::divide($variables[$i + 1]->getValue(), $messages[$i + 1]->getValue()); $anotherInverseOfNewPrecisionSum += $weightsSquared[$i] / $diff->getPrecision(); $weightedMeanSum += $weights[$i] * ($variables[$i + 1]->getValue()->getPrecisionMean() - $messages[$i + 1]->getValue()->getPrecisionMean()) / ($variables[$i + 1]->getValue()->getPrecision() - $messages[$i + 1]->getValue()->getPrecision()); $anotherWeightedMeanSum += $weights[$i] * $diff->getPrecisionMean() / $diff->getPrecision(); } $newPrecision = 1.0 / $inverseOfNewPrecisionSum; $anotherNewPrecision = 1.0 / $anotherInverseOfNewPrecisionSum; $newPrecisionMean = $newPrecision * $weightedMeanSum; $anotherNewPrecisionMean = $anotherNewPrecision * $anotherWeightedMeanSum; $newMessage = GaussianDistribution::fromPrecisionMean($newPrecisionMean, $newPrecision); $oldMarginalWithoutMessage = GaussianDistribution::divide($marginal0, $message0); $newMarginal = GaussianDistribution::multiply($oldMarginalWithoutMessage, $newMessage); // Update the message and marginal $messages[0]->setValue($newMessage); $variables[0]->setValue($newMarginal); // Return the difference in the new marginal $finalDiff = GaussianDistribution::subtract($newMarginal, $marginal0); return $finalDiff; }
public static function wWithinMargin($teamPerformanceDifference, $drawMargin) { $teamPerformanceDifferenceAbsoluteValue = abs($teamPerformanceDifference); $denominator = GaussianDistribution::cumulativeTo($drawMargin - $teamPerformanceDifferenceAbsoluteValue) - GaussianDistribution::cumulativeTo(-$drawMargin - $teamPerformanceDifferenceAbsoluteValue); if ($denominator < 2.222758749E-162) { return 1.0; } $vt = self::vWithinMargin($teamPerformanceDifferenceAbsoluteValue, $drawMargin); return $vt * $vt + (($drawMargin - $teamPerformanceDifferenceAbsoluteValue) * GaussianDistribution::at($drawMargin - $teamPerformanceDifferenceAbsoluteValue) - (-$drawMargin - $teamPerformanceDifferenceAbsoluteValue) * GaussianDistribution::at(-$drawMargin - $teamPerformanceDifferenceAbsoluteValue)) / $denominator; }