Skip to content

Commit fc10db3

Browse files
committed
moving default implementation into Euclidean namespace
1 parent 2844c3b commit fc10db3

File tree

16 files changed

+178
-362
lines changed

16 files changed

+178
-362
lines changed

src/Algorithm.php

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use Kmeans\Interfaces\PointCollectionInterface;
1212
use Kmeans\Interfaces\PointInterface;
1313

14-
class Algorithm implements AlgorithmInterface
14+
abstract class Algorithm implements AlgorithmInterface
1515
{
1616
private InitializationSchemeInterface $initScheme;
1717

@@ -25,6 +25,10 @@ public function __construct(InitializationSchemeInterface $initScheme)
2525
$this->initScheme = $initScheme;
2626
}
2727

28+
abstract protected function getDistanceBetween(PointInterface $pointA, PointInterface $pointB): float;
29+
30+
abstract protected function findCentroid(PointCollectionInterface $points): PointInterface;
31+
2832
public function registerIterationCallback(callable $callback): void
2933
{
3034
$this->iterationCallbacks[] = $callback;
@@ -48,18 +52,6 @@ public function clusterize(PointCollectionInterface $points, int $nbClusters): C
4852
return $clusters;
4953
}
5054

51-
protected function getDistanceBetween(PointInterface $pointA, PointInterface $pointB): float
52-
{
53-
return Math::euclideanDist($pointA->getCoordinates(), $pointB->getCoordinates());
54-
}
55-
56-
protected function findCentroid(PointCollectionInterface $points): PointInterface
57-
{
58-
return new Point($points->getSpace(), Math::centroid(
59-
array_map(fn (PointInterface $point) => $point->getCoordinates(), iterator_to_array($points))
60-
));
61-
}
62-
6355
private function iterate(ClusterCollectionInterface $clusters): bool
6456
{
6557
/** @var \SplObjectStorage<ClusterInterface, null> */
@@ -110,7 +102,7 @@ private function getClosestCluster(ClusterCollectionInterface $clusters, PointIn
110102
return $closest;
111103
}
112104

113-
protected function invokeIterationCallbacks(ClusterCollectionInterface $clusters): void
105+
private function invokeIterationCallbacks(ClusterCollectionInterface $clusters): void
114106
{
115107
foreach ($this->iterationCallbacks as $callback) {
116108
$callback($this, $clusters);

src/Euclidean/Algorithm.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Kmeans\Euclidean;
4+
5+
use Kmeans\Algorithm as BaseAlgorithm;
6+
use Kmeans\Interfaces\PointCollectionInterface;
7+
use Kmeans\Interfaces\PointInterface;
8+
use Kmeans\Math;
9+
10+
class Algorithm extends BaseAlgorithm
11+
{
12+
protected function getDistanceBetween(PointInterface $pointA, PointInterface $pointB): float
13+
{
14+
return Math::euclideanDist($pointA->getCoordinates(), $pointB->getCoordinates());
15+
}
16+
17+
protected function findCentroid(PointCollectionInterface $points): PointInterface
18+
{
19+
return new Point($points->getSpace(), Math::centroid(
20+
array_map(fn (PointInterface $point) => $point->getCoordinates(), iterator_to_array($points))
21+
));
22+
}
23+
}

src/Point.php renamed to src/Euclidean/Point.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Kmeans;
3+
namespace Kmeans\Euclidean;
44

55
use Kmeans\Concerns\HasSpaceTrait;
66
use Kmeans\Interfaces\PointInterface;
@@ -25,6 +25,12 @@ class Point implements PointInterface
2525
*/
2626
public function __construct(SpaceInterface $space, array $coordinates)
2727
{
28+
if (! $space instanceof Space) {
29+
throw new \LogicException(
30+
"An euclidean point must belong to an euclidean space."
31+
);
32+
}
33+
2834
$this->setSpace($space);
2935
$this->coordinates = $this->sanitizeCoordinates($coordinates);
3036
}
@@ -50,6 +56,7 @@ public function setData($data): void
5056
*/
5157
private function sanitizeCoordinates(array $coordinates): array
5258
{
59+
assert($this->space instanceof Space);
5360
if (count($coordinates) != $this->space->getDimensions()) {
5461
throw new \InvalidArgumentException(sprintf(
5562
"Invalid set of coordinates: %d coordinates expected, %d given",

src/Space.php renamed to src/Euclidean/Space.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Kmeans;
3+
namespace Kmeans\Euclidean;
44

55
use Kmeans\Interfaces\SpaceInterface;
66

@@ -14,7 +14,9 @@ class Space implements SpaceInterface
1414
public function __construct(int $dimensions)
1515
{
1616
if ($dimensions < 1) {
17-
throw new \InvalidArgumentException("Invalid space dimentions: {$dimensions}");
17+
throw new \InvalidArgumentException(
18+
"Invalid space dimentions: {$dimensions}"
19+
);
1820
}
1921

2022
$this->dimensions = $dimensions;
@@ -27,6 +29,7 @@ public function getDimensions(): int
2729

2830
public function isEqualTo(SpaceInterface $space): bool
2931
{
30-
return $this->getDimensions() == $space->getDimensions();
32+
return $space instanceof self
33+
&& $this->dimensions == $space->dimensions;
3134
}
3235
}

src/Gps/Point.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Kmeans\Gps;
44

5-
use Kmeans\Point as BasePoint;
5+
use Kmeans\Euclidean\Point as BasePoint;
66

77
/**
88
* @method array{0: float, 1: float} getCoordinates()

src/Gps/Space.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
namespace Kmeans\Gps;
44

5-
use Kmeans\Space as BaseSpace;
5+
use Kmeans\Interfaces\SpaceInterface;
66

7-
class Space extends BaseSpace
7+
class Space implements SpaceInterface
88
{
9-
public function __construct()
9+
public function isEqualTo(SpaceInterface $other): bool
1010
{
11-
parent::__construct(2);
11+
return $other instanceof self;
1212
}
1313
}

src/Interfaces/SpaceInterface.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,5 @@
44

55
interface SpaceInterface
66
{
7-
/**
8-
* @return int<1, max>
9-
*/
10-
public function getDimensions(): int;
11-
127
public function isEqualTo(self $space): bool;
138
}

tests/Unit/ClusterCollectionTest.php

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,20 @@
44

55
use Kmeans\Cluster;
66
use Kmeans\ClusterCollection;
7+
use Kmeans\Euclidean\Point;
8+
use Kmeans\Euclidean\Space;
79
use Kmeans\Interfaces\ClusterInterface;
8-
use Kmeans\Point;
9-
use Kmeans\Space;
1010
use PHPUnit\Framework\TestCase;
1111

1212
/**
13-
* @coversDefaultClass \Kmeans\ClusterCollection
14-
* @uses \Kmeans\Space
13+
* @covers \Kmeans\ClusterCollection
1514
* @uses \Kmeans\Cluster
16-
* @uses \Kmeans\Point
15+
* @uses \Kmeans\Euclidean\Point
16+
* @uses \Kmeans\Euclidean\Space
1717
* @uses \Kmeans\PointCollection
1818
*/
1919
class ClusterCollectionTest extends TestCase
2020
{
21-
/**
22-
* @covers ::__construct
23-
* @covers ::getSpace
24-
* @covers ::attach
25-
* @covers ::contains
26-
*/
2721
public function testConstructingClusterWithPoints(): void
2822
{
2923
$space = new Space(1);
@@ -40,12 +34,6 @@ public function testConstructingClusterWithPoints(): void
4034
);
4135
}
4236

43-
/**
44-
* @covers ::__construct
45-
* @covers ::attach
46-
* @covers ::contains
47-
* @covers ::detach
48-
*/
4937
public function testAddingAndRemovingClustersFromCollection(): void
5038
{
5139
$space = new Space(4);
@@ -77,10 +65,6 @@ public function testAddingAndRemovingClustersFromCollection(): void
7765
);
7866
}
7967

80-
/**
81-
* @covers ::__construct
82-
* @covers ::attach
83-
*/
8468
public function testAddingInvalidClusterToCollection(): void
8569
{
8670
$this->expectException(\InvalidArgumentException::class);
@@ -94,12 +78,6 @@ public function testAddingInvalidClusterToCollection(): void
9478
$collection->attach($cluster);
9579
}
9680

97-
/**
98-
* @covers ::__construct
99-
* @covers ::attach
100-
* @covers ::detach
101-
* @covers ::count
102-
*/
10381
public function testCount(): void
10482
{
10583
$space = new Space(4);
@@ -125,15 +103,6 @@ public function testCount(): void
125103
$this->assertEquals(0, count($collection));
126104
}
127105

128-
/**
129-
* @covers ::__construct
130-
* @covers ::attach
131-
* @covers ::current
132-
* @covers ::key
133-
* @covers ::next
134-
* @covers ::rewind
135-
* @covers ::valid
136-
*/
137106
public function testIterator(): void
138107
{
139108
$space = new Space(4);

0 commit comments

Comments
 (0)