Files
trueskill/src/TrueSkill/Factors/GaussianGreaterThanFactor.php

88 lines
2.7 KiB
PHP
Raw Normal View History

2022-07-05 15:55:47 +02:00
<?php
namespace DNW\Skills\TrueSkill\Factors;
2022-07-05 15:33:34 +02:00
use DNW\Skills\FactorGraphs\Message;
use DNW\Skills\FactorGraphs\Variable;
2022-07-05 15:55:47 +02:00
use DNW\Skills\Numerics\GaussianDistribution;
use DNW\Skills\TrueSkill\TruncatedGaussianCorrectionFunctions;
/**
* Factor representing a team difference that has exceeded the draw margin.
*
* See the accompanying math paper for more details.
*/
class GaussianGreaterThanFactor extends GaussianFactor
{
private $_epsilon;
public function __construct($epsilon, Variable $variable)
{
2022-07-05 15:55:47 +02:00
parent::__construct(\sprintf('%s > %.2f', $variable, $epsilon));
$this->_epsilon = $epsilon;
$this->createVariableToMessageBinding($variable);
}
public function getLogNormalization()
{
/** @var Variable[] $vars */
$vars = $this->getVariables();
$marginal = $vars[0]->getValue();
/** @var Message[] $messages */
$messages = $this->getMessages();
$message = $messages[0]->getValue();
$messageFromVariable = GaussianDistribution::divide($marginal, $message);
2022-07-05 15:55:47 +02:00
return -GaussianDistribution::logProductNormalization($messageFromVariable, $message)
+
log(
GaussianDistribution::cumulativeTo(
($messageFromVariable->getMean() - $this->_epsilon) /
$messageFromVariable->getStandardDeviation()
)
);
}
protected function updateMessageVariable(Message $message, Variable $variable)
{
$oldMarginal = clone $variable->getValue();
$oldMessage = clone $message->getValue();
$messageFromVar = GaussianDistribution::divide($oldMarginal, $oldMessage);
$c = $messageFromVar->getPrecision();
$d = $messageFromVar->getPrecisionMean();
$sqrtC = sqrt($c);
$dOnSqrtC = $d / $sqrtC;
$epsilsonTimesSqrtC = $this->_epsilon * $sqrtC;
$d = $messageFromVar->getPrecisionMean();
$denom = 1.0 - TruncatedGaussianCorrectionFunctions::wExceedsMargin($dOnSqrtC, $epsilsonTimesSqrtC);
$newPrecision = $c / $denom;
$newPrecisionMean = (
$d +
$sqrtC *
TruncatedGaussianCorrectionFunctions::vExceedsMargin($dOnSqrtC, $epsilsonTimesSqrtC)
) / $denom;
$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);
}
2022-07-05 15:55:47 +02:00
}