public function testFindClosestCentroid() { $x = array(1, 1, 1, 1); $centroids = array(array(2, 2, 2, 2), array(3, 3, 3, 3), array(4, 4, 4, 4), array(5, 5, 5, 5), array(1, 3, 3, 5), array(1, 6, 7, 8), array(9, 9, 9, 9), array(100, 100, 100, 100)); $this->assertEquals(0, _ll_closest_centroid($x, $centroids)); for ($i = 0; $i < 100; $i++) { shuffle($centroids); $expected = array_search(array(2, 2, 2, 2), $centroids); $this->assertEquals($expected, _ll_closest_centroid($x, $centroids)); } $x = array(100, 100, 100, 100); $expected = array_search(array(100, 100, 100, 100), $centroids); $this->assertEquals($expected, _ll_closest_centroid($x, $centroids)); $x = array(6, 4, 6, 4); $expected = array_search(array(5, 5, 5, 5), $centroids); $this->assertEquals($expected, _ll_closest_centroid($x, $centroids)); }
function ll_kmeans($xs, $k) { if ($k > count($xs)) { return false; } $centroids = _ll_init_centroids($xs, $k); $belongs_to = array(); do { for ($i = 0; $i < count($xs); $i++) { // I reversed the order here (to store the centroids as indexes in the array) // for complexity reasons. $belongs_to[_ll_closest_centroid($xs[$i], $centroids)][] = $i; } $old_centroids = $centroids; $centroids = _ll_reposition_centroids($centroids, $belongs_to, $xs); $continue = $old_centroids == $centroids; } while ($continue); return $belongs_to; }