* optimal k-means solution (given good starting points).
*
* @param datapoints Rows containing WeightedVectors
*/
private void iterativeAssignment(List<? extends WeightedVector> datapoints) {
DistanceMeasure l2 = new EuclideanDistanceMeasure();
// closestClusterDistances.get(i) is the distance from the i'th cluster to its closest
// neighboring cluster.
List<Double> closestClusterDistances = Lists.newArrayListWithExpectedSize(numClusters);
// clusterAssignments[i] == j means that the i'th point is assigned to the j'th cluster. When
// these don't change, we are done.
List<Integer> clusterAssignments = Lists.newArrayListWithExpectedSize(datapoints.size());
// Each point is assigned to the invalid "-1" cluster initially.
for (int i = 0; i < datapoints.size(); ++i) {
clusterAssignments.add(-1);
}
boolean changed = true;
for (int i = 0; changed && i < maxNumIterations; i++) {
// We compute what the distance between each cluster and its closest neighbor is to set a
// proportional distance threshold for points that should be involved in calculating the
// centroid.
closestClusterDistances.clear();
for (Vector center : centroids) {
Vector closestOtherCluster = centroids.search(center, 2).get(1).getValue();
closestClusterDistances.add(l2.distance(center, closestOtherCluster));
}
// Copies the current cluster centroids to newClusters and sets their weights to 0. This is
// so we calculate the new centroids as we go through the datapoints.
List<Centroid> newCentroids = Lists.newArrayList();