mirror of
https://github.com/furyfire/trueskill.git
synced 2025-01-16 01:47:39 +00:00
General cleanup and removal of all unnecessary references
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
|
coverage
|
||||||
nbproject
|
nbproject
|
||||||
.idea
|
.idea
|
||||||
vendor
|
vendor
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?php namespace Moserware\Skills\Elo;
|
<?php namespace Moserware\Skills\Elo;
|
||||||
|
|
||||||
|
use Moserware\Skills\GameInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Including Elo's scheme as a simple comparison.
|
* Including Elo's scheme as a simple comparison.
|
||||||
* See http://en.wikipedia.org/wiki/Elo_rating_system#Theory
|
* See http://en.wikipedia.org/wiki/Elo_rating_system#Theory
|
||||||
@ -22,7 +24,7 @@ class FideEloCalculator extends TwoPlayerEloCalculator
|
|||||||
return new FideEloCalculator(new ProvisionalFideKFactor());
|
return new FideEloCalculator(new ProvisionalFideKFactor());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPlayerWinProbability($gameInfo, $playerRating, $opponentRating)
|
public function getPlayerWinProbability(GameInfo $gameInfo, $playerRating, $opponentRating)
|
||||||
{
|
{
|
||||||
$ratingDifference = $opponentRating - $playerRating;
|
$ratingDifference = $opponentRating - $playerRating;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php namespace Moserware\Skills\Elo;
|
<?php namespace Moserware\Skills\Elo;
|
||||||
|
|
||||||
use Moserware\Skills\GameInfo;
|
use Moserware\Skills\GameInfo;
|
||||||
use Moserware\Numerics\GaussianDistribution;
|
use Moserware\Skills\Numerics\GaussianDistribution;
|
||||||
|
|
||||||
class GaussianEloCalculator extends TwoPlayerEloCalculator
|
class GaussianEloCalculator extends TwoPlayerEloCalculator
|
||||||
{
|
{
|
||||||
@ -21,6 +21,7 @@ class GaussianEloCalculator extends TwoPlayerEloCalculator
|
|||||||
return GaussianDistribution::cumulativeTo(
|
return GaussianDistribution::cumulativeTo(
|
||||||
$ratingDifference
|
$ratingDifference
|
||||||
/
|
/
|
||||||
(sqrt(2) * $gameInfo->getBeta()));
|
(sqrt(2) * $gameInfo->getBeta())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,7 +6,6 @@ use Moserware\Skills\PairwiseComparison;
|
|||||||
use Moserware\Skills\RankSorter;
|
use Moserware\Skills\RankSorter;
|
||||||
use Moserware\Skills\SkillCalculator;
|
use Moserware\Skills\SkillCalculator;
|
||||||
use Moserware\Skills\SkillCalculatorSupportedOptions;
|
use Moserware\Skills\SkillCalculatorSupportedOptions;
|
||||||
|
|
||||||
use Moserware\Skills\PlayersRange;
|
use Moserware\Skills\PlayersRange;
|
||||||
use Moserware\Skills\TeamsRange;
|
use Moserware\Skills\TeamsRange;
|
||||||
|
|
||||||
@ -20,10 +19,8 @@ abstract class TwoPlayerEloCalculator extends SkillCalculator
|
|||||||
$this->_kFactor = $kFactor;
|
$this->_kFactor = $kFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function calculateNewRatings(GameInfo $gameInfo,
|
public function calculateNewRatings(GameInfo $gameInfo, array $teamsOfPlayerToRatings, array $teamRanks)
|
||||||
array $teamsOfPlayerToRatings,
|
{
|
||||||
array $teamRanks)
|
|
||||||
{
|
|
||||||
$this->validateTeamCountAndPlayersCountPerTeam($teamsOfPlayerToRatings);
|
$this->validateTeamCountAndPlayersCountPerTeam($teamsOfPlayerToRatings);
|
||||||
RankSorter::sort($teamsOfPlayerToRatings, $teamRanks);
|
RankSorter::sort($teamsOfPlayerToRatings, $teamRanks);
|
||||||
|
|
||||||
@ -71,9 +68,9 @@ abstract class TwoPlayerEloCalculator extends SkillCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract function getPlayerWinProbability($gameInfo, $playerRating, $opponentRating);
|
public abstract function getPlayerWinProbability(GameInfo $gameInfo, $playerRating, $opponentRating);
|
||||||
|
|
||||||
public function calculateMatchQuality(GameInfo $gameInfo, array &$teamsOfPlayerToRatings)
|
public function calculateMatchQuality(GameInfo $gameInfo, array $teamsOfPlayerToRatings)
|
||||||
{
|
{
|
||||||
$this->validateTeamCountAndPlayersCountPerTeam($teamsOfPlayerToRatings);
|
$this->validateTeamCountAndPlayersCountPerTeam($teamsOfPlayerToRatings);
|
||||||
$team1 = $teamsOfPlayerToRatings[0];
|
$team1 = $teamsOfPlayerToRatings[0];
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
|
// XXX: This class is not used anywhere
|
||||||
class DefaultVariable extends Variable
|
class DefaultVariable extends Variable
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
@ -9,12 +10,12 @@ class DefaultVariable extends Variable
|
|||||||
parent::__construct("Default", null);
|
parent::__construct("Default", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &getValue()
|
public function getValue()
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setValue(&$value)
|
public function setValue($value)
|
||||||
{
|
{
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
|
@ -34,24 +34,26 @@ abstract class Factor
|
|||||||
return count($this->_messages);
|
return count($this->_messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function &getVariables()
|
protected function getVariables()
|
||||||
{
|
{
|
||||||
return $this->_variables;
|
return $this->_variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function &getMessages()
|
protected function getMessages()
|
||||||
{
|
{
|
||||||
return $this->_messages;
|
return $this->_messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the message and marginal of the i-th variable that the factor is connected to
|
* Update the message and marginal of the i-th variable that the factor is connected to
|
||||||
|
* @param $messageIndex
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function updateMessageIndex($messageIndex)
|
public function updateMessageIndex($messageIndex)
|
||||||
{
|
{
|
||||||
Guard::argumentIsValidIndex($messageIndex, count($this->_messages), "messageIndex");
|
Guard::argumentIsValidIndex($messageIndex, count($this->_messages), "messageIndex");
|
||||||
$message = &$this->_messages[$messageIndex];
|
$message = $this->_messages[$messageIndex];
|
||||||
$variable = &$this->_messageToVariableBinding->getValue($message);
|
$variable = $this->_messageToVariableBinding->getValue($message);
|
||||||
return $this->updateMessageVariable($message, $variable);
|
return $this->updateMessageVariable($message, $variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,41 +67,41 @@ abstract class Factor
|
|||||||
*/
|
*/
|
||||||
public function resetMarginals()
|
public function resetMarginals()
|
||||||
{
|
{
|
||||||
$allValues = &$this->_messageToVariableBinding->getAllValues();
|
$allValues = $this->_messageToVariableBinding->getAllValues();
|
||||||
foreach ($allValues as &$currentVariable) {
|
foreach ($allValues as $currentVariable) {
|
||||||
$currentVariable->resetToPrior();
|
$currentVariable->resetToPrior();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the ith message to the marginal and returns the log-normalization constant
|
* Sends the ith message to the marginal and returns the log-normalization constant
|
||||||
|
* @param $messageIndex
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function sendMessageIndex($messageIndex)
|
public function sendMessageIndex($messageIndex)
|
||||||
{
|
{
|
||||||
Guard::argumentIsValidIndex($messageIndex, count($this->_messages), "messageIndex");
|
Guard::argumentIsValidIndex($messageIndex, count($this->_messages), "messageIndex");
|
||||||
|
|
||||||
$message = &$this->_messages[$messageIndex];
|
$message = $this->_messages[$messageIndex];
|
||||||
$variable = &$this->_messageToVariableBinding->getValue($message);
|
$variable = $this->_messageToVariableBinding->getValue($message);
|
||||||
return $this->sendMessageVariable($message, $variable);
|
return $this->sendMessageVariable($message, $variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract function sendMessageVariable(Message &$message, Variable &$variable);
|
protected abstract function sendMessageVariable(Message $message, Variable $variable);
|
||||||
|
|
||||||
public abstract function &createVariableToMessageBinding(Variable &$variable);
|
public abstract function createVariableToMessageBinding(Variable $variable);
|
||||||
|
|
||||||
protected function &createVariableToMessageBindingWithMessage(Variable &$variable, Message &$message)
|
protected function createVariableToMessageBindingWithMessage(Variable $variable, Message $message)
|
||||||
{
|
{
|
||||||
$index = count($this->_messages);
|
|
||||||
$localMessages = &$this->_messages;
|
|
||||||
$localMessages[] = &$message;
|
|
||||||
$this->_messageToVariableBinding->setValue($message, $variable);
|
$this->_messageToVariableBinding->setValue($message, $variable);
|
||||||
$localVariables = &$this->_variables;
|
$this->_messages[] = $message;
|
||||||
$localVariables[] = &$variable;
|
$this->_variables[] = $variable;
|
||||||
return $message;
|
return $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
return ($this->_name != null) ? $this->_name : base::__toString();
|
return ($this->_name != null) ? $this->_name : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,14 +4,13 @@ class FactorGraph
|
|||||||
{
|
{
|
||||||
private $_variableFactory;
|
private $_variableFactory;
|
||||||
|
|
||||||
public function &getVariableFactory()
|
public function getVariableFactory()
|
||||||
{
|
{
|
||||||
$factory = &$this->_variableFactory;
|
return $this->_variableFactory;
|
||||||
return $factory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setVariableFactory(VariableFactory &$factory)
|
public function setVariableFactory(VariableFactory $factory)
|
||||||
{
|
{
|
||||||
$this->_variableFactory = &$factory;
|
$this->_variableFactory = $factory;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
<?php namespace Moserware\Skills\FactorGraphs;
|
<?php namespace Moserware\Skills\FactorGraphs;
|
||||||
|
// edit this
|
||||||
abstract class FactorGraphLayer
|
abstract class FactorGraphLayer
|
||||||
{
|
{
|
||||||
private $_localFactors = array();
|
private $_localFactors = array();
|
||||||
@ -7,38 +7,39 @@ abstract class FactorGraphLayer
|
|||||||
private $_inputVariablesGroups = array();
|
private $_inputVariablesGroups = array();
|
||||||
private $_parentFactorGraph;
|
private $_parentFactorGraph;
|
||||||
|
|
||||||
protected function __construct(FactorGraph &$parentGraph)
|
protected function __construct(FactorGraph $parentGraph)
|
||||||
{
|
{
|
||||||
$this->_parentFactorGraph = &$parentGraph;
|
$this->_parentFactorGraph = $parentGraph;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function &getInputVariablesGroups()
|
protected function getInputVariablesGroups()
|
||||||
{
|
{
|
||||||
$inputVariablesGroups = &$this->_inputVariablesGroups;
|
return $this->_inputVariablesGroups;
|
||||||
return $inputVariablesGroups;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK
|
// HACK
|
||||||
|
|
||||||
public function &getParentFactorGraph()
|
public function getParentFactorGraph()
|
||||||
{
|
{
|
||||||
$parentFactorGraph = &$this->_parentFactorGraph;
|
return $this->_parentFactorGraph;
|
||||||
return $parentFactorGraph;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This reference is still needed
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function &getOutputVariablesGroups()
|
public function &getOutputVariablesGroups()
|
||||||
{
|
{
|
||||||
$outputVariablesGroups = &$this->_outputVariablesGroups;
|
return $this->_outputVariablesGroups;
|
||||||
return $outputVariablesGroups;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &getLocalFactors()
|
public function getLocalFactors()
|
||||||
{
|
{
|
||||||
$localFactors = &$this->_localFactors;
|
return $this->_localFactors;
|
||||||
return $localFactors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setInputVariablesGroups(&$value)
|
public function setInputVariablesGroups($value)
|
||||||
{
|
{
|
||||||
$this->_inputVariablesGroups = $value;
|
$this->_inputVariablesGroups = $value;
|
||||||
}
|
}
|
||||||
@ -48,7 +49,7 @@ abstract class FactorGraphLayer
|
|||||||
return new ScheduleSequence($name, $itemsToSequence);
|
return new ScheduleSequence($name, $itemsToSequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function addLayerFactor(Factor &$factor)
|
protected function addLayerFactor(Factor $factor)
|
||||||
{
|
{
|
||||||
$this->_localFactors[] = $factor;
|
$this->_localFactors[] = $factor;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ class FactorList
|
|||||||
|
|
||||||
public function getLogNormalization()
|
public function getLogNormalization()
|
||||||
{
|
{
|
||||||
$list = &$this->_list;
|
$list = $this->_list;
|
||||||
foreach ($list as &$currentFactor) {
|
foreach ($list as &$currentFactor) {
|
||||||
$currentFactor->resetMarginals();
|
$currentFactor->resetMarginals();
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ class FactorList
|
|||||||
return count($this->_list);
|
return count($this->_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &addFactor(Factor &$factor)
|
public function addFactor(Factor $factor)
|
||||||
{
|
{
|
||||||
$this->_list[] = $factor;
|
$this->_list[] = $factor;
|
||||||
return $factor;
|
return $factor;
|
||||||
|
@ -4,15 +4,14 @@ class KeyedVariable extends Variable
|
|||||||
{
|
{
|
||||||
private $_key;
|
private $_key;
|
||||||
|
|
||||||
public function __construct(&$key, $name, &$prior)
|
public function __construct($key, $name, $prior)
|
||||||
{
|
{
|
||||||
parent::__construct($name, $prior);
|
parent::__construct($name, $prior);
|
||||||
$this->_key = &$key;
|
$this->_key = $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &getKey()
|
public function getKey()
|
||||||
{
|
{
|
||||||
$key = &$this->_key;
|
return $this->_key;
|
||||||
return $key;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,21 +5,20 @@ class Message
|
|||||||
private $_name;
|
private $_name;
|
||||||
private $_value;
|
private $_value;
|
||||||
|
|
||||||
public function __construct(&$value = null, $name = null)
|
public function __construct($value = null, $name = null)
|
||||||
{
|
{
|
||||||
$this->_name = $name;
|
$this->_name = $name;
|
||||||
$this->_value = $value;
|
$this->_value = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function& getValue()
|
public function getValue()
|
||||||
{
|
{
|
||||||
$value = &$this->_value;
|
return $this->_value;
|
||||||
return $value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setValue(&$value)
|
public function setValue($value)
|
||||||
{
|
{
|
||||||
$this->_value = &$value;
|
$this->_value = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __toString()
|
public function __toString()
|
||||||
|
@ -5,7 +5,7 @@ class ScheduleLoop extends Schedule
|
|||||||
private $_maxDelta;
|
private $_maxDelta;
|
||||||
private $_scheduleToLoop;
|
private $_scheduleToLoop;
|
||||||
|
|
||||||
public function __construct($name, Schedule &$scheduleToLoop, $maxDelta)
|
public function __construct($name, Schedule $scheduleToLoop, $maxDelta)
|
||||||
{
|
{
|
||||||
parent::__construct($name);
|
parent::__construct($name);
|
||||||
$this->_scheduleToLoop = $scheduleToLoop;
|
$this->_scheduleToLoop = $scheduleToLoop;
|
||||||
|
@ -14,8 +14,8 @@ class ScheduleSequence extends Schedule
|
|||||||
{
|
{
|
||||||
$maxDelta = 0;
|
$maxDelta = 0;
|
||||||
|
|
||||||
$schedules = &$this->_schedules;
|
$schedules = $this->_schedules;
|
||||||
foreach ($schedules as &$currentSchedule) {
|
foreach ($schedules as $currentSchedule) {
|
||||||
$currentVisit = $currentSchedule->visit($depth + 1, $maxDepth);
|
$currentVisit = $currentSchedule->visit($depth + 1, $maxDepth);
|
||||||
$maxDelta = max($currentVisit, $maxDelta);
|
$maxDelta = max($currentVisit, $maxDelta);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ class ScheduleStep extends Schedule
|
|||||||
private $_factor;
|
private $_factor;
|
||||||
private $_index;
|
private $_index;
|
||||||
|
|
||||||
public function __construct($name, Factor &$factor, $index)
|
public function __construct($name, Factor $factor, $index)
|
||||||
{
|
{
|
||||||
parent::__construct($name);
|
parent::__construct($name);
|
||||||
$this->_factor = $factor;
|
$this->_factor = $factor;
|
||||||
@ -14,7 +14,7 @@ class ScheduleStep extends Schedule
|
|||||||
|
|
||||||
public function visit($depth = -1, $maxDepth = 0)
|
public function visit($depth = -1, $maxDepth = 0)
|
||||||
{
|
{
|
||||||
$currentFactor = &$this->_factor;
|
$currentFactor = $this->_factor;
|
||||||
$delta = $currentFactor->updateMessageIndex($this->_index);
|
$delta = $currentFactor->updateMessageIndex($this->_index);
|
||||||
return $delta;
|
return $delta;
|
||||||
}
|
}
|
||||||
|
@ -7,22 +7,21 @@ class Variable
|
|||||||
private $_prior;
|
private $_prior;
|
||||||
private $_value;
|
private $_value;
|
||||||
|
|
||||||
public function __construct($name, &$prior)
|
public function __construct($name, $prior)
|
||||||
{
|
{
|
||||||
$this->_name = "Variable[" . $name . "]";
|
$this->_name = "Variable[" . $name . "]";
|
||||||
$this->_prior = $prior;
|
$this->_prior = $prior;
|
||||||
$this->resetToPrior();
|
$this->resetToPrior();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &getValue()
|
public function getValue()
|
||||||
{
|
{
|
||||||
$value = &$this->_value;
|
return $this->_value;
|
||||||
return $value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setValue(&$value)
|
public function setValue($value)
|
||||||
{
|
{
|
||||||
$this->_value = &$value;
|
$this->_value = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resetToPrior()
|
public function resetToPrior()
|
||||||
|
@ -7,17 +7,17 @@ class VariableFactory
|
|||||||
|
|
||||||
public function __construct($variablePriorInitializer)
|
public function __construct($variablePriorInitializer)
|
||||||
{
|
{
|
||||||
$this->_variablePriorInitializer = &$variablePriorInitializer;
|
$this->_variablePriorInitializer = $variablePriorInitializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &createBasicVariable($name)
|
public function createBasicVariable($name)
|
||||||
{
|
{
|
||||||
$initializer = $this->_variablePriorInitializer;
|
$initializer = $this->_variablePriorInitializer;
|
||||||
$newVar = new Variable($name, $initializer());
|
$newVar = new Variable($name, $initializer());
|
||||||
return $newVar;
|
return $newVar;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &createKeyedVariable(&$key, $name)
|
public function createKeyedVariable($key, $name)
|
||||||
{
|
{
|
||||||
$initializer = $this->_variablePriorInitializer;
|
$initializer = $this->_variablePriorInitializer;
|
||||||
$newVar = new KeyedVariable($key, $name, $initializer());
|
$newVar = new KeyedVariable($key, $name, $initializer());
|
||||||
|
@ -8,30 +8,30 @@ class HashMap
|
|||||||
private $_hashToValue = array();
|
private $_hashToValue = array();
|
||||||
private $_hashToKey = array();
|
private $_hashToKey = array();
|
||||||
|
|
||||||
public function &getValue(&$key)
|
public function getValue($key)
|
||||||
{
|
{
|
||||||
$hash = self::getHash($key);
|
$hash = self::getHash($key);
|
||||||
$hashValue = &$this->_hashToValue[$hash];
|
$hashValue = $this->_hashToValue[$hash];
|
||||||
return $hashValue;
|
return $hashValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setValue(&$key, &$value)
|
public function setValue($key, $value)
|
||||||
{
|
{
|
||||||
$hash = self::getHash($key);
|
$hash = self::getHash($key);
|
||||||
$this->_hashToKey[$hash] = &$key;
|
$this->_hashToKey[$hash] = $key;
|
||||||
$this->_hashToValue[$hash] = &$value;
|
$this->_hashToValue[$hash] = $value;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &getAllKeys()
|
public function getAllKeys()
|
||||||
{
|
{
|
||||||
$keys = &array_values($this->_hashToKey);
|
$keys = array_values($this->_hashToKey);
|
||||||
return $keys;
|
return $keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAllValues()
|
public function getAllValues()
|
||||||
{
|
{
|
||||||
$values = &array_values($this->_hashToValue);
|
$values = array_values($this->_hashToValue);
|
||||||
return $values;
|
return $values;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ class HashMap
|
|||||||
return count($this->_hashToKey);
|
return count($this->_hashToKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getHash(&$key)
|
private static function getHash($key)
|
||||||
{
|
{
|
||||||
if (is_object($key)) {
|
if (is_object($key)) {
|
||||||
return spl_object_hash($key);
|
return spl_object_hash($key);
|
||||||
|
@ -109,7 +109,8 @@ class GaussianDistribution
|
|||||||
{
|
{
|
||||||
return max(
|
return max(
|
||||||
abs($left->_precisionMean - $right->_precisionMean),
|
abs($left->_precisionMean - $right->_precisionMean),
|
||||||
sqrt(abs($left->_precision - $right->_precision)));
|
sqrt(abs($left->_precision - $right->_precision))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computes the absolute difference between two Gaussians
|
// Computes the absolute difference between two Gaussians
|
||||||
@ -133,8 +134,10 @@ class GaussianDistribution
|
|||||||
|
|
||||||
public static function divide(GaussianDistribution $numerator, GaussianDistribution $denominator)
|
public static function divide(GaussianDistribution $numerator, GaussianDistribution $denominator)
|
||||||
{
|
{
|
||||||
return GaussianDistribution::fromPrecisionMean($numerator->_precisionMean - $denominator->_precisionMean,
|
return GaussianDistribution::fromPrecisionMean(
|
||||||
$numerator->_precision - $denominator->_precision);
|
$numerator->_precisionMean - $denominator->_precisionMean,
|
||||||
|
$numerator->_precision - $denominator->_precision
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function logRatioNormalization(GaussianDistribution $numerator, GaussianDistribution $denominator)
|
public static function logRatioNormalization(GaussianDistribution $numerator, GaussianDistribution $denominator)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?php namespace Moserware\Skills\Numerics;
|
<?php namespace Moserware\Skills\Numerics;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
class Matrix
|
class Matrix
|
||||||
{
|
{
|
||||||
const ERROR_TOLERANCE = 0.0000000001;
|
const ERROR_TOLERANCE = 0.0000000001;
|
||||||
@ -20,12 +22,10 @@ class Matrix
|
|||||||
$data = array();
|
$data = array();
|
||||||
$result = new Matrix($rows, $columns, $data);
|
$result = new Matrix($rows, $columns, $data);
|
||||||
|
|
||||||
for($currentColumn = 0; $currentColumn < $columns; $currentColumn++)
|
for ($currentColumn = 0; $currentColumn < $columns; $currentColumn++) {
|
||||||
{
|
|
||||||
$currentColumnData = $columnValues[$currentColumn];
|
$currentColumnData = $columnValues[$currentColumn];
|
||||||
|
|
||||||
for($currentRow = 0; $currentRow < $rows; $currentRow++)
|
for ($currentRow = 0; $currentRow < $rows; $currentRow++) {
|
||||||
{
|
|
||||||
$result->setValue($currentRow, $currentColumn, $currentColumnData[$currentRow]);
|
$result->setValue($currentRow, $currentColumn, $currentColumnData[$currentRow]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,10 +41,8 @@ class Matrix
|
|||||||
$result = new Matrix($rows, $cols);
|
$result = new Matrix($rows, $cols);
|
||||||
$currentIndex = 2;
|
$currentIndex = 2;
|
||||||
|
|
||||||
for($currentRow = 0; $currentRow < $rows; $currentRow++)
|
for ($currentRow = 0; $currentRow < $rows; $currentRow++) {
|
||||||
{
|
for ($currentCol = 0; $currentCol < $cols; $currentCol++) {
|
||||||
for($currentCol = 0; $currentCol < $cols; $currentCol++)
|
|
||||||
{
|
|
||||||
$result->setValue($currentRow, $currentCol, $args[$currentIndex++]);
|
$result->setValue($currentRow, $currentCol, $args[$currentIndex++]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,12 +78,10 @@ class Matrix
|
|||||||
$rowMatrixData = $this->_matrixRowData;
|
$rowMatrixData = $this->_matrixRowData;
|
||||||
for ($currentRowTransposeMatrix = 0;
|
for ($currentRowTransposeMatrix = 0;
|
||||||
$currentRowTransposeMatrix < $this->_columnCount;
|
$currentRowTransposeMatrix < $this->_columnCount;
|
||||||
$currentRowTransposeMatrix++)
|
$currentRowTransposeMatrix++) {
|
||||||
{
|
|
||||||
for ($currentColumnTransposeMatrix = 0;
|
for ($currentColumnTransposeMatrix = 0;
|
||||||
$currentColumnTransposeMatrix < $this->_rowCount;
|
$currentColumnTransposeMatrix < $this->_rowCount;
|
||||||
$currentColumnTransposeMatrix++)
|
$currentColumnTransposeMatrix++) {
|
||||||
{
|
|
||||||
$transposeMatrix[$currentRowTransposeMatrix][$currentColumnTransposeMatrix] =
|
$transposeMatrix[$currentRowTransposeMatrix][$currentColumnTransposeMatrix] =
|
||||||
$rowMatrixData[$currentColumnTransposeMatrix][$currentRowTransposeMatrix];
|
$rowMatrixData[$currentColumnTransposeMatrix][$currentRowTransposeMatrix];
|
||||||
}
|
}
|
||||||
@ -102,19 +98,16 @@ class Matrix
|
|||||||
public function getDeterminant()
|
public function getDeterminant()
|
||||||
{
|
{
|
||||||
// Basic argument checking
|
// Basic argument checking
|
||||||
if (!$this->isSquare())
|
if (!$this->isSquare()) {
|
||||||
{
|
|
||||||
throw new Exception("Matrix must be square!");
|
throw new Exception("Matrix must be square!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->_rowCount == 1)
|
if ($this->_rowCount == 1) {
|
||||||
{
|
|
||||||
// Really happy path :)
|
// Really happy path :)
|
||||||
return $this->_matrixRowData[0][0];
|
return $this->_matrixRowData[0][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->_rowCount == 2)
|
if ($this->_rowCount == 2) {
|
||||||
{
|
|
||||||
// Happy path!
|
// Happy path!
|
||||||
// Given:
|
// Given:
|
||||||
// | a b |
|
// | a b |
|
||||||
@ -124,7 +117,7 @@ class Matrix
|
|||||||
$b = $this->_matrixRowData[0][1];
|
$b = $this->_matrixRowData[0][1];
|
||||||
$c = $this->_matrixRowData[1][0];
|
$c = $this->_matrixRowData[1][0];
|
||||||
$d = $this->_matrixRowData[1][1];
|
$d = $this->_matrixRowData[1][1];
|
||||||
return $a*$d - $b*$c;
|
return $a * $d - $b * $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
// I use the Laplace expansion here since it's straightforward to implement.
|
// I use the Laplace expansion here since it's straightforward to implement.
|
||||||
@ -136,11 +129,10 @@ class Matrix
|
|||||||
$result = 0.0;
|
$result = 0.0;
|
||||||
|
|
||||||
// I expand along the first row
|
// I expand along the first row
|
||||||
for ($currentColumn = 0; $currentColumn < $this->_columnCount; $currentColumn++)
|
for ($currentColumn = 0; $currentColumn < $this->_columnCount; $currentColumn++) {
|
||||||
{
|
|
||||||
$firstRowColValue = $this->_matrixRowData[0][$currentColumn];
|
$firstRowColValue = $this->_matrixRowData[0][$currentColumn];
|
||||||
$cofactor = $this->getCofactor(0, $currentColumn);
|
$cofactor = $this->getCofactor(0, $currentColumn);
|
||||||
$itemToAdd = $firstRowColValue*$cofactor;
|
$itemToAdd = $firstRowColValue * $cofactor;
|
||||||
$result = $result + $itemToAdd;
|
$result = $result + $itemToAdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,14 +141,12 @@ class Matrix
|
|||||||
|
|
||||||
public function getAdjugate()
|
public function getAdjugate()
|
||||||
{
|
{
|
||||||
if (!$this->isSquare())
|
if (!$this->isSquare()) {
|
||||||
{
|
|
||||||
throw new Exception("Matrix must be square!");
|
throw new Exception("Matrix must be square!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// See http://en.wikipedia.org/wiki/Adjugate_matrix
|
// See http://en.wikipedia.org/wiki/Adjugate_matrix
|
||||||
if ($this->_rowCount == 2)
|
if ($this->_rowCount == 2) {
|
||||||
{
|
|
||||||
// Happy path!
|
// Happy path!
|
||||||
// Adjugate of:
|
// Adjugate of:
|
||||||
// | a b |
|
// | a b |
|
||||||
@ -170,17 +160,15 @@ class Matrix
|
|||||||
$c = $this->_matrixRowData[1][0];
|
$c = $this->_matrixRowData[1][0];
|
||||||
$d = $this->_matrixRowData[1][1];
|
$d = $this->_matrixRowData[1][1];
|
||||||
|
|
||||||
return new SquareMatrix( $d, -$b,
|
return new SquareMatrix($d, -$b,
|
||||||
-$c, $a);
|
-$c, $a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The idea is that it's the transpose of the cofactors
|
// The idea is that it's the transpose of the cofactors
|
||||||
$result = array();
|
$result = array();
|
||||||
|
|
||||||
for ($currentColumn = 0; $currentColumn < $this->_columnCount; $currentColumn++)
|
for ($currentColumn = 0; $currentColumn < $this->_columnCount; $currentColumn++) {
|
||||||
{
|
for ($currentRow = 0; $currentRow < $this->_rowCount; $currentRow++) {
|
||||||
for ($currentRow = 0; $currentRow < $this->_rowCount; $currentRow++)
|
|
||||||
{
|
|
||||||
$result[$currentColumn][$currentRow] = $this->getCofactor($currentRow, $currentColumn);
|
$result[$currentColumn][$currentRow] = $this->getCofactor($currentRow, $currentColumn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,9 +178,8 @@ class Matrix
|
|||||||
|
|
||||||
public function getInverse()
|
public function getInverse()
|
||||||
{
|
{
|
||||||
if (($this->_rowCount == 1) && ($this->_columnCount == 1))
|
if (($this->_rowCount == 1) && ($this->_columnCount == 1)) {
|
||||||
{
|
return new SquareMatrix(1.0 / $this->_matrixRowData[0][0]);
|
||||||
return new SquareMatrix(1.0/$this->_matrixRowData[0][0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take the simple approach:
|
// Take the simple approach:
|
||||||
@ -209,11 +196,9 @@ class Matrix
|
|||||||
$columns = $matrix->getColumnCount();
|
$columns = $matrix->getColumnCount();
|
||||||
$newValues = array();
|
$newValues = array();
|
||||||
|
|
||||||
for ($currentRow = 0; $currentRow < $rows; $currentRow++)
|
for ($currentRow = 0; $currentRow < $rows; $currentRow++) {
|
||||||
{
|
for ($currentColumn = 0; $currentColumn < $columns; $currentColumn++) {
|
||||||
for ($currentColumn = 0; $currentColumn < $columns; $currentColumn++)
|
$newValues[$currentRow][$currentColumn] = $scalarValue * $matrix->getValue($currentRow, $currentColumn);
|
||||||
{
|
|
||||||
$newValues[$currentRow][$currentColumn] = $scalarValue*$matrix->getValue($currentRow, $currentColumn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,11 +208,10 @@ class Matrix
|
|||||||
public static function add($left, $right)
|
public static function add($left, $right)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
($left->getRowCount() != $right->getRowCount())
|
($left->getRowCount() != $right->getRowCount())
|
||||||
||
|
||
|
||||||
($left->getColumnCount() != $right->getColumnCount())
|
($left->getColumnCount() != $right->getColumnCount())
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
throw new Exception("Matrices must be of the same size");
|
throw new Exception("Matrices must be of the same size");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,14 +219,12 @@ class Matrix
|
|||||||
|
|
||||||
$resultMatrix = array();
|
$resultMatrix = array();
|
||||||
|
|
||||||
for ($currentRow = 0; $currentRow < $left->getRowCount(); $currentRow++)
|
for ($currentRow = 0; $currentRow < $left->getRowCount(); $currentRow++) {
|
||||||
{
|
for ($currentColumn = 0; $currentColumn < $right->getColumnCount(); $currentColumn++) {
|
||||||
for ($currentColumn = 0; $currentColumn < $right->getColumnCount(); $currentColumn++)
|
|
||||||
{
|
|
||||||
$resultMatrix[$currentRow][$currentColumn] =
|
$resultMatrix[$currentRow][$currentColumn] =
|
||||||
$left->getValue($currentRow, $currentColumn)
|
$left->getValue($currentRow, $currentColumn)
|
||||||
+
|
+
|
||||||
$right->getValue($currentRow, $currentColumn);
|
$right->getValue($currentRow, $currentColumn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,8 +236,7 @@ class Matrix
|
|||||||
// Just your standard matrix multiplication.
|
// Just your standard matrix multiplication.
|
||||||
// See http://en.wikipedia.org/wiki/Matrix_multiplication for details
|
// See http://en.wikipedia.org/wiki/Matrix_multiplication for details
|
||||||
|
|
||||||
if ($left->getColumnCount() != $right->getRowCount())
|
if ($left->getColumnCount() != $right->getRowCount()) {
|
||||||
{
|
|
||||||
throw new Exception("The width of the left matrix must match the height of the right matrix");
|
throw new Exception("The width of the left matrix must match the height of the right matrix");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,17 +245,14 @@ class Matrix
|
|||||||
|
|
||||||
$resultMatrix = array();
|
$resultMatrix = array();
|
||||||
|
|
||||||
for ($currentRow = 0; $currentRow < $resultRows; $currentRow++)
|
for ($currentRow = 0; $currentRow < $resultRows; $currentRow++) {
|
||||||
{
|
for ($currentColumn = 0; $currentColumn < $resultColumns; $currentColumn++) {
|
||||||
for ($currentColumn = 0; $currentColumn < $resultColumns; $currentColumn++)
|
|
||||||
{
|
|
||||||
$productValue = 0;
|
$productValue = 0;
|
||||||
|
|
||||||
for ($vectorIndex = 0; $vectorIndex < $left->getColumnCount(); $vectorIndex++)
|
for ($vectorIndex = 0; $vectorIndex < $left->getColumnCount(); $vectorIndex++) {
|
||||||
{
|
|
||||||
$leftValue = $left->getValue($currentRow, $vectorIndex);
|
$leftValue = $left->getValue($currentRow, $vectorIndex);
|
||||||
$rightValue = $right->getValue($vectorIndex, $currentColumn);
|
$rightValue = $right->getValue($vectorIndex, $currentColumn);
|
||||||
$vectorIndexProduct = $leftValue*$rightValue;
|
$vectorIndexProduct = $leftValue * $rightValue;
|
||||||
$productValue = $productValue + $vectorIndexProduct;
|
$productValue = $productValue + $vectorIndexProduct;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,7 +261,7 @@ class Matrix
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new Matrix($resultRows, $resultColumns, $resultMatrix);
|
return new Matrix($resultRows, $resultColumns, $resultMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getMinorMatrix($rowToRemove, $columnToRemove)
|
private function getMinorMatrix($rowToRemove, $columnToRemove)
|
||||||
{
|
{
|
||||||
@ -294,19 +272,15 @@ class Matrix
|
|||||||
|
|
||||||
$actualRow = 0;
|
$actualRow = 0;
|
||||||
|
|
||||||
for ($currentRow = 0; $currentRow < $this->_rowCount; $currentRow++)
|
for ($currentRow = 0; $currentRow < $this->_rowCount; $currentRow++) {
|
||||||
{
|
if ($currentRow == $rowToRemove) {
|
||||||
if ($currentRow == $rowToRemove)
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$actualCol = 0;
|
$actualCol = 0;
|
||||||
|
|
||||||
for ($currentColumn = 0; $currentColumn < $this->_columnCount; $currentColumn++)
|
for ($currentColumn = 0; $currentColumn < $this->_columnCount; $currentColumn++) {
|
||||||
{
|
if ($currentColumn == $columnToRemove) {
|
||||||
if ($currentColumn == $columnToRemove)
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,41 +300,33 @@ class Matrix
|
|||||||
// See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for details
|
// See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for details
|
||||||
// REVIEW: should things be reversed since I'm 0 indexed?
|
// REVIEW: should things be reversed since I'm 0 indexed?
|
||||||
$sum = $rowToRemove + $columnToRemove;
|
$sum = $rowToRemove + $columnToRemove;
|
||||||
$isEven = ($sum%2 == 0);
|
$isEven = ($sum % 2 == 0);
|
||||||
|
|
||||||
if ($isEven)
|
if ($isEven) {
|
||||||
{
|
|
||||||
return $this->getMinorMatrix($rowToRemove, $columnToRemove)->getDeterminant();
|
return $this->getMinorMatrix($rowToRemove, $columnToRemove)->getDeterminant();
|
||||||
}
|
} else {
|
||||||
else
|
return -1.0 * $this->getMinorMatrix($rowToRemove, $columnToRemove)->getDeterminant();
|
||||||
{
|
|
||||||
return -1.0*$this->getMinorMatrix($rowToRemove, $columnToRemove)->getDeterminant();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function equals($otherMatrix)
|
public function equals($otherMatrix)
|
||||||
{
|
{
|
||||||
// If one is null, but not both, return false.
|
// If one is null, but not both, return false.
|
||||||
if ($otherMatrix == null)
|
if ($otherMatrix == null) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($this->_rowCount != $otherMatrix->getRowCount()) || ($this->_columnCount != $otherMatrix->getColumnCount()))
|
if (($this->_rowCount != $otherMatrix->getRowCount()) || ($this->_columnCount != $otherMatrix->getColumnCount())) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ($currentRow = 0; $currentRow < $this->_rowCount; $currentRow++)
|
for ($currentRow = 0; $currentRow < $this->_rowCount; $currentRow++) {
|
||||||
{
|
for ($currentColumn = 0; $currentColumn < $this->_columnCount; $currentColumn++) {
|
||||||
for ($currentColumn = 0; $currentColumn < $this->_columnCount; $currentColumn++)
|
|
||||||
{
|
|
||||||
$delta =
|
$delta =
|
||||||
abs($this->_matrixRowData[$currentRow][$currentColumn] -
|
abs($this->_matrixRowData[$currentRow][$currentColumn] -
|
||||||
$otherMatrix->getValue($currentRow, $currentColumn));
|
$otherMatrix->getValue($currentRow, $currentColumn));
|
||||||
|
|
||||||
if ($delta > self::ERROR_TOLERANCE)
|
if ($delta > self::ERROR_TOLERANCE) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,7 @@ class Vector extends Matrix
|
|||||||
public function __construct(array $vectorValues)
|
public function __construct(array $vectorValues)
|
||||||
{
|
{
|
||||||
$columnValues = array();
|
$columnValues = array();
|
||||||
foreach($vectorValues as $currentVectorValue)
|
foreach ($vectorValues as $currentVectorValue) {
|
||||||
{
|
|
||||||
$columnValues[] = array($currentVectorValue);
|
$columnValues[] = array($currentVectorValue);
|
||||||
}
|
}
|
||||||
parent::__construct(count($vectorValues), 1, $columnValues);
|
parent::__construct(count($vectorValues), 1, $columnValues);
|
||||||
|
@ -34,9 +34,8 @@ class Player implements ISupportPartialPlay, ISupportPartialUpdate
|
|||||||
/**
|
/**
|
||||||
* The identifier for the player, such as a name.
|
* The identifier for the player, such as a name.
|
||||||
*/
|
*/
|
||||||
public function &getId()
|
public function getId()
|
||||||
{
|
{
|
||||||
$id = &$this->_Id;
|
|
||||||
return $this->_Id;
|
return $this->_Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,27 +9,24 @@ class RatingContainer
|
|||||||
$this->_playerToRating = new HashMap();
|
$this->_playerToRating = new HashMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &getRating(Player &$player)
|
public function getRating(Player $player)
|
||||||
{
|
{
|
||||||
$rating = &$this->_playerToRating->getValue($player);
|
return $this->_playerToRating->getValue($player);
|
||||||
return $rating;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setRating(Player &$player, Rating $rating)
|
public function setRating(Player $player, Rating $rating)
|
||||||
{
|
{
|
||||||
return $this->_playerToRating->setValue($player, $rating);
|
return $this->_playerToRating->setValue($player, $rating);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &getAllPlayers()
|
public function getAllPlayers()
|
||||||
{
|
{
|
||||||
$allPlayers = &$this->_playerToRating->getAllKeys();
|
return $this->_playerToRating->getAllKeys();
|
||||||
return $allPlayers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &getAllRatings()
|
public function getAllRatings()
|
||||||
{
|
{
|
||||||
$allRatings = &$this->_playerToRating->getAllValues();
|
return $this->_playerToRating->getAllValues();
|
||||||
return $allRatings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function count()
|
public function count()
|
||||||
|
@ -37,23 +37,21 @@ abstract class SkillCalculator
|
|||||||
* @param array $teamsOfPlayerToRatings A mapping of team players and their ratings.
|
* @param array $teamsOfPlayerToRatings A mapping of team players and their ratings.
|
||||||
* @return The quality of the match between the teams as a percentage (0% = bad, 100% = well matched).
|
* @return The quality of the match between the teams as a percentage (0% = bad, 100% = well matched).
|
||||||
*/
|
*/
|
||||||
public abstract function calculateMatchQuality(GameInfo $gameInfo,
|
public abstract function calculateMatchQuality(GameInfo $gameInfo, array $teamsOfPlayerToRatings);
|
||||||
array &$teamsOfPlayerToRatings);
|
|
||||||
|
|
||||||
public function isSupported($option)
|
public function isSupported($option)
|
||||||
{
|
{
|
||||||
return ($this->_supportedOptions & $option) == $option;
|
return ($this->_supportedOptions & $option) == $option;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function validateTeamCountAndPlayersCountPerTeam(array &$teamsOfPlayerToRatings)
|
protected function validateTeamCountAndPlayersCountPerTeam(array $teamsOfPlayerToRatings)
|
||||||
{
|
{
|
||||||
self::validateTeamCountAndPlayersCountPerTeamWithRanges($teamsOfPlayerToRatings, $this->_totalTeamsAllowed, $this->_playersPerTeamAllowed);
|
self::validateTeamCountAndPlayersCountPerTeamWithRanges($teamsOfPlayerToRatings, $this->_totalTeamsAllowed, $this->_playersPerTeamAllowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function validateTeamCountAndPlayersCountPerTeamWithRanges(
|
private static function validateTeamCountAndPlayersCountPerTeamWithRanges(array $teams,
|
||||||
array &$teams,
|
TeamsRange $totalTeams,
|
||||||
TeamsRange &$totalTeams,
|
PlayersRange $playersPerTeam)
|
||||||
PlayersRange &$playersPerTeam)
|
|
||||||
{
|
{
|
||||||
$countOfTeams = 0;
|
$countOfTeams = 0;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
class Team extends RatingContainer
|
class Team extends RatingContainer
|
||||||
{
|
{
|
||||||
public function __construct(Player &$player = null, Rating $rating = null)
|
public function __construct(Player $player = null, Rating $rating = null)
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ class Team extends RatingContainer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addPlayer(Player &$player, Rating $rating)
|
public function addPlayer(Player $player, Rating $rating)
|
||||||
{
|
{
|
||||||
$this->setRating($player, $rating);
|
$this->setRating($player, $rating);
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -7,8 +7,8 @@ class Teams
|
|||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
$result = array();
|
$result = array();
|
||||||
|
|
||||||
foreach ($args as &$currentTeam) {
|
foreach ($args as $currentTeam) {
|
||||||
$localCurrentTeam = &$currentTeam;
|
$localCurrentTeam = $currentTeam;
|
||||||
$result[] = $localCurrentTeam;
|
$result[] = $localCurrentTeam;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,8 +43,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
|
|||||||
return $factorGraph->getUpdatedRatings();
|
return $factorGraph->getUpdatedRatings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function calculateMatchQuality(GameInfo $gameInfo,
|
public function calculateMatchQuality(GameInfo $gameInfo, array $teams)
|
||||||
array &$teams)
|
|
||||||
{
|
{
|
||||||
// We need to create the A matrix which is the player team assigments.
|
// We need to create the A matrix which is the player team assigments.
|
||||||
$teamAssignmentsList = $teams;
|
$teamAssignmentsList = $teams;
|
||||||
@ -87,7 +86,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getPlayerMeansVector(array &$teamAssignmentsList)
|
private static function getPlayerMeansVector(array $teamAssignmentsList)
|
||||||
{
|
{
|
||||||
// A simple vector of all the player means.
|
// A simple vector of all the player means.
|
||||||
return new Vector(self::getPlayerRatingValues($teamAssignmentsList,
|
return new Vector(self::getPlayerRatingValues($teamAssignmentsList,
|
||||||
@ -96,7 +95,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getPlayerCovarianceMatrix(array &$teamAssignmentsList)
|
private static function getPlayerCovarianceMatrix(array $teamAssignmentsList)
|
||||||
{
|
{
|
||||||
// This is a square matrix whose diagonal values represent the variance (square of standard deviation) of all
|
// This is a square matrix whose diagonal values represent the variance (square of standard deviation) of all
|
||||||
// players.
|
// players.
|
||||||
@ -108,8 +107,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper function that gets a list of values for all player ratings
|
// Helper function that gets a list of values for all player ratings
|
||||||
private static function getPlayerRatingValues(array &$teamAssignmentsList,
|
private static function getPlayerRatingValues(array $teamAssignmentsList, $playerRatingFunction)
|
||||||
$playerRatingFunction)
|
|
||||||
{
|
{
|
||||||
$playerRatingValues = array();
|
$playerRatingValues = array();
|
||||||
|
|
||||||
@ -122,7 +120,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
|
|||||||
return $playerRatingValues;
|
return $playerRatingValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function createPlayerTeamAssignmentMatrix(&$teamAssignmentsList, $totalPlayers)
|
private static function createPlayerTeamAssignmentMatrix($teamAssignmentsList, $totalPlayers)
|
||||||
{
|
{
|
||||||
// The team assignment matrix is often referred to as the "A" matrix. It's a matrix whose rows represent the players
|
// The team assignment matrix is often referred to as the "A" matrix. It's a matrix whose rows represent the players
|
||||||
// and the columns represent teams. At Matrix[row, column] represents that player[row] is on team[col]
|
// and the columns represent teams. At Matrix[row, column] represents that player[row] is on team[col]
|
||||||
|
@ -18,19 +18,19 @@ abstract class GaussianFactor extends Factor
|
|||||||
* @param Variable $variable
|
* @param Variable $variable
|
||||||
* @return float|int
|
* @return float|int
|
||||||
*/
|
*/
|
||||||
protected function sendMessageVariable(Message &$message, Variable &$variable)
|
protected function sendMessageVariable(Message $message, Variable $variable)
|
||||||
{
|
{
|
||||||
$marginal = &$variable->getValue();
|
$marginal = $variable->getValue();
|
||||||
$messageValue = &$message->getValue();
|
$messageValue = $message->getValue();
|
||||||
$logZ = GaussianDistribution::logProductNormalization($marginal, $messageValue);
|
$logZ = GaussianDistribution::logProductNormalization($marginal, $messageValue);
|
||||||
$variable->setValue(GaussianDistribution::multiply($marginal, $messageValue));
|
$variable->setValue(GaussianDistribution::multiply($marginal, $messageValue));
|
||||||
return $logZ;
|
return $logZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &createVariableToMessageBinding(Variable &$variable)
|
public function createVariableToMessageBinding(Variable $variable)
|
||||||
{
|
{
|
||||||
$newDistribution = GaussianDistribution::fromPrecisionMean(0, 0);
|
$newDistribution = GaussianDistribution::fromPrecisionMean(0, 0);
|
||||||
$binding = &parent::createVariableToMessageBindingWithMessage($variable,
|
$binding = parent::createVariableToMessageBindingWithMessage($variable,
|
||||||
new Message(
|
new Message(
|
||||||
$newDistribution,
|
$newDistribution,
|
||||||
sprintf("message from %s to %s", $this, $variable)));
|
sprintf("message from %s to %s", $this, $variable)));
|
||||||
|
@ -14,7 +14,7 @@ class GaussianGreaterThanFactor extends GaussianFactor
|
|||||||
{
|
{
|
||||||
private $_epsilon;
|
private $_epsilon;
|
||||||
|
|
||||||
public function __construct($epsilon, Variable &$variable)
|
public function __construct($epsilon, Variable $variable)
|
||||||
{
|
{
|
||||||
parent::__construct(\sprintf("%s > %.2f", $variable, $epsilon));
|
parent::__construct(\sprintf("%s > %.2f", $variable, $epsilon));
|
||||||
$this->_epsilon = $epsilon;
|
$this->_epsilon = $epsilon;
|
||||||
@ -23,20 +23,26 @@ class GaussianGreaterThanFactor extends GaussianFactor
|
|||||||
|
|
||||||
public function getLogNormalization()
|
public function getLogNormalization()
|
||||||
{
|
{
|
||||||
$vars = &$this->getVariables();
|
/** @var Variable[] $vars */
|
||||||
$marginal = &$vars[0]->getValue();
|
$vars = $this->getVariables();
|
||||||
$messages = &$this->getMessages();
|
$marginal = $vars[0]->getValue();
|
||||||
$message = &$messages[0]->getValue();
|
|
||||||
|
/** @var Message[] $messages */
|
||||||
|
$messages = $this->getMessages();
|
||||||
|
$message = $messages[0]->getValue();
|
||||||
$messageFromVariable = GaussianDistribution::divide($marginal, $message);
|
$messageFromVariable = GaussianDistribution::divide($marginal, $message);
|
||||||
return -GaussianDistribution::logProductNormalization($messageFromVariable, $message)
|
return -GaussianDistribution::logProductNormalization($messageFromVariable, $message)
|
||||||
+
|
+
|
||||||
log(
|
log(
|
||||||
GaussianDistribution::cumulativeTo(($messageFromVariable->getMean() - $this->_epsilon) /
|
GaussianDistribution::cumulativeTo(
|
||||||
$messageFromVariable->getStandardDeviation()));
|
($messageFromVariable->getMean() - $this->_epsilon) /
|
||||||
|
$messageFromVariable->getStandardDeviation()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function updateMessageVariable(Message &$message, Variable &$variable)
|
protected function updateMessageVariable(Message $message, Variable $variable)
|
||||||
{
|
{
|
||||||
$oldMarginal = clone $variable->getValue();
|
$oldMarginal = clone $variable->getValue();
|
||||||
$oldMessage = clone $message->getValue();
|
$oldMessage = clone $message->getValue();
|
||||||
@ -55,16 +61,18 @@ class GaussianGreaterThanFactor extends GaussianFactor
|
|||||||
$denom = 1.0 - TruncatedGaussianCorrectionFunctions::wExceedsMargin($dOnSqrtC, $epsilsonTimesSqrtC);
|
$denom = 1.0 - TruncatedGaussianCorrectionFunctions::wExceedsMargin($dOnSqrtC, $epsilsonTimesSqrtC);
|
||||||
|
|
||||||
$newPrecision = $c / $denom;
|
$newPrecision = $c / $denom;
|
||||||
$newPrecisionMean = ($d +
|
$newPrecisionMean = (
|
||||||
|
$d +
|
||||||
$sqrtC *
|
$sqrtC *
|
||||||
TruncatedGaussianCorrectionFunctions::vExceedsMargin($dOnSqrtC, $epsilsonTimesSqrtC)) /
|
TruncatedGaussianCorrectionFunctions::vExceedsMargin($dOnSqrtC, $epsilsonTimesSqrtC)
|
||||||
$denom;
|
) / $denom;
|
||||||
|
|
||||||
$newMarginal = GaussianDistribution::fromPrecisionMean($newPrecisionMean, $newPrecision);
|
$newMarginal = GaussianDistribution::fromPrecisionMean($newPrecisionMean, $newPrecision);
|
||||||
|
|
||||||
$newMessage = GaussianDistribution::divide(
|
$newMessage = GaussianDistribution::divide(
|
||||||
GaussianDistribution::multiply($oldMessage, $newMarginal),
|
GaussianDistribution::multiply($oldMessage, $newMarginal),
|
||||||
$oldMarginal);
|
$oldMarginal
|
||||||
|
);
|
||||||
|
|
||||||
// Update the message and marginal
|
// Update the message and marginal
|
||||||
$message->setValue($newMessage);
|
$message->setValue($newMessage);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?php namespace Moserware\Skills\TrueSkill\Factors;
|
<?php namespace Moserware\Skills\TrueSkill\Factors;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Moserware\Skills\FactorGraphs\KeyedVariable;
|
||||||
use Moserware\Skills\FactorGraphs\Message;
|
use Moserware\Skills\FactorGraphs\Message;
|
||||||
use Moserware\Skills\FactorGraphs\Variable;
|
use Moserware\Skills\FactorGraphs\Variable;
|
||||||
use Moserware\Skills\Numerics\GaussianDistribution;
|
use Moserware\Skills\Numerics\GaussianDistribution;
|
||||||
@ -14,7 +15,7 @@ class GaussianLikelihoodFactor extends GaussianFactor
|
|||||||
{
|
{
|
||||||
private $_precision;
|
private $_precision;
|
||||||
|
|
||||||
public function __construct($betaSquared, Variable &$variable1, Variable &$variable2)
|
public function __construct($betaSquared, Variable $variable1, Variable $variable2)
|
||||||
{
|
{
|
||||||
parent::__construct(sprintf("Likelihood of %s going to %s", $variable2, $variable1));
|
parent::__construct(sprintf("Likelihood of %s going to %s", $variable2, $variable1));
|
||||||
$this->_precision = 1.0 / $betaSquared;
|
$this->_precision = 1.0 / $betaSquared;
|
||||||
@ -24,16 +25,18 @@ class GaussianLikelihoodFactor extends GaussianFactor
|
|||||||
|
|
||||||
public function getLogNormalization()
|
public function getLogNormalization()
|
||||||
{
|
{
|
||||||
$vars = &$this->getVariables();
|
/** @var KeyedVariable[]|mixed $vars */
|
||||||
$messages = &$this->getMessages();
|
$vars = $this->getVariables();
|
||||||
|
/** @var Message[] $messages */
|
||||||
|
$messages = $this->getMessages();
|
||||||
|
|
||||||
return GaussianDistribution::logRatioNormalization(
|
return GaussianDistribution::logRatioNormalization(
|
||||||
$vars[0]->getValue(),
|
$vars[0]->getValue(),
|
||||||
$messages[0]->getValue());
|
$messages[0]->getValue()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateHelper(Message &$message1, Message &$message2,
|
private function updateHelper(Message $message1, Message $message2, Variable $variable1, Variable $variable2)
|
||||||
Variable &$variable1, Variable &$variable2)
|
|
||||||
{
|
{
|
||||||
$message1Value = clone $message1->getValue();
|
$message1Value = clone $message1->getValue();
|
||||||
$message2Value = clone $message2->getValue();
|
$message2Value = clone $message2->getValue();
|
||||||
@ -45,7 +48,8 @@ class GaussianLikelihoodFactor extends GaussianFactor
|
|||||||
|
|
||||||
$newMessage = GaussianDistribution::fromPrecisionMean(
|
$newMessage = GaussianDistribution::fromPrecisionMean(
|
||||||
$a * ($marginal2->getPrecisionMean() - $message2Value->getPrecisionMean()),
|
$a * ($marginal2->getPrecisionMean() - $message2Value->getPrecisionMean()),
|
||||||
$a * ($marginal2->getPrecision() - $message2Value->getPrecision()));
|
$a * ($marginal2->getPrecision() - $message2Value->getPrecision())
|
||||||
|
);
|
||||||
|
|
||||||
$oldMarginalWithoutMessage = GaussianDistribution::divide($marginal1, $message1Value);
|
$oldMarginalWithoutMessage = GaussianDistribution::divide($marginal1, $message1Value);
|
||||||
|
|
||||||
@ -62,8 +66,8 @@ class GaussianLikelihoodFactor extends GaussianFactor
|
|||||||
|
|
||||||
public function updateMessageIndex($messageIndex)
|
public function updateMessageIndex($messageIndex)
|
||||||
{
|
{
|
||||||
$messages = &$this->getMessages();
|
$messages = $this->getMessages();
|
||||||
$vars = &$this->getVariables();
|
$vars = $this->getVariables();
|
||||||
|
|
||||||
switch ($messageIndex) {
|
switch ($messageIndex) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -13,7 +13,7 @@ class GaussianPriorFactor extends GaussianFactor
|
|||||||
{
|
{
|
||||||
private $_newMessage;
|
private $_newMessage;
|
||||||
|
|
||||||
public function __construct($mean, $variance, Variable &$variable)
|
public function __construct($mean, $variance, Variable $variable)
|
||||||
{
|
{
|
||||||
parent::__construct(sprintf("Prior value going to %s", $variable));
|
parent::__construct(sprintf("Prior value going to %s", $variable));
|
||||||
$this->_newMessage = new GaussianDistribution($mean, sqrt($variance));
|
$this->_newMessage = new GaussianDistribution($mean, sqrt($variance));
|
||||||
@ -23,18 +23,17 @@ class GaussianPriorFactor extends GaussianFactor
|
|||||||
$this->createVariableToMessageBindingWithMessage($variable, $newMessage);
|
$this->createVariableToMessageBindingWithMessage($variable, $newMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function updateMessageVariable(Message &$message, Variable &$variable)
|
protected function updateMessageVariable(Message $message, Variable $variable)
|
||||||
{
|
{
|
||||||
$oldMarginal = clone $variable->getValue();
|
$oldMarginal = clone $variable->getValue();
|
||||||
$oldMessage = $message;
|
$oldMessage = $message;
|
||||||
$newMarginal =
|
$newMarginal = GaussianDistribution::fromPrecisionMean(
|
||||||
GaussianDistribution::fromPrecisionMean(
|
$oldMarginal->getPrecisionMean() + $this->_newMessage->getPrecisionMean() - $oldMessage->getValue()->getPrecisionMean(),
|
||||||
$oldMarginal->getPrecisionMean() + $this->_newMessage->getPrecisionMean() - $oldMessage->getValue()->getPrecisionMean(),
|
$oldMarginal->getPrecision() + $this->_newMessage->getPrecision() - $oldMessage->getValue()->getPrecision()
|
||||||
$oldMarginal->getPrecision() + $this->_newMessage->getPrecision() - $oldMessage->getValue()->getPrecision());
|
);
|
||||||
|
|
||||||
$variable->setValue($newMarginal);
|
$variable->setValue($newMarginal);
|
||||||
$newMessage = &$this->_newMessage;
|
$message->setValue($this->_newMessage);
|
||||||
$message->setValue($newMessage);
|
|
||||||
return GaussianDistribution::subtract($oldMarginal, $newMarginal);
|
return GaussianDistribution::subtract($oldMarginal, $newMarginal);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,7 +20,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
|
|||||||
private $_weights;
|
private $_weights;
|
||||||
private $_weightsSquared;
|
private $_weightsSquared;
|
||||||
|
|
||||||
public function __construct(Variable &$sumVariable, array &$variablesToSum, array &$variableWeights = null)
|
public function __construct(Variable $sumVariable, array $variablesToSum, array $variableWeights = null)
|
||||||
{
|
{
|
||||||
parent::__construct(self::createName($sumVariable, $variablesToSum, $variableWeights));
|
parent::__construct(self::createName($sumVariable, $variablesToSum, $variableWeights));
|
||||||
$this->_weights = array();
|
$this->_weights = array();
|
||||||
@ -29,7 +29,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
|
|||||||
// The first weights are a straightforward copy
|
// The first weights are a straightforward copy
|
||||||
// v_0 = a_1*v_1 + a_2*v_2 + ... + a_n * v_n
|
// v_0 = a_1*v_1 + a_2*v_2 + ... + a_n * v_n
|
||||||
$variableWeightsLength = count($variableWeights);
|
$variableWeightsLength = count($variableWeights);
|
||||||
$this->_weights[0] = \array_fill(0, count($variableWeights), 0);
|
$this->_weights[0] = array_fill(0, count($variableWeights), 0);
|
||||||
|
|
||||||
for ($i = 0; $i < $variableWeightsLength; $i++) {
|
for ($i = 0; $i < $variableWeightsLength; $i++) {
|
||||||
$weight = &$variableWeights[$i];
|
$weight = &$variableWeights[$i];
|
||||||
@ -104,16 +104,16 @@ class GaussianWeightedSumFactor extends GaussianFactor
|
|||||||
|
|
||||||
$this->createVariableToMessageBinding($sumVariable);
|
$this->createVariableToMessageBinding($sumVariable);
|
||||||
|
|
||||||
foreach ($variablesToSum as &$currentVariable) {
|
foreach ($variablesToSum as $currentVariable) {
|
||||||
$localCurrentVariable = &$currentVariable;
|
$localCurrentVariable = $currentVariable;
|
||||||
$this->createVariableToMessageBinding($localCurrentVariable);
|
$this->createVariableToMessageBinding($localCurrentVariable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLogNormalization()
|
public function getLogNormalization()
|
||||||
{
|
{
|
||||||
$vars = &$this->getVariables();
|
$vars = $this->getVariables();
|
||||||
$messages = &$this->getMessages();
|
$messages = $this->getMessages();
|
||||||
|
|
||||||
$result = 0.0;
|
$result = 0.0;
|
||||||
|
|
||||||
@ -126,9 +126,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateHelper(array &$weights, array &$weightsSquared,
|
private function updateHelper(array $weights, array $weightsSquared, array $messages, array $variables)
|
||||||
array &$messages,
|
|
||||||
array &$variables)
|
|
||||||
{
|
{
|
||||||
// Potentially look at http://mathworld.wolfram.com/NormalSumDistribution.html for clues as
|
// Potentially look at http://mathworld.wolfram.com/NormalSumDistribution.html for clues as
|
||||||
// to what it's doing
|
// to what it's doing
|
||||||
@ -185,23 +183,23 @@ class GaussianWeightedSumFactor extends GaussianFactor
|
|||||||
|
|
||||||
public function updateMessageIndex($messageIndex)
|
public function updateMessageIndex($messageIndex)
|
||||||
{
|
{
|
||||||
$allMessages = &$this->getMessages();
|
$allMessages = $this->getMessages();
|
||||||
$allVariables = &$this->getVariables();
|
$allVariables = $this->getVariables();
|
||||||
|
|
||||||
Guard::argumentIsValidIndex($messageIndex, count($allMessages), "messageIndex");
|
Guard::argumentIsValidIndex($messageIndex, count($allMessages), "messageIndex");
|
||||||
|
|
||||||
$updatedMessages = array();
|
$updatedMessages = array();
|
||||||
$updatedVariables = array();
|
$updatedVariables = array();
|
||||||
|
|
||||||
$indicesToUse = &$this->_variableIndexOrdersForWeights[$messageIndex];
|
$indicesToUse = $this->_variableIndexOrdersForWeights[$messageIndex];
|
||||||
|
|
||||||
// The tricky part here is that we have to put the messages and variables in the same
|
// The tricky part here is that we have to put the messages and variables in the same
|
||||||
// order as the weights. Thankfully, the weights and messages share the same index numbers,
|
// order as the weights. Thankfully, the weights and messages share the same index numbers,
|
||||||
// so we just need to make sure they're consistent
|
// so we just need to make sure they're consistent
|
||||||
$allMessagesCount = count($allMessages);
|
$allMessagesCount = count($allMessages);
|
||||||
for ($i = 0; $i < $allMessagesCount; $i++) {
|
for ($i = 0; $i < $allMessagesCount; $i++) {
|
||||||
$updatedMessages[] = &$allMessages[$indicesToUse[$i]];
|
$updatedMessages[] = $allMessages[$indicesToUse[$i]];
|
||||||
$updatedVariables[] = &$allVariables[$indicesToUse[$i]];
|
$updatedVariables[] = $allVariables[$indicesToUse[$i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->updateHelper($this->_weights[$messageIndex],
|
return $this->updateHelper($this->_weights[$messageIndex],
|
||||||
|
@ -14,7 +14,7 @@ class GaussianWithinFactor extends GaussianFactor
|
|||||||
{
|
{
|
||||||
private $_epsilon;
|
private $_epsilon;
|
||||||
|
|
||||||
public function __construct($epsilon, Variable &$variable)
|
public function __construct($epsilon, Variable $variable)
|
||||||
{
|
{
|
||||||
parent::__construct(sprintf("%s <= %.2f", $variable, $epsilon));
|
parent::__construct(sprintf("%s <= %.2f", $variable, $epsilon));
|
||||||
$this->_epsilon = $epsilon;
|
$this->_epsilon = $epsilon;
|
||||||
@ -23,11 +23,13 @@ class GaussianWithinFactor extends GaussianFactor
|
|||||||
|
|
||||||
public function getLogNormalization()
|
public function getLogNormalization()
|
||||||
{
|
{
|
||||||
$variables = &$this->getVariables();
|
/** @var Variable[] $variables */
|
||||||
$marginal = &$variables[0]->getValue();
|
$variables = $this->getVariables();
|
||||||
|
$marginal = $variables[0]->getValue();
|
||||||
|
|
||||||
$messages = &$this->getMessages();
|
/** @var Message[] $messages */
|
||||||
$message = &$messages[0]->getValue();
|
$messages = $this->getMessages();
|
||||||
|
$message = $messages[0]->getValue();
|
||||||
$messageFromVariable = GaussianDistribution::divide($marginal, $message);
|
$messageFromVariable = GaussianDistribution::divide($marginal, $message);
|
||||||
$mean = $messageFromVariable->getMean();
|
$mean = $messageFromVariable->getMean();
|
||||||
$std = $messageFromVariable->getStandardDeviation();
|
$std = $messageFromVariable->getStandardDeviation();
|
||||||
@ -38,7 +40,7 @@ class GaussianWithinFactor extends GaussianFactor
|
|||||||
return -GaussianDistribution::logProductNormalization($messageFromVariable, $message) + log($z);
|
return -GaussianDistribution::logProductNormalization($messageFromVariable, $message) + log($z);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function updateMessageVariable(Message &$message, Variable &$variable)
|
protected function updateMessageVariable(Message $message, Variable $variable)
|
||||||
{
|
{
|
||||||
$oldMarginal = clone $variable->getValue();
|
$oldMarginal = clone $variable->getValue();
|
||||||
$oldMessage = clone $message->getValue();
|
$oldMessage = clone $message->getValue();
|
||||||
@ -55,15 +57,16 @@ class GaussianWithinFactor extends GaussianFactor
|
|||||||
|
|
||||||
$denominator = 1.0 - TruncatedGaussianCorrectionFunctions::wWithinMargin($dOnSqrtC, $epsilonTimesSqrtC);
|
$denominator = 1.0 - TruncatedGaussianCorrectionFunctions::wWithinMargin($dOnSqrtC, $epsilonTimesSqrtC);
|
||||||
$newPrecision = $c / $denominator;
|
$newPrecision = $c / $denominator;
|
||||||
$newPrecisionMean = ($d +
|
$newPrecisionMean = ( $d +
|
||||||
$sqrtC *
|
$sqrtC *
|
||||||
TruncatedGaussianCorrectionFunctions::vWithinMargin($dOnSqrtC, $epsilonTimesSqrtC)) /
|
TruncatedGaussianCorrectionFunctions::vWithinMargin($dOnSqrtC, $epsilonTimesSqrtC)
|
||||||
$denominator;
|
) / $denominator;
|
||||||
|
|
||||||
$newMarginal = GaussianDistribution::fromPrecisionMean($newPrecisionMean, $newPrecision);
|
$newMarginal = GaussianDistribution::fromPrecisionMean($newPrecisionMean, $newPrecision);
|
||||||
$newMessage = GaussianDistribution::divide(
|
$newMessage = GaussianDistribution::divide(
|
||||||
GaussianDistribution::multiply($oldMessage, $newMarginal),
|
GaussianDistribution::multiply($oldMessage, $newMarginal),
|
||||||
$oldMarginal);
|
$oldMarginal
|
||||||
|
);
|
||||||
|
|
||||||
// Update the message and marginal
|
// Update the message and marginal
|
||||||
$message->setValue($newMessage);
|
$message->setValue($newMessage);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?php namespace Moserware\Skills\TrueSkill\Layers;
|
<?php namespace Moserware\Skills\TrueSkill\Layers;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use Moserware\Skills\FactorGraphs\ScheduleLoop;
|
use Moserware\Skills\FactorGraphs\ScheduleLoop;
|
||||||
use Moserware\Skills\FactorGraphs\ScheduleSequence;
|
use Moserware\Skills\FactorGraphs\ScheduleSequence;
|
||||||
use Moserware\Skills\FactorGraphs\ScheduleStep;
|
use Moserware\Skills\FactorGraphs\ScheduleStep;
|
||||||
@ -11,30 +12,31 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
|
|||||||
private $_TeamDifferencesComparisonLayer;
|
private $_TeamDifferencesComparisonLayer;
|
||||||
private $_TeamPerformancesToTeamPerformanceDifferencesLayer;
|
private $_TeamPerformancesToTeamPerformanceDifferencesLayer;
|
||||||
|
|
||||||
public function __construct(TrueSkillFactorGraph &$parentGraph,
|
public function __construct(TrueSkillFactorGraph $parentGraph,
|
||||||
TeamPerformancesToTeamPerformanceDifferencesLayer &$teamPerformancesToPerformanceDifferences,
|
TeamPerformancesToTeamPerformanceDifferencesLayer $teamPerformancesToPerformanceDifferences,
|
||||||
TeamDifferencesComparisonLayer &$teamDifferencesComparisonLayer)
|
TeamDifferencesComparisonLayer $teamDifferencesComparisonLayer)
|
||||||
{
|
{
|
||||||
parent::__construct($parentGraph);
|
parent::__construct($parentGraph);
|
||||||
$this->_TeamPerformancesToTeamPerformanceDifferencesLayer = $teamPerformancesToPerformanceDifferences;
|
$this->_TeamPerformancesToTeamPerformanceDifferencesLayer = $teamPerformancesToPerformanceDifferences;
|
||||||
$this->_TeamDifferencesComparisonLayer = $teamDifferencesComparisonLayer;
|
$this->_TeamDifferencesComparisonLayer = $teamDifferencesComparisonLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function &getLocalFactors()
|
public function getLocalFactors()
|
||||||
{
|
{
|
||||||
$localFactors =
|
$localFactors = array_merge($this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors(),
|
||||||
array_merge($this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors(),
|
$this->_TeamDifferencesComparisonLayer->getLocalFactors()
|
||||||
$this->_TeamDifferencesComparisonLayer->getLocalFactors());
|
);
|
||||||
|
|
||||||
return $localFactors;
|
return $localFactors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildLayer()
|
public function buildLayer()
|
||||||
{
|
{
|
||||||
$inputVariablesGroups = &$this->getInputVariablesGroups();
|
$inputVariablesGroups = $this->getInputVariablesGroups();
|
||||||
$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->setInputVariablesGroups($inputVariablesGroups);
|
$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->setInputVariablesGroups($inputVariablesGroups);
|
||||||
$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->buildLayer();
|
$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->buildLayer();
|
||||||
|
|
||||||
$teamDifferencesOutputVariablesGroups = &$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getOutputVariablesGroups();
|
$teamDifferencesOutputVariablesGroups = $this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getOutputVariablesGroups();
|
||||||
$this->_TeamDifferencesComparisonLayer->setInputVariablesGroups($teamDifferencesOutputVariablesGroups);
|
$this->_TeamDifferencesComparisonLayer->setInputVariablesGroups($teamDifferencesOutputVariablesGroups);
|
||||||
$this->_TeamDifferencesComparisonLayer->buildLayer();
|
$this->_TeamDifferencesComparisonLayer->buildLayer();
|
||||||
}
|
}
|
||||||
@ -44,7 +46,7 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
|
|||||||
switch (count($this->getInputVariablesGroups())) {
|
switch (count($this->getInputVariablesGroups())) {
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
throw new InvalidOperationException();
|
throw new Exception('InvalidOperation');
|
||||||
case 2:
|
case 2:
|
||||||
$loop = $this->createTwoTeamInnerPriorLoopSchedule();
|
$loop = $this->createTwoTeamInnerPriorLoopSchedule();
|
||||||
break;
|
break;
|
||||||
@ -57,10 +59,11 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
|
|||||||
$totalTeamDifferences = count($this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors());
|
$totalTeamDifferences = count($this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors());
|
||||||
$totalTeams = $totalTeamDifferences + 1;
|
$totalTeams = $totalTeamDifferences + 1;
|
||||||
|
|
||||||
$localFactors = &$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors();
|
$localFactors = $this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors();
|
||||||
|
|
||||||
|
$firstDifferencesFactor = $localFactors[0];
|
||||||
|
$lastDifferencesFactor = $localFactors[$totalTeamDifferences - 1];
|
||||||
|
|
||||||
$firstDifferencesFactor = &$localFactors[0];
|
|
||||||
$lastDifferencesFactor = &$localFactors[$totalTeamDifferences - 1];
|
|
||||||
$innerSchedule = new ScheduleSequence(
|
$innerSchedule = new ScheduleSequence(
|
||||||
"inner schedule",
|
"inner schedule",
|
||||||
array(
|
array(
|
||||||
@ -79,11 +82,11 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
|
|||||||
|
|
||||||
private function createTwoTeamInnerPriorLoopSchedule()
|
private function createTwoTeamInnerPriorLoopSchedule()
|
||||||
{
|
{
|
||||||
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = &$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors();
|
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = $this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors();
|
||||||
$teamDifferencesComparisonLayerLocalFactors = &$this->_TeamDifferencesComparisonLayer->getLocalFactors();
|
$teamDifferencesComparisonLayerLocalFactors = $this->_TeamDifferencesComparisonLayer->getLocalFactors();
|
||||||
|
|
||||||
$firstPerfToTeamDiff = &$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[0];
|
$firstPerfToTeamDiff = $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[0];
|
||||||
$firstTeamDiffComparison = &$teamDifferencesComparisonLayerLocalFactors[0];
|
$firstTeamDiffComparison = $teamDifferencesComparisonLayerLocalFactors[0];
|
||||||
$itemsToSequence = array(
|
$itemsToSequence = array(
|
||||||
new ScheduleStep(
|
new ScheduleStep(
|
||||||
"send team perf to perf differences",
|
"send team perf to perf differences",
|
||||||
@ -107,11 +110,11 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
|
|||||||
$forwardScheduleList = array();
|
$forwardScheduleList = array();
|
||||||
|
|
||||||
for ($i = 0; $i < $totalTeamDifferences - 1; $i++) {
|
for ($i = 0; $i < $totalTeamDifferences - 1; $i++) {
|
||||||
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = &$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors();
|
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = $this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors();
|
||||||
$teamDifferencesComparisonLayerLocalFactors = &$this->_TeamDifferencesComparisonLayer->getLocalFactors();
|
$teamDifferencesComparisonLayerLocalFactors = $this->_TeamDifferencesComparisonLayer->getLocalFactors();
|
||||||
|
|
||||||
$currentTeamPerfToTeamPerfDiff = &$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$i];
|
$currentTeamPerfToTeamPerfDiff = $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$i];
|
||||||
$currentTeamDiffComparison = &$teamDifferencesComparisonLayerLocalFactors[$i];
|
$currentTeamDiffComparison = $teamDifferencesComparisonLayerLocalFactors[$i];
|
||||||
|
|
||||||
$currentForwardSchedulePiece =
|
$currentForwardSchedulePiece =
|
||||||
$this->scheduleSequence(
|
$this->scheduleSequence(
|
||||||
@ -135,12 +138,12 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
|
|||||||
$backwardScheduleList = array();
|
$backwardScheduleList = array();
|
||||||
|
|
||||||
for ($i = 0; $i < $totalTeamDifferences - 1; $i++) {
|
for ($i = 0; $i < $totalTeamDifferences - 1; $i++) {
|
||||||
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = &$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors();
|
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = $this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors();
|
||||||
$teamDifferencesComparisonLayerLocalFactors = &$this->_TeamDifferencesComparisonLayer->getLocalFactors();
|
$teamDifferencesComparisonLayerLocalFactors = $this->_TeamDifferencesComparisonLayer->getLocalFactors();
|
||||||
|
|
||||||
$differencesFactor = &$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$totalTeamDifferences - 1 - $i];
|
$differencesFactor = $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$totalTeamDifferences - 1 - $i];
|
||||||
$comparisonFactor = &$teamDifferencesComparisonLayerLocalFactors[$totalTeamDifferences - 1 - $i];
|
$comparisonFactor = $teamDifferencesComparisonLayerLocalFactors[$totalTeamDifferences - 1 - $i];
|
||||||
$performancesToDifferencesFactor = &$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$totalTeamDifferences - 1 - $i];
|
$performancesToDifferencesFactor = $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$totalTeamDifferences - 1 - $i];
|
||||||
|
|
||||||
$currentBackwardSchedulePiece = new ScheduleSequence(
|
$currentBackwardSchedulePiece = new ScheduleSequence(
|
||||||
"current backward schedule piece",
|
"current backward schedule piece",
|
||||||
|
@ -9,17 +9,17 @@ use Moserware\Skills\TrueSkill\TrueSkillFactorGraph;
|
|||||||
|
|
||||||
class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLayer
|
class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLayer
|
||||||
{
|
{
|
||||||
public function __construct(TrueSkillFactorGraph &$parentGraph)
|
public function __construct(TrueSkillFactorGraph $parentGraph)
|
||||||
{
|
{
|
||||||
parent::__construct($parentGraph);
|
parent::__construct($parentGraph);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildLayer()
|
public function buildLayer()
|
||||||
{
|
{
|
||||||
$inputVariablesGroups = &$this->getInputVariablesGroups();
|
$inputVariablesGroups = $this->getInputVariablesGroups();
|
||||||
foreach ($inputVariablesGroups as &$currentTeam) {
|
foreach ($inputVariablesGroups as $currentTeam) {
|
||||||
$localCurrentTeam = &$currentTeam;
|
$localCurrentTeam = $currentTeam;
|
||||||
$teamPerformance = &$this->createOutputVariable($localCurrentTeam);
|
$teamPerformance = $this->createOutputVariable($localCurrentTeam);
|
||||||
$newSumFactor = $this->createPlayerToTeamSumFactor($localCurrentTeam, $teamPerformance);
|
$newSumFactor = $this->createPlayerToTeamSumFactor($localCurrentTeam, $teamPerformance);
|
||||||
|
|
||||||
$this->addLayerFactor($newSumFactor);
|
$this->addLayerFactor($newSumFactor);
|
||||||
@ -32,9 +32,9 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
|
|||||||
|
|
||||||
public function createPriorSchedule()
|
public function createPriorSchedule()
|
||||||
{
|
{
|
||||||
$localFactors = &$this->getLocalFactors();
|
$localFactors = $this->getLocalFactors();
|
||||||
|
|
||||||
$sequence = &$this->scheduleSequence(
|
$sequence = $this->scheduleSequence(
|
||||||
array_map(
|
array_map(
|
||||||
function ($weightedSumFactor) {
|
function ($weightedSumFactor) {
|
||||||
return new ScheduleStep("Perf to Team Perf Step", $weightedSumFactor, 0);
|
return new ScheduleStep("Perf to Team Perf Step", $weightedSumFactor, 0);
|
||||||
@ -44,11 +44,11 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
|
|||||||
return $sequence;
|
return $sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createPlayerToTeamSumFactor(&$teamMembers, &$sumVariable)
|
protected function createPlayerToTeamSumFactor($teamMembers, $sumVariable)
|
||||||
{
|
{
|
||||||
$weights = array_map(
|
$weights = array_map(
|
||||||
function ($v) {
|
function ($v) {
|
||||||
$player = &$v->getKey();
|
$player = $v->getKey();
|
||||||
return PartialPlay::getPartialPlayPercentage($player);
|
return PartialPlay::getPartialPlayPercentage($player);
|
||||||
},
|
},
|
||||||
$teamMembers);
|
$teamMembers);
|
||||||
@ -63,9 +63,9 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
|
|||||||
public function createPosteriorSchedule()
|
public function createPosteriorSchedule()
|
||||||
{
|
{
|
||||||
$allFactors = array();
|
$allFactors = array();
|
||||||
$localFactors = &$this->getLocalFactors();
|
$localFactors = $this->getLocalFactors();
|
||||||
foreach ($localFactors as &$currentFactor) {
|
foreach ($localFactors as $currentFactor) {
|
||||||
$localCurrentFactor = &$currentFactor;
|
$localCurrentFactor = $currentFactor;
|
||||||
$numberOfMessages = $localCurrentFactor->getNumberOfMessages();
|
$numberOfMessages = $localCurrentFactor->getNumberOfMessages();
|
||||||
for ($currentIteration = 1; $currentIteration < $numberOfMessages; $currentIteration++) {
|
for ($currentIteration = 1; $currentIteration < $numberOfMessages; $currentIteration++) {
|
||||||
$allFactors[] = new ScheduleStep("team sum perf @" . $currentIteration,
|
$allFactors[] = new ScheduleStep("team sum perf @" . $currentIteration,
|
||||||
@ -75,15 +75,14 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
|
|||||||
return $this->scheduleSequence($allFactors, "all of the team's sum iterations");
|
return $this->scheduleSequence($allFactors, "all of the team's sum iterations");
|
||||||
}
|
}
|
||||||
|
|
||||||
private function &createOutputVariable(&$team)
|
private function createOutputVariable($team)
|
||||||
{
|
{
|
||||||
$memberNames = \array_map(function ($currentPlayer) {
|
$memberNames = array_map(function ($currentPlayer) {
|
||||||
return (string)($currentPlayer->getKey());
|
return (string)($currentPlayer->getKey());
|
||||||
},
|
}, $team);
|
||||||
$team);
|
|
||||||
|
|
||||||
$teamMemberNames = \join(", ", $memberNames);
|
$teamMemberNames = \join(", ", $memberNames);
|
||||||
$outputVariable = &$this->getParentFactorGraph()->getVariableFactory()->createBasicVariable("Team[" . $teamMemberNames . "]'s performance");
|
$outputVariable = $this->getParentFactorGraph()->getVariableFactory()->createBasicVariable("Team[" . $teamMemberNames . "]'s performance");
|
||||||
return $outputVariable;
|
return $outputVariable;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,7 +13,7 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
|
|||||||
{
|
{
|
||||||
private $_teams;
|
private $_teams;
|
||||||
|
|
||||||
public function __construct(TrueSkillFactorGraph &$parentGraph, array &$teams)
|
public function __construct(TrueSkillFactorGraph $parentGraph, array $teams)
|
||||||
{
|
{
|
||||||
parent::__construct($parentGraph);
|
parent::__construct($parentGraph);
|
||||||
$this->_teams = $teams;
|
$this->_teams = $teams;
|
||||||
@ -21,17 +21,17 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
|
|||||||
|
|
||||||
public function buildLayer()
|
public function buildLayer()
|
||||||
{
|
{
|
||||||
$teams = &$this->_teams;
|
$teams = $this->_teams;
|
||||||
foreach ($teams as &$currentTeam) {
|
foreach ($teams as $currentTeam) {
|
||||||
$localCurrentTeam = &$currentTeam;
|
$localCurrentTeam = $currentTeam;
|
||||||
$currentTeamSkills = array();
|
$currentTeamSkills = array();
|
||||||
|
|
||||||
$currentTeamAllPlayers = $localCurrentTeam->getAllPlayers();
|
$currentTeamAllPlayers = $localCurrentTeam->getAllPlayers();
|
||||||
foreach ($currentTeamAllPlayers as &$currentTeamPlayer) {
|
foreach ($currentTeamAllPlayers as $currentTeamPlayer) {
|
||||||
$localCurrentTeamPlayer = &$currentTeamPlayer;
|
$localCurrentTeamPlayer = $currentTeamPlayer;
|
||||||
$currentTeamPlayerRating = $currentTeam->getRating($localCurrentTeamPlayer);
|
$currentTeamPlayerRating = $currentTeam->getRating($localCurrentTeamPlayer);
|
||||||
$playerSkill = &$this->createSkillOutputVariable($localCurrentTeamPlayer);
|
$playerSkill = $this->createSkillOutputVariable($localCurrentTeamPlayer);
|
||||||
$priorFactor = &$this->createPriorFactor($localCurrentTeamPlayer, $currentTeamPlayerRating, $playerSkill);
|
$priorFactor = $this->createPriorFactor($localCurrentTeamPlayer, $currentTeamPlayerRating, $playerSkill);
|
||||||
$this->addLayerFactor($priorFactor);
|
$this->addLayerFactor($priorFactor);
|
||||||
$currentTeamSkills[] = $playerSkill;
|
$currentTeamSkills[] = $playerSkill;
|
||||||
}
|
}
|
||||||
@ -43,17 +43,17 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
|
|||||||
|
|
||||||
public function createPriorSchedule()
|
public function createPriorSchedule()
|
||||||
{
|
{
|
||||||
$localFactors = &$this->getLocalFactors();
|
$localFactors = $this->getLocalFactors();
|
||||||
return $this->scheduleSequence(
|
return $this->scheduleSequence(
|
||||||
array_map(
|
array_map(
|
||||||
function (&$prior) {
|
function ($prior) {
|
||||||
return new ScheduleStep("Prior to Skill Step", $prior, 0);
|
return new ScheduleStep("Prior to Skill Step", $prior, 0);
|
||||||
},
|
},
|
||||||
$localFactors),
|
$localFactors),
|
||||||
"All priors");
|
"All priors");
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createPriorFactor(&$player, Rating &$priorRating, Variable &$skillsVariable)
|
private function createPriorFactor($player, Rating $priorRating, Variable $skillsVariable)
|
||||||
{
|
{
|
||||||
return new GaussianPriorFactor(
|
return new GaussianPriorFactor(
|
||||||
$priorRating->getMean(),
|
$priorRating->getMean(),
|
||||||
@ -63,11 +63,11 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function &createSkillOutputVariable(&$key)
|
private function createSkillOutputVariable($key)
|
||||||
{
|
{
|
||||||
$parentFactorGraph = &$this->getParentFactorGraph();
|
$parentFactorGraph = $this->getParentFactorGraph();
|
||||||
$variableFactory = &$parentFactorGraph->getVariableFactory();
|
$variableFactory = $parentFactorGraph->getVariableFactory();
|
||||||
$skillOutputVariable = &$variableFactory->createKeyedVariable($key, $key . "'s skill");
|
$skillOutputVariable = $variableFactory->createKeyedVariable($key, $key . "'s skill");
|
||||||
return $skillOutputVariable;
|
return $skillOutputVariable;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,23 +8,23 @@ use Moserware\Skills\TrueSkill\Factors\GaussianLikelihoodFactor;
|
|||||||
|
|
||||||
class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
|
class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
|
||||||
{
|
{
|
||||||
public function __construct(TrueSkillFactorGraph &$parentGraph)
|
public function __construct(TrueSkillFactorGraph $parentGraph)
|
||||||
{
|
{
|
||||||
parent::__construct($parentGraph);
|
parent::__construct($parentGraph);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildLayer()
|
public function buildLayer()
|
||||||
{
|
{
|
||||||
$inputVariablesGroups = &$this->getInputVariablesGroups();
|
$inputVariablesGroups = $this->getInputVariablesGroups();
|
||||||
$outputVariablesGroups = &$this->getOutputVariablesGroups();
|
$outputVariablesGroups = &$this->getOutputVariablesGroups();
|
||||||
|
|
||||||
foreach ($inputVariablesGroups as &$currentTeam) {
|
foreach ($inputVariablesGroups as $currentTeam) {
|
||||||
$currentTeamPlayerPerformances = array();
|
$currentTeamPlayerPerformances = array();
|
||||||
|
|
||||||
foreach ($currentTeam as &$playerSkillVariable) {
|
foreach ($currentTeam as $playerSkillVariable) {
|
||||||
$localPlayerSkillVariable = &$playerSkillVariable;
|
$localPlayerSkillVariable = $playerSkillVariable;
|
||||||
$currentPlayer = &$localPlayerSkillVariable->getKey();
|
$currentPlayer = $localPlayerSkillVariable->getKey();
|
||||||
$playerPerformance = &$this->createOutputVariable($currentPlayer);
|
$playerPerformance = $this->createOutputVariable($currentPlayer);
|
||||||
$newLikelihoodFactor = $this->createLikelihood($localPlayerSkillVariable, $playerPerformance);
|
$newLikelihoodFactor = $this->createLikelihood($localPlayerSkillVariable, $playerPerformance);
|
||||||
$this->addLayerFactor($newLikelihoodFactor);
|
$this->addLayerFactor($newLikelihoodFactor);
|
||||||
$currentTeamPlayerPerformances[] = $playerPerformance;
|
$currentTeamPlayerPerformances[] = $playerPerformance;
|
||||||
@ -34,7 +34,7 @@ class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createLikelihood(KeyedVariable &$playerSkill, KeyedVariable &$playerPerformance)
|
private function createLikelihood(KeyedVariable $playerSkill, KeyedVariable $playerPerformance)
|
||||||
{
|
{
|
||||||
return new GaussianLikelihoodFactor(
|
return new GaussianLikelihoodFactor(
|
||||||
BasicMath::square($this->getParentFactorGraph()->getGameInfo()->getBeta()),
|
BasicMath::square($this->getParentFactorGraph()->getGameInfo()->getBeta()),
|
||||||
@ -43,15 +43,15 @@ class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function &createOutputVariable(&$key)
|
private function createOutputVariable($key)
|
||||||
{
|
{
|
||||||
$outputVariable = &$this->getParentFactorGraph()->getVariableFactory()->createKeyedVariable($key, $key . "'s performance");
|
$outputVariable = $this->getParentFactorGraph()->getVariableFactory()->createKeyedVariable($key, $key . "'s performance");
|
||||||
return $outputVariable;
|
return $outputVariable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createPriorSchedule()
|
public function createPriorSchedule()
|
||||||
{
|
{
|
||||||
$localFactors = &$this->getLocalFactors();
|
$localFactors = $this->getLocalFactors();
|
||||||
return $this->scheduleSequence(
|
return $this->scheduleSequence(
|
||||||
array_map(
|
array_map(
|
||||||
function ($likelihood) {
|
function ($likelihood) {
|
||||||
@ -63,7 +63,7 @@ class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
|
|||||||
|
|
||||||
public function createPosteriorSchedule()
|
public function createPosteriorSchedule()
|
||||||
{
|
{
|
||||||
$localFactors = &$this->getLocalFactors();
|
$localFactors = $this->getLocalFactors();
|
||||||
return $this->scheduleSequence(
|
return $this->scheduleSequence(
|
||||||
array_map(
|
array_map(
|
||||||
function ($likelihood) {
|
function ($likelihood) {
|
||||||
|
@ -10,22 +10,22 @@ class TeamDifferencesComparisonLayer extends TrueSkillFactorGraphLayer
|
|||||||
private $_epsilon;
|
private $_epsilon;
|
||||||
private $_teamRanks;
|
private $_teamRanks;
|
||||||
|
|
||||||
public function __construct(TrueSkillFactorGraph &$parentGraph, array &$teamRanks)
|
public function __construct(TrueSkillFactorGraph $parentGraph, array $teamRanks)
|
||||||
{
|
{
|
||||||
parent::__construct($parentGraph);
|
parent::__construct($parentGraph);
|
||||||
$this->_teamRanks = $teamRanks;
|
$this->_teamRanks = $teamRanks;
|
||||||
$gameInfo = &$this->getParentFactorGraph()->getGameInfo();
|
$gameInfo = $this->getParentFactorGraph()->getGameInfo();
|
||||||
$this->_epsilon = DrawMargin::getDrawMarginFromDrawProbability($gameInfo->getDrawProbability(), $gameInfo->getBeta());
|
$this->_epsilon = DrawMargin::getDrawMarginFromDrawProbability($gameInfo->getDrawProbability(), $gameInfo->getBeta());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildLayer()
|
public function buildLayer()
|
||||||
{
|
{
|
||||||
$inputVarGroups = &$this->getInputVariablesGroups();
|
$inputVarGroups = $this->getInputVariablesGroups();
|
||||||
$inputVarGroupsCount = count($inputVarGroups);
|
$inputVarGroupsCount = count($inputVarGroups);
|
||||||
|
|
||||||
for ($i = 0; $i < $inputVarGroupsCount; $i++) {
|
for ($i = 0; $i < $inputVarGroupsCount; $i++) {
|
||||||
$isDraw = ($this->_teamRanks[$i] == $this->_teamRanks[$i + 1]);
|
$isDraw = ($this->_teamRanks[$i] == $this->_teamRanks[$i + 1]);
|
||||||
$teamDifference = &$inputVarGroups[$i][0];
|
$teamDifference = $inputVarGroups[$i][0];
|
||||||
|
|
||||||
$factor =
|
$factor =
|
||||||
$isDraw
|
$isDraw
|
||||||
|
@ -6,23 +6,23 @@ use Moserware\Skills\TrueSkill\Factors\GaussianWeightedSumFactor;
|
|||||||
|
|
||||||
class TeamPerformancesToTeamPerformanceDifferencesLayer extends TrueSkillFactorGraphLayer
|
class TeamPerformancesToTeamPerformanceDifferencesLayer extends TrueSkillFactorGraphLayer
|
||||||
{
|
{
|
||||||
public function __construct(TrueSkillFactorGraph &$parentGraph)
|
public function __construct(TrueSkillFactorGraph $parentGraph)
|
||||||
{
|
{
|
||||||
parent::__construct($parentGraph);
|
parent::__construct($parentGraph);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildLayer()
|
public function buildLayer()
|
||||||
{
|
{
|
||||||
$inputVariablesGroups = &$this->getInputVariablesGroups();
|
$inputVariablesGroups = $this->getInputVariablesGroups();
|
||||||
$inputVariablesGroupsCount = count($inputVariablesGroups);
|
$inputVariablesGroupsCount = count($inputVariablesGroups);
|
||||||
$outputVariablesGroup = &$this->getOutputVariablesGroups();
|
$outputVariablesGroup = &$this->getOutputVariablesGroups();
|
||||||
|
|
||||||
for ($i = 0; $i < $inputVariablesGroupsCount - 1; $i++)
|
for ($i = 0; $i < $inputVariablesGroupsCount - 1; $i++)
|
||||||
{
|
{
|
||||||
$strongerTeam = &$inputVariablesGroups[$i][0];
|
$strongerTeam = $inputVariablesGroups[$i][0];
|
||||||
$weakerTeam = &$inputVariablesGroups[$i + 1][0];
|
$weakerTeam = $inputVariablesGroups[$i + 1][0];
|
||||||
|
|
||||||
$currentDifference = &$this->createOutputVariable();
|
$currentDifference = $this->createOutputVariable();
|
||||||
$newDifferencesFactor = $this->createTeamPerformanceToDifferenceFactor($strongerTeam, $weakerTeam, $currentDifference);
|
$newDifferencesFactor = $this->createTeamPerformanceToDifferenceFactor($strongerTeam, $weakerTeam, $currentDifference);
|
||||||
$this->addLayerFactor($newDifferencesFactor);
|
$this->addLayerFactor($newDifferencesFactor);
|
||||||
|
|
||||||
@ -31,17 +31,18 @@ class TeamPerformancesToTeamPerformanceDifferencesLayer extends TrueSkillFactorG
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createTeamPerformanceToDifferenceFactor(
|
private function createTeamPerformanceToDifferenceFactor(Variable $strongerTeam,
|
||||||
Variable &$strongerTeam, Variable &$weakerTeam, Variable &$output)
|
Variable $weakerTeam,
|
||||||
|
Variable $output)
|
||||||
{
|
{
|
||||||
$teams = array($strongerTeam, $weakerTeam);
|
$teams = array($strongerTeam, $weakerTeam);
|
||||||
$weights = array(1.0, -1.0);
|
$weights = array(1.0, -1.0);
|
||||||
return new GaussianWeightedSumFactor($output, $teams, $weights);
|
return new GaussianWeightedSumFactor($output, $teams, $weights);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function &createOutputVariable()
|
private function createOutputVariable()
|
||||||
{
|
{
|
||||||
$outputVariable = &$this->getParentFactorGraph()->getVariableFactory()->createBasicVariable("Team performance difference");
|
$outputVariable = $this->getParentFactorGraph()->getVariableFactory()->createBasicVariable("Team performance difference");
|
||||||
return $outputVariable;
|
return $outputVariable;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,7 +5,7 @@ use Moserware\Skills\TrueSkill\TrueSkillFactorGraph;
|
|||||||
|
|
||||||
abstract class TrueSkillFactorGraphLayer extends FactorGraphLayer
|
abstract class TrueSkillFactorGraphLayer extends FactorGraphLayer
|
||||||
{
|
{
|
||||||
public function __construct(TrueSkillFactorGraph &$parentGraph)
|
public function __construct(TrueSkillFactorGraph $parentGraph)
|
||||||
{
|
{
|
||||||
parent::__construct($parentGraph);
|
parent::__construct($parentGraph);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?php namespace Moserware\Skills\TrueSkill;
|
<?php namespace Moserware\Skills\TrueSkill;
|
||||||
|
|
||||||
use Moserware\Skills\GameInfo;
|
use Moserware\Skills\GameInfo;
|
||||||
|
use Moserware\Skills\Numerics\GaussianDistribution;
|
||||||
use Moserware\Skills\Rating;
|
use Moserware\Skills\Rating;
|
||||||
use Moserware\Skills\RatingContainer;
|
use Moserware\Skills\RatingContainer;
|
||||||
use Moserware\Skills\FactorGraphs\FactorGraph;
|
use Moserware\Skills\FactorGraphs\FactorGraph;
|
||||||
@ -20,7 +21,7 @@ class TrueSkillFactorGraph extends FactorGraph
|
|||||||
private $_layers;
|
private $_layers;
|
||||||
private $_priorLayer;
|
private $_priorLayer;
|
||||||
|
|
||||||
public function __construct(GameInfo &$gameInfo, array &$teams, array $teamRanks)
|
public function __construct(GameInfo $gameInfo, array $teams, array $teamRanks)
|
||||||
{
|
{
|
||||||
$this->_priorLayer = new PlayerPriorValuesToSkillsLayer($this, $teams);
|
$this->_priorLayer = new PlayerPriorValuesToSkillsLayer($this, $teams);
|
||||||
$this->_gameInfo = $gameInfo;
|
$this->_gameInfo = $gameInfo;
|
||||||
@ -50,15 +51,15 @@ class TrueSkillFactorGraph extends FactorGraph
|
|||||||
{
|
{
|
||||||
$lastOutput = null;
|
$lastOutput = null;
|
||||||
|
|
||||||
$layers = &$this->_layers;
|
$layers = $this->_layers;
|
||||||
foreach ($layers as &$currentLayer) {
|
foreach ($layers as $currentLayer) {
|
||||||
if ($lastOutput != null) {
|
if ($lastOutput != null) {
|
||||||
$currentLayer->setInputVariablesGroups($lastOutput);
|
$currentLayer->setInputVariablesGroups($lastOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
$currentLayer->buildLayer();
|
$currentLayer->buildLayer();
|
||||||
|
|
||||||
$lastOutput = &$currentLayer->getOutputVariablesGroups();
|
$lastOutput = $currentLayer->getOutputVariablesGroups();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,11 +73,11 @@ class TrueSkillFactorGraph extends FactorGraph
|
|||||||
{
|
{
|
||||||
$factorList = new FactorList();
|
$factorList = new FactorList();
|
||||||
|
|
||||||
$layers = &$this->_layers;
|
$layers = $this->_layers;
|
||||||
foreach ($layers as &$currentLayer) {
|
foreach ($layers as $currentLayer) {
|
||||||
$localFactors = &$currentLayer->getLocalFactors();
|
$localFactors = $currentLayer->getLocalFactors();
|
||||||
foreach ($localFactors as &$currentFactor) {
|
foreach ($localFactors as $currentFactor) {
|
||||||
$localCurrentFactor = &$currentFactor;
|
$localCurrentFactor = $currentFactor;
|
||||||
$factorList->addFactor($localCurrentFactor);
|
$factorList->addFactor($localCurrentFactor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,17 +90,17 @@ class TrueSkillFactorGraph extends FactorGraph
|
|||||||
{
|
{
|
||||||
$fullSchedule = array();
|
$fullSchedule = array();
|
||||||
|
|
||||||
$layers = &$this->_layers;
|
$layers = $this->_layers;
|
||||||
foreach ($layers as &$currentLayer) {
|
foreach ($layers as $currentLayer) {
|
||||||
$currentPriorSchedule = $currentLayer->createPriorSchedule();
|
$currentPriorSchedule = $currentLayer->createPriorSchedule();
|
||||||
if ($currentPriorSchedule != null) {
|
if ($currentPriorSchedule != null) {
|
||||||
$fullSchedule[] = $currentPriorSchedule;
|
$fullSchedule[] = $currentPriorSchedule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$allLayersReverse = \array_reverse($this->_layers);
|
$allLayersReverse = array_reverse($this->_layers);
|
||||||
|
|
||||||
foreach ($allLayersReverse as &$currentLayer) {
|
foreach ($allLayersReverse as $currentLayer) {
|
||||||
$currentPosteriorSchedule = $currentLayer->createPosteriorSchedule();
|
$currentPosteriorSchedule = $currentLayer->createPosteriorSchedule();
|
||||||
if ($currentPosteriorSchedule != null) {
|
if ($currentPosteriorSchedule != null) {
|
||||||
$fullSchedule[] = $currentPosteriorSchedule;
|
$fullSchedule[] = $currentPosteriorSchedule;
|
||||||
@ -113,10 +114,10 @@ class TrueSkillFactorGraph extends FactorGraph
|
|||||||
{
|
{
|
||||||
$result = new RatingContainer();
|
$result = new RatingContainer();
|
||||||
|
|
||||||
$priorLayerOutputVariablesGroups = &$this->_priorLayer->getOutputVariablesGroups();
|
$priorLayerOutputVariablesGroups = $this->_priorLayer->getOutputVariablesGroups();
|
||||||
foreach ($priorLayerOutputVariablesGroups as &$currentTeam) {
|
foreach ($priorLayerOutputVariablesGroups as $currentTeam) {
|
||||||
foreach ($currentTeam as &$currentPlayer) {
|
foreach ($currentTeam as $currentPlayer) {
|
||||||
$localCurrentPlayer = &$currentPlayer->getKey();
|
$localCurrentPlayer = $currentPlayer->getKey();
|
||||||
$newRating = new Rating($currentPlayer->getValue()->getMean(),
|
$newRating = new Rating($currentPlayer->getValue()->getMean(),
|
||||||
$currentPlayer->getValue()->getStandardDeviation());
|
$currentPlayer->getValue()->getStandardDeviation());
|
||||||
|
|
||||||
|
@ -38,8 +38,12 @@ class TruncatedGaussianCorrectionFunctions
|
|||||||
*
|
*
|
||||||
* In the reference F# implementation, this is referred to as "the multiplicative
|
* In the reference F# implementation, this is referred to as "the multiplicative
|
||||||
* correction of a single-sided truncated Gaussian with unit variance."
|
* correction of a single-sided truncated Gaussian with unit variance."
|
||||||
|
*
|
||||||
|
* @param $teamPerformanceDifference
|
||||||
|
* @param $drawMargin
|
||||||
|
* @param $c
|
||||||
|
* @return float
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public static function wExceedsMarginScaled($teamPerformanceDifference, $drawMargin, $c)
|
public static function wExceedsMarginScaled($teamPerformanceDifference, $drawMargin, $c)
|
||||||
{
|
{
|
||||||
return self::wExceedsMargin($teamPerformanceDifference / $c, $drawMargin / $c);
|
return self::wExceedsMargin($teamPerformanceDifference / $c, $drawMargin / $c);
|
||||||
|
@ -9,7 +9,6 @@ use Moserware\Skills\Rating;
|
|||||||
use Moserware\Skills\RatingContainer;
|
use Moserware\Skills\RatingContainer;
|
||||||
use Moserware\Skills\SkillCalculator;
|
use Moserware\Skills\SkillCalculator;
|
||||||
use Moserware\Skills\SkillCalculatorSupportedOptions;
|
use Moserware\Skills\SkillCalculatorSupportedOptions;
|
||||||
|
|
||||||
use Moserware\Skills\PlayersRange;
|
use Moserware\Skills\PlayersRange;
|
||||||
use Moserware\Skills\TeamsRange;
|
use Moserware\Skills\TeamsRange;
|
||||||
|
|
||||||
@ -126,7 +125,7 @@ class TwoPlayerTrueSkillCalculator extends SkillCalculator
|
|||||||
/**
|
/**
|
||||||
* {@inheritdoc }
|
* {@inheritdoc }
|
||||||
*/
|
*/
|
||||||
public function calculateMatchQuality(GameInfo $gameInfo, array &$teams)
|
public function calculateMatchQuality(GameInfo $gameInfo, array $teams)
|
||||||
{
|
{
|
||||||
Guard::argumentNotNull($gameInfo, "gameInfo");
|
Guard::argumentNotNull($gameInfo, "gameInfo");
|
||||||
$this->validateTeamCountAndPlayersCountPerTeam($teams);
|
$this->validateTeamCountAndPlayersCountPerTeam($teams);
|
||||||
@ -146,18 +145,18 @@ class TwoPlayerTrueSkillCalculator extends SkillCalculator
|
|||||||
$player2SigmaSquared = BasicMath::square($player2Rating->getStandardDeviation());
|
$player2SigmaSquared = BasicMath::square($player2Rating->getStandardDeviation());
|
||||||
|
|
||||||
// This is the square root part of the equation:
|
// This is the square root part of the equation:
|
||||||
$sqrtPart =
|
$sqrtPart = sqrt(
|
||||||
sqrt(
|
(2*$betaSquared)
|
||||||
(2*$betaSquared)
|
/
|
||||||
/
|
(2*$betaSquared + $player1SigmaSquared + $player2SigmaSquared)
|
||||||
(2*$betaSquared + $player1SigmaSquared + $player2SigmaSquared));
|
);
|
||||||
|
|
||||||
// This is the exponent part of the equation:
|
// This is the exponent part of the equation:
|
||||||
$expPart =
|
$expPart = exp(
|
||||||
exp(
|
(-1*BasicMath::square($player1Rating->getMean() - $player2Rating->getMean()))
|
||||||
(-1*BasicMath::square($player1Rating->getMean() - $player2Rating->getMean()))
|
/
|
||||||
/
|
(2*(2*$betaSquared + $player1SigmaSquared + $player2SigmaSquared))
|
||||||
(2*(2*$betaSquared + $player1SigmaSquared + $player2SigmaSquared)));
|
);
|
||||||
|
|
||||||
return $sqrtPart*$expPart;
|
return $sqrtPart*$expPart;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ class TwoTeamTrueSkillCalculator extends SkillCalculator
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static function updatePlayerRatings(GameInfo $gameInfo,
|
private static function updatePlayerRatings(GameInfo $gameInfo,
|
||||||
RatingContainer &$newPlayerRatings,
|
RatingContainer $newPlayerRatings,
|
||||||
Team $selfTeam,
|
Team $selfTeam,
|
||||||
Team $otherTeam,
|
Team $otherTeam,
|
||||||
$selfToOtherTeamComparison)
|
$selfToOtherTeamComparison)
|
||||||
@ -119,9 +119,9 @@ class TwoTeamTrueSkillCalculator extends SkillCalculator
|
|||||||
$rankMultiplier = 1;
|
$rankMultiplier = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
$selfTeamAllPlayers = &$selfTeam->getAllPlayers();
|
$selfTeamAllPlayers = $selfTeam->getAllPlayers();
|
||||||
foreach ($selfTeamAllPlayers as &$selfTeamCurrentPlayer) {
|
foreach ($selfTeamAllPlayers as $selfTeamCurrentPlayer) {
|
||||||
$localSelfTeamCurrentPlayer = &$selfTeamCurrentPlayer;
|
$localSelfTeamCurrentPlayer = $selfTeamCurrentPlayer;
|
||||||
$previousPlayerRating = $selfTeam->getRating($localSelfTeamCurrentPlayer);
|
$previousPlayerRating = $selfTeam->getRating($localSelfTeamCurrentPlayer);
|
||||||
|
|
||||||
$meanMultiplier = (BasicMath::square($previousPlayerRating->getStandardDeviation()) + $tauSquared) / $c;
|
$meanMultiplier = (BasicMath::square($previousPlayerRating->getStandardDeviation()) + $tauSquared) / $c;
|
||||||
@ -141,7 +141,7 @@ class TwoTeamTrueSkillCalculator extends SkillCalculator
|
|||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function calculateMatchQuality(GameInfo $gameInfo, array &$teams)
|
public function calculateMatchQuality(GameInfo $gameInfo, array $teams)
|
||||||
{
|
{
|
||||||
Guard::argumentNotNull($gameInfo, "gameInfo");
|
Guard::argumentNotNull($gameInfo, "gameInfo");
|
||||||
$this->validateTeamCountAndPlayersCountPerTeam($teams);
|
$this->validateTeamCountAndPlayersCountPerTeam($teams);
|
||||||
|
Reference in New Issue
Block a user