/* 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 hh.moea.SteadyStateFastNonDominatedSorting; 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; private SteadyStateFastNonDominatedSorting enlu; /** * 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); // } enlu = new SteadyStateFastNonDominatedSorting(); computeFitnessForLastFront(); } @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); enlu.addSolution(offspring[0], 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); } if (enlu.getLastFront() != null) { for (Integer i : enlu.getLastFront()) { Solution solution = population.get(i); front.add(solution); } 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())); } } }