package models.clusters;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import models.distances.IDistance;
import views.Cluster;
import views.Star;
/**
* Implementation of the k-means algorithm
* @author clement
*
*/
public class KMeans implements IClusteringAlgorithm {
private final String name = "K-Means";
private IDistance d;
private Cluster[] clusters;
private List<Star> stars;
public void setParams(int k, IDistance d, Iterable<Star> stars) {
this.d = d;
clusters= new Cluster[k];
this.stars = new LinkedList<Star>();
for (Star s : stars) {
this.stars.add(s);
}
}
@Override
public void run() {
for(int i = 0; i< clusters.length ; ++i){
clusters[i] = new Cluster(randomPick());
}
for(Star s : stars){
double min = d.get(s, clusters[0].getCentroid());
int index = 0;
for(int i = 1; i< clusters.length ; ++i){
double currentDist = d.get(s, clusters[i].getCentroid());
if(currentDist < min){
min = currentDist;
index = i;
}
}
clusters[index].addAndMerge(s);
}
// Small final optimization
reassign();
}
public void reassign(){
for(int i = 0; i<clusters.length; ++i){
clusters[i].clear();
}
for(Star s : stars){
double min = d.get(s, clusters[0].getCentroid());
int index = 0;
for(int i = 1; i< clusters.length ; ++i){
double currentDist = d.get(s, clusters[i].getCentroid());
if(currentDist < min){
min = currentDist;
index = i;
}
}
clusters[index].add(s);
}
}
private Star randomPick() {
int index = (int) (Math.random() * stars.size());
return stars.get(index);
}
private Iterable<Cluster> getClusters() {
run();
return Arrays.asList(clusters);
}
@Override
public String getName() {
return this.name;
}
public Iterable<Cluster> getClusters(int nClusters, IDistance distance,
Iterable<Star> stars) {
setParams(nClusters, distance, stars);
return getClusters();
}
@Override
public Iterable<Cluster> getClusters(String params, IDistance distance,
Iterable<Star> stars) {
return getClusters(Integer.parseInt(params), distance, stars);
}
@Override
public String getOptionString() {
return "nClusters";
}
@Override
public String getDefaultOptionsValue() {
return "100";
}
}