Skip to content

Commit

Permalink
Smaller fixes, added new tests
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidBelicza committed Sep 20, 2020
1 parent 381cdb9 commit abd5acb
Show file tree
Hide file tree
Showing 12 changed files with 423 additions and 44 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ PageRank
</p>

<p align="center">
This source code is an OOP implementation of the PageRank algorithm, under MIT licence.
This source code is an OOP implementation of the PageRank algorithm.
<br />The minimum required PHP version is 7.4.
<br />
<br />
Expand All @@ -35,7 +35,7 @@ long-running calculation can be scheduled in batches using the Strategy OOP patt
iteration number.
* However, the iteration stops when the ranks are accurate enough even if the max iteration didn't reach its limit.
* The accuracy measured by the float epsilon constant.
* At the end the algorithm normalizes the ranks between 0 and 1 and then scale them between 1 and 10. The scaling range
* At the end, the algorithm normalizes the ranks between 0 and 1 and then scale them between 1 and 10. The scaling range
is configurable.
* Getting, setting, updating the nodes from the resource is a responsibility of the NodeDataSourceStrategyInterface.
* The package provides a simple implementation of the NodeDataSourceStrategyInterface that only keeps the nodes in the
Expand Down
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
"email": "[email protected]"
}
],
"require": {},
"require": {
"php": "7.4.*"
},
"autoload": {
"psr-4": {
"PhpScience\\PageRank\\": [
"src",
"tests/unit",
"tests/functional"
]
}
Expand Down
40 changes: 0 additions & 40 deletions src/Service/Normalizer.php

This file was deleted.

1 change: 1 addition & 0 deletions src/Service/PageRankAlgorithm.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace PhpScience\PageRank\Service;

use PhpScience\PageRank\Data\NodeCollectionInterface;
use PhpScience\PageRank\Service\PageRankAlgorithm\NormalizerInterface;
use PhpScience\PageRank\Service\PageRankAlgorithm\RankingInterface;
use PhpScience\PageRank\Strategy\NodeDataSourceStrategyInterface;

Expand Down
60 changes: 60 additions & 0 deletions src/Service/PageRankAlgorithm/Normalizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types=1);

namespace PhpScience\PageRank\Service\PageRankAlgorithm;

use PhpScience\PageRank\Data\NodeCollectionInterface;

