/* 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.single; import java.util.ArrayList; import java.util.List; import java.util.Properties; import org.moeaframework.algorithm.AbstractAlgorithm; import org.moeaframework.core.Algorithm; import org.moeaframework.core.NondominatedPopulation; import org.moeaframework.core.Problem; import org.moeaframework.core.spi.AlgorithmFactory; import org.moeaframework.util.TypedProperties; import org.moeaframework.util.weights.RandomGenerator; /** * Instantiates and runs several instances of a single objective algorithm. * This is intended to be used with single-objective optimizers that use * weighted aggregation of the objectives. This is based on the Repeated Single * Objective (RSO) algorithm by E. J. Hughes [1], where he investigates running * many single-objective optimizers (one many) compared to running a single * many-objective optimizer (many once). * <p> * Be mindful of how running multiple instances affects the {@link #step()}. * Each step performs one iteration of each instance. Thus, given 50 instances * of an algorithm with a population size of 100, then 5000 evaluations will * occur each step. In [1], they decrease the population size for the single * objective optimizers. * <p> * References: * <ol> * <li>E. J. Hughes. "Evolutionary many-objective optimization: many once or * one many." 2005 IEEE Congress on Evolutionary Computation, * pp. 222-227. * </ol> */ public class RepeatedSingleObjective extends AbstractAlgorithm { /** * The name of the algorithm. */ private final String algorithmName; /** * Any additional algorithm properties. */ private final Properties properties; /** * A list of the instantiated algorithms. */ private final List<Algorithm> algorithms; /** * Constructs a new instance of the Many-Once algorithm, which runs many * instances of a single-objective optimizer with varying weights. * * @param problem the problem * @param algorithmName the algorithm name * @param properties the algorithm properties * @param instances the number of instances */ public RepeatedSingleObjective(Problem problem, String algorithmName, Properties properties, int instances) { super(problem); this.algorithmName = algorithmName; this.properties = properties; // setup the algorithm instances List<double[]> weights = new RandomGenerator( problem.getNumberOfObjectives(), instances).generate(); algorithms = new ArrayList<Algorithm>(); for (double[] weight : weights) { algorithms.add(createInstance(weight)); } } @Override public int getNumberOfEvaluations() { int evaluations = 0; for (Algorithm algorithm : algorithms) { evaluations += algorithm.getNumberOfEvaluations(); } return evaluations; } @Override public NondominatedPopulation getResult() { NondominatedPopulation result = new NondominatedPopulation(); for (Algorithm algorithm : algorithms) { result.addAll(algorithm.getResult()); } return result; } @Override protected void initialize() { super.initialize(); // call iterate to force each algorithm to initialize iterate(); } @Override protected void iterate() { for (Algorithm algorithm : algorithms) { algorithm.step(); } } /** * Constructs a new instance of the algorithm using the given weights. * This assumes the weights are passed using the {@code "weights"} property. * * @param weights the weights * @return the new algorithm instance */ protected Algorithm createInstance(double[] weights) { TypedProperties typedProperties = new TypedProperties( new Properties(properties)); typedProperties.setDoubleArray("weights", weights); return AlgorithmFactory.getInstance().getAlgorithm( algorithmName, typedProperties.getProperties(), problem); } }