/* Copyright 2009-2016 David Hadka
*
* This file is part of the MOEA Framework.
*
* The MOEA Framework is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* The MOEA Framework is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the MOEA Framework. If not, see <http://www.gnu.org/licenses/>.
*/
package org.moeaframework.algorithm;
import java.io.Serializable;
import java.util.Comparator;
import org.moeaframework.core.FastNondominatedSorting;
import org.moeaframework.core.FitnessEvaluator;
import org.moeaframework.core.Initialization;
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.FitnessComparator;
import org.moeaframework.core.comparator.NondominatedSortingComparator;
import org.moeaframework.core.comparator.RankComparator;
import org.moeaframework.core.operator.TournamentSelection;
/**
* Implementation of the S-metric Selection MOEA (SMS-MOEA). The S metric is
* also known as the hypervolume indicator.
* <p>
* References:
* <ol>
* <li>Emmerich, M., N. Beume, and B. Naujoks (2007). An EMO Algorithm Using
* the Hypervolume Measure as Selection Criterion. European Journal of
* Operational Research, 3:1653-1669.
*/
public class SMSEMOA extends AbstractEvolutionaryAlgorithm {
/**
* The fitness evaluator to use (e.g., hypervolume or additive-epsilon
* indicator).
*/
private FitnessEvaluator fitnessEvaluator;
/**
* The selection operator.
*/
private Selection selection;
/**
* The variation operator.
*/
private Variation variation;
/**
* Constructs a new SMS-EMOA instance.
*
* @param problem the problem
* @param initialization the initialization operator
* @param variation the variation operator
* @param fitnessEvaluator the fitness evaluator
*/
public SMSEMOA(Problem problem, Initialization initialization,
Variation variation, FitnessEvaluator fitnessEvaluator) {
super(problem,
new Population(),
null,
initialization);
this.variation = variation;
this.fitnessEvaluator = fitnessEvaluator;
if (fitnessEvaluator == null) {
selection = new TournamentSelection(
new NondominatedSortingComparator());
} else {
selection = new TournamentSelection(
new NondominatedFitnessComparator());
}
}
@Override
protected void initialize() {
super.initialize();
// rank the solutions
new FastNondominatedSorting().evaluate(population);
if (fitnessEvaluator != null) {
fitnessEvaluator.evaluate(population);
}
}
@Override
protected void iterate() {
int populationSize = population.size();
Solution[] parents = selection.select(variation.getArity(), population);
Solution[] offspring = variation.evolve(parents);
evaluate(offspring[0]);
population.add(offspring[0]);
// rank the solutions and remove the worst
new FastNondominatedSorting().evaluate(population);
if (fitnessEvaluator == null) {
population.truncate(populationSize,
new NondominatedSortingComparator());
} else {
computeFitnessForLastFront();
population.truncate(populationSize,
new NondominatedFitnessComparator());
}
}
/**
* Computes the fitness for the last front.
*/
private void computeFitnessForLastFront() {
Population front = new Population();
int rank = 0;
for (Solution solution : population) {
int solutionRank = (Integer)solution.getAttribute(
FastNondominatedSorting.RANK_ATTRIBUTE);
if (solutionRank > rank) {
front.clear();
rank = solutionRank;
}
if (solutionRank == rank) {
front.add(solution);
}
solution.setAttribute(FitnessEvaluator.FITNESS_ATTRIBUTE, 0.0);
}
fitnessEvaluator.evaluate(front);
}
private class NondominatedFitnessComparator extends ChainedComparator
implements Comparator<Solution>, Serializable {
private static final long serialVersionUID = -4088873047790962685L;
public NondominatedFitnessComparator() {
super(new RankComparator(), new FitnessComparator(
fitnessEvaluator.areLargerValuesPreferred()));
}
}
}