/* 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.core.fitness; import org.moeaframework.core.FitnessEvaluator; import org.moeaframework.core.NondominatedPopulation; import org.moeaframework.core.Solution; import org.moeaframework.core.comparator.DominanceComparator; import org.moeaframework.core.comparator.FitnessComparator; import org.moeaframework.core.comparator.ParetoDominanceComparator; /** * Maintains a non-dominated archive of solutions with a maximum capacity. * If the size exceeds the capacity, one or more solutions are pruned based on * the fitness calculation. The fitness calculation only occurs when the * addition of a solution exceeds the capacity. The fitness can be manually * calculated by calling {@link #update()}. */ public class FitnessBasedArchive extends NondominatedPopulation { /** * The maximum capacity of this archive. */ private final int capacity; /** * The fitness evaluator for computing the fitness of solutions. */ private final FitnessEvaluator fitnessEvaluator; /** * The fitness comparator for comparing fitness values. */ private final FitnessComparator fitnessComparator; /** * Constructs an empty fitness-based archive. * * @param evaluator the fitness evaluator for computing the fitness of * solutions * @param capacity the maximum capacity of this archive */ public FitnessBasedArchive(FitnessEvaluator evaluator, int capacity) { this(evaluator, capacity, new ParetoDominanceComparator()); } /** * Constructs an empty fitness-based archive. * * @param evaluator the fitness evaluator for computing the fitness of * solutions * @param capacity the maximum capacity of this archive * @param comparator the dominance comparator */ public FitnessBasedArchive(FitnessEvaluator evaluator, int capacity, DominanceComparator comparator) { super(comparator); this.fitnessEvaluator = evaluator; this.capacity = capacity; fitnessComparator = new FitnessComparator( evaluator.areLargerValuesPreferred()); } /** * Constructs a fitness-based archive initialized with the specified * solutions. * * @param evaluator the fitness evaluator for computing the fitness of * solutions * @param capacity the maximum capacity of this archive * @param comparator the dominance comparator * @param iterable the solutions used to initialize this population */ public FitnessBasedArchive(FitnessEvaluator evaluator, int capacity, DominanceComparator comparator, Iterable<? extends Solution> iterable) { this(evaluator, capacity, comparator); addAll(iterable); } /** * Constructs a fitness-based archive initialized with the specified * solutions. * * @param evaluator the fitness evaluator for computing the fitness of * solutions * @param capacity the maximum capacity of this archive * @param iterable the solutions used to initialize this population */ public FitnessBasedArchive(FitnessEvaluator evaluator, int capacity, Iterable<? extends Solution> iterable) { this(evaluator, capacity, new ParetoDominanceComparator(), iterable); } @Override public boolean add(Solution solution) { boolean solutionAdded = super.add(solution); if (solutionAdded) { if (size() > capacity) { update(); truncate(capacity, fitnessComparator); } } return solutionAdded; } /** * Updates the fitness of all solutions in this population. */ public void update() { fitnessEvaluator.evaluate(this); } }