mirror of
https://github.com/furyfire/trueskill.git
synced 2025-03-29 04:13:22 +00:00
Start of factor graph port. Things don't work yet, but a lot of syntax updates towards PHP
This commit is contained in:
96
PHPSkills/FactorGraphs/Factor.php
Normal file
96
PHPSkills/FactorGraphs/Factor.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
namespace Moserware\Skills\FactorGraphs;
|
||||
|
||||
require_once(dirname(__FILE__) . "../Guard.php");
|
||||
require_once(dirname(__FILE__) . "../HashMap.php");
|
||||
|
||||
use Moserware\Skills\Guard;
|
||||
use Moserware\Skills\HashMap;
|
||||
|
||||
class Factor
|
||||
{
|
||||
private $_messages = array();
|
||||
private $_messageToVariableBinding;
|
||||
|
||||
private $_name;
|
||||
private $_variables = array();
|
||||
|
||||
protected function __construct($name)
|
||||
{
|
||||
$this->_name = "Factor[" . $name . "]";
|
||||
$this->_messagesToVariableBinding = new HashMap();
|
||||
}
|
||||
|
||||
/// Returns the log-normalization constant of that factor
|
||||
public function getLogNormalization()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Returns the number of messages that the factor has
|
||||
public function getNumberOfMessages()
|
||||
{
|
||||
return count($this->_messages);
|
||||
}
|
||||
|
||||
protected function getVariables()
|
||||
{
|
||||
return $this->_variables;
|
||||
}
|
||||
|
||||
protected function getMessages()
|
||||
{
|
||||
return $this->_messages;
|
||||
}
|
||||
|
||||
/// Update the message and marginal of the i-th variable that the factor is connected to
|
||||
public function updateMessageIndex($messageIndex)
|
||||
{
|
||||
Guard::argumentIsValidIndex($messageIndex, count($this->_messages), "messageIndex");
|
||||
return $this->updateMessageVariable($this->_messages[$messageIndex], $this->_messageToVariableBinding->getValue($messageIndex));
|
||||
}
|
||||
|
||||
protected function updateMessageVariable($message, $variable)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
/// Resets the marginal of the variables a factor is connected to
|
||||
public function resetMarginals()
|
||||
{
|
||||
foreach ($this->_messageToVariableBindings->getAllValues() as $currentVariable)
|
||||
{
|
||||
$currentVariable->resetToPrior();
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends the ith message to the marginal and returns the log-normalization constant
|
||||
public function sendMessageIndex($messageIndex)
|
||||
{
|
||||
Guard::argumentIsValidIndex($messageIndex, count($_messages), "messageIndex");
|
||||
|
||||
$message = $this->_messages[$messageIndex];
|
||||
$variable = $this->_messageToVariableBinding->getValue($message);
|
||||
return $this->sendMessageVariable($message, $variable);
|
||||
}
|
||||
|
||||
protected abstract function sendMessageVariable($message, $variable);
|
||||
|
||||
public abstract function createVariableToMessageBinding($variable);
|
||||
|
||||
protected function createVariableToMessageBinding($variable, $message)
|
||||
{
|
||||
$index = count($this->_messages);
|
||||
$this->_messages[] = $message;
|
||||
$this->_messageToVariableBinding->setValue($message) = $variable;
|
||||
$this->_variables[] = $variable;
|
||||
return $message;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return ($this->_name != null) ? $this->_name : base::__toString();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
18
PHPSkills/FactorGraphs/FactorGraph.php
Normal file
18
PHPSkills/FactorGraphs/FactorGraph.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
namespace Moserware\Skills\FactorGraphs;
|
||||
|
||||
class FactorGraph
|
||||
{
|
||||
private $_variableFactory;
|
||||
|
||||
public function getVariableFactory()
|
||||
{
|
||||
return $this->_variableFactory;
|
||||
}
|
||||
|
||||
public function setVariableFactory($factory)
|
||||
{
|
||||
$this->_variableFactory = $factory;
|
||||
}
|
||||
}
|
||||
?>
|
67
PHPSkills/FactorGraphs/FactorGraphLayer.php
Normal file
67
PHPSkills/FactorGraphs/FactorGraphLayer.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
namespace Moserware\Skills\FactorGraphs;
|
||||
|
||||
abstract class FactorGraphLayer
|
||||
{
|
||||
private $_localFactors = array();
|
||||
private $_outputVariablesGroups = array();
|
||||
private $_inputVariablesGroups = array();
|
||||
private $_parentFactorGraph;
|
||||
|
||||
protected function __construct($parentGraph)
|
||||
{
|
||||
$this->_parentFactorGraph = $parentGraph;
|
||||
}
|
||||
|
||||
protected function getInputVariablesGroups()
|
||||
{
|
||||
return $this->_inputVariablesGroups;
|
||||
}
|
||||
|
||||
// HACK
|
||||
|
||||
public function getParentFactorGraph()
|
||||
{
|
||||
return $this->_parentFactorGraph;
|
||||
}
|
||||
|
||||
public function getOutputVariablesGroups()
|
||||
{
|
||||
return $this->_outputVariablesGroups;
|
||||
}
|
||||
|
||||
public function getLocalFactors()
|
||||
{
|
||||
return $this->_localFactors;
|
||||
}
|
||||
|
||||
public function setInputVariablesGroups($value)
|
||||
{
|
||||
$this->_inputVariablesGroups = $value;
|
||||
}
|
||||
|
||||
protected function scheduleSequence($itemsToSequence)
|
||||
{
|
||||
return new ScheduleSequence($itemsToSequence);
|
||||
}
|
||||
|
||||
protected function addLayerFactor($factor)
|
||||
{
|
||||
$this->_localFactors[] = $factor;
|
||||
}
|
||||
|
||||
public abstract function buildLayer();
|
||||
|
||||
public function createPriorSchedule()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function createPosteriorSchedule()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
57
PHPSkills/FactorGraphs/FactorList.php
Normal file
57
PHPSkills/FactorGraphs/FactorList.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Moserware\Skills\FactorGraphs;
|
||||
|
||||
/// <summary>
|
||||
/// Helper class for computing the factor graph's normalization constant.
|
||||
/// </summary>
|
||||
class FactorList
|
||||
{
|
||||
private $_list = array();
|
||||
|
||||
public function getLogNormalization()
|
||||
{
|
||||
foreach($this->_list as $currentFactor)
|
||||
{
|
||||
$currentFactor->resetMarginals();
|
||||
}
|
||||
|
||||
$sumLogZ = 0.0;
|
||||
|
||||
$listCount = count($this->_list);
|
||||
|
||||
for ($i = 0; $i < $listCount; $i++)
|
||||
{
|
||||
$f = $this->_list[$i];
|
||||
|
||||
$numberOfMessages = $f->getNumberOfMessages();
|
||||
|
||||
for ($j = 0; $j < $numberOfMessages; $j++)
|
||||
{
|
||||
$sumLogZ += $f->sendMessageIndex($j);
|
||||
}
|
||||
}
|
||||
|
||||
$sumLogS = 0;
|
||||
|
||||
foreach($this->_list as $currentFactor)
|
||||
{
|
||||
$sumLogS = $sumLogS + $currentFactor->getLogNormalization();
|
||||
}
|
||||
|
||||
return $sumLogZ + $sumLogS;
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->_list);
|
||||
}
|
||||
|
||||
public function addFactor(Factor $factor)
|
||||
{
|
||||
$this->_list[] = $factor;
|
||||
return $factor;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
28
PHPSkills/FactorGraphs/Message.php
Normal file
28
PHPSkills/FactorGraphs/Message.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
namespace Moserware\Skills\FactorGraphs;
|
||||
|
||||
class Message
|
||||
{
|
||||
private $_nameFormat;
|
||||
private $_nameFormatArgs;
|
||||
private $_value;
|
||||
|
||||
public function __construct($value = null, $nameFormat = null, $args = null)
|
||||
{
|
||||
$this->_nameFormat = $nameFormat;
|
||||
$this->_nameFormatArgs = $args;
|
||||
$this->_value = $value;
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->_value;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->_nameFormat; //return (_NameFormat == null) ? base.ToString() : String.Format(_NameFormat, _NameFormatArgs);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
89
PHPSkills/FactorGraphs/Schedule.php
Normal file
89
PHPSkills/FactorGraphs/Schedule.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
namespace Moserware\Skills\FactorGraphs;
|
||||
|
||||
abstract class Schedule
|
||||
{
|
||||
private $_name;
|
||||
|
||||
protected function __construct($name)
|
||||
{
|
||||
$this->_name = $name;
|
||||
}
|
||||
|
||||
public abstract function visit($depth = -1, $maxDepth = 0);
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->_name;
|
||||
}
|
||||
}
|
||||
|
||||
class ScheduleStep extends Schedule
|
||||
{
|
||||
private $_factor;
|
||||
private $_index;
|
||||
|
||||
public function __construct($name, $factor, $index)
|
||||
{
|
||||
parent::__construct($name);
|
||||
$this->_factor = $factor;
|
||||
$this->_index = $index;
|
||||
}
|
||||
|
||||
public function visit($depth, $maxDepth)
|
||||
{
|
||||
$delta = $this->_factor->updateMessageIndex($this->_index);
|
||||
return $delta;
|
||||
}
|
||||
}
|
||||
|
||||
class ScheduleSequence extends Schedule
|
||||
{
|
||||
private $_schedules;
|
||||
|
||||
public function __construct($name, $schedules)
|
||||
{
|
||||
parent::__construct($name);
|
||||
$this->_schedules = $schedules;
|
||||
}
|
||||
|
||||
public function visit($depth, $maxDepth)
|
||||
{
|
||||
$maxDelta = 0;
|
||||
|
||||
foreach ($this->_schedules as $currentSchedule)
|
||||
{
|
||||
$maxDelta = max($currentSchedule->visit($depth + 1, $maxDepth), $maxDelta);
|
||||
}
|
||||
|
||||
return $maxDelta;
|
||||
}
|
||||
}
|
||||
|
||||
class ScheduleLoop extends Schedule
|
||||
{
|
||||
private $_maxDelta;
|
||||
private $_scheduleToLoop;
|
||||
|
||||
public function __construct($name, Schedule $scheduleToLoop, $maxDelta)
|
||||
{
|
||||
parent::__construct($name);
|
||||
$this->_scheduleToLoop = $scheduleToLoop;
|
||||
$this->_maxDelta = $maxDelta;
|
||||
}
|
||||
|
||||
public function visit($depth, $maxDepth)
|
||||
{
|
||||
$totalIterations = 1;
|
||||
$delta = $this->_scheduleToLoop->visit($depth + 1, $maxDepth);
|
||||
while ($delta > $this->_maxDelta)
|
||||
{
|
||||
$delta = $this->_scheduleToLoop->visit($depth + 1, $maxDepth);
|
||||
$totalIterations++;
|
||||
}
|
||||
|
||||
return $delta;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
71
PHPSkills/FactorGraphs/Variable.php
Normal file
71
PHPSkills/FactorGraphs/Variable.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
namespace Moserware\Skills\FactorGraphs;
|
||||
|
||||
class Variable
|
||||
{
|
||||
private $_name;
|
||||
private $_prior;
|
||||
private $_value;
|
||||
|
||||
public function __construct($name, $prior)
|
||||
{
|
||||
$this->_name = "Variable[" . $name . "]";
|
||||
$this->_prior = $prior;
|
||||
$this->resetToPrior();
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->_value;
|
||||
}
|
||||
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->_value = $value;
|
||||
}
|
||||
|
||||
public function resetToPrior()
|
||||
{
|
||||
$this->_value = $this->_prior;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->_name;
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultVariable extends Variable
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct("Default", null);
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setValue($value)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
class KeyedVariable extends Variable
|
||||
{
|
||||
private $_key;
|
||||
public function __construct($key, $name, $prior)
|
||||
{
|
||||
parent::__construct($name, $prior);
|
||||
$this->_key = $key;
|
||||
}
|
||||
|
||||
public function getKey()
|
||||
{
|
||||
return $this->_key;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
28
PHPSkills/FactorGraphs/VariableFactory.php
Normal file
28
PHPSkills/FactorGraphs/VariableFactory.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Moserware\Skills\FactorGraphs;
|
||||
|
||||
class VariableFactory
|
||||
{
|
||||
// using a Func<TValue> to encourage fresh copies in case it's overwritten
|
||||
private $_variablePriorInitializer;
|
||||
|
||||
public function __construct($variablePriorInitializer)
|
||||
{
|
||||
$this->_variablePriorInitializer = $variablePriorInitializer;
|
||||
}
|
||||
|
||||
public function createBasicVariable()
|
||||
{
|
||||
$newVar = new Variable($this->_variablePriorInitializer());
|
||||
return $newVar;
|
||||
}
|
||||
|
||||
public function createKeyedVariable($key)
|
||||
{
|
||||
$newVar = new KeyedVariable($key, $this->_variablePriorInitializer());
|
||||
return $newVar;
|
||||
}
|
||||
}s
|
||||
|
||||
?>
|
Reference in New Issue
Block a user