NSGA2Utils.java
package net.bmahe.genetics4j.moo.nsga2.impl;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.stream.IntStream;
import org.apache.commons.lang3.Validate;
import net.bmahe.genetics4j.moo.ObjectiveDistance;
public class NSGA2Utils {
private NSGA2Utils() {
}
public static <T> double[] crowdingDistanceAssignment(final int numberObjectives, final List<T> fitnessScore,
final Function<Integer, Comparator<T>> objectiveComparator, final ObjectiveDistance<T> objectiveDistance) {
Validate.isTrue(numberObjectives > 0);
Validate.notNull(fitnessScore);
Validate.isTrue(fitnessScore.isEmpty() == false);
Validate.notNull(objectiveComparator);
Validate.notNull(objectiveDistance);
final double[] distances = new double[fitnessScore.size()];
for (int m = 0; m < numberObjectives; m++) {
final Comparator<T> objective = objectiveComparator.apply(m);
final int[] sortedIndexes = IntStream.range(0, fitnessScore.size())
.boxed()
.sorted((a, b) -> objective.compare(fitnessScore.get(a), fitnessScore.get(b)))
.mapToInt((e) -> e)
.toArray();
distances[sortedIndexes[0]] = Double.POSITIVE_INFINITY;
distances[sortedIndexes[sortedIndexes.length - 1]] = Double.POSITIVE_INFINITY;
final T minFitnessByObjective = fitnessScore.get(sortedIndexes[0]);
final T maxFitnessByObjective = fitnessScore.get(sortedIndexes[sortedIndexes.length - 1]);
final double maxDistance = objectiveDistance.distance(minFitnessByObjective, maxFitnessByObjective, m);
for (int i = 1; i < sortedIndexes.length - 1; i++) {
final T previousFitness = fitnessScore.get(sortedIndexes[i - 1]);
final T nextFitness = fitnessScore.get(sortedIndexes[i + 1]);
if (maxDistance > 0.0) {
distances[i] += objectiveDistance.distance(previousFitness, nextFitness, m) / maxDistance;
}
}
}
return distances;
}
}