Passed
Pull Request — master (#429)
by
unknown
03:47
created

Cluster::setCoordinates()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Phpml\Clustering\KMeans;
6
7
use IteratorAggregate;
8
use LogicException;
9
use SplObjectStorage;
10
11
class Cluster extends Point implements IteratorAggregate
12
{
13
    /**
14
     * @var Space
15
     */
16
    protected $space;
17
18
    /**
19
     * @var SplObjectStorage|Point[]
20
     */
21
    protected $points;
22
23
    public function __construct(Space $space, array $coordinates)
24
    {
25
        parent::__construct($coordinates);
26
        $this->space = $space;
27
        $this->points = new SplObjectStorage();
28
    }
29
30
    public function getPoints(): array
31
    {
32
        $points = [];
33
        foreach ($this->points as $point) {
34
            if ($point->label === null) {
35
                $points[] = $point;
36
            } else {
37
                $points[$point->label] = $point;
38
            }
39
        }
40
41
        return $points;
42
    }
43
44
    public function getSpace(): Space
45
    {
46
        return $this->space;
47
    }
48
49
    public function toArray(): array
50
    {
51
        return [
52
            'centroid' => parent::toArray(),
53
            'points' => array_map(function ($point) {
54
                return $point->toArray();
55
            }, $this->getPoints()),
56
        ];
57
    }
58
59
    public function attach(Point $point): Point
60
    {
61
        if ($point instanceof self) {
62
            throw new LogicException('Cannot attach a cluster to another');
63
        }
64
65
        $this->points->attach($point);
66
67
        return $point;
68
    }
69
70
    public function detach(Point $point): Point
71
    {
72
        $this->points->detach($point);
73
74
        return $point;
75
    }
76
77
    public function attachAll(SplObjectStorage $points): void
78
    {
79
        $this->points->addAll($points);
80
    }
81
82
    public function detachAll(SplObjectStorage $points): void
83
    {
84
        $this->points->removeAll($points);
85
    }
86
87
    public function updateCentroid(): void
88
    {
89
        $count = count($this->points);
90
        if ($count === 0) {
91
            return;
92
        }
93
94
        $centroid = $this->space->newPoint(array_fill(0, $this->dimension, 0));
95
96
        foreach ($this->points as $point) {
97
            for ($n = 0; $n < $this->dimension; ++$n) {
98
                $centroid->coordinates[$n] += $point->coordinates[$n];
99
            }
100
        }
101
102
        for ($n = 0; $n < $this->dimension; ++$n) {
103
            $this->coordinates[$n] = $centroid->coordinates[$n] / $count;
104
        }
105
    }
106
107
    /**
108
     * @return Point[]|SplObjectStorage
109
     */
110
    public function getIterator()
111
    {
112
        return $this->points;
113
    }
114
115
    public function count(): int
116
    {
117
        return count($this->points);
118
    }
119
120
    public function setCoordinates(array $newCoordinates): void
121
    {
122
        $this->coordinates = $newCoordinates;
123
    }
124
}
125