Another pass at fixing up references

This commit is contained in:
Jeff Moser 2010-09-30 08:25:31 -04:00
parent 5368f7528e
commit 803a0816a8
28 changed files with 168 additions and 103 deletions

@ -5,7 +5,7 @@ namespace Moserware\Skills\Elo;
require_once(dirname(__FILE__) . "/TwoPlayerEloCalculator.php"); require_once(dirname(__FILE__) . "/TwoPlayerEloCalculator.php");
require_once(dirname(__FILE__) . "/FideKFactor.php"); require_once(dirname(__FILE__) . "/FideKFactor.php");
/** 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
* for more details * for more details
*/ */

@ -50,7 +50,7 @@ abstract class Factor
{ {
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($this->_messages[$messageIndex]); $variable = &$this->_messageToVariableBinding->getValue($message);
return $this->updateMessageVariable($message, $variable); return $this->updateMessageVariable($message, $variable);
} }
@ -62,7 +62,8 @@ abstract class Factor
/// Resets the marginal of the variables a factor is connected to /// Resets the marginal of the variables a factor is connected to
public function resetMarginals() public function resetMarginals()
{ {
foreach ($this->_messageToVariableBinding->getAllValues() as $currentVariable) $allValues = &$this->_messageToVariableBinding->getAllValues();
foreach ($allValues as $currentVariable)
{ {
$currentVariable->resetToPrior(); $currentVariable->resetToPrior();
} }
@ -73,21 +74,21 @@ abstract class Factor
{ {
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); $index = count($this->_messages);
$this->_messages[] = $message; $this->_messages[] = &$message;
$this->_messageToVariableBinding->setValue($message, $variable); $this->_messageToVariableBinding->setValue($message, $variable);
$this->_variables[] = $variable; $this->_variables[] = &$variable;
return $message; return $message;
} }

@ -1,16 +1,19 @@
<?php <?php
namespace Moserware\Skills\FactorGraphs; namespace Moserware\Skills\FactorGraphs;
require_once(dirname(__FILE__) . "/VariableFactory.php");
class FactorGraph class FactorGraph
{ {
private $_variableFactory; private $_variableFactory;
public function &getVariableFactory() public function &getVariableFactory()
{ {
return $this->_variableFactory; $factory = &$this->_variableFactory;
return $factory;
} }
public function setVariableFactory(&$factory) public function setVariableFactory(VariableFactory &$factory)
{ {
$this->_variableFactory = &$factory; $this->_variableFactory = &$factory;
} }

@ -1,6 +1,7 @@
<?php <?php
namespace Moserware\Skills\FactorGraphs; namespace Moserware\Skills\FactorGraphs;
require_once(dirname(__FILE__) . "/Factor.php");
require_once(dirname(__FILE__) . "/FactorGraph.php"); require_once(dirname(__FILE__) . "/FactorGraph.php");
require_once(dirname(__FILE__) . "/Schedule.php"); require_once(dirname(__FILE__) . "/Schedule.php");
@ -18,24 +19,28 @@ abstract class FactorGraphLayer
protected function &getInputVariablesGroups() protected function &getInputVariablesGroups()
{ {
return $this->_inputVariablesGroups; $inputVariablesGroups = &$this->_inputVariablesGroups;
return $inputVariablesGroups;
} }
// HACK // HACK
public function &getParentFactorGraph() public function &getParentFactorGraph()
{ {
return $this->_parentFactorGraph; $parentFactorGraph = &$this->_parentFactorGraph;
return $parentFactorGraph;
} }
public function &getOutputVariablesGroups() public function &getOutputVariablesGroups()
{ {
return $this->_outputVariablesGroups; $outputVariablesGroups = &$this->_outputVariablesGroups;
return $outputVariablesGroups;
} }
public function &getLocalFactors() public function &getLocalFactors()
{ {
return $this->_localFactors; $localFactors = &$this->_localFactors;
return $localFactors;
} }
public function setInputVariablesGroups(&$value) public function setInputVariablesGroups(&$value)
@ -43,12 +48,12 @@ abstract class FactorGraphLayer
$this->_inputVariablesGroups = $value; $this->_inputVariablesGroups = $value;
} }
protected function scheduleSequence($itemsToSequence, $name) protected function scheduleSequence(array $itemsToSequence, $name)
{ {
return new ScheduleSequence($name, $itemsToSequence); return new ScheduleSequence($name, $itemsToSequence);
} }
protected function addLayerFactor(&$factor) protected function addLayerFactor(Factor &$factor)
{ {
$this->_localFactors[] = $factor; $this->_localFactors[] = $factor;
} }

@ -13,7 +13,8 @@ class FactorList
public function getLogNormalization() public function getLogNormalization()
{ {
foreach($this->_list as $currentFactor) $list = &$this->_list;
foreach($list as &$currentFactor)
{ {
$currentFactor->resetMarginals(); $currentFactor->resetMarginals();
} }
@ -36,7 +37,7 @@ class FactorList
$sumLogS = 0; $sumLogS = 0;
foreach($this->_list as $currentFactor) foreach($list as &$currentFactor)
{ {
$sumLogS = $sumLogS + $currentFactor->getLogNormalization(); $sumLogS = $sumLogS + $currentFactor->getLogNormalization();
} }
@ -49,7 +50,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;

@ -6,7 +6,7 @@ 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;
@ -14,7 +14,8 @@ class Message
public function& getValue() public function& getValue()
{ {
return $this->_value; $value = &$this->_value;
return $value;
} }
public function setValue(&$value) public function setValue(&$value)

@ -1,6 +1,8 @@
<?php <?php
namespace Moserware\Skills\FactorGraphs; namespace Moserware\Skills\FactorGraphs;
require_once(dirname(__FILE__) . "/Factor.php");
abstract class Schedule abstract class Schedule
{ {
private $_name; private $_name;
@ -23,7 +25,7 @@ class ScheduleStep extends Schedule
private $_factor; private $_factor;
private $_index; private $_index;
public function __construct($name, $factor, $index) public function __construct($name, Factor &$factor, $index)
{ {
parent::__construct($name); parent::__construct($name);
$this->_factor = $factor; $this->_factor = $factor;
@ -41,7 +43,7 @@ class ScheduleSequence extends Schedule
{ {
private $_schedules; private $_schedules;
public function __construct($name, $schedules) public function __construct($name, array $schedules)
{ {
parent::__construct($name); parent::__construct($name);
$this->_schedules = $schedules; $this->_schedules = $schedules;
@ -51,7 +53,8 @@ class ScheduleSequence extends Schedule
{ {
$maxDelta = 0; $maxDelta = 0;
foreach ($this->_schedules as $currentSchedule) $schedules = &$this->_schedules;
foreach ($schedules as &$currentSchedule)
{ {
$maxDelta = max($currentSchedule->visit($depth + 1, $maxDepth), $maxDelta); $maxDelta = max($currentSchedule->visit($depth + 1, $maxDepth), $maxDelta);
} }
@ -65,7 +68,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;

@ -7,7 +7,7 @@ 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;
@ -16,7 +16,8 @@ class Variable
public function &getValue() public function &getValue()
{ {
return $this->_value; $value = &$this->_value;
return $value;
} }
public function setValue(&$value) public function setValue(&$value)
@ -42,12 +43,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();
} }
@ -56,7 +57,7 @@ class DefaultVariable extends Variable
class KeyedVariable extends Variable 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;

@ -14,14 +14,14 @@ class VariableFactory
$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());

@ -7,10 +7,11 @@ 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);
return $this->_hashToValue[$hash]; $hashValue = &$this->_hashToValue[$hash];
return $hashValue;
} }
public function setValue($key, $value) public function setValue($key, $value)

@ -15,7 +15,7 @@ function square($x)
return $x * $x; return $x * $x;
} }
function sum($itemsToSum, $funcName ) function sum(array $itemsToSum, $funcName )
{ {
$mappedItems = array_map($funcName, $itemsToSum); $mappedItems = array_map($funcName, $itemsToSum);
return array_sum($mappedItems); return array_sum($mappedItems);

@ -30,9 +30,26 @@ class GaussianDistribution
$this->_mean = $mean; $this->_mean = $mean;
$this->_standardDeviation = $standardDeviation; $this->_standardDeviation = $standardDeviation;
$this->_variance = square($standardDeviation); $this->_variance = square($standardDeviation);
if($this->_variance != 0)
{
$this->_precision = 1.0/$this->_variance; $this->_precision = 1.0/$this->_variance;
$this->_precisionMean = $this->_precision*$this->_mean; $this->_precisionMean = $this->_precision*$this->_mean;
} }
else
{
$this->_precision = \INF;
if($this->_mean == 0)
{
$this->_precisionMean = 0;
}
else
{
$this->_precisionMean = \INF;
}
}
}
public function getMean() public function getMean()
{ {

@ -38,8 +38,9 @@ class Player implements ISupportPartialPlay, ISupportPartialUpdate
/// <summary> /// <summary>
/// The identifier for the player, such as a name. /// The identifier for the player, such as a name.
/// </summary> /// </summary>
public function getId() public function &getId()
{ {
$id = &$this->_Id;
return $this->_Id; return $this->_Id;
} }

@ -12,9 +12,10 @@ class RatingContainer
$this->_playerToRating = new HashMap(); $this->_playerToRating = new HashMap();
} }
public function getRating($player) public function &getRating($player)
{ {
return $this->_playerToRating->getValue($player); $rating = &$this->_playerToRating->getValue($player);
return $rating;
} }
public function setRating($player, $rating) public function setRating($player, $rating)

@ -5,7 +5,7 @@ require_once(dirname(__FILE__) . '/RatingContainer.php');
class Team extends RatingContainer class Team extends RatingContainer
{ {
public function __construct($player = null, $rating = null) public function __construct(&$player = null, &$rating = null)
{ {
parent::__construct(); parent::__construct();
@ -15,7 +15,7 @@ class Team extends RatingContainer
} }
} }
public function addPlayer($player, $rating) public function addPlayer(&$player, &$rating)
{ {
$this->setRating($player, $rating); $this->setRating($player, $rating);
return $this; return $this;

@ -8,7 +8,7 @@ class Teams
$args = \func_get_args(); $args = \func_get_args();
$result = array(); $result = array();
foreach ($args as $currentTeam) { foreach ($args as &$currentTeam) {
$result[] = $currentTeam; $result[] = $currentTeam;
} }

@ -29,12 +29,13 @@ abstract class GaussianFactor extends Factor
return $logZ; return $logZ;
} }
public function createVariableToMessageBinding(Variable &$variable) public function &createVariableToMessageBinding(Variable &$variable)
{ {
return parent::createVariableToMessageBindingWithMessage($variable, $binding = &parent::createVariableToMessageBindingWithMessage($variable,
new Message( new Message(
GaussianDistribution::fromPrecisionMean(0, 0), GaussianDistribution::fromPrecisionMean(0, 0),
sprintf("message from %s to %s", $this, $variable))); sprintf("message from %s to %s", $this, $variable)));
return $binding;
} }
} }

@ -28,8 +28,8 @@ class GaussianLikelihoodFactor extends GaussianFactor
public function getLogNormalization() public function getLogNormalization()
{ {
$vars = $this->getVariables(); $vars = &$this->getVariables();
$messages = $this->getMessages(); $messages = &$this->getMessages();
return GaussianDistribution::logRatioNormalization( return GaussianDistribution::logRatioNormalization(
$vars[0]->getValue(), $vars[0]->getValue(),

@ -118,7 +118,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
$this->createVariableToMessageBinding($sumVariable); $this->createVariableToMessageBinding($sumVariable);
foreach ($variablesToSum as $currentVariable) foreach ($variablesToSum as &$currentVariable)
{ {
$this->createVariableToMessageBinding($currentVariable); $this->createVariableToMessageBinding($currentVariable);
} }

@ -33,8 +33,8 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->setInputVariablesGroups($inputVariablesGroups); $this->_TeamPerformancesToTeamPerformanceDifferencesLayer->setInputVariablesGroups($inputVariablesGroups);
$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->buildLayer(); $this->_TeamPerformancesToTeamPerformanceDifferencesLayer->buildLayer();
$this->_TeamDifferencesComparisonLayer->setInputVariablesGroups( $teamDifferencesOutputVariablesGroups = &$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getOutputVariablesGroups();
$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getOutputVariablesGroups()); $this->_TeamDifferencesComparisonLayer->setInputVariablesGroups($teamDifferencesOutputVariablesGroups);
$this->_TeamDifferencesComparisonLayer->buildLayer(); $this->_TeamDifferencesComparisonLayer->buildLayer();
} }
@ -65,10 +65,10 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
$loop, $loop,
new ScheduleStep( new ScheduleStep(
"teamPerformanceToPerformanceDifferenceFactors[0] @ 1", "teamPerformanceToPerformanceDifferenceFactors[0] @ 1",
$localFactors[0], 1), &$localFactors[0], 1),
new ScheduleStep( new ScheduleStep(
sprintf("teamPerformanceToPerformanceDifferenceFactors[teamTeamDifferences = %d - 1] @ 2", $totalTeamDifferences), sprintf("teamPerformanceToPerformanceDifferenceFactors[teamTeamDifferences = %d - 1] @ 2", $totalTeamDifferences),
$localFactors[$totalTeamDifferences - 1], 2) &$localFactors[$totalTeamDifferences - 1], 2)
) )
); );
@ -83,11 +83,11 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
$itemsToSequence = array( $itemsToSequence = array(
new ScheduleStep( new ScheduleStep(
"send team perf to perf differences", "send team perf to perf differences",
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[0], &$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[0],
0), 0),
new ScheduleStep( new ScheduleStep(
"send to greater than or within factor", "send to greater than or within factor",
$teamDifferencesComparisonLayerLocalFactors[0], &$teamDifferencesComparisonLayerLocalFactors[0],
0) 0)
); );
@ -112,16 +112,16 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
array( array(
new ScheduleStep( new ScheduleStep(
sprintf("team perf to perf diff %d", $i), sprintf("team perf to perf diff %d", $i),
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$i], 0), &$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$i], 0),
new ScheduleStep( new ScheduleStep(
sprintf("greater than or within result factor %d", $i), sprintf("greater than or within result factor %d", $i),
$teamDifferencesComparisonLayerLocalFactors[$i], 0), &$teamDifferencesComparisonLayerLocalFactors[$i], 0),
new ScheduleStep( new ScheduleStep(
sprintf("team perf to perf diff factors [%d], 2", $i), sprintf("team perf to perf diff factors [%d], 2", $i),
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$i], 2) &$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$i], 2)
), sprintf("current forward schedule piece %d", $i)); ), sprintf("current forward schedule piece %d", $i));
$forwardScheduleList[] = &$currentForwardSchedulePiece; $forwardScheduleList[] = $currentForwardSchedulePiece;
} }
$forwardSchedule = new ScheduleSequence("forward schedule", $forwardScheduleList); $forwardSchedule = new ScheduleSequence("forward schedule", $forwardScheduleList);
@ -133,20 +133,24 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = &$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors(); $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = &$this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors();
$teamDifferencesComparisonLayerLocalFactors = &$this->_TeamDifferencesComparisonLayer->getLocalFactors(); $teamDifferencesComparisonLayerLocalFactors = &$this->_TeamDifferencesComparisonLayer->getLocalFactors();
$differencesFactor = &$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$totalTeamDifferences - 1 - $i];
$comparisonFactor = &$teamDifferencesComparisonLayerLocalFactors[$totalTeamDifferences - 1 - $i];
$performancesToDifferencesFactor = &$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$totalTeamDifferences - 1 - $i];
$currentBackwardSchedulePiece = new ScheduleSequence( $currentBackwardSchedulePiece = new ScheduleSequence(
"current backward schedule piece", "current backward schedule piece",
array( array(
new ScheduleStep( new ScheduleStep(
sprintf("teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - %d] @ 0", $i), sprintf("teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - %d] @ 0", $i),
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$totalTeamDifferences - 1 - $i], 0), $differencesFactor, 0),
new ScheduleStep( new ScheduleStep(
sprintf("greaterThanOrWithinResultFactors[totalTeamDifferences - 1 - %d] @ 0", $i), sprintf("greaterThanOrWithinResultFactors[totalTeamDifferences - 1 - %d] @ 0", $i),
$teamDifferencesComparisonLayerLocalFactors[$totalTeamDifferences - 1 - $i], 0), $comparisonFactor, 0),
new ScheduleStep( new ScheduleStep(
sprintf("teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - %d] @ 1", $i), sprintf("teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - %d] @ 1", $i),
$teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$totalTeamDifferences - 1 - $i], 1) $performancesToDifferencesFactor, 1)
)); ));
$backwardScheduleList[] = &$currentBackwardSchedulePiece; $backwardScheduleList[] = $currentBackwardSchedulePiece;
} }
$backwardSchedule = new ScheduleSequence("backward schedule", $backwardScheduleList); $backwardSchedule = new ScheduleSequence("backward schedule", $backwardScheduleList);

