Passed
Push — master ( e83f7b...d953ef )
by Arkadiusz
03:28
created

src/Phpml/Clustering/KMeans/Cluster.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Phpml\Clustering\KMeans;
6
7
use Countable;
8
use IteratorAggregate;
9
use LogicException;
10
use SplObjectStorage;
11
12
class Cluster extends Point implements IteratorAggregate, Countable
13
{
14
    /**
15
     * @var Space
16
     */
17
    protected $space;
18
19
    /**
20
     * @var SplObjectStorage|Point[]
21
     */
22
    protected $points;
23
24
    public function __construct(Space $space, array $coordinates)
25
    {
26
        parent::__construct($coordinates);
27
        $this->space = $space;
28
        $this->points = new SplObjectStorage();
29
    }
30
31
    public function getPoints(): array
32
    {
33
        $points = [];
34
        foreach ($this->points as $point) {
35
            $points[] = $point->toArray();
36
        }
37
38
        return $points;
39
    }
40
41
    public function toArray(): array
42
    {
43
        return [
44
            'centroid' => parent::toArray(),
45
            'points' => $this->getPoints(),
46
        ];
47
    }
48
49
    public function attach(Point $point): Point
50
    {
51
        if ($point instanceof self) {
52
            throw new LogicException('cannot attach a cluster to another');
53
        }
54
55
        $this->points->attach($point);
56
57
        return $point;
58
    }
59
60
    public function detach(Point $point): Point
61
    {
62
        $this->points->detach($point);
63
64
        return $point;
65
    }
66
67
    public function attachAll(SplObjectStorage $points): void
68
    {
69
        $this->points->addAll($points);
70
    }
71
72
    public function detachAll(SplObjectStorage $points): void
73
    {
74
        $this->points->removeAll($points);
75
    }
76
77
    public function updateCentroid(): void
78
    {
79
        $count = count($this->points);
80
        if (!$count) {
81
            return;
82
        }
83
84
        $centroid = $this->space->newPoint(array_fill(0, $this->dimension, 0));
85
86
        foreach ($this->points as $point) {
87 View Code Duplication
            for ($n = 0; $n < $this->dimension; ++$n) {
88
                $centroid->coordinates[$n] += $point->coordinates[$n];
89
            }
90
        }
91
92 View Code Duplication
        for ($n = 0; $n < $this->dimension; ++$n) {
93
            $this->coordinates[$n] = $centroid->coordinates[$n] / $count;
94
        }
95
    }
96
97
    /**
98
     * @return Point[]|SplObjectStorage
99
     */
100
    public function getIterator()
101
    {
102
        return $this->points;
0 ignored issues
show
Bug Compatibility introduced by Arkadiusz Kondas
The expression $this->points; of type SplObjectStorage|Phpml\Clustering\KMeans\Point[] adds the type Phpml\Clustering\KMeans\Point[] to the return on line 102 which is incompatible with the return type declared by the interface IteratorAggregate::getIterator of type Traversable.
Loading history...
103
    }
104
105
    /**
106
     * @return mixed
107
     */
108
    public function count()
109
    {
110
        return count($this->points);
111
    }
112
113
    public function setCoordinates(array $newCoordinates): void
114
    {
115
        $this->coordinates = $newCoordinates;
116
    }
117
}
118