class Normalizer implements NormalizerInterface
{
private float $scaleBottom;
private float $scaleTop;

public function __construct(
float $scaleBottom = 1,
float $scaleTop = 10
) {
$this->scaleBottom = $scaleBottom;
$this->scaleTop = $scaleTop;
}

public function normalize(
NodeCollectionInterface $nodeCollection,
float $lowestRank,
float $highestRank
): void {
$divider = $this->getDivider($lowestRank, $highestRank);

foreach ($nodeCollection->getNodes() as $node) {
$rank = $this->getScaledRank(
$node->getRank(),
$lowestRank,
$divider
);
$node->setRank($rank);
}
}

private function getDivider(float $lowestRank, float $highestRank): float
{
$divider = $highestRank - $lowestRank;

if (.0 === $divider) {
$divider = 1;
}

return $divider;
}

private function getScaledRank(
float $value,
float $lowestRank,
float $divider
): float {
$normalized = ($value - $lowestRank) / $divider;
$multiplier = $this->scaleTop - $this->scaleBottom;

return ($normalized * $multiplier) + $this->scaleBottom;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace PhpScience\PageRank\Service;
namespace PhpScience\PageRank\Service\PageRankAlgorithm;

use PhpScience\PageRank\Data\NodeCollectionInterface;

Expand Down
1 change: 1 addition & 0 deletions tests/functional/Service/PageRankAlgorithmTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use PhpScience\PageRank\Builder\NodeBuilder;
use PhpScience\PageRank\Builder\NodeCollectionBuilder;
use PhpScience\PageRank\Service\PageRankAlgorithm\Normalizer;
use PhpScience\PageRank\Service\PageRankAlgorithm\RankComparator;
use PhpScience\PageRank\Service\PageRankAlgorithm\Ranking;
use PhpScience\PageRank\Strategy\MemorySourceStrategy;
Expand Down
3 changes: 3 additions & 0 deletions tests/phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
colors="true">

<testsuites>
<testsuite name="Unit Tests">
<directory>../tests/unit</directory>
</testsuite>
<testsuite name="Functional Tests">
<directory>../tests/functional</directory>
</testsuite>
Expand Down
31 changes: 31 additions & 0 deletions tests/unit/Builder/NodeBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace PhpScience\PageRank\Builder;

use PHPUnit\Framework\TestCase;

class NodeBuilderTest extends TestCase
{
private NodeBuilder $nodeBuilder;

protected function setUp(): void
{
$this->nodeBuilder = new NodeBuilder();
}

public function testBuild(): void
{
$expected = 0.25;

$data = [
'id' => 1,
'rank' => $expected
];

$actual = $this->nodeBuilder->build($data);

static::assertSame($expected, $actual->getRank());
}
}
100 changes: 100 additions & 0 deletions tests/unit/Service/PageRankAlgorithm/NormalizerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

declare(strict_types=1);

namespace PhpScience\PageRank\Service\PageRankAlgorithm;

use PhpScience\PageRank\Data\NodeCollectionInterface;
use PhpScience\PageRank\Data\NodeInterface;
use PHPUnit\Framework\TestCase;

class NormalizerTest extends TestCase
{
/**
* @dataProvider dataProviderNormalize
*
* @param float $originalRank
* @param float $scaleBottom
* @param float $scaleTop
* @param float $lowestRank
* @param float $highestRank
* @param float $expectedRank
*/
public function testNormalize(
float $originalRank,
float $scaleBottom,
float $scaleTop,
float $lowestRank,
float $highestRank,
float $expectedRank
): void {
$nodeCollection = $this
->createMock(NodeCollectionInterface::class);
$node = $this
->createMock(NodeInterface::class);

$nodeCollection
->expects($this->once())
->method('getNodes')
->willReturn([$node]);

$node
->expects($this->once())
->method('getRank')
->willReturn($originalRank);

$node
->expects($this->once())
->method('setRank')
->with($expectedRank);

$normalizer = new Normalizer(
$scaleBottom,
$scaleTop
);

$normalizer->normalize(
$nodeCollection,
$lowestRank,
$highestRank
);
}

public function dataProviderNormalize(): array
{
return [
'realistic' => [
1.234,
1.0,
10.0,
-5.0,
5.0,
6.6106
],
'division_by_zero' => [
5,
1.0,
10.0,
5.0,
5.0,
1.0
],
'division_by_float_epsilon' => [
5,
1.0,
10.0,
5.0,
5.0 + PHP_FLOAT_EPSILON,
1.0
],
'scale_from_minus' => [
0.12577,
-5,
5,
100,
1000,
-6.109713666666667
]
];
}
}
58 changes: 58 additions & 0 deletions tests/unit/Service/PageRankAlgorithm/RankComparatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace PhpScience\PageRank\Service\PageRankAlgorithm;

use PHPUnit\Framework\TestCase;

class RankComparatorTest extends TestCase
{
private RankComparator $rankComparator;

protected function setUp(): void
{
$this->rankComparator = new RankComparator();
}

/**
* @dataProvider dataProviderIsEqual
*
* @param float $rank1
* @param float $rank2
* @param bool $expected
*/
public function testIsEqual(
float $rank1,
float $rank2,
bool $expected
): void {
$actual = $this->rankComparator->isEqual($rank1, $rank2);

static::assertSame($expected, $actual);
}

public function dataProviderIsEqual(): array
{
return [
'not_equal' => [
.1, .2, false
],
'equal' => [
.1, .1, true
],
'absolute_value_of_minus' => [
.1, .2, false
],
'absolute_of_minus_one_is_bigger_than_float_epsilon' => [
1, 2, false
],
'smallest_representable_difference' => [
1, 1 + PHP_FLOAT_EPSILON, false
],
'non_representable_difference' => [
1, 1 + 2.2204460492503e-17, true
]
];
}
}
Loading

0 comments on commit abd5acb

Please sign in to comment.