/** * Returns a new {@link MSOPS} instance. * * @param properties the properties for customizing the new {@code MSOPS} instance * @param problem the problem * @return a new {@code MSOPS} instance */ private Algorithm newMSOPS(TypedProperties properties, Problem problem) { if (!checkType(RealVariable.class, problem)) { throw new FrameworkException("unsupported decision variable type"); } int populationSize = (int) properties.getDouble("populationSize", 100); int numberOfWeights = (int) properties.getDouble("numberOfWeights", 50); Initialization initialization = new RandomInitialization(problem, populationSize); List<double[]> weights = new RandomGenerator(problem.getNumberOfObjectives(), numberOfWeights).generate(); // normalize weights so their magnitude is 1 for (int i = 0; i < weights.size(); i++) { weights.set(i, Vector.normalize(weights.get(i))); } MSOPSRankedPopulation population = new MSOPSRankedPopulation(weights); DifferentialEvolutionSelection selection = new DifferentialEvolutionSelection(); DifferentialEvolutionVariation variation = (DifferentialEvolutionVariation) OperatorFactory.getInstance().getVariation("de", properties, problem); return new MSOPS(problem, population, selection, variation, initialization); }
/** * Returns a new {@link MOEAD} instance. Only real encodings are supported. * * @param properties the properties for customizing the new {@code MOEAD} instance * @param problem the problem * @return a new {@code MOEAD} instance * @throws FrameworkException if the decision variables are not real valued */ private Algorithm newMOEAD(TypedProperties properties, Problem problem) { if (!checkType(RealVariable.class, problem)) { throw new FrameworkException("unsupported decision variable type"); } int populationSize = (int) properties.getDouble("populationSize", 100); // enforce population size lower bound if (populationSize < problem.getNumberOfObjectives()) { System.err.println("increasing MOEA/D population size"); populationSize = problem.getNumberOfObjectives(); } Initialization initialization = new RandomInitialization(problem, populationSize); Variation variation = OperatorFactory.getInstance().getVariation("de+pm", properties, problem); int neighborhoodSize = 20; int eta = 2; if (properties.contains("neighborhoodSize")) { neighborhoodSize = Math.max(2, (int) (properties.getDouble("neighborhoodSize", 0.1) * populationSize)); } if (neighborhoodSize > populationSize) { neighborhoodSize = populationSize; } if (properties.contains("eta")) { eta = Math.max(2, (int) (properties.getDouble("eta", 0.01) * populationSize)); } MOEAD algorithm = new MOEAD( problem, neighborhoodSize, initialization, variation, properties.getDouble("delta", 0.9), eta, (int) properties.getDouble("updateUtility", -1)); return algorithm; }
/** * Returns the distance in objective space between the two solutions. * * @param problem the problem * @param a the first solution * @param b the second solution * @param power the power ({@code 1.0} for Manhattan distance, {@code 2.0} for Euclidean distance) * @return the distance in objective space between the two solutions */ private static double distance(Problem problem, Solution a, Solution b, double power) { double distance = 0.0; for (int i = 0; i < problem.getNumberOfObjectives(); i++) { distance += Math.pow(Math.abs(a.getObjective(i) - b.getObjective(i)), power); } return Math.pow(distance, 1.0 / power); }
/** * Returns {@code true} if all decision variables are assignment-compatible with the specified * type; {@code false} otherwise. * * @param type the type of decision variable * @param problem the problem * @return {@code true} if all decision variables are assignment-compatible with the specified * type; {@code false} otherwise */ private boolean checkType(Class<? extends Variable> type, Problem problem) { Solution solution = problem.newSolution(); for (int i = 0; i < solution.getNumberOfVariables(); i++) { if (!type.isInstance(solution.getVariable(i))) { return false; } } return true; }
/** * Returns a new {@link SMPSO} instance. * * @param properties the properties for customizing the new {@code SMPSO} instance * @param problem the problem * @return a new {@code SMPSO} instance */ private Algorithm newSMPSO(TypedProperties properties, Problem problem) { if (!checkType(RealVariable.class, problem)) { throw new FrameworkException("unsupported decision variable type"); } int populationSize = (int) properties.getDouble("populationSize", 100); int archiveSize = (int) properties.getDouble("archiveSize", 100); double mutationProbability = properties.getDouble("pm.rate", 1.0 / problem.getNumberOfVariables()); double distributionIndex = properties.getDouble("pm.distributionIndex", 20.0); return new SMPSO(problem, populationSize, archiveSize, mutationProbability, distributionIndex); }
/** * Returns a new {@link CMAES} instance. * * @param properties the properties for customizing the new {@code CMAES} instance * @param problem the problem * @return a new {@code CMAES} instance */ private Algorithm newCMAES(TypedProperties properties, Problem problem) { if (!checkType(RealVariable.class, problem)) { throw new FrameworkException("unsupported decision variable type"); } int lambda = (int) properties.getDouble("lambda", 100); double cc = properties.getDouble("cc", -1.0); double cs = properties.getDouble("cs", -1.0); double damps = properties.getDouble("damps", -1.0); double ccov = properties.getDouble("ccov", -1.0); double ccovsep = properties.getDouble("ccovsep", -1.0); double sigma = properties.getDouble("sigma", -1.0); int diagonalIterations = (int) properties.getDouble("diagonalIterations", 0); String indicator = properties.getString("indicator", "crowding"); double[] initialSearchPoint = properties.getDoubleArray("initialSearchPoint", null); NondominatedPopulation archive = null; FitnessEvaluator fitnessEvaluator = null; if (problem.getNumberOfObjectives() == 1) { archive = new NondominatedPopulation(); } else { archive = new EpsilonBoxDominanceArchive( properties.getDoubleArray( "epsilon", new double[] {EpsilonHelper.getEpsilon(problem)})); } if ("hypervolume".equals(indicator)) { fitnessEvaluator = new HypervolumeFitnessEvaluator(problem); } else if ("epsilon".equals(indicator)) { fitnessEvaluator = new AdditiveEpsilonIndicatorFitnessEvaluator(problem); } CMAES cmaes = new CMAES( problem, lambda, fitnessEvaluator, archive, initialSearchPoint, false, cc, cs, damps, ccov, ccovsep, sigma, diagonalIterations); return cmaes; }
@Override public Solution[] initialize() { Solution[] initialPopulation = new Solution[populationSize]; for (int i = 0; i < populationSize; i++) { Solution solution = problem.newSolution(); for (int j = 0; j < solution.getNumberOfVariables(); j++) { solution.getVariable(j).randomize(); } initialPopulation[i] = solution; } return initialPopulation; }
/** * Returns a new {@link OMOPSO} instance. * * @param properties the properties for customizing the new {@code OMOPSO} instance * @param problem the problem * @return a new {@code OMOPSO} instance */ private Algorithm newOMOPSO(TypedProperties properties, Problem problem) { if (!checkType(RealVariable.class, problem)) { throw new FrameworkException("unsupported decision variable type"); } int populationSize = (int) properties.getDouble("populationSize", 100); int archiveSize = (int) properties.getDouble("archiveSize", 100); int maxIterations = (int) properties.getDouble("maxEvaluations", 25000) / populationSize; double mutationProbability = properties.getDouble("mutationProbability", 1.0 / problem.getNumberOfVariables()); double perturbationIndex = properties.getDouble("perturbationIndex", 0.5); double[] epsilon = properties.getDoubleArray("epsilon", new double[] {EpsilonHelper.getEpsilon(problem)}); return new OMOPSO( problem, populationSize, archiveSize, epsilon, mutationProbability, perturbationIndex, maxIterations); }
/** * Returns a new {@link IBEA} instance. * * @param properties the properties for customizing the new {@code IBEA} instance * @param problem the problem * @return a new {@code IBEA} instance */ private Algorithm newIBEA(TypedProperties properties, Problem problem) { if (problem.getNumberOfConstraints() > 0) { throw new ProviderNotFoundException( "IBEA", new ProviderLookupException("constraints not supported")); } int populationSize = (int) properties.getDouble("populationSize", 100); String indicator = properties.getString("indicator", "hypervolume"); IndicatorFitnessEvaluator fitnessEvaluator = null; Initialization initialization = new RandomInitialization(problem, populationSize); Variation variation = OperatorFactory.getInstance().getVariation(null, properties, problem); if ("hypervolume".equals(indicator)) { fitnessEvaluator = new HypervolumeFitnessEvaluator(problem); } else if ("epsilon".equals(indicator)) { fitnessEvaluator = new AdditiveEpsilonIndicatorFitnessEvaluator(problem); } else { throw new IllegalArgumentException("invalid indicator: " + indicator); } return new IBEA(problem, null, initialization, variation, fitnessEvaluator); }
/** * Returns a new {@link RVEA} instance. * * @param properties the properties for customizing the new {@code RVEA} instance * @param problem the problem * @return a new {@code RVEA} instance */ private Algorithm newRVEA(TypedProperties properties, Problem problem) { int divisionsOuter = 4; int divisionsInner = 0; if (problem.getNumberOfObjectives() < 2) { throw new FrameworkException("RVEA requires at least two objectives"); } if (properties.contains("divisionsOuter") && properties.contains("divisionsInner")) { divisionsOuter = (int) properties.getDouble("divisionsOuter", 4); divisionsInner = (int) properties.getDouble("divisionsInner", 0); } else if (properties.contains("divisions")) { divisionsOuter = (int) properties.getDouble("divisions", 4); } else if (problem.getNumberOfObjectives() == 1) { divisionsOuter = 100; } else if (problem.getNumberOfObjectives() == 2) { divisionsOuter = 99; } else if (problem.getNumberOfObjectives() == 3) { divisionsOuter = 12; } else if (problem.getNumberOfObjectives() == 4) { divisionsOuter = 8; } else if (problem.getNumberOfObjectives() == 5) { divisionsOuter = 6; } else if (problem.getNumberOfObjectives() == 6) { divisionsOuter = 4; divisionsInner = 1; } else if (problem.getNumberOfObjectives() == 7) { divisionsOuter = 3; divisionsInner = 2; } else if (problem.getNumberOfObjectives() == 8) { divisionsOuter = 3; divisionsInner = 2; } else if (problem.getNumberOfObjectives() == 9) { divisionsOuter = 3; divisionsInner = 2; } else if (problem.getNumberOfObjectives() == 10) { divisionsOuter = 3; divisionsInner = 2; } else { divisionsOuter = 2; divisionsInner = 1; } // compute number of reference vectors int populationSize = (int) (CombinatoricsUtils.binomialCoefficient( problem.getNumberOfObjectives() + divisionsOuter - 1, divisionsOuter) + (divisionsInner == 0 ? 0 : CombinatoricsUtils.binomialCoefficient( problem.getNumberOfObjectives() + divisionsInner - 1, divisionsInner))); Initialization initialization = new RandomInitialization(problem, populationSize); ReferenceVectorGuidedPopulation population = new ReferenceVectorGuidedPopulation( problem.getNumberOfObjectives(), divisionsOuter, divisionsInner, properties.getDouble("alpha", 2.0)); if (!properties.contains("sbx.swap")) { properties.setBoolean("sbx.swap", false); } if (!properties.contains("sbx.distributionIndex")) { properties.setDouble("sbx.distributionIndex", 30.0); } if (!properties.contains("pm.distributionIndex")) { properties.setDouble("pm.distributionIndex", 20.0); } Variation variation = OperatorFactory.getInstance().getVariation(null, properties, problem); int maxGenerations = (int) (properties.getDouble("maxEvaluations", 10000) / populationSize); int adaptFrequency = (int) properties.getDouble("adaptFrequency", maxGenerations / 10); return new RVEA(problem, population, variation, initialization, maxGenerations, adaptFrequency); }
/** * Returns a new {@link DBEA} instance. * * @param properties the properties for customizing the new {@code DBEA} instance * @param problem the problem * @return a new {@code DBEA} instance */ private Algorithm newDBEA(TypedProperties properties, Problem problem) { int divisionsOuter = 4; int divisionsInner = 0; if (properties.contains("divisionsOuter") && properties.contains("divisionsInner")) { divisionsOuter = (int) properties.getDouble("divisionsOuter", 4); divisionsInner = (int) properties.getDouble("divisionsInner", 0); } else if (properties.contains("divisions")) { divisionsOuter = (int) properties.getDouble("divisions", 4); } else if (problem.getNumberOfObjectives() == 1) { divisionsOuter = 100; } else if (problem.getNumberOfObjectives() == 2) { divisionsOuter = 99; } else if (problem.getNumberOfObjectives() == 3) { divisionsOuter = 12; } else if (problem.getNumberOfObjectives() == 4) { divisionsOuter = 8; } else if (problem.getNumberOfObjectives() == 5) { divisionsOuter = 6; } else if (problem.getNumberOfObjectives() == 6) { divisionsOuter = 4; divisionsInner = 1; } else if (problem.getNumberOfObjectives() == 7) { divisionsOuter = 3; divisionsInner = 2; } else if (problem.getNumberOfObjectives() == 8) { divisionsOuter = 3; divisionsInner = 2; } else if (problem.getNumberOfObjectives() == 9) { divisionsOuter = 3; divisionsInner = 2; } else if (problem.getNumberOfObjectives() == 10) { divisionsOuter = 3; divisionsInner = 2; } else { divisionsOuter = 2; divisionsInner = 1; } int populationSize = (int) (CombinatoricsUtils.binomialCoefficient( problem.getNumberOfObjectives() + divisionsOuter - 1, divisionsOuter) + (divisionsInner == 0 ? 0 : CombinatoricsUtils.binomialCoefficient( problem.getNumberOfObjectives() + divisionsInner - 1, divisionsInner))); Initialization initialization = new RandomInitialization(problem, populationSize); Variation variation = OperatorFactory.getInstance().getVariation(null, properties, problem); return new DBEA(problem, initialization, variation, divisionsOuter, divisionsInner); }
/** * Returns a new {@link NSGAIII} instance. * * @param properties the properties for customizing the new {@code NSGAIII} instance * @param problem the problem * @return a new {@code NSGAIII} instance */ private Algorithm newNSGAIII(TypedProperties properties, Problem problem) { int divisionsOuter = 4; int divisionsInner = 0; if (properties.contains("divisionsOuter") && properties.contains("divisionsInner")) { divisionsOuter = (int) properties.getDouble("divisionsOuter", 4); divisionsInner = (int) properties.getDouble("divisionsInner", 0); } else if (properties.contains("divisions")) { divisionsOuter = (int) properties.getDouble("divisions", 4); } else if (problem.getNumberOfObjectives() == 1) { divisionsOuter = 100; } else if (problem.getNumberOfObjectives() == 2) { divisionsOuter = 99; } else if (problem.getNumberOfObjectives() == 3) { divisionsOuter = 12; } else if (problem.getNumberOfObjectives() == 4) { divisionsOuter = 8; } else if (problem.getNumberOfObjectives() == 5) { divisionsOuter = 6; } else if (problem.getNumberOfObjectives() == 6) { divisionsOuter = 4; divisionsInner = 1; } else if (problem.getNumberOfObjectives() == 7) { divisionsOuter = 3; divisionsInner = 2; } else if (problem.getNumberOfObjectives() == 8) { divisionsOuter = 3; divisionsInner = 2; } else if (problem.getNumberOfObjectives() == 9) { divisionsOuter = 3; divisionsInner = 2; } else if (problem.getNumberOfObjectives() == 10) { divisionsOuter = 3; divisionsInner = 2; } else { divisionsOuter = 2; divisionsInner = 1; } int populationSize; if (properties.contains("populationSize")) { populationSize = (int) properties.getDouble("populationSize", 100); } else { // compute number of reference points populationSize = (int) (CombinatoricsUtils.binomialCoefficient( problem.getNumberOfObjectives() + divisionsOuter - 1, divisionsOuter) + (divisionsInner == 0 ? 0 : CombinatoricsUtils.binomialCoefficient( problem.getNumberOfObjectives() + divisionsInner - 1, divisionsInner))); // round up to a multiple of 4 populationSize = (int) Math.ceil(populationSize / 4d) * 4; } Initialization initialization = new RandomInitialization(problem, populationSize); ReferencePointNondominatedSortingPopulation population = new ReferencePointNondominatedSortingPopulation( problem.getNumberOfObjectives(), divisionsOuter, divisionsInner); Selection selection = null; if (problem.getNumberOfConstraints() == 0) { selection = new Selection() { @Override public Solution[] select(int arity, Population population) { Solution[] result = new Solution[arity]; for (int i = 0; i < arity; i++) { result[i] = population.get(PRNG.nextInt(population.size())); } return result; } }; } else { selection = new TournamentSelection( 2, new ChainedComparator( new AggregateConstraintComparator(), new DominanceComparator() { @Override public int compare(Solution solution1, Solution solution2) { return PRNG.nextBoolean() ? -1 : 1; } })); } // disable swapping variables in SBX operator to remain consistent with // Deb's implementation (thanks to Haitham Seada for identifying this // discrepancy) if (!properties.contains("sbx.swap")) { properties.setBoolean("sbx.swap", false); } if (!properties.contains("sbx.distributionIndex")) { properties.setDouble("sbx.distributionIndex", 30.0); } if (!properties.contains("pm.distributionIndex")) { properties.setDouble("pm.distributionIndex", 20.0); } Variation variation = OperatorFactory.getInstance().getVariation(null, properties, problem); return new NSGAII(problem, population, null, selection, variation, initialization); }