mirror of
				https://github.com/furyfire/trueskill.git
				synced 2025-11-04 10:12:28 +01: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