Cluster   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 18
eloc 36
dl 0
loc 105
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A attach() 0 9 2
A getPoints() 0 12 3
A updateCentroid() 0 17 5
A attachAll() 0 3 1
A toArray() 0 5 1
A count() 0 3 1
A detachAll() 0 3 1
A getIterator() 0 3 1
A detach() 0 5 1
A setCoordinates() 0 3 1
A __construct() 0 5 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->toArray();
36
            } else {
37
                $points[$point->label] = $point->toArray();
38
            }
39
        }
40
41
        return $points;
42
    }
43
44
    public function toArray(): array
45
    {
46
        return [
47
            'centroid' => parent::toArray(),
48
            'points' => $this->getPoints(),
49
        ];
50
    }
51
52
    public function attach(Point $point): Point
53
    {
54
        if ($point instanceof self) {
55
            throw new LogicException('Cannot attach a cluster to another');
56
        }
57
58
        $this->points->attach($point);
59
60
        return $point;
61
    }
62
63
    public function detach(Point $point): Point
64
    {
65
        $this->points->detach($point);
66
67
        return $point;
68
    }
69
70
    public function attachAll(SplObjectStorage $points): void
71
    {
72
        $this->points->addAll($points);
73
    }
74
75
    public function detachAll(SplObjectStorage $points): void
76
    {
77
        $this->points->removeAll($points);
78
    }
79
80
    public function updateCentroid(): void
81
    {
82
        $count = count($this->points);
83
        if ($count === 0) {
84
            return;
85
        }
86
87
        $centroid = $this->space->newPoint(array_fill(0, $this->dimension, 0));
88
89
        foreach ($this->points as $point) {
90
            for ($n = 0; $n < $this->dimension; ++$n) {
91
                $centroid->coordinates[$n] += $point->coordinates[$n];
92
            }
93
        }
94
95
        for ($n = 0; $n < $this->dimension; ++$n) {
96
            $this->coordinates[$n] = $centroid->coordinates[$n] / $count;
97
        }
98
    }
99
100
    /**
101
     * @return Point[]|SplObjectStorage
102
     */
103
    public function getIterator()
104
    {
105
        return $this->points;
106
    }
107
108
    public function count(): int
109
    {
110
        return count($this->points);
111
    }
112
113
    public function setCoordinates(array $newCoordinates): void
114
    {
115
        $this->coordinates = $newCoordinates;
116
    }
117
}
118