@ -39,14 +39,17 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
public function createPriorSchedule() public function createPriorSchedule()
{ {
return $this->scheduleSequence( $localFactors = &$this->getLocalFactors();
$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);
}, },
$this->getLocalFactors()), $localFactors),
"all player perf to team perf schedule"); "all player perf to team perf schedule");
return $sequence;
} }
protected function createPlayerToTeamSumFactor(&$teamMembers, &$sumVariable) protected function createPlayerToTeamSumFactor(&$teamMembers, &$sumVariable)
@ -69,7 +72,8 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
{ {
// BLOG // BLOG
$allFactors = array(); $allFactors = array();
foreach($this->getLocalFactors() as $currentFactor) $localFactors = &$this->getLocalFactors();
foreach($localFactors as &$currentFactor)
{ {
$numberOfMessages = $currentFactor->getNumberOfMessages(); $numberOfMessages = $currentFactor->getNumberOfMessages();
for($currentIteration = 1; $currentIteration < $numberOfMessages; $currentIteration++) for($currentIteration = 1; $currentIteration < $numberOfMessages; $currentIteration++)

@ -1,15 +1,20 @@
<?php <?php
namespace Moserware\Skills\TrueSkill\Layers; namespace Moserware\Skills\TrueSkill\Layers;
require_once(dirname(__FILE__) . "/../../Rating.php");
require_once(dirname(__FILE__) . "/../../FactorGraphs/Schedule.php"); require_once(dirname(__FILE__) . "/../../FactorGraphs/Schedule.php");
require_once(dirname(__FILE__) . "/../../FactorGraphs/Variable.php");
require_once(dirname(__FILE__) . "/../../Numerics/BasicMath.php"); require_once(dirname(__FILE__) . "/../../Numerics/BasicMath.php");
require_once(dirname(__FILE__) . "/../TrueSkillFactorGraph.php"); require_once(dirname(__FILE__) . "/../TrueSkillFactorGraph.php");
require_once(dirname(__FILE__) . "/../Factors/GaussianPriorFactor.php"); require_once(dirname(__FILE__) . "/../Factors/GaussianPriorFactor.php");
require_once(dirname(__FILE__) . "/TrueSkillFactorGraphLayer.php"); require_once(dirname(__FILE__) . "/TrueSkillFactorGraphLayer.php");
use Moserware\Skills\Rating;
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;
use Moserware\Skills\FactorGraphs\Variable;
use Moserware\Numerics\GaussianDistribution;
use Moserware\Skills\TrueSkill\TrueSkillFactorGraph; use Moserware\Skills\TrueSkill\TrueSkillFactorGraph;
use Moserware\Skills\TrueSkill\Factors\GaussianPriorFactor; use Moserware\Skills\TrueSkill\Factors\GaussianPriorFactor;
@ -27,11 +32,13 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
public function buildLayer() public function buildLayer()
{ {
foreach ($this->_teams as $currentTeam) $teams = &$this->_teams;
foreach ($teams as &$currentTeam)
{ {
$currentTeamSkills = array(); $currentTeamSkills = array();
foreach ($currentTeam->getAllPlayers() as $currentTeamPlayer) $currentTeamAllPlayers = &$currentTeam->getAllPlayers();
foreach ($currentTeamAllPlayers as &$currentTeamPlayer)
{ {
$currentTeamPlayerRating = $currentTeam->getRating($currentTeamPlayer); $currentTeamPlayerRating = $currentTeam->getRating($currentTeamPlayer);
$playerSkill = $this->createSkillOutputVariable($currentTeamPlayer); $playerSkill = $this->createSkillOutputVariable($currentTeamPlayer);
@ -47,17 +54,18 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
public function createPriorSchedule() public function createPriorSchedule()
{ {
$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);
}, },
$this->getLocalFactors()), $localFactors),
"All priors"); "All priors");
} }
private function createPriorFactor(&$player, &$priorRating, &$skillsVariable) private function createPriorFactor(&$player, Rating &$priorRating, Variable &$skillsVariable)
{ {
return new GaussianPriorFactor($priorRating->getMean(), return new GaussianPriorFactor($priorRating->getMean(),
square($priorRating->getStandardDeviation()) + square($priorRating->getStandardDeviation()) +
@ -67,8 +75,8 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
private function createSkillOutputVariable($key) private function createSkillOutputVariable($key)
{ {
$parentFactorGraph = $this->getParentFactorGraph(); $parentFactorGraph = &$this->getParentFactorGraph();
$variableFactory = $parentFactorGraph->getVariableFactory(); $variableFactory = &$parentFactorGraph->getVariableFactory();
return $variableFactory->createKeyedVariable($key, $key . "'s skill"); return $variableFactory->createKeyedVariable($key, $key . "'s skill");
} }
} }

@ -2,12 +2,14 @@
namespace Moserware\Skills\TrueSkill\Layers; namespace Moserware\Skills\TrueSkill\Layers;
require_once(dirname(__FILE__) . "/../../FactorGraphs/Schedule.php"); require_once(dirname(__FILE__) . "/../../FactorGraphs/Schedule.php");
require_once(dirname(__FILE__) . "/../../FactorGraphs/Variable.php");
require_once(dirname(__FILE__) . "/../../Numerics/BasicMath.php"); require_once(dirname(__FILE__) . "/../../Numerics/BasicMath.php");
require_once(dirname(__FILE__) . "/../TrueSkillFactorGraph.php"); require_once(dirname(__FILE__) . "/../TrueSkillFactorGraph.php");
require_once(dirname(__FILE__) . "/../Factors/GaussianLikelihoodFactor.php"); require_once(dirname(__FILE__) . "/../Factors/GaussianLikelihoodFactor.php");
require_once(dirname(__FILE__) . "/TrueSkillFactorGraphLayer.php"); require_once(dirname(__FILE__) . "/TrueSkillFactorGraphLayer.php");
use Moserware\Skills\FactorGraphs\ScheduleStep; use Moserware\Skills\FactorGraphs\ScheduleStep;
use Moserware\Skills\FactorGraphs\KeyedVariable;
use Moserware\Skills\TrueSkill\TrueSkillFactorGraph; use Moserware\Skills\TrueSkill\TrueSkillFactorGraph;
use Moserware\Skills\TrueSkill\Factors\GaussianLikelihoodFactor; use Moserware\Skills\TrueSkill\Factors\GaussianLikelihoodFactor;
@ -20,7 +22,10 @@ class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
public function buildLayer() public function buildLayer()
{ {
foreach ($this->getInputVariablesGroups() as $currentTeam) $inputVariablesGroups = &$this->getInputVariablesGroups();
$outputVariablesGroups = &$this->getOutputVariablesGroups();
foreach ($inputVariablesGroups as &$currentTeam)
{ {
$currentTeamPlayerPerformances = array(); $currentTeamPlayerPerformances = array();
@ -32,12 +37,11 @@ class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
$currentTeamPlayerPerformances[] = $playerPerformance; $currentTeamPlayerPerformances[] = $playerPerformance;
} }
$outputVariablesGroups = &$this->getOutputVariablesGroups();
$outputVariablesGroups[] = $currentTeamPlayerPerformances; $outputVariablesGroups[] = $currentTeamPlayerPerformances;
} }
} }
private function createLikelihood(&$playerSkill, &$playerPerformance) private function createLikelihood(KeyedVariable &$playerSkill, KeyedVariable &$playerPerformance)
{ {
return new GaussianLikelihoodFactor(square($this->getParentFactorGraph()->getGameInfo()->getBeta()), $playerPerformance, $playerSkill); return new GaussianLikelihoodFactor(square($this->getParentFactorGraph()->getGameInfo()->getBeta()), $playerPerformance, $playerSkill);
} }
@ -49,25 +53,27 @@ class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
public function createPriorSchedule() public function createPriorSchedule()
{ {
$localFactors = &$this->getLocalFactors();
return $this->scheduleSequence( return $this->scheduleSequence(
array_map( array_map(
function($likelihood) function($likelihood)
{ {
return new ScheduleStep("Skill to Perf step", $likelihood, 0); return new ScheduleStep("Skill to Perf step", $likelihood, 0);
}, },
$this->getLocalFactors()), $localFactors),
"All skill to performance sending"); "All skill to performance sending");
} }
public function createPosteriorSchedule() public function createPosteriorSchedule()
{ {
$localFactors = &$this->getLocalFactors();
return $this->scheduleSequence( return $this->scheduleSequence(
array_map( array_map(
function($likelihood) function($likelihood)
{ {
return new ScheduleStep("name", $likelihood, 1); return new ScheduleStep("name", $likelihood, 1);
}, },
$this->getLocalFactors()), $localFactors),
"All skill to performance sending"); "All skill to performance sending");
} }
} }

@ -21,7 +21,7 @@ class TeamDifferencesComparisonLayer extends TrueSkillFactorGraphLayer
{ {
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());
} }
@ -33,7 +33,7 @@ class TeamDifferencesComparisonLayer extends TrueSkillFactorGraphLayer
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

