More type work.

This commit is contained in:
Jens True 2023-08-02 10:10:57 +00:00
parent a60187a3fd
commit 5c7471963c
14 changed files with 43 additions and 38 deletions

@ -21,7 +21,7 @@ abstract class FactorGraphLayer
// HACK // HACK
public function getParentFactorGraph() public function getParentFactorGraph(): FactorGraph
{ {
return $this->parentFactorGraph; return $this->parentFactorGraph;
} }

@ -4,8 +4,9 @@ namespace DNW\Skills\FactorGraphs;
class Message implements \Stringable class Message implements \Stringable
{ {
public function __construct(private $value = null, private $name = null) public function __construct(private ?object $value = null, private ?string $name = null)
{ {
} }
public function getValue() public function getValue()

@ -4,7 +4,7 @@ namespace DNW\Skills\Numerics;
class IdentityMatrix extends DiagonalMatrix class IdentityMatrix extends DiagonalMatrix
{ {
public function __construct($rows) public function __construct(int $rows)
{ {
parent::__construct(array_fill(0, $rows, 1)); parent::__construct(array_fill(0, $rows, 1));
} }

@ -8,7 +8,7 @@ class Matrix
{ {
public const ERROR_TOLERANCE = 0.0000000001; public const ERROR_TOLERANCE = 0.0000000001;
public function __construct(private int $rowCount = 0, private int $columnCount = 0, private $matrixRowData = null) public function __construct(private int $rowCount = 0, private int $columnCount = 0, private array $matrixRowData = array())
{ {
} }
@ -28,12 +28,10 @@ class Matrix
return $result; return $result;
} }
public static function fromRowsColumns(...$args): Matrix public static function fromRowsColumns(int $rows, int $cols, float|int ...$args): Matrix
{ {
$rows = $args[0];
$cols = $args[1];
$result = new Matrix($rows, $cols); $result = new Matrix($rows, $cols);
$currentIndex = 2; $currentIndex = 0;
for ($currentRow = 0; $currentRow < $rows; $currentRow++) { for ($currentRow = 0; $currentRow < $rows; $currentRow++) {
for ($currentCol = 0; $currentCol < $cols; $currentCol++) { for ($currentCol = 0; $currentCol < $cols; $currentCol++) {

@ -11,21 +11,21 @@ class Player implements ISupportPartialPlay, ISupportPartialUpdate, \Stringable
private const DEFAULT_PARTIAL_UPDATE_PERCENTAGE = 1.0; private const DEFAULT_PARTIAL_UPDATE_PERCENTAGE = 1.0;
private $PartialPlayPercentage; private float $PartialPlayPercentage;
private $PartialUpdatePercentage; private float $PartialUpdatePercentage;
/** /**
* Constructs a player. * 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 number $partialPlayPercentage The weight percentage to give this player when calculating a new rank. * @param float $partialPlayPercentage The weight percentage to give this player when calculating a new rank.
* @param number $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. * @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.
*/ */
public function __construct( public function __construct(
private $Id, private mixed $Id,
$partialPlayPercentage = self::DEFAULT_PARTIAL_PLAY_PERCENTAGE, float $partialPlayPercentage = self::DEFAULT_PARTIAL_PLAY_PERCENTAGE,
$partialUpdatePercentage = self::DEFAULT_PARTIAL_UPDATE_PERCENTAGE float $partialUpdatePercentage = self::DEFAULT_PARTIAL_UPDATE_PERCENTAGE
) { ) {
// If they don't want to give a player an id, that's ok... // If they don't want to give a player an id, that's ok...
Guard::argumentInRangeInclusive($partialPlayPercentage, 0.0, 1.0, 'partialPlayPercentage'); Guard::argumentInRangeInclusive($partialPlayPercentage, 0.0, 1.0, 'partialPlayPercentage');
@ -37,7 +37,7 @@ class Player implements ISupportPartialPlay, ISupportPartialUpdate, \Stringable
/** /**
* The identifier for the player, such as a name. * The identifier for the player, such as a name.
*/ */
public function getId() public function getId(): mixed
{ {
return $this->Id; return $this->Id;
} }
@ -45,7 +45,7 @@ class Player implements ISupportPartialPlay, ISupportPartialUpdate, \Stringable
/** /**
* Indicates the percent of the time the player should be weighted where 0.0 indicates the player didn't play and 1.0 indicates the player played 100% of the time. * Indicates the percent of the time the player should be weighted where 0.0 indicates the player didn't play and 1.0 indicates the player played 100% of the time.
*/ */
public function getPartialPlayPercentage() public function getPartialPlayPercentage(): float
{ {
return $this->PartialPlayPercentage; return $this->PartialPlayPercentage;
} }
@ -53,7 +53,7 @@ class Player implements ISupportPartialPlay, ISupportPartialUpdate, \Stringable
/** /**
* Indicated how much of a skill update a player should receive where 0.0 represents no update and 1.0 represents 100% of the update. * Indicated how much of a skill update a player should receive where 0.0 represents no update and 1.0 represents 100% of the update.
*/ */
public function getPartialUpdatePercentage() public function getPartialUpdatePercentage(): float
{ {
return $this->PartialUpdatePercentage; return $this->PartialUpdatePercentage;
} }

@ -10,7 +10,7 @@ use Exception;
abstract class SkillCalculator abstract class SkillCalculator
{ {
protected function __construct( protected function __construct(
private $supportedOptions, private int $supportedOptions,
private readonly TeamsRange $totalTeamsAllowed, private readonly TeamsRange $totalTeamsAllowed,
private readonly PlayersRange $playersPerTeamAllowed private readonly PlayersRange $playersPerTeamAllowed
) { ) {
@ -22,13 +22,13 @@ abstract class SkillCalculator
* @param GameInfo $gameInfo Parameters for the game. * @param GameInfo $gameInfo Parameters for the game.
* @param array $teamsOfPlayerToRatings A mapping of team players and their ratings. * @param array $teamsOfPlayerToRatings A mapping of team players and their ratings.
* @param array $teamRanks The ranks of the teams where 1 is first place. For a tie, repeat the number (e.g. 1, 2, 2). * @param array $teamRanks The ranks of the teams where 1 is first place. For a tie, repeat the number (e.g. 1, 2, 2).
* @return All the players and their new ratings. * @return RatingContainer All the players and their new ratings.
*/ */
abstract public function calculateNewRatings( abstract public function calculateNewRatings(
GameInfo $gameInfo, GameInfo $gameInfo,
array $teamsOfPlayerToRatings, array $teamsOfPlayerToRatings,
array $teamRanks array $teamRanks
); ): RatingContainer;
/** /**
* Calculates the match quality as the likelihood of all teams drawing. * Calculates the match quality as the likelihood of all teams drawing.

@ -4,6 +4,9 @@ namespace DNW\Skills;
class Teams class Teams
{ {
/**
* @return Team[]
*/
public static function concat(Team ...$args/*variable arguments*/): array public static function concat(Team ...$args/*variable arguments*/): array
{ {
$result = []; $result = [];

@ -86,7 +86,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
return exp($expPart) * sqrt($sqrtPart); return exp($expPart) * sqrt($sqrtPart);
} }
private static function getPlayerMeansVector(array $teamAssignmentsList) private static function getPlayerMeansVector(array $teamAssignmentsList): Vector
{ {
// A simple vector of all the player means. // A simple vector of all the player means.
return new Vector( return new Vector(
@ -97,7 +97,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
); );
} }
private static function getPlayerCovarianceMatrix(array $teamAssignmentsList) private static function getPlayerCovarianceMatrix(array $teamAssignmentsList): DiagonalMatrix
{ {
// This is a square matrix whose diagonal values represent the variance (square of standard deviation) of all // This is a square matrix whose diagonal values represent the variance (square of standard deviation) of all
// players. // players.
@ -110,7 +110,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
} }
// Helper function that gets a list of values for all player ratings // Helper function that gets a list of values for all player ratings
private static function getPlayerRatingValues(array $teamAssignmentsList, $playerRatingFunction) private static function getPlayerRatingValues(array $teamAssignmentsList, \Closure $playerRatingFunction): array
{ {
$playerRatingValues = []; $playerRatingValues = [];

@ -14,16 +14,16 @@ use DNW\Skills\TrueSkill\TruncatedGaussianCorrectionFunctions;
*/ */
class GaussianGreaterThanFactor extends GaussianFactor class GaussianGreaterThanFactor extends GaussianFactor
{ {
private $epsilon; private float $epsilon;
public function __construct($epsilon, Variable $variable) public function __construct(float $epsilon, Variable $variable)
{ {
parent::__construct(\sprintf('%s > %.2f', $variable, $epsilon)); parent::__construct(\sprintf('%s > %.2f', $variable, $epsilon));
$this->epsilon = $epsilon; $this->epsilon = $epsilon;
$this->createVariableToMessageBinding($variable); $this->createVariableToMessageBinding($variable);
} }
public function getLogNormalization() public function getLogNormalization(): float
{ {
/** /**
* @var Variable[] $vars * @var Variable[] $vars
@ -48,7 +48,7 @@ class GaussianGreaterThanFactor extends GaussianFactor
); );
} }
protected function updateMessageVariable(Message $message, Variable $variable) protected function updateMessageVariable(Message $message, Variable $variable): float
{ {
$oldMarginal = clone $variable->getValue(); $oldMarginal = clone $variable->getValue();
$oldMessage = clone $message->getValue(); $oldMessage = clone $message->getValue();

@ -70,7 +70,7 @@ class GaussianLikelihoodFactor extends GaussianFactor
return GaussianDistribution::subtract($newMarginal, $marginal1); return GaussianDistribution::subtract($newMarginal, $marginal1);
} }
public function updateMessageIndex($messageIndex): float public function updateMessageIndex(int $messageIndex): float
{ {
$messages = $this->getMessages(); $messages = $this->getMessages();
$vars = $this->getVariables(); $vars = $this->getVariables();

@ -6,10 +6,11 @@ use DNW\Skills\FactorGraphs\ScheduleStep;
use DNW\Skills\FactorGraphs\ScheduleSequence; use DNW\Skills\FactorGraphs\ScheduleSequence;
use DNW\Skills\PartialPlay; use DNW\Skills\PartialPlay;
use DNW\Skills\TrueSkill\Factors\GaussianWeightedSumFactor; use DNW\Skills\TrueSkill\Factors\GaussianWeightedSumFactor;
use DNW\Skills\FactorGraphs\Variable;
class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLayer class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLayer
{ {
public function buildLayer() public function buildLayer(): void
{ {
$inputVariablesGroups = $this->getInputVariablesGroups(); $inputVariablesGroups = $this->getInputVariablesGroups();
foreach ($inputVariablesGroups as $currentTeam) { foreach ($inputVariablesGroups as $currentTeam) {
@ -38,7 +39,7 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
); );
} }
protected function createPlayerToTeamSumFactor($teamMembers, $sumVariable): GaussianWeightedSumFactor protected function createPlayerToTeamSumFactor(array $teamMembers, Variable $sumVariable): GaussianWeightedSumFactor
{ {
$weights = array_map( $weights = array_map(
function ($v) { function ($v) {
@ -75,7 +76,7 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
return $this->scheduleSequence($allFactors, "all of the team's sum iterations"); return $this->scheduleSequence($allFactors, "all of the team's sum iterations");
} }
private function createOutputVariable($team) private function createOutputVariable(array $team): Variable
{ {
$memberNames = array_map(fn ($currentPlayer) => (string) ($currentPlayer->getKey()), $team); $memberNames = array_map(fn ($currentPlayer) => (string) ($currentPlayer->getKey()), $team);

@ -9,6 +9,7 @@ use DNW\Skills\Numerics\BasicMath;
use DNW\Skills\Rating; use DNW\Skills\Rating;
use DNW\Skills\TrueSkill\Factors\GaussianPriorFactor; use DNW\Skills\TrueSkill\Factors\GaussianPriorFactor;
use DNW\Skills\TrueSkill\TrueSkillFactorGraph; use DNW\Skills\TrueSkill\TrueSkillFactorGraph;
use DNW\Skills\FactorGraphs\ScheduleSequence;
// We intentionally have no Posterior schedule since the only purpose here is to // We intentionally have no Posterior schedule since the only purpose here is to
// start the process. // start the process.
@ -19,7 +20,7 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
parent::__construct($parentGraph); parent::__construct($parentGraph);
} }
public function buildLayer() public function buildLayer(): void
{ {
$teams = $this->teams; $teams = $this->teams;
foreach ($teams as $currentTeam) { foreach ($teams as $currentTeam) {
@ -41,7 +42,7 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
} }
} }
public function createPriorSchedule() public function createPriorSchedule(): ScheduleSequence
{ {
$localFactors = $this->getLocalFactors(); $localFactors = $this->getLocalFactors();
@ -54,7 +55,7 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
); );
} }
private function createPriorFactor(Rating $priorRating, Variable $skillsVariable) private function createPriorFactor(Rating $priorRating, Variable $skillsVariable): GaussianPriorFactor
{ {
return new GaussianPriorFactor( return new GaussianPriorFactor(
$priorRating->getMean(), $priorRating->getMean(),

@ -7,7 +7,7 @@ use DNW\Skills\TrueSkill\Factors\GaussianWeightedSumFactor;
class TeamPerformancesToTeamPerformanceDifferencesLayer extends TrueSkillFactorGraphLayer class TeamPerformancesToTeamPerformanceDifferencesLayer extends TrueSkillFactorGraphLayer
{ {
public function buildLayer() public function buildLayer(): void
{ {
$inputVariablesGroups = $this->getInputVariablesGroups(); $inputVariablesGroups = $this->getInputVariablesGroups();
$inputVariablesGroupsCount = is_countable($inputVariablesGroups) ? count($inputVariablesGroups) : 0; $inputVariablesGroupsCount = is_countable($inputVariablesGroups) ? count($inputVariablesGroups) : 0;
@ -30,14 +30,14 @@ class TeamPerformancesToTeamPerformanceDifferencesLayer extends TrueSkillFactorG
Variable $strongerTeam, Variable $strongerTeam,
Variable $weakerTeam, Variable $weakerTeam,
Variable $output Variable $output
) { ): GaussianWeightedSumFactor {
$teams = [$strongerTeam, $weakerTeam]; $teams = [$strongerTeam, $weakerTeam];
$weights = [1.0, -1.0]; $weights = [1.0, -1.0];
return new GaussianWeightedSumFactor($output, $teams, $weights); return new GaussianWeightedSumFactor($output, $teams, $weights);
} }
private function createOutputVariable() private function createOutputVariable(): Variable
{ {
return $this->getParentFactorGraph()->getVariableFactory()->createBasicVariable('Team performance difference'); return $this->getParentFactorGraph()->getVariableFactory()->createBasicVariable('Team performance difference');
} }

@ -10,6 +10,7 @@ use DNW\Skills\GameInfo;
use DNW\Skills\Numerics\GaussianDistribution; use DNW\Skills\Numerics\GaussianDistribution;
use DNW\Skills\Rating; use DNW\Skills\Rating;
use DNW\Skills\RatingContainer; use DNW\Skills\RatingContainer;
use DNW\Skills\FactorGraphs\FactorGraphLayer;
use DNW\Skills\TrueSkill\Layers\IteratedTeamDifferencesInnerLayer; use DNW\Skills\TrueSkill\Layers\IteratedTeamDifferencesInnerLayer;
use DNW\Skills\TrueSkill\Layers\PlayerPerformancesToTeamPerformancesLayer; use DNW\Skills\TrueSkill\Layers\PlayerPerformancesToTeamPerformancesLayer;
use DNW\Skills\TrueSkill\Layers\PlayerPriorValuesToSkillsLayer; use DNW\Skills\TrueSkill\Layers\PlayerPriorValuesToSkillsLayer;