* @since 1.0.0 */ private array $pageRanks = []; /** * Relation array * * Array of elements where every element has an array of incoming links/relations * * @var array[] * @since 1.0.0 */ private array $relations = []; /** * Amount of outgoing links from an element * * @var int[] * @since 1.0.0 */ private array $outgoing = []; /** * Constructor. * * @param array[] $relations Relations between elements (keys => link from, array => link to) * @param bool $isUnique Only consider unique relations * @param float $damping Damping value * * @since 1.0.0 */ public function __construct(array $relations, bool $isUnique = true, float $damping = 0.85) { $this->damping = $damping; foreach ($relations as $key => $relation) { $this->outgoing[$key] = \count($relation); if (!isset($this->relations[$key])) { $this->relations[$key] = []; } foreach ($relation as $linkTo) { if (!isset($this->relations[$linkTo])) { $this->relations[$linkTo] = []; } if (!isset($this->outgoing[$linkTo])) { $this->outgoing[$linkTo] = 0; } if (!$isUnique || !\in_array($key, $this->relations[$linkTo])) { $this->relations[$linkTo][] = $key; } } } } /** * Calculate the rank based on a start rank for the different elements * * A different start rank for different elements might make sense if the elements are not uniform from the very beginning * * @param int $iterations Algorithm iterations * @param null|array $startRank Start rank for an element * * @return array * * @since 1.0.0 */ public function calculateRanks(int $iterations = 20, ?array $startRank = null) : array { if ($startRank !== null) { $this->pageRanks = $startRank; } else { foreach ($this->relations as $key => $relation) { $this->pageRanks[$key] = 0.0; } } for ($i = 0; $i < $iterations; ++$i) { foreach ($this->relations as $key => $relation) { $PR = 0.0; foreach ($relation as $linkFrom) { $PR += $this->pageRanks[$linkFrom] / $this->outgoing[$linkFrom]; } $this->pageRanks[$key] = 1 - $this->damping + $this->damping * $PR; } } return $this->pageRanks; } }