@ -22,18 +22,18 @@ class TeamPerformancesToTeamPerformanceDifferencesLayer extends TrueSkillFactorG
{ {
$inputVariablesGroups = &$this->getInputVariablesGroups(); $inputVariablesGroups = &$this->getInputVariablesGroups();
$inputVariablesGroupsCount = count($inputVariablesGroups); $inputVariablesGroupsCount = count($inputVariablesGroups);
$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);
// REVIEW: Does it make sense to have groups of one? // REVIEW: Does it make sense to have groups of one?
$outputVariablesGroup = &$this->getOutputVariablesGroups();
$outputVariablesGroup[] = array($currentDifference); $outputVariablesGroup[] = array($currentDifference);
} }
} }

@ -68,7 +68,8 @@ class TrueSkillFactorGraph extends FactorGraph
{ {
$lastOutput = null; $lastOutput = null;
foreach ($this->_layers as $currentLayer) $layers = &$this->_layers;
foreach ($layers as &$currentLayer)
{ {
if ($lastOutput != null) if ($lastOutput != null)
{ {
@ -91,9 +92,11 @@ class TrueSkillFactorGraph extends FactorGraph
{ {
$factorList = new FactorList(); $factorList = new FactorList();
foreach ($this->_layers as $currentLayer) $layers = &$this->_layers;
foreach ($layers as &$currentLayer)
{ {
foreach ($currentLayer->getLocalFactors() as $currentFactor) $localFactors = &$currentLayer->getLocalFactors();
foreach ($localFactors as &$currentFactor)
{ {
$factorList->addFactor($currentFactor); $factorList->addFactor($currentFactor);
} }
@ -107,7 +110,8 @@ class TrueSkillFactorGraph extends FactorGraph
{ {
$fullSchedule = array(); $fullSchedule = array();
foreach ($this->_layers as $currentLayer) $layers = &$this->_layers;
foreach ($layers as &$currentLayer)
{ {
$currentPriorSchedule = $currentLayer->createPriorSchedule(); $currentPriorSchedule = $currentLayer->createPriorSchedule();
if ($currentPriorSchedule != null) if ($currentPriorSchedule != null)
@ -118,7 +122,7 @@ class TrueSkillFactorGraph extends FactorGraph
$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)
@ -134,9 +138,10 @@ class TrueSkillFactorGraph extends FactorGraph
{ {
$result = new RatingContainer(); $result = new RatingContainer();
foreach ($this->_priorLayer->getOutputVariablesGroups() as $currentTeam) $priorLayerOutputVariablesGroups = &$this->_priorLayer->getOutputVariablesGroups();
foreach ($priorLayerOutputVariablesGroups as &$currentTeam)
{ {
foreach ($currentTeam as $currentPlayer) foreach ($currentTeam as &$currentPlayer)
{ {
$newRating = new Rating($currentPlayer->getValue()->getMean(), $newRating = new Rating($currentPlayer->getValue()->getMean(),
$currentPlayer->getValue()->getStandardDeviation()); $currentPlayer->getValue()->getStandardDeviation());

@ -2,6 +2,7 @@
namespace Moserware\Skills\TrueSkill; namespace Moserware\Skills\TrueSkill;
require_once(dirname(__FILE__) . "/../GameInfo.php");
require_once(dirname(__FILE__) . "/../Guard.php"); require_once(dirname(__FILE__) . "/../Guard.php");
require_once(dirname(__FILE__) . "/../PairwiseComparison.php"); require_once(dirname(__FILE__) . "/../PairwiseComparison.php");
require_once(dirname(__FILE__) . "/../RankSorter.php"); require_once(dirname(__FILE__) . "/../RankSorter.php");
@ -17,6 +18,7 @@ require_once(dirname(__FILE__) . "/../Numerics/BasicMath.php");
require_once(dirname(__FILE__) . "/DrawMargin.php"); require_once(dirname(__FILE__) . "/DrawMargin.php");
require_once(dirname(__FILE__) . "/TruncatedGaussianCorrectionFunctions.php"); require_once(dirname(__FILE__) . "/TruncatedGaussianCorrectionFunctions.php");
use Moserware\Skills\GameInfo;
use Moserware\Skills\Guard; use Moserware\Skills\Guard;
use Moserware\Skills\PairwiseComparison; use Moserware\Skills\PairwiseComparison;
use Moserware\Skills\RankSorter; use Moserware\Skills\RankSorter;
@ -42,7 +44,7 @@ class TwoPlayerTrueSkillCalculator extends SkillCalculator
parent::__construct(SkillCalculatorSupportedOptions::NONE, TeamsRange::exactly(2), PlayersRange::exactly(1)); parent::__construct(SkillCalculatorSupportedOptions::NONE, TeamsRange::exactly(2), PlayersRange::exactly(1));
} }
public function calculateNewRatings($gameInfo, public function calculateNewRatings(GameInfo &$gameInfo,
array $teams, array $teams,
array $teamRanks) array $teamRanks)
{ {
@ -82,7 +84,7 @@ class TwoPlayerTrueSkillCalculator extends SkillCalculator
return $results; return $results;
} }
private static function calculateNewRating($gameInfo, $selfRating, $opponentRating, $comparison) private static function calculateNewRating(GameInfo $gameInfo, Rating $selfRating, Rating $opponentRating, $comparison)
{ {
$drawMargin = DrawMargin::getDrawMarginFromDrawProbability($gameInfo->getDrawProbability(), $drawMargin = DrawMargin::getDrawMarginFromDrawProbability($gameInfo->getDrawProbability(),
$gameInfo->getBeta()); $gameInfo->getBeta());
@ -138,7 +140,7 @@ class TwoPlayerTrueSkillCalculator extends SkillCalculator
} }
/// <inheritdoc/> /// <inheritdoc/>
public function calculateMatchQuality($gameInfo, array $teams) public function calculateMatchQuality(GameInfo $gameInfo, array $teams)
{ {
Guard::argumentNotNull($gameInfo, "gameInfo"); Guard::argumentNotNull($gameInfo, "gameInfo");
$this->validateTeamCountAndPlayersCountPerTeam($teams); $this->validateTeamCountAndPlayersCountPerTeam($teams);

@ -47,7 +47,7 @@ class TwoTeamTrueSkillCalculator extends SkillCalculator
parent::__construct(SkillCalculatorSupportedOptions::NONE, TeamsRange::exactly(2), PlayersRange::atLeast(1)); parent::__construct(SkillCalculatorSupportedOptions::NONE, TeamsRange::exactly(2), PlayersRange::atLeast(1));
} }
public function calculateNewRatings($gameInfo, public function calculateNewRatings(GameInfo $gameInfo,
array $teams, array $teams,
array $teamRanks) array $teamRanks)
{ {
@ -164,7 +164,7 @@ class TwoTeamTrueSkillCalculator extends SkillCalculator
} }
/// <inheritdoc/> /// <inheritdoc/>
public function calculateMatchQuality($gameInfo, array $teams) public function calculateMatchQuality(GameInfo $gameInfo, array $teams)
{ {
Guard::argumentNotNull($gameInfo, "gameInfo"); Guard::argumentNotNull($gameInfo, "gameInfo");
$this->validateTeamCountAndPlayersCountPerTeam($teams); $this->validateTeamCountAndPlayersCountPerTeam($teams);