def clusterPopulation(self): """Clusters the given population into k clusters using balanced k-leader-means clustering.""" # TODO: POSSIBLE CHANGE = CALCULATE OPTIMAL k VALUE # The first leader is the solution with maximum value in an arbitrary objective. leaders = [self.population[0]] for solution in self.population: if solution.fitness[0] > leaders[0].fitness[0]: leaders[0] = solution # The solution with the largest nearest-leader distance is chosen as the next leader, # repeated k - 1 times to obtain k leaders. for _ in range(self.amountOfClusters - 1): nearestLeaderDistance = {} for solution in self.population: if solution not in leaders: nearestLeaderDistance[solution] = util.euclidianDistance( solution.fitness, leaders[0].fitness) for leader in leaders: leaderDistance = util.euclidianDistance( solution.fitness, leader.fitness) if leaderDistance < nearestLeaderDistance[solution]: nearestLeaderDistance[solution] = leaderDistance leader = max(nearestLeaderDistance, key=nearestLeaderDistance.get) leaders.append(leader) # k-means clustering is performed with k leaders as the initial cluster means. clusters = [] for leader in leaders: mean = leader.fitness cluster = Cluster(mean, self.problem) clusters.append(cluster) # Perform k-means clustering until all clusters are unchanged. while True in [cluster.changed for cluster in clusters]: for solution in self.population: nearestCluster = clusters[0] nearestClusterDistance = util.euclidianDistance( solution.fitness, nearestCluster.mean) for cluster in clusters: clusterDistance = util.euclidianDistance( solution.fitness, cluster.mean) if clusterDistance < nearestClusterDistance: nearestCluster = cluster nearestClusterDistance = clusterDistance nearestCluster.append(solution) for cluster in clusters: cluster.computeMean() cluster.clear() # Expand the clusters with the closest c solutions. c = int(2 / self.amountOfClusters * self.populationSize) for cluster in clusters: distance = {} for solution in self.population: distance[solution] = util.euclidianDistance( solution.fitness, cluster.mean) for _ in range(c): if len(distance) > 0: solution = min(distance, key=distance.get) del distance[solution] cluster.append(solution) self.clusters = clusters