mirror of
https://github.com/furyfire/trueskill.git
synced 2025-01-15 17:37:39 +00:00
Compare commits
9 Commits
7b09658c25
...
063a64a4f6
Author | SHA1 | Date | |
---|---|---|---|
063a64a4f6 | |||
796bd993d0 | |||
bbff1fbbbc | |||
ae5d2a8b73 | |||
0095829906 | |||
e5a96226ca | |||
11fafc129a | |||
73ef2f45c8 | |||
fd91e9b0c1 |
70
composer.lock
generated
70
composer.lock
generated
@ -822,21 +822,21 @@
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v4.18.0",
|
||||
"version": "v4.19.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999"
|
||||
"reference": "4e1b88d21c69391150ace211e9eaf05810858d0b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999",
|
||||
"reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4e1b88d21c69391150ace211e9eaf05810858d0b",
|
||||
"reference": "4e1b88d21c69391150ace211e9eaf05810858d0b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-tokenizer": "*",
|
||||
"php": ">=7.0"
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"ircmaxell/php-yacc": "^0.0.7",
|
||||
@ -872,9 +872,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.19.1"
|
||||
},
|
||||
"time": "2023-12-10T21:03:43+00:00"
|
||||
"time": "2024-03-17T08:10:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
@ -1287,16 +1287,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.10.60",
|
||||
"version": "1.10.63",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "95dcea7d6c628a3f2f56d091d8a0219485a86bbe"
|
||||
"reference": "ad12836d9ca227301f5fb9960979574ed8628339"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/95dcea7d6c628a3f2f56d091d8a0219485a86bbe",
|
||||
"reference": "95dcea7d6c628a3f2f56d091d8a0219485a86bbe",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/ad12836d9ca227301f5fb9960979574ed8628339",
|
||||
"reference": "ad12836d9ca227301f5fb9960979574ed8628339",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1345,20 +1345,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-03-07T13:30:19+00:00"
|
||||
"time": "2024-03-18T16:53:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "10.1.13",
|
||||
"version": "10.1.14",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "d51c3aec14896d5e80b354fad58e998d1980f8f8"
|
||||
"reference": "e3f51450ebffe8e0efdf7346ae966a656f7d5e5b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d51c3aec14896d5e80b354fad58e998d1980f8f8",
|
||||
"reference": "d51c3aec14896d5e80b354fad58e998d1980f8f8",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e3f51450ebffe8e0efdf7346ae966a656f7d5e5b",
|
||||
"reference": "e3f51450ebffe8e0efdf7346ae966a656f7d5e5b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1415,7 +1415,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.13"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.14"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1423,7 +1423,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-03-09T16:54:15+00:00"
|
||||
"time": "2024-03-12T15:33:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
@ -1670,16 +1670,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "10.5.12",
|
||||
"version": "10.5.13",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "41a9886b85ac7bf3929853baf96b95361cd69d2b"
|
||||
"reference": "20a63fc1c6db29b15da3bd02d4b6cf59900088a7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/41a9886b85ac7bf3929853baf96b95361cd69d2b",
|
||||
"reference": "41a9886b85ac7bf3929853baf96b95361cd69d2b",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/20a63fc1c6db29b15da3bd02d4b6cf59900088a7",
|
||||
"reference": "20a63fc1c6db29b15da3bd02d4b6cf59900088a7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1751,7 +1751,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.12"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.13"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1767,7 +1767,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-03-09T12:04:07+00:00"
|
||||
"time": "2024-03-12T15:37:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psalm/plugin-phpunit",
|
||||
@ -1934,16 +1934,16 @@
|
||||
},
|
||||
{
|
||||
"name": "rector/rector",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/rectorphp/rector.git",
|
||||
"reference": "7596fa6da06c6a20c012efe6bb3d9188a9113b11"
|
||||
"reference": "c59507a9090b465d65e1aceed91e5b81986e375b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/rectorphp/rector/zipball/7596fa6da06c6a20c012efe6bb3d9188a9113b11",
|
||||
"reference": "7596fa6da06c6a20c012efe6bb3d9188a9113b11",
|
||||
"url": "https://api.github.com/repos/rectorphp/rector/zipball/c59507a9090b465d65e1aceed91e5b81986e375b",
|
||||
"reference": "c59507a9090b465d65e1aceed91e5b81986e375b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1978,7 +1978,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/rectorphp/rector/issues",
|
||||
"source": "https://github.com/rectorphp/rector/tree/1.0.2"
|
||||
"source": "https://github.com/rectorphp/rector/tree/1.0.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1986,7 +1986,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-03-03T12:32:31+00:00"
|
||||
"time": "2024-03-14T15:04:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
@ -3661,16 +3661,16 @@
|
||||
},
|
||||
{
|
||||
"name": "vimeo/psalm",
|
||||
"version": "5.23.0",
|
||||
"version": "5.23.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vimeo/psalm.git",
|
||||
"reference": "005e3184fb6de4350a873b9b8c4dc3cede9db762"
|
||||
"reference": "8471a896ccea3526b26d082f4461eeea467f10a4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/vimeo/psalm/zipball/005e3184fb6de4350a873b9b8c4dc3cede9db762",
|
||||
"reference": "005e3184fb6de4350a873b9b8c4dc3cede9db762",
|
||||
"url": "https://api.github.com/repos/vimeo/psalm/zipball/8471a896ccea3526b26d082f4461eeea467f10a4",
|
||||
"reference": "8471a896ccea3526b26d082f4461eeea467f10a4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3767,7 +3767,7 @@
|
||||
"issues": "https://github.com/vimeo/psalm/issues",
|
||||
"source": "https://github.com/vimeo/psalm"
|
||||
},
|
||||
"time": "2024-03-09T19:39:11+00:00"
|
||||
"time": "2024-03-11T20:33:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
|
@ -8,7 +8,7 @@ use DNW\Skills\Guard;
|
||||
use DNW\Skills\HashMap;
|
||||
use Exception;
|
||||
|
||||
abstract class Factor implements \Stringable
|
||||
abstract class Factor
|
||||
{
|
||||
/**
|
||||
* @var Message[] $messages
|
||||
@ -17,16 +17,13 @@ abstract class Factor implements \Stringable
|
||||
|
||||
private readonly HashMap $messageToVariableBinding;
|
||||
|
||||
private readonly string $name;
|
||||
|
||||
/**
|
||||
* @var Variable[] $variables
|
||||
*/
|
||||
private array $variables = [];
|
||||
|
||||
protected function __construct(string $name)
|
||||
protected function __construct()
|
||||
{
|
||||
$this->name = 'Factor[' . $name . ']';
|
||||
$this->messageToVariableBinding = new HashMap();
|
||||
}
|
||||
|
||||
@ -80,7 +77,7 @@ abstract class Factor implements \Stringable
|
||||
|
||||
protected function updateMessageVariable(Message $message, Variable $variable): float
|
||||
{
|
||||
throw new Exception();
|
||||
throw new Exception("Must override updateMessageVariable(" . $message::class . ", " . $variable::class . ")");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -121,9 +118,4 @@ abstract class Factor implements \Stringable
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
@ -70,9 +70,9 @@ abstract class FactorGraphLayer
|
||||
/**
|
||||
* @param Schedule[] $itemsToSequence
|
||||
*/
|
||||
protected function scheduleSequence(array $itemsToSequence, string $name): ScheduleSequence
|
||||
protected function scheduleSequence(array $itemsToSequence): ScheduleSequence
|
||||
{
|
||||
return new ScheduleSequence($name, $itemsToSequence);
|
||||
return new ScheduleSequence($itemsToSequence);
|
||||
}
|
||||
|
||||
protected function addLayerFactor(Factor $factor): void
|
||||
|
@ -6,9 +6,9 @@ namespace DNW\Skills\FactorGraphs;
|
||||
|
||||
class KeyedVariable extends Variable
|
||||
{
|
||||
public function __construct(private readonly mixed $key, string $name, mixed $prior)
|
||||
public function __construct(private readonly mixed $key, mixed $prior)
|
||||
{
|
||||
parent::__construct($name, $prior);
|
||||
parent::__construct($prior);
|
||||
}
|
||||
|
||||
public function getKey(): mixed
|
||||
|
@ -6,9 +6,9 @@ namespace DNW\Skills\FactorGraphs;
|
||||
|
||||
use DNW\Skills\Numerics\GaussianDistribution;
|
||||
|
||||
class Message implements \Stringable
|
||||
class Message
|
||||
{
|
||||
public function __construct(private GaussianDistribution $value, private readonly string $name)
|
||||
public function __construct(private GaussianDistribution $value)
|
||||
{
|
||||
}
|
||||
|
||||
@ -21,9 +21,4 @@ class Message implements \Stringable
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
@ -4,16 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace DNW\Skills\FactorGraphs;
|
||||
|
||||
abstract class Schedule implements \Stringable
|
||||
abstract class Schedule
|
||||
{
|
||||
protected function __construct(private readonly string $name)
|
||||
{
|
||||
}
|
||||
|
||||
abstract public function visit(int $depth = -1, int $maxDepth = 0): float;
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,8 @@ namespace DNW\Skills\FactorGraphs;
|
||||
|
||||
class ScheduleLoop extends Schedule
|
||||
{
|
||||
public function __construct(string $name, private readonly Schedule $scheduleToLoop, private readonly float $maxDelta)
|
||||
public function __construct(private readonly Schedule $scheduleToLoop, private readonly float $maxDelta)
|
||||
{
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
public function visit(int $depth = -1, int $maxDepth = 0): float
|
||||
|
@ -9,9 +9,8 @@ class ScheduleSequence extends Schedule
|
||||
/**
|
||||
* @param Schedule[] $schedules
|
||||
*/
|
||||
public function __construct(string $name, private readonly array $schedules)
|
||||
public function __construct(private readonly array $schedules)
|
||||
{
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
public function visit(int $depth = -1, int $maxDepth = 0): float
|
||||
|
@ -6,15 +6,12 @@ namespace DNW\Skills\FactorGraphs;
|
||||
|
||||
class ScheduleStep extends Schedule
|
||||
{
|
||||
public function __construct(string $name, private readonly Factor $factor, private readonly int $index)
|
||||
public function __construct(private readonly Factor $factor, private readonly int $index)
|
||||
{
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
public function visit(int $depth = -1, int $maxDepth = 0): float
|
||||
{
|
||||
$currentFactor = $this->factor;
|
||||
|
||||
return $currentFactor->updateMessageIndex($this->index);
|
||||
return $this->factor->updateMessageIndex($this->index);
|
||||
}
|
||||
}
|
||||
|
@ -6,15 +6,12 @@ namespace DNW\Skills\FactorGraphs;
|
||||
|
||||
use DNW\Skills\Numerics\GaussianDistribution;
|
||||
|
||||
class Variable implements \Stringable
|
||||
class Variable
|
||||
{
|
||||
private readonly string $name;
|
||||
|
||||
private mixed $value;
|
||||
|
||||
public function __construct(string $name, private GaussianDistribution $prior)
|
||||
public function __construct(private GaussianDistribution $prior)
|
||||
{
|
||||
$this->name = 'Variable[' . $name . ']';
|
||||
$this->resetToPrior();
|
||||
}
|
||||
|
||||
@ -32,9 +29,4 @@ class Variable implements \Stringable
|
||||
{
|
||||
$this->value = $this->prior;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
@ -10,17 +10,17 @@ class VariableFactory
|
||||
{
|
||||
}
|
||||
|
||||
public function createBasicVariable(string $name): Variable
|
||||
public function createBasicVariable(): Variable
|
||||
{
|
||||
$initializer = $this->variablePriorInitializer;
|
||||
|
||||
return new Variable($name, $initializer());
|
||||
return new Variable($initializer());
|
||||
}
|
||||
|
||||
public function createKeyedVariable(mixed $key, string $name): KeyedVariable
|
||||
public function createKeyedVariable(mixed $key): KeyedVariable
|
||||
{
|
||||
$initializer = $this->variablePriorInitializer;
|
||||
|
||||
return new KeyedVariable($key, $name, $initializer());
|
||||
return new KeyedVariable($key, $initializer());
|
||||
}
|
||||
}
|
||||
|
@ -19,16 +19,16 @@ class HashMap
|
||||
*/
|
||||
private array $hashToKey = [];
|
||||
|
||||
public function getValue(string|object $key): mixed
|
||||
public function getValue(object $key): object
|
||||
{
|
||||
$hash = self::getHash($key);
|
||||
$hash = spl_object_id($key);
|
||||
|
||||
return $this->hashToValue[$hash];
|
||||
}
|
||||
|
||||
public function setValue(string|object $key, mixed $value): self
|
||||
public function setValue(object $key, mixed $value): self
|
||||
{
|
||||
$hash = self::getHash($key);
|
||||
$hash = spl_object_id($key);
|
||||
$this->hashToKey[$hash] = $key;
|
||||
$this->hashToValue[$hash] = $value;
|
||||
|
||||
@ -55,13 +55,4 @@ class HashMap
|
||||
{
|
||||
return count($this->hashToKey);
|
||||
}
|
||||
|
||||
private static function getHash(string|object $key): string
|
||||
{
|
||||
if (is_object($key)) {
|
||||
return spl_object_hash($key);
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,12 @@ namespace DNW\Skills\Numerics;
|
||||
* @author Jeff Moser <jeff@moserware.com>
|
||||
* @copyright 2010 Jeff Moser
|
||||
*/
|
||||
class GaussianDistribution implements \Stringable
|
||||
class GaussianDistribution
|
||||
{
|
||||
private const DEFAULT_STANDARD_DEVIATION = 1.0;
|
||||
|
||||
private const DEFAULT_MEAN = 0.0;
|
||||
|
||||
/**
|
||||
* Square Root 2π.
|
||||
* Precalculated constant for performance reasons
|
||||
@ -31,17 +35,21 @@ class GaussianDistribution implements \Stringable
|
||||
private const M_LOG_SQRT_2_PI = 0.9189385332046727417803297364056176398613974736377834128171515404;
|
||||
|
||||
// precision and precisionMean are used because they make multiplying and dividing simpler
|
||||
// (the the accompanying math paper for more details)
|
||||
private float $precision;
|
||||
// (see the accompanying math paper for more details)
|
||||
private float $precision = 1.0;
|
||||
|
||||
private float $precisionMean;
|
||||
private float $precisionMean = 0.0;
|
||||
|
||||
private float $variance;
|
||||
private float $variance = 1.0;
|
||||
|
||||
public function __construct(private float $mean = 0.0, private float $standardDeviation = 1.0)
|
||||
public function __construct(private float $mean = self::DEFAULT_MEAN, private float $standardDeviation = self::DEFAULT_STANDARD_DEVIATION)
|
||||
{
|
||||
$this->variance = BasicMath::square($standardDeviation);
|
||||
if ($mean == self::DEFAULT_MEAN && $standardDeviation == self::DEFAULT_STANDARD_DEVIATION) {
|
||||
//Use all the defaults
|
||||
return;
|
||||
}
|
||||
|
||||
$this->variance = BasicMath::square($standardDeviation);
|
||||
if ($this->variance != 0) {
|
||||
$this->precision = 1.0 / $this->variance;
|
||||
$this->precisionMean = $this->precision * $this->mean;
|
||||
@ -180,7 +188,7 @@ class GaussianDistribution implements \Stringable
|
||||
return $multiplier * $expPart;
|
||||
}
|
||||
|
||||
public static function cumulativeTo(float $x, float $mean = 0.0, float $standardDeviation = 1.0): float
|
||||
public static function cumulativeTo(float $x): float
|
||||
{
|
||||
$result = GaussianDistribution::errorFunctionCumulativeTo(-M_SQRT1_2 * $x);
|
||||
|
||||
@ -270,9 +278,4 @@ class GaussianDistribution implements \Stringable
|
||||
// From numerical recipes, page 320
|
||||
return $mean - M_SQRT2 * $standardDeviation * GaussianDistribution::inverseErrorFunctionCumulativeTo(2 * $x);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('mean=%.4f standardDeviation=%.4f', $this->mean, $this->standardDeviation);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ namespace DNW\Skills;
|
||||
/**
|
||||
* Represents a player who has a Rating.
|
||||
*/
|
||||
class Player implements ISupportPartialPlay, ISupportPartialUpdate, \Stringable
|
||||
class Player implements ISupportPartialPlay, ISupportPartialUpdate
|
||||
{
|
||||
private const DEFAULT_PARTIAL_PLAY_PERCENTAGE = 1.0; // = 100% play time
|
||||
|
||||
@ -20,7 +20,7 @@ class Player implements ISupportPartialPlay, ISupportPartialUpdate, \Stringable
|
||||
/**
|
||||
* Constructs a player.
|
||||
*
|
||||
* @param mixed $Id The identifier for the player, such as a name.
|
||||
* @param mixed $Id The identifier for the player, such as a name.
|
||||
* @param float $partialPlayPercentage The weight percentage to give this player when calculating a new rank.
|
||||
* @param float $partialUpdatePercentage Indicated how much of a skill update a player should receive where 0 represents no update and 1.0 represents 100% of the update.
|
||||
*/
|
||||
@ -59,9 +59,4 @@ class Player implements ISupportPartialPlay, ISupportPartialUpdate, \Stringable
|
||||
{
|
||||
return $this->PartialUpdatePercentage;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return (string)$this->Id;
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use DNW\Skills\Numerics\GaussianDistribution;
|
||||
/**
|
||||
* Container for a player's rating.
|
||||
*/
|
||||
class Rating implements \Stringable
|
||||
class Rating
|
||||
{
|
||||
private const CONSERVATIVE_STANDARD_DEVIATION_MULTIPLIER = 3;
|
||||
|
||||
@ -73,9 +73,4 @@ class Rating implements \Stringable
|
||||
|
||||
return new Rating($partialPosteriorGaussion->getMean(), $partialPosteriorGaussion->getStandardDeviation(), $prior->conservativeStandardDeviationMultiplier);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('mean=%.4f, standardDeviation=%.4f', $this->mean, $this->standardDeviation);
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ abstract class GaussianFactor extends Factor
|
||||
$variable,
|
||||
new Message(
|
||||
$newDistribution,
|
||||
sprintf('message from %s to %s', (string)$this, (string)$variable)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -16,12 +16,9 @@ use DNW\Skills\TrueSkill\TruncatedGaussianCorrectionFunctions;
|
||||
*/
|
||||
class GaussianGreaterThanFactor extends GaussianFactor
|
||||
{
|
||||
private readonly float $epsilon;
|
||||
|
||||
public function __construct(float $epsilon, Variable $variable)
|
||||
public function __construct(private readonly float $epsilon, Variable $variable)
|
||||
{
|
||||
parent::__construct(\sprintf('%s > %.2f', (string)$variable, $epsilon));
|
||||
$this->epsilon = $epsilon;
|
||||
parent::__construct();
|
||||
$this->createVariableToMessageBinding($variable);
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,8 @@ class GaussianLikelihoodFactor extends GaussianFactor
|
||||
|
||||
public function __construct(float $betaSquared, Variable $variable1, Variable $variable2)
|
||||
{
|
||||
parent::__construct(sprintf('Likelihood of %s going to %s', (string)$variable2, (string)$variable1));
|
||||
//Likelihood of $variable1 going to $variable2
|
||||
parent::__construct();
|
||||
$this->precision = 1.0 / $betaSquared;
|
||||
$this->createVariableToMessageBinding($variable1);
|
||||
$this->createVariableToMessageBinding($variable2);
|
||||
|
@ -19,11 +19,11 @@ class GaussianPriorFactor extends GaussianFactor
|
||||
|
||||
public function __construct(float $mean, float $variance, Variable $variable)
|
||||
{
|
||||
parent::__construct(sprintf('Prior value going to %s', (string)$variable));
|
||||
//Prior value going to $variable
|
||||
parent::__construct();
|
||||
$this->newMessage = new GaussianDistribution($mean, sqrt($variance));
|
||||
$newMessage = new Message(
|
||||
GaussianDistribution::fromPrecisionMean(0, 0),
|
||||
sprintf('message from %s to %s', (string)$this, (string)$variable)
|
||||
GaussianDistribution::fromPrecisionMean(0, 0)
|
||||
);
|
||||
|
||||
$this->createVariableToMessageBindingWithMessage($variable, $newMessage);
|
||||
|
@ -42,7 +42,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
|
||||
*/
|
||||
public function __construct(Variable $sumVariable, array $variablesToSum, array $variableWeights)
|
||||
{
|
||||
parent::__construct(self::createName((string)$sumVariable, $variablesToSum, $variableWeights));
|
||||
parent::__construct();
|
||||
|
||||
// The first weights are a straightforward copy
|
||||
// v_0 = a_1*v_1 + a_2*v_2 + ... + a_n * v_n
|
||||
@ -235,42 +235,4 @@ class GaussianWeightedSumFactor extends GaussianFactor
|
||||
$updatedVariables
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Variable[] $variablesToSum
|
||||
* @param float[] $weights
|
||||
*/
|
||||
private static function createName(string $sumVariable, array $variablesToSum, array $weights): string
|
||||
{
|
||||
// TODO: Perf? Use PHP equivalent of StringBuilder? implode on arrays?
|
||||
$result = $sumVariable;
|
||||
$result .= ' = ';
|
||||
|
||||
$totalVars = count($variablesToSum);
|
||||
for ($i = 0; $i < $totalVars; ++$i) {
|
||||
$isFirst = ($i == 0);
|
||||
|
||||
if ($isFirst && ($weights[$i] < 0)) {
|
||||
$result .= '-';
|
||||
}
|
||||
|
||||
$absValue = sprintf('%.2f', \abs($weights[$i])); // 0.00?
|
||||
$result .= $absValue;
|
||||
$result .= '*[';
|
||||
$result .= (string)$variablesToSum[$i];
|
||||
$result .= ']';
|
||||
|
||||
$isLast = ($i === $totalVars - 1);
|
||||
|
||||
if (! $isLast) {
|
||||
if ($weights[$i + 1] >= 0) {
|
||||
$result .= ' + ';
|
||||
} else {
|
||||
$result .= ' - ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
@ -16,12 +16,10 @@ use DNW\Skills\TrueSkill\TruncatedGaussianCorrectionFunctions;
|
||||
*/
|
||||
class GaussianWithinFactor extends GaussianFactor
|
||||
{
|
||||
private readonly float $epsilon;
|
||||
|
||||
public function __construct(float $epsilon, Variable $variable)
|
||||
public function __construct(private readonly float $epsilon, Variable $variable)
|
||||
{
|
||||
parent::__construct(sprintf('%s <= %.2f', (string)$variable, $epsilon));
|
||||
$this->epsilon = $epsilon;
|
||||
//$epsilon <= $variable
|
||||
parent::__construct();
|
||||
$this->createVariableToMessageBinding($variable);
|
||||
}
|
||||
|
||||
|
@ -63,17 +63,17 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
|
||||
$firstDifferencesFactor = $localFactors[0];
|
||||
$lastDifferencesFactor = $localFactors[$totalTeamDifferences - 1];
|
||||
|
||||
//inner schedule
|
||||
return new ScheduleSequence(
|
||||
'inner schedule',
|
||||
[
|
||||
$loop,
|
||||
//teamPerformanceToPerformanceDifferenceFactors[0] @ 1
|
||||
new ScheduleStep(
|
||||
'teamPerformanceToPerformanceDifferenceFactors[0] @ 1',
|
||||
$firstDifferencesFactor,
|
||||
1
|
||||
),
|
||||
//teamPerformanceToPerformanceDifferenceFactors[teamTeamDifferences = %d - 1] @ 2
|
||||
new ScheduleStep(
|
||||
sprintf('teamPerformanceToPerformanceDifferenceFactors[teamTeamDifferences = %d - 1] @ 2', $totalTeamDifferences),
|
||||
$lastDifferencesFactor,
|
||||
2
|
||||
),
|
||||
@ -89,21 +89,21 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
|
||||
$firstPerfToTeamDiff = $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[0];
|
||||
$firstTeamDiffComparison = $teamDifferencesComparisonLayerLocalFactors[0];
|
||||
$itemsToSequence = [
|
||||
//send team perf to perf differences
|
||||
new ScheduleStep(
|
||||
'send team perf to perf differences',
|
||||
$firstPerfToTeamDiff,
|
||||
0
|
||||
),
|
||||
//send to greater than or within factor
|
||||
new ScheduleStep(
|
||||
'send to greater than or within factor',
|
||||
$firstTeamDiffComparison,
|
||||
0
|
||||
),
|
||||
];
|
||||
|
||||
//loop of just two teams inner sequence
|
||||
return $this->scheduleSequence(
|
||||
$itemsToSequence,
|
||||
'loop of just two teams inner sequence'
|
||||
$itemsToSequence
|
||||
);
|
||||
}
|
||||
|
||||
@ -120,32 +120,33 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
|
||||
$currentTeamPerfToTeamPerfDiff = $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$i];
|
||||
$currentTeamDiffComparison = $teamDifferencesComparisonLayerLocalFactors[$i];
|
||||
|
||||
//current forward schedule piece $i
|
||||
$currentForwardSchedulePiece =
|
||||
$this->scheduleSequence(
|
||||
[
|
||||
//team perf to perf diff
|
||||
new ScheduleStep(
|
||||
sprintf('team perf to perf diff %d', $i),
|
||||
$currentTeamPerfToTeamPerfDiff,
|
||||
0
|
||||
),
|
||||
//greater than or within result factor
|
||||
new ScheduleStep(
|
||||
sprintf('greater than or within result factor %d', $i),
|
||||
$currentTeamDiffComparison,
|
||||
0
|
||||
),
|
||||
//'team perf to perf diff factors
|
||||
new ScheduleStep(
|
||||
sprintf('team perf to perf diff factors [%d], 2', $i),
|
||||
$currentTeamPerfToTeamPerfDiff,
|
||||
2
|
||||
),
|
||||
],
|
||||
sprintf('current forward schedule piece %d', $i)
|
||||
]
|
||||
);
|
||||
|
||||
$forwardScheduleList[] = $currentForwardSchedulePiece;
|
||||
}
|
||||
|
||||
$forwardSchedule = new ScheduleSequence('forward schedule', $forwardScheduleList);
|
||||
//forward schedule
|
||||
$forwardSchedule = new ScheduleSequence($forwardScheduleList);
|
||||
|
||||
$backwardScheduleList = [];
|
||||
|
||||
@ -157,21 +158,21 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
|
||||
$comparisonFactor = $teamDifferencesComparisonLayerLocalFactors[$totalTeamDifferences - 1 - $i];
|
||||
$performancesToDifferencesFactor = $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$totalTeamDifferences - 1 - $i];
|
||||
|
||||
//current backward schedule piece
|
||||
$currentBackwardSchedulePiece = new ScheduleSequence(
|
||||
'current backward schedule piece',
|
||||
[
|
||||
//teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - %d] @ 0
|
||||
new ScheduleStep(
|
||||
sprintf('teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - %d] @ 0', $i),
|
||||
$differencesFactor,
|
||||
0
|
||||
),
|
||||
//greaterThanOrWithinResultFactors[totalTeamDifferences - 1 - %d] @ 0
|
||||
new ScheduleStep(
|
||||
sprintf('greaterThanOrWithinResultFactors[totalTeamDifferences - 1 - %d] @ 0', $i),
|
||||
$comparisonFactor,
|
||||
0
|
||||
),
|
||||
//teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - %d] @ 1
|
||||
new ScheduleStep(
|
||||
sprintf('teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - %d] @ 1', $i),
|
||||
$performancesToDifferencesFactor,
|
||||
1
|
||||
),
|
||||
@ -180,18 +181,19 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
|
||||
$backwardScheduleList[] = $currentBackwardSchedulePiece;
|
||||
}
|
||||
|
||||
$backwardSchedule = new ScheduleSequence('backward schedule', $backwardScheduleList);
|
||||
//backward schedule
|
||||
$backwardSchedule = new ScheduleSequence($backwardScheduleList);
|
||||
|
||||
$forwardBackwardScheduleToLoop =
|
||||
//forward Backward Schedule To Loop
|
||||
new ScheduleSequence(
|
||||
'forward Backward Schedule To Loop',
|
||||
[$forwardSchedule, $backwardSchedule]
|
||||
);
|
||||
|
||||
$initialMaxDelta = 0.0001;
|
||||
|
||||
//loop with max delta
|
||||
return new ScheduleLoop(
|
||||
sprintf('loop with max delta of %f', $initialMaxDelta),
|
||||
$forwardBackwardScheduleToLoop,
|
||||
$initialMaxDelta
|
||||
);
|
||||
|
@ -7,8 +7,6 @@ namespace DNW\Skills\TrueSkill\Layers;
|
||||
use DNW\Skills\FactorGraphs\ScheduleStep;
|
||||
use DNW\Skills\FactorGraphs\ScheduleSequence;
|
||||
use DNW\Skills\PartialPlay;
|
||||
use DNW\Skills\Player;
|
||||
use DNW\Skills\Team;
|
||||
use DNW\Skills\TrueSkill\Factors\GaussianWeightedSumFactor;
|
||||
use DNW\Skills\FactorGraphs\Variable;
|
||||
use DNW\Skills\FactorGraphs\KeyedVariable;
|
||||
@ -23,7 +21,7 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
|
||||
*/
|
||||
foreach ($inputVariablesGroups as $currentTeam) {
|
||||
$localCurrentTeam = $currentTeam;
|
||||
$teamPerformance = $this->createOutputVariable($localCurrentTeam);
|
||||
$teamPerformance = $this->createOutputVariable();
|
||||
$newSumFactor = $this->createPlayerToTeamSumFactor($localCurrentTeam, $teamPerformance);
|
||||
|
||||
$this->addLayerFactor($newSumFactor);
|
||||
@ -38,12 +36,13 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
|
||||
{
|
||||
$localFactors = $this->getLocalFactors();
|
||||
|
||||
//all player perf to team perf schedule
|
||||
return $this->scheduleSequence(
|
||||
array_map(
|
||||
static fn($weightedSumFactor): ScheduleStep => new ScheduleStep('Perf to Team Perf Step', $weightedSumFactor, 0),
|
||||
//Perf to Team Perf Step
|
||||
static fn($weightedSumFactor): ScheduleStep => new ScheduleStep($weightedSumFactor, 0),
|
||||
$localFactors
|
||||
),
|
||||
'all player perf to team perf schedule'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -75,26 +74,23 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
|
||||
$localCurrentFactor = $currentFactor;
|
||||
$numberOfMessages = $localCurrentFactor->getNumberOfMessages();
|
||||
for ($currentIteration = 1; $currentIteration < $numberOfMessages; ++$currentIteration) {
|
||||
//team sum perf
|
||||
$allFactors[] = new ScheduleStep(
|
||||
'team sum perf @' . $currentIteration,
|
||||
$localCurrentFactor,
|
||||
$currentIteration
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->scheduleSequence($allFactors, "all of the team's sum iterations");
|
||||
//all of the team's sum iterations
|
||||
return $this->scheduleSequence($allFactors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param KeyedVariable[] $team
|
||||
* Team's performance
|
||||
*/
|
||||
private function createOutputVariable(array $team): Variable
|
||||
private function createOutputVariable(): Variable
|
||||
{
|
||||
$memberNames = array_map(static fn($currentPlayer): string => (string)($currentPlayer->getKey()), $team);
|
||||
|
||||
$teamMemberNames = \implode(', ', $memberNames);
|
||||
|
||||
return $this->getParentFactorGraph()->getVariableFactory()->createBasicVariable('Team[' . $teamMemberNames . "]'s performance");
|
||||
return $this->getParentFactorGraph()->getVariableFactory()->createBasicVariable();
|
||||
}
|
||||
}
|
||||
|
@ -53,12 +53,13 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
|
||||
{
|
||||
$localFactors = $this->getLocalFactors();
|
||||
|
||||
//All priors
|
||||
return $this->scheduleSequence(
|
||||
array_map(
|
||||
static fn($prior): ScheduleStep => new ScheduleStep('Prior to Skill Step', $prior, 0),
|
||||
//Prior to Skill Step
|
||||
static fn($prior): ScheduleStep => new ScheduleStep($prior, 0),
|
||||
$localFactors
|
||||
),
|
||||
'All priors'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -77,6 +78,6 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
|
||||
$parentFactorGraph = $this->getParentFactorGraph();
|
||||
$variableFactory = $parentFactorGraph->getVariableFactory();
|
||||
|
||||
return $variableFactory->createKeyedVariable($key, $key . "'s skill");
|
||||
return $variableFactory->createKeyedVariable($key);
|
||||
}
|
||||
}
|
||||
|
@ -48,19 +48,20 @@ class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
|
||||
|
||||
private function createOutputVariable(mixed $key): KeyedVariable
|
||||
{
|
||||
return $this->getParentFactorGraph()->getVariableFactory()->createKeyedVariable($key, $key . "'s performance");
|
||||
return $this->getParentFactorGraph()->getVariableFactory()->createKeyedVariable($key);
|
||||
}
|
||||
|
||||
public function createPriorSchedule(): ?ScheduleSequence
|
||||
{
|
||||
$localFactors = $this->getLocalFactors();
|
||||
|
||||
//All skill to performance sending
|
||||
return $this->scheduleSequence(
|
||||
array_map(
|
||||
static fn($likelihood): ScheduleStep => new ScheduleStep('Skill to Perf step', $likelihood, 0),
|
||||
//Skill to Perf step
|
||||
static fn($likelihood): ScheduleStep => new ScheduleStep($likelihood, 0),
|
||||
$localFactors
|
||||
),
|
||||
'All skill to performance sending'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -68,12 +69,12 @@ class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
|
||||
{
|
||||
$localFactors = $this->getLocalFactors();
|
||||
|
||||
//All skill to performance sending
|
||||
return $this->scheduleSequence(
|
||||
array_map(
|
||||
static fn($likelihood): ScheduleStep => new ScheduleStep('name', $likelihood, 1),
|
||||
static fn($likelihood): ScheduleStep => new ScheduleStep($likelihood, 1),
|
||||
$localFactors
|
||||
),
|
||||
'All skill to performance sending'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -40,8 +40,11 @@ class TeamPerformancesToTeamPerformanceDifferencesLayer extends TrueSkillFactorG
|
||||
return new GaussianWeightedSumFactor($output, $teams, $weights);
|
||||
}
|
||||
|
||||
/**
|
||||
* Team performance difference
|
||||
*/
|
||||
private function createOutputVariable(): Variable
|
||||
{
|
||||
return $this->getParentFactorGraph()->getVariableFactory()->createBasicVariable('Team performance difference');
|
||||
return $this->getParentFactorGraph()->getVariableFactory()->createBasicVariable();
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +124,8 @@ class TrueSkillFactorGraph extends FactorGraph
|
||||
}
|
||||
}
|
||||
|
||||
return new ScheduleSequence('Full schedule', $fullSchedule);
|
||||
//Full schedule
|
||||
return new ScheduleSequence($fullSchedule);
|
||||
}
|
||||
|
||||
public function getUpdatedRatings(): RatingContainer
|
||||
|
@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DNW\Skills\Tests\FactorGraphs;
|
||||
|
||||
use DNW\Skills\FactorGraphs\ScheduleStep;
|
||||
use DNW\Skills\FactorGraphs\Factor;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ScheduleStepTest extends TestCase
|
||||
{
|
||||
public function testtoStringInterface(): void
|
||||
{
|
||||
$stub = $this->createStub(Factor::class);
|
||||
$ss = new ScheduleStep('dummy', $stub, 0);
|
||||
$this->assertEquals('dummy', (string)$ss);
|
||||
}
|
||||
}
|
@ -13,13 +13,12 @@ class VariableTest extends TestCase
|
||||
public function testGetterSetter(): void
|
||||
{
|
||||
$gd_prior = new GaussianDistribution();
|
||||
$var = new Variable('dummy', $gd_prior);
|
||||
$var = new Variable($gd_prior);
|
||||
$this->assertEquals($gd_prior, $var->getValue());
|
||||
|
||||
$gd_new = new GaussianDistribution();
|
||||
$this->assertEquals($gd_new, $var->getValue());
|
||||
$var->resetToPrior();
|
||||
$this->assertEquals($gd_prior, $var->getValue());
|
||||
$this->assertEquals('Variable[dummy]', (string)$var);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ class PlayerTest extends TestCase
|
||||
public function testPlayerObjectGetterSetter(): void
|
||||
{
|
||||
$p = new Player('dummy', 0.1, 0.2);
|
||||
$this->assertEquals('dummy', (string)$p);
|
||||
$this->assertEquals('dummy', $p->getId());
|
||||
$this->assertEquals(0.1, $p->getPartialPlayPercentage());
|
||||
$this->assertEquals(0.2, $p->getPartialUpdatePercentage());
|
||||
|
@ -15,7 +15,6 @@ class RatingTest extends TestCase
|
||||
$this->assertEquals(100, $rating->getMean());
|
||||
$this->assertEquals(10, $rating->getStandardDeviation());
|
||||
$this->assertEquals(50, $rating->getConservativeRating());
|
||||
$this->assertEquals("mean=100.0000, standardDeviation=10.0000", (string)$rating);
|
||||
}
|
||||
|
||||
public function testPartialUpdate(): void
|
||||
@ -26,10 +25,8 @@ class RatingTest extends TestCase
|
||||
|
||||
$rating_partial = $rating->getPartialUpdate($ratingOld, $ratingNew, 0.5);
|
||||
|
||||
|
||||
$this->assertEquals(150, $rating_partial->getMean());
|
||||
$this->assertEquals(10, $rating_partial->getStandardDeviation());
|
||||
$this->assertEquals(100, $rating_partial->getConservativeRating());
|
||||
$this->assertEquals("mean=150.0000, standardDeviation=10.0000", (string)$rating_partial);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user