/* 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.problem.BBOB2016;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.moeaframework.core.FrameworkException;
import org.moeaframework.core.NondominatedPopulation;
import org.moeaframework.core.Problem;
import org.moeaframework.core.spi.ProblemProvider;
/*
* The following source code is derived from the Coco Framework available at
* <https://github.com/numbbo/coco> under the 3-clause BSD license. The
* original code is copyright 2013 by the NumBBO/CoCO team. See the AUTHORS
* file located in the Coco Framework repository for more details.
*/
/**
* Problem provider for all problems in the BBOB 2016 test suite. This test
* suite consists of bi-objective problems constructed from two single-objective
* functions. Each single-objective function name follows the pattern:
* <pre>
* bbob_f001_d02_i05
* </pre>
* In this case, we are requesting the fifth instance of the first BBOB
* function with 2 decision variables. The location of the optimum differs in
* each instance. To create the name of a BBOB 2016 problem supported by this
* problem provider, separate two function names with two underscores, such
* as:
* <pre>
* bbob_f001_d02_i05__bbob_f021_d02_i07
* </pre>
* The dimension or number of decision variables must be identical in both
* functions.
*/
public class BBOB2016Problems extends ProblemProvider {
@Override
public Problem getProblem(String name) {
Pattern pattern = Pattern.compile(
"^bbob_f([0-9]+)_i([0-9]+)_d([0-9]+)__bbob_f([0-9]+)_i([0-9]+)_d([0-9]+)$");
Matcher matcher = pattern.matcher(name);
if (matcher.matches()) {
return new StackedProblem(
createInstance(
Integer.parseInt(matcher.group(1)),
Integer.parseInt(matcher.group(3)),
Integer.parseInt(matcher.group(2))),
createInstance(
Integer.parseInt(matcher.group(4)),
Integer.parseInt(matcher.group(6)),
Integer.parseInt(matcher.group(5))));
} else {
return null;
}
}
@Override
public NondominatedPopulation getReferenceSet(String name) {
return null;
}
/**
* Constructs an instance of one of the BBOB test functions.
*
* @param function the index of the test function
* @param dimension the number of decision variables
* @param instance the function instance
* @return the BBOB test function
*/
public static BBOBFunction createInstance(int function, int dimension, int instance) {
int rseed = function + 10000 * instance;
if (function == 1) {
double[] xopt = BBOBUtils.computeXOpt(rseed, dimension);
double fopt = BBOBUtils.computeFOpt(function, instance);
BBOBFunction problem = new Sphere(dimension);
problem = new TransformVariablesShift(problem, xopt);
problem = new TransformObjectiveShift(problem, fopt);
return problem;
} else if (function == 2) {
double[] xopt = BBOBUtils.computeXOpt(rseed, dimension);
double fopt = BBOBUtils.computeFOpt(function, instance);
BBOBFunction problem = new Ellipsoid(dimension);
problem = new TransformVariablesOscillate(problem);
problem = new TransformVariablesShift(problem, xopt);
problem = new TransformObjectiveShift(problem, fopt);
return problem;
} else if (function == 6) {
double[] xopt = BBOBUtils.computeXOpt(rseed, dimension);
double fopt = BBOBUtils.computeFOpt(function, instance);
double[] b = new double[dimension];
double[][] M = new double[dimension][dimension];
double[][] rot1 = BBOBUtils.computeRotation(rseed + 1000000, dimension);
double[][] rot2 = BBOBUtils.computeRotation(rseed, dimension);
for (int i = 0; i < dimension; i++) {
b[i] = 0.0;
for (int j = 0; j < dimension; j++) {
M[i][j] = 0.0;
for (int k = 0; k < dimension; k++) {
double exponent = 1.0 * k / (dimension - 1.0);
M[i][j] += rot1[i][k] * Math.pow(Math.sqrt(10.0), exponent) * rot2[k][j];
}
}
}
BBOBFunction problem = new AttractiveSector(dimension, xopt);
problem = new TransformObjectiveOscillate(problem);
problem = new TransformObjectivePower(problem, 0.9);
problem = new TransformObjectiveShift(problem, fopt);
problem = new TransformVariablesAffine(problem, M, b);
problem = new TransformVariablesShift(problem, xopt);
return problem;
} else if (function == 8) {
double[] xopt = BBOBUtils.computeXOpt(rseed, dimension);
double fopt = BBOBUtils.computeFOpt(function, instance);
double[] minusOne = new double[dimension];
for (int i = 0; i < dimension; i++) {
minusOne[i] = -1.0;
xopt[i] *= 0.75;
}
BBOBFunction problem = new Rosenbrock(dimension);
problem = new TransformVariablesShift(problem, minusOne);
problem = new TransformVariablesScale(problem, Math.max(1.0, Math.sqrt(dimension / 8.0)));
problem = new TransformVariablesShift(problem, xopt);
problem = new TransformObjectiveShift(problem, fopt);
return problem;
} else if (function == 13) {
double[] xopt = BBOBUtils.computeXOpt(rseed, dimension);
double fopt = BBOBUtils.computeFOpt(function, instance);
double[] b = new double[dimension];
double[][] M = new double[dimension][dimension];
double[][] rot1 = BBOBUtils.computeRotation(rseed + 1000000, dimension);
double[][] rot2 = BBOBUtils.computeRotation(rseed, dimension);
for (int i = 0; i < dimension; i++) {
b[i] = 0.0;
for (int j = 0; j < dimension; j++) {
M[i][j] = 0.0;
for (int k = 0; k < dimension; k++) {
double exponent = 1.0 * k / (dimension - 1.0);
M[i][j] += rot1[i][k] * Math.pow(Math.sqrt(10.0), exponent) * rot2[k][j];
}
}
}
BBOBFunction problem = new SharpRidge(dimension);
problem = new TransformObjectiveShift(problem, fopt);
problem = new TransformVariablesAffine(problem, M, b);
problem = new TransformVariablesShift(problem, xopt);
return problem;
} else if (function == 14) {
double[] xopt = BBOBUtils.computeXOpt(rseed, dimension);
double fopt = BBOBUtils.computeFOpt(function, instance);
double[] b = new double[dimension];
double[][] M = BBOBUtils.computeRotation(rseed + 1000000, dimension);
BBOBFunction problem = new DifferentPowers(dimension);
problem = new TransformObjectiveShift(problem, fopt);
problem = new TransformVariablesAffine(problem, M, b);
problem = new TransformVariablesShift(problem, xopt);
return problem;
} else if (function == 15) {
double[] xopt = BBOBUtils.computeXOpt(rseed, dimension);
double fopt = BBOBUtils.computeFOpt(function, instance);
double[] zeros = new double[dimension];
double[] b = new double[dimension];
double[][] M = new double[dimension][dimension];
double[][] rot1 = BBOBUtils.computeRotation(rseed + 1000000, dimension);
double[][] rot2 = BBOBUtils.computeRotation(rseed, dimension);
for (int i = 0; i < dimension; i++) {
b[i] = 0.0;
for (int j = 0; j < dimension; j++) {
M[i][j] = 0.0;
for (int k = 0; k < dimension; k++) {
double exponent = 1.0 * k / (dimension - 1.0);
M[i][j] += rot1[i][k] * Math.pow(Math.sqrt(10.0), exponent) * rot2[k][j];
}
}
}
BBOBFunction problem = new Rastrigin(dimension);
problem = new TransformObjectiveShift(problem, fopt);
problem = new TransformVariablesAffine(problem, M, b);
problem = new TransformVariablesAsymmetric(problem, 0.2);
problem = new TransformVariablesOscillate(problem);
problem = new TransformVariablesAffine(problem, rot1, zeros);
problem = new TransformVariablesShift(problem, xopt);
return problem;
} else if (function == 17) {
double[] xopt = BBOBUtils.computeXOpt(rseed, dimension);
double fopt = BBOBUtils.computeFOpt(function, instance);
double[] zeros = new double[dimension];
double[] b = new double[dimension];
double[][] M = new double[dimension][dimension];
double[][] rot1 = BBOBUtils.computeRotation(rseed + 1000000, dimension);
double[][] rot2 = BBOBUtils.computeRotation(rseed, dimension);
for (int i = 0; i < dimension; i++) {
b[i] = 0.0;
for (int j = 0; j < dimension; j++) {
double exponent = 1.0 * i / (dimension - 1.0);
M[i][j] += rot2[i][j] * Math.pow(Math.sqrt(10.0), exponent);
}
}
BBOBFunction problem = new Schaffers(dimension);
problem = new TransformObjectiveShift(problem, fopt);
problem = new TransformVariablesAffine(problem, M, b);
problem = new TransformVariablesAsymmetric(problem, 0.5);
problem = new TransformVariablesAffine(problem, rot1, zeros);
problem = new TransformVariablesShift(problem, xopt);
problem = new TransformObjectivePenalize(problem, 10.0);
return problem;
} else if (function == 20) {
double[] tmp1 = BBOBUtils.computeXOpt(rseed, dimension);
double fopt = BBOBUtils.computeFOpt(function, instance);
double[] xopt = new double[dimension];
double[] tmp2 = new double[dimension];
double[] b = new double[dimension];
double[][] M = new double[dimension][dimension];
for (int i = 0; i < dimension; i++) {
xopt[i] = 0.5 * 4.2096874633;
if (tmp1[i] - 0.5 < 0.0) {
xopt[i] *= -1;
}
}
for (int i = 0; i < dimension; i++) {
b[i] = 0.0;
for (int j = 0; j < dimension; j++) {
if (i == j) {
double exponent = 1.0 * i / (dimension - 1.0);
M[i][j] += Math.pow(Math.sqrt(10.0), exponent);
}
}
}
for (int i = 0; i < dimension; i++) {
tmp1[i] = -2 * Math.abs(xopt[i]);
tmp2[i] = 2 * Math.abs(xopt[i]);
}
BBOBFunction problem = new Schwefel(dimension);
problem = new TransformObjectiveShift(problem, fopt);
problem = new TransformVariablesScale(problem, 100);
problem = new TransformVariablesShift(problem, tmp1);
problem = new TransformVariablesAffine(problem, M, b);
problem = new TransformVariablesShift(problem, tmp2);
problem = new TransformVariablesZHat(problem, xopt);
problem = new TransformVariablesScale(problem, 2);
problem = new TransformVariablesXHat(problem, rseed);
return problem;
} else if (function == 21) {
int numberOfPeaks = 101;
double maxcondition = 1000.0;
double maxcondition1 = Math.sqrt(1000.0);
double b = 10.0;
double c = 5.0;
double[] fitvalues = { 1.1, 9.1 };
double[] xopt = new double[dimension];
double fopt = BBOBUtils.computeFOpt(function, instance);
double[][] xLocal = new double[dimension][numberOfPeaks];
double[][] arrScales = new double[numberOfPeaks][dimension];
double[][] rotation = BBOBUtils.computeRotation(rseed, dimension);
/* Initialize all the data of the inner problem */
double[] gallagher_peaks = BBOBUtils.uniform(numberOfPeaks-1, rseed);
List<Integer> rperm = new ArrayList<Integer>();
for (int i = 0; i < numberOfPeaks-1; i++) {
rperm.add(i);
}
Collections.sort(rperm, new GallagherPeakComprator(gallagher_peaks));
/* Random permutation */
double[] arrCondition = new double[numberOfPeaks];
arrCondition[0] = maxcondition1;
double[] peaks = new double[numberOfPeaks];
peaks[0] = 10;
for (int i = 1; i < numberOfPeaks; i++) {
arrCondition[i] = Math.pow(maxcondition, rperm.get(i-1) / (numberOfPeaks - 2.0));
peaks[i] = (i - 1.0) / (numberOfPeaks - 2.0) * (fitvalues[1] - fitvalues[0]) + fitvalues[0];
}
for (int i = 0; i < numberOfPeaks; i++) {
rperm.clear();
gallagher_peaks = BBOBUtils.uniform(dimension, rseed + (1000*i));
for (int j = 0; j < dimension; j++) {
rperm.add(j);
}
Collections.sort(rperm, new GallagherPeakComprator(gallagher_peaks));
for (int j = 0; j < dimension; j++) {
arrScales[i][j] = Math.pow(arrCondition[i], rperm.get(j) / (dimension - 1.0) - 0.5);
}
}
gallagher_peaks = BBOBUtils.uniform(dimension*numberOfPeaks, rseed);
for (int i = 0; i < dimension; i++) {
xopt[i] = 0.8 * (b * gallagher_peaks[i] - c);
for (int j = 0; j < numberOfPeaks; j++) {
xLocal[i][j] = 0.0;
for (int k = 0; k < dimension; k++) {
xLocal[i][j] += rotation[i][k] * (b * gallagher_peaks[j * dimension + k] - c);
}
if (j == 0) {
xLocal[i][j] *= 0.8;
}
}
}
BBOBFunction problem = new Gallagher(dimension, rotation, xLocal, arrScales, peaks);
problem = new TransformObjectiveShift(problem, fopt);
return problem;
} else {
throw new FrameworkException("unknown BBOB function " + function);
}
}
/**
* Comparator used by the Gallagher function to order the peaks by height.
*/
private static class GallagherPeakComprator implements Comparator<Integer> {
/**
* The height of each peak.
*/
private final double[] gallagher_peaks;
/**
* Constructs a new comparator for ordering Gallagher peaks by height.
*
* @param gallagher_peaks the height of each peak
*/
public GallagherPeakComprator(double[] gallagher_peaks) {
super();
this.gallagher_peaks = gallagher_peaks;
}
@Override
public int compare(Integer i1, Integer i2) {
return Double.compare(gallagher_peaks[i1], gallagher_peaks[i2]);
}
}
}