Completed
Push — master ( d19ddb...95fc13 )
by Arkadiusz
03:08
created

Cluster   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 136
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 2
dl 0
loc 136
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getPoints() 0 9 2
A toArray() 0 7 1
A attach() 0 10 2
A detach() 0 6 1
A attachAll() 0 4 1
A detachAll() 0 4 1
B updateCentroid() 0 18 5
A getIterator() 0 4 1
A count() 0 4 1
A setCoordinates() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Phpml\Clustering\KMeans;
6
7
use IteratorAggregate;
8
use Countable;
9
use SplObjectStorage;
10
use LogicException;
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
    /**
25
     * @param Space $space
26
     * @param array $coordinates
27
     */
28
    public function __construct(Space $space, array $coordinates)
29
    {
30
        parent::__construct($coordinates);
31
        $this->space = $space;
32
        $this->points = new SplObjectStorage();
33
    }
34
35
    /**
36
     * @return array
37
     */
38
    public function getPoints()
39
    {
40
        $points = [];
41
        foreach ($this->points as $point) {
42
            $points[] = $point->toArray();
43
        }
44
45
        return $points;
46
    }
47
48
    /**
49
     * @return array
50
     */
51
    public function toArray()
52
    {
53
        return array(
54
            'centroid' => parent::toArray(),
55
            'points' => $this->getPoints(),
56
        );
57
    }
58
59
    /**
60
     * @param Point $point
61
     *
62
     * @return Point
63
     *
64
     * @throws \LogicException
65
     */
66
    public function attach(Point $point)
67
    {
68
        if ($point instanceof self) {
69
            throw new LogicException('cannot attach a cluster to another');
70
        }
71
72
        $this->points->attach($point);
73
74
        return $point;
75
    }
76
77
    /**
78
     * @param Point $point
79
     *
80
     * @return Point
81
     */
82
    public function detach(Point $point)
83
    {
84
        $this->points->detach($point);
85
86
        return $point;
87
    }
88
89
    /**
90
     * @param SplObjectStorage $points
91
     */
92
    public function attachAll(SplObjectStorage $points)
93
    {
94
        $this->points->addAll($points);
95
    }
96
97
    /**
98
     * @param SplObjectStorage $points
99
     */
100
    public function detachAll(SplObjectStorage $points)
101
    {
102
        $this->points->removeAll($points);
103
    }
104
105
    public function updateCentroid()
106
    {
107
        if (!$count = count($this->points)) {
108
            return;
109
        }
110
111
        $centroid = $this->space->newPoint(array_fill(0, $this->dimension, 0));
112
113
        foreach ($this->points as $point) {
114
            for ($n = 0; $n < $this->dimension; ++$n) {
115
                $centroid->coordinates[$n] += $point->coordinates[$n];
116
            }
117
        }
118
119
        for ($n = 0; $n < $this->dimension; ++$n) {
120
            $this->coordinates[$n] = $centroid->coordinates[$n] / $count;
121
        }
122
    }
123
124
    /**
125
     * @return Point[]|SplObjectStorage
126
     */
127
    public function getIterator()
128
    {
129
        return $this->points;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->points; of type SplObjectStorage|Phpml\Clustering\KMeans\Point[] adds the type Phpml\Clustering\KMeans\Point[] to the return on line 129 which is incompatible with the return type declared by the interface IteratorAggregate::getIterator of type Traversable.
Loading history...
130
    }
131
132
    /**
133
     * @return mixed
134
     */
135
    public function count()
136
    {
137
        return count($this->points);
138
    }
139
    
140
    /**
141
    * @param array $newCoordinates
142
    */
143
    public function setCoordinates(array $newCoordinates)
144
    {
145
        $this->coordinates = $newCoordinates;
146
    }    
147
}
148