/* 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.NotSerializableException; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.moeaframework.core.EvolutionaryAlgorithm; import org.moeaframework.core.Initialization; import org.moeaframework.core.NondominatedPopulation; import org.moeaframework.core.Population; import org.moeaframework.core.Problem; import org.moeaframework.core.Solution; /** * Abstract class providing default implementations for several * {@link EvolutionaryAlgorithm} methods. Primarily, the {@link #initialize()} * method generates and evaluates the initial population, adding the solutions * to the archive if available. The {@link #getResult()} method returns the * non-dominated solutions from the population and, if available, the archive. * The majority of evolutionary algorithms should only need to override the * {@link #iterate()} method. */ public abstract class AbstractEvolutionaryAlgorithm extends AbstractAlgorithm implements EvolutionaryAlgorithm { /** * The current population. */ protected final Population population; /** * The archive storing the non-dominated solutions. */ protected final NondominatedPopulation archive; /** * The initialization operator. */ protected final Initialization initialization; /** * Constructs an abstract evolutionary algorithm. * * @param problem the problem being solved * @param population the population * @param archive the archive storing the non-dominated solutions * @param initialization the initialization operator */ public AbstractEvolutionaryAlgorithm(Problem problem, Population population, NondominatedPopulation archive, Initialization initialization) { super(problem); this.population = population; this.archive = archive; this.initialization = initialization; } @Override public NondominatedPopulation getResult() { Population population = getPopulation(); NondominatedPopulation archive = getArchive(); NondominatedPopulation result = new NondominatedPopulation(); result.addAll(population); if (archive != null) { result.addAll(archive); } return result; } @Override protected void initialize() { super.initialize(); Population population = getPopulation(); NondominatedPopulation archive = getArchive(); Solution[] initialSolutions = initialization.initialize(); evaluateAll(initialSolutions); population.addAll(initialSolutions); if (archive != null) { archive.addAll(population); } } @Override public NondominatedPopulation getArchive() { return archive; } @Override public Population getPopulation() { return population; } @Override public Serializable getState() throws NotSerializableException { if (!isInitialized()) { throw new AlgorithmInitializationException(this, "algorithm not initialized"); } List<Solution> populationList = new ArrayList<Solution>(); List<Solution> archiveList = new ArrayList<Solution>(); for (Solution solution : population) { populationList.add(solution); } if (archive != null) { for (Solution solution : archive) { archiveList.add(solution); } } return new EvolutionaryAlgorithmState(getNumberOfEvaluations(), populationList, archiveList); } @Override public void setState(Object objState) throws NotSerializableException { super.initialize(); EvolutionaryAlgorithmState state = (EvolutionaryAlgorithmState)objState; numberOfEvaluations = state.getNumberOfEvaluations(); population.addAll(state.getPopulation()); if (archive != null) { archive.addAll(state.getArchive()); } } /** * Proxy for serializing and deserializing the state of an * {@code AbstractEvolutionaryAlgorithm}. This proxy supports saving * the {@code numberOfEvaluations}, {@code population} and {@code archive}. */ private static class EvolutionaryAlgorithmState implements Serializable { private static final long serialVersionUID = -6186688380313335557L; /** * The number of objective function evaluations. */ private final int numberOfEvaluations; /** * The population stored in a serializable list. */ private final List<Solution> population; /** * The archive stored in a serializable list. */ private final List<Solution> archive; /** * Constructs a proxy to serialize and deserialize the state of an * {@code AbstractEvolutionaryAlgorithm}. * * @param numberOfEvaluations the number of objective function * evaluations * @param population the population stored in a serializable list * @param archive the archive stored in a serializable list */ public EvolutionaryAlgorithmState(int numberOfEvaluations, List<Solution> population, List<Solution> archive) { super(); this.numberOfEvaluations = numberOfEvaluations; this.population = population; this.archive = archive; } /** * Returns the number of objective function evaluations. * * @return the number of objective function evaluations */ public int getNumberOfEvaluations() { return numberOfEvaluations; } /** * Returns the population stored in a serializable list. * * @return the population stored in a serializable list */ public List<Solution> getPopulation() { return population; } /** * Returns the archive stored in a serializable list. * * @return the archive stored in a serializable list */ public List<Solution> getArchive() { return archive; } } }