/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package hh.moea;
import java.util.Collection;
import java.util.Iterator;
import org.moeaframework.algorithm.NSGAII;
import org.moeaframework.core.EpsilonBoxDominanceArchive;
import static org.moeaframework.core.FastNondominatedSorting.CROWDING_ATTRIBUTE;
import org.moeaframework.core.Initialization;
import org.moeaframework.core.NondominatedSortingPopulation;
import org.moeaframework.core.ParallelPRNG;
import org.moeaframework.core.Population;
import org.moeaframework.core.Problem;
import org.moeaframework.core.Selection;
import org.moeaframework.core.Solution;
import org.moeaframework.core.Variation;
import org.moeaframework.core.comparator.ChainedComparator;
import org.moeaframework.core.comparator.CrowdingComparator;
import org.moeaframework.core.comparator.RankComparator;
import org.moeaframework.core.operator.TournamentSelection;
/**
* Steady state NSGAII uses Efficient Nondomination Level Update from Li, Ke,
* Kalyanmoy Deb, Qingfu Zhang, Senior Member, and Qiang Zhang. 2015. “Efficient
* Non-Domination Level Update Method for Steady-State Evolutionary
* Multi-Objective Optimization.” COIN Report Number 2015022
*
* @author nozomihitomi
*/
public class SteadyStateNSGAII extends NSGAII {
protected SteadyStateFastNonDominatedSorting enlu;
private ParallelPRNG pprng;
public SteadyStateNSGAII(Problem problem, NondominatedSortingPopulation population,
EpsilonBoxDominanceArchive archive, Selection selection, Variation variation, Initialization initialization) {
super(problem, population, archive,
selection, variation, initialization);
pprng = new ParallelPRNG();
}
@Override
protected void initialize() {
super.initialize();
// rank the solutions
enlu = new SteadyStateFastNonDominatedSorting();
enlu.evaluate(population);
}
@Override
public void iterate() {
Population offspring = new Population();
Solution[] parents = selection.select(variation.getArity(),
population);
Solution[] children = variation.evolve(parents);
offspring.addAll(children);
evaluateAll(offspring);
for (Solution child : offspring) {
enlu.addSolution(child, population);
int removeIndex = findWorstSolution();
population.remove(removeIndex);
}
}
/**
* Gets the solution to remove from the population. The solution that is the
* most crowded in the last front will be removed
*/
protected int findWorstSolution() {
int removeIndex = -1;
Collection<Integer> lastFront = enlu.getLastFront();
if (lastFront.size() <= 2) {
Iterator<Integer> iter = lastFront.iterator();
int rand = pprng.nextInt(lastFront.size());
for (int i = 0; i < lastFront.size(); i++) {
int index = iter.next();
if (i == rand) {
removeIndex = index;
}
}
} else {
Population lastFrontPop = new Population();
for (Integer index : enlu.getLastFront()) {
lastFrontPop.add(population.get(index));
}
enlu.updateCrowdingDistance(lastFrontPop);
//find solution with lowest crowding distance
double minCrowdingDist = Double.POSITIVE_INFINITY;
for (Integer index : enlu.getLastFront()) {
double dist = (double) population.get(index).getAttribute(CROWDING_ATTRIBUTE);
if (dist < minCrowdingDist) {
minCrowdingDist = dist;
removeIndex = index;
}
}
}
return removeIndex;
}
}