2022-07-05 15:55:47 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace DNW\Skills\TrueSkill;
|
2016-05-24 14:10:39 +02:00
|
|
|
|
2022-07-05 15:33:34 +02:00
|
|
|
use DNW\Skills\FactorGraphs\FactorGraph;
|
|
|
|
use DNW\Skills\FactorGraphs\FactorList;
|
|
|
|
use DNW\Skills\FactorGraphs\ScheduleSequence;
|
|
|
|
use DNW\Skills\FactorGraphs\VariableFactory;
|
2022-07-05 15:55:47 +02:00
|
|
|
use DNW\Skills\GameInfo;
|
|
|
|
use DNW\Skills\Numerics\GaussianDistribution;
|
|
|
|
use DNW\Skills\Rating;
|
|
|
|
use DNW\Skills\RatingContainer;
|
2022-07-05 15:33:34 +02:00
|
|
|
use DNW\Skills\TrueSkill\Layers\IteratedTeamDifferencesInnerLayer;
|
|
|
|
use DNW\Skills\TrueSkill\Layers\PlayerPerformancesToTeamPerformancesLayer;
|
|
|
|
use DNW\Skills\TrueSkill\Layers\PlayerPriorValuesToSkillsLayer;
|
|
|
|
use DNW\Skills\TrueSkill\Layers\PlayerSkillsToPerformancesLayer;
|
|
|
|
use DNW\Skills\TrueSkill\Layers\TeamDifferencesComparisonLayer;
|
|
|
|
use DNW\Skills\TrueSkill\Layers\TeamPerformancesToTeamPerformanceDifferencesLayer;
|
2010-09-18 17:56:57 -04:00
|
|
|
|
|
|
|
class TrueSkillFactorGraph extends FactorGraph
|
|
|
|
{
|
|
|
|
private $_layers;
|
2022-07-05 15:55:47 +02:00
|
|
|
|
2016-05-24 14:10:39 +02:00
|
|
|
private $_priorLayer;
|
2010-09-18 17:56:57 -04:00
|
|
|
|
2022-07-05 16:21:06 +02:00
|
|
|
public function __construct(private readonly GameInfo $_gameInfo, array $teams, array $teamRanks)
|
2010-09-18 17:56:57 -04:00
|
|
|
{
|
|
|
|
$this->_priorLayer = new PlayerPriorValuesToSkillsLayer($this, $teams);
|
2010-09-25 15:46:23 -04:00
|
|
|
$newFactory = new VariableFactory(
|
2022-07-05 16:32:18 +02:00
|
|
|
fn () => GaussianDistribution::fromPrecisionMean(0, 0));
|
2016-05-24 14:10:39 +02:00
|
|
|
|
2010-09-25 15:46:23 -04:00
|
|
|
$this->setVariableFactory($newFactory);
|
2022-07-05 15:55:47 +02:00
|
|
|
$this->_layers = [
|
2016-05-24 14:10:39 +02:00
|
|
|
$this->_priorLayer,
|
|
|
|
new PlayerSkillsToPerformancesLayer($this),
|
|
|
|
new PlayerPerformancesToTeamPerformancesLayer($this),
|
|
|
|
new IteratedTeamDifferencesInnerLayer(
|
|
|
|
$this,
|
|
|
|
new TeamPerformancesToTeamPerformanceDifferencesLayer($this),
|
2022-07-05 15:55:47 +02:00
|
|
|
new TeamDifferencesComparisonLayer($this, $teamRanks)),
|
|
|
|
];
|
2010-09-18 17:56:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
public function getGameInfo()
|
|
|
|
{
|
|
|
|
return $this->_gameInfo;
|
|
|
|
}
|
|
|
|
|
2023-08-01 12:43:58 +00:00
|
|
|
public function buildGraph(): void
|
2010-09-18 17:56:57 -04:00
|
|
|
{
|
|
|
|
$lastOutput = null;
|
|
|
|
|
2016-05-24 16:31:21 +02:00
|
|
|
$layers = $this->_layers;
|
|
|
|
foreach ($layers as $currentLayer) {
|
2016-05-24 14:10:39 +02:00
|
|
|
if ($lastOutput != null) {
|
2010-09-18 17:56:57 -04:00
|
|
|
$currentLayer->setInputVariablesGroups($lastOutput);
|
|
|
|
}
|
|
|
|
|
|
|
|
$currentLayer->buildLayer();
|
|
|
|
|
2016-05-24 16:31:21 +02:00
|
|
|
$lastOutput = $currentLayer->getOutputVariablesGroups();
|
2010-09-18 17:56:57 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-01 12:43:58 +00:00
|
|
|
public function runSchedule(): void
|
2010-09-18 17:56:57 -04:00
|
|
|
{
|
|
|
|
$fullSchedule = $this->createFullSchedule();
|
2022-07-05 16:21:06 +02:00
|
|
|
$fullSchedule->visit();
|
2010-09-18 17:56:57 -04:00
|
|
|
}
|
|
|
|
|
2023-08-01 12:43:58 +00:00
|
|
|
public function getProbabilityOfRanking(): float
|
2010-09-18 17:56:57 -04:00
|
|
|
{
|
|
|
|
$factorList = new FactorList();
|
|
|
|
|
2016-05-24 16:31:21 +02:00
|
|
|
$layers = $this->_layers;
|
|
|
|
foreach ($layers as $currentLayer) {
|
|
|
|
$localFactors = $currentLayer->getLocalFactors();
|
|
|
|
foreach ($localFactors as $currentFactor) {
|
|
|
|
$localCurrentFactor = $currentFactor;
|
2010-10-02 21:15:47 -04:00
|
|
|
$factorList->addFactor($localCurrentFactor);
|
2010-09-18 17:56:57 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$logZ = $factorList->getLogNormalization();
|
2022-07-05 15:55:47 +02:00
|
|
|
|
2010-09-18 17:56:57 -04:00
|
|
|
return exp($logZ);
|
|
|
|
}
|
|
|
|
|
2023-08-01 12:43:58 +00:00
|
|
|
private function createFullSchedule(): ScheduleSequence
|
2010-09-18 17:56:57 -04:00
|
|
|
{
|
2022-07-05 15:55:47 +02:00
|
|
|
$fullSchedule = [];
|
2010-09-18 17:56:57 -04:00
|
|
|
|
2016-05-24 16:31:21 +02:00
|
|
|
$layers = $this->_layers;
|
|
|
|
foreach ($layers as $currentLayer) {
|
2010-09-28 08:12:06 -04:00
|
|
|
$currentPriorSchedule = $currentLayer->createPriorSchedule();
|
2016-05-24 14:10:39 +02:00
|
|
|
if ($currentPriorSchedule != null) {
|
2010-09-28 08:12:06 -04:00
|
|
|
$fullSchedule[] = $currentPriorSchedule;
|
2010-09-18 17:56:57 -04:00
|
|
|
}
|
|
|
|
}
|
2016-05-24 14:10:39 +02:00
|
|
|
|
2016-05-24 16:31:21 +02:00
|
|
|
$allLayersReverse = array_reverse($this->_layers);
|
2010-09-18 17:56:57 -04:00
|
|
|
|
2016-05-24 16:31:21 +02:00
|
|
|
foreach ($allLayersReverse as $currentLayer) {
|
2010-09-18 17:56:57 -04:00
|
|
|
$currentPosteriorSchedule = $currentLayer->createPosteriorSchedule();
|
2016-05-24 14:10:39 +02:00
|
|
|
if ($currentPosteriorSchedule != null) {
|
2010-09-25 12:50:33 -04:00
|
|
|
$fullSchedule[] = $currentPosteriorSchedule;
|
2010-09-18 17:56:57 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-05 15:55:47 +02:00
|
|
|
return new ScheduleSequence('Full schedule', $fullSchedule);
|
2010-09-18 17:56:57 -04:00
|
|
|
}
|
|
|
|
|
2023-08-01 12:13:24 +00:00
|
|
|
public function getUpdatedRatings(): RatingContainer
|
2010-09-18 17:56:57 -04:00
|
|
|
{
|
2010-09-28 22:40:54 -04:00
|
|
|
$result = new RatingContainer();
|
2010-09-18 17:56:57 -04:00
|
|
|
|
2016-05-24 16:31:21 +02:00
|
|
|
$priorLayerOutputVariablesGroups = $this->_priorLayer->getOutputVariablesGroups();
|
|
|
|
foreach ($priorLayerOutputVariablesGroups as $currentTeam) {
|
|
|
|
foreach ($currentTeam as $currentPlayer) {
|
|
|
|
$localCurrentPlayer = $currentPlayer->getKey();
|
2010-09-28 22:40:54 -04:00
|
|
|
$newRating = new Rating($currentPlayer->getValue()->getMean(),
|
2016-05-24 14:10:39 +02:00
|
|
|
$currentPlayer->getValue()->getStandardDeviation());
|
2010-09-28 22:40:54 -04:00
|
|
|
|
2010-10-02 21:15:47 -04:00
|
|
|
$result->setRating($localCurrentPlayer, $newRating);
|
2010-09-18 17:56:57 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
2022-07-05 15:55:47 +02:00
|
|
|
}
|