//
// Special Session on Real-Parameter Optimization at CEC-05
// Edinburgh, UK, 2-5 Sept. 2005
//
// Organizers:
// Prof. Kalyanmoy Deb
// deb@iitk.ac.in
// http://www.iitk.ac.in/kangal/deb.htm
// A/Prof. P. N. Suganthan
// epnsugan@ntu.edu.sg
// http://www.ntu.edu.sg/home/EPNSugan
//
// Java version of the org.uma.test functions
//
// Matlab reference code
// http://www.ntu.edu.sg/home/EPNSugan
//
// Java version developer:
// Assistant Prof. Ying-ping Chen
// Department of Computer Science
// National Chiao Tung University
// HsinChu City, Taiwan
// ypchen@csie.nctu.edu.tw
// http://www.csie.nctu.edu.tw/~ypchen/
//
// Typical use of the org.uma.test functions in the Benchmark:
//
// // Create a Benchmark object
// Benchmark theBenchmark = new Benchmark();
// // Use the factory function call to create a org.uma.test function object
// // org.uma.test function 3 with 50 dimension
// // the object class is "TestFunc"
// TestFunc aTestFunc = theBenchmark.testFunctionFactory(3, 50);
// // Invoke the function with x
// double experimentoutput = aTestFunc.f(x);
//
// Version 0.90
// Currently, this version cannot handle any numbers of dimensions.
// It cannot generate the shifted global optima and rotation matrices
// that are not provided with the Matlab reference code.
// It can handle all cases whose data files are provided with
// the Matlab reference code.
// Version 0.91
// Revised according to the Matlab reference code and the PDF document
// dated March 8, 2005.
//
package org.uma.jmetal.problem.singleobjective.cec2005competitioncode;
import org.uma.jmetal.util.JMetalException;
import org.uma.jmetal.util.JMetalLogger;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.logging.Level;
public class Benchmark {
// Fixed (class) parameters
static final public String CEC2005SUPPORTDATADIRECTORY = "cec2005CompetitionResources/supportData" ;
static final private String CEC2005Code = "org.uma.jmetal.problem.singleobjective.cec2005competitioncode" ;
static final public int NUM_TEST_FUNC = 25;
static final public String DEFAULT_FILE_BIAS = CEC2005SUPPORTDATADIRECTORY + "/fbias_data.txt";
static final public String[] test_func_class_names = {
"F01_shifted_sphere",
"F02_shifted_schwefel",
"F03_shifted_rotated_high_cond_elliptic",
"F04_shifted_schwefel_noise",
"F05_schwefel_global_opt_bound",
"F06_shifted_rosenbrock",
"F07_shifted_rotated_griewank",
"F08_shifted_rotated_ackley_global_opt_bound",
"F09_shifted_rastrigin",
"F10_shifted_rotated_rastrigin",
"F11_shifted_rotated_weierstrass",
"F12_schwefel",
"F13_shifted_expanded_griewank_rosenbrock",
"F14_shifted_rotated_expanded_scaffer",
"F15_hybrid_composition_1",
"F16_rotated_hybrid_composition_1",
"F17_rotated_hybrid_composition_1_noise",
"F18_rotated_hybrid_composition_2",
"F19_rotated_hybrid_composition_2_narrow_basin_global_opt",
"F20_rotated_hybrid_composition_2_global_opt_bound",
"F21_rotated_hybrid_composition_3",
"F22_rotated_hybrid_composition_3_high_cond_num_matrix",
"F23_noncontinuous_rotated_hybrid_composition_3",
"F24_rotated_hybrid_composition_4",
"F25_rotated_hybrid_composition_4_bound"
};
// For certain functions, some essential data can be calculated beforehand.
// Hence, a maximum supported number of dimensions should be specified.
// Specifiy the number of dimensions here if you need more.
static final public int MAX_SUPPORT_DIM = 100;
static final public double PIx2 = Math.PI * 2.0;
// Formatter for the number representation
static final public DecimalFormat scientificFormatter =
new DecimalFormat("0.0000000000000000E00");
static final public DecimalFormat numberFormatter = scientificFormatter;
static final public DecimalFormat percentageFormatter = new DecimalFormat("0.0000000000");
// Random number generator
// If you want to plan a specific seed, do it here.
static final public Random random = new Random();
// Class loader & reflection
static final public ClassLoader loader = ClassLoader.getSystemClassLoader();
static final Class<?>[] test_func_arg_types = {int.class, double.class};
// Class variables
static private double[] m_iSqrt;
// Instance variables
private double[] m_biases;
// Constructors
// Load the data common to all org.uma.test functions.
// Get ready for creating org.uma.test function instances.
public Benchmark() throws JMetalException {
this(DEFAULT_FILE_BIAS);
}
public Benchmark(String file_bias) throws JMetalException {
m_biases = new double[NUM_TEST_FUNC];
m_iSqrt = new double[MAX_SUPPORT_DIM];
loadRowVectorFromFile(file_bias, NUM_TEST_FUNC, m_biases);
for (int i = 0; i < MAX_SUPPORT_DIM; i++) {
m_iSqrt[i] = Math.sqrt(((double) i) + 1.0);
}
}
// Entry point
// If the Benchmark class is executed as a stand-alone application,
// its job is to run the org.uma.test on all the org.uma.test functions.
static public void main(String args[]) throws JMetalException {
Benchmark theBenchmark = new Benchmark();
theBenchmark.runTest(0);
}
// Sphere function
static public double sphere(double[] x) {
double sum = 0.0;
for (int i = 0; i < x.length; i++) {
sum += x[i] * x[i];
}
return (sum);
}
// Sphere function with noise
static public double sphere_noise(double[] x) {
double sum = 0.0;
for (int i = 0; i < x.length; i++) {
sum += x[i] * x[i];
}
// NOISE
// Comment the next line to remove the noise
sum *= (1.0 + 0.1 * Math.abs(random.nextGaussian()));
return (sum);
}
// Schwefel's problem 1.2
static public double schwefel_102(double[] x) {
double prev_sum, curr_sum, outer_sum;
curr_sum = x[0];
outer_sum = (curr_sum * curr_sum);
for (int i = 1; i < x.length; i++) {
prev_sum = curr_sum;
curr_sum = prev_sum + x[i];
outer_sum += (curr_sum * curr_sum);
}
return (outer_sum);
}
//
// Basic functions
//
// Rosenbrock's function
static public double rosenbrock(double[] x) {
double sum = 0.0;
for (int i = 0; i < (x.length - 1); i++) {
double temp1 = (x[i] * x[i]) - x[i + 1];
double temp2 = x[i] - 1.0;
sum += (100.0 * temp1 * temp1) + (temp2 * temp2);
}
return (sum);
}
// F2: Rosenbrock's Function -- 2D version
static public double F2(double x, double y) {
double temp1 = (x * x) - y;
double temp2 = x - 1.0;
return ((100.0 * temp1 * temp1) + (temp2 * temp2));
}
// Griewank's function
static public double griewank(double[] x) {
double sum = 0.0;
double product = 1.0;
for (int i = 0; i < x.length; i++) {
sum += ((x[i] * x[i]) / 4000.0);
product *= Math.cos(x[i] / m_iSqrt[i]);
}
return (sum - product + 1.0);
}
// F8: Griewank's Function -- 1D version
static public double F8(double x) {
return (((x * x) / 4000.0) - Math.cos(x) + 1.0);
}
// Ackley's function
static public double ackley(double[] x) {
double sum1 = 0.0;
double sum2 = 0.0;
for (int i = 0; i < x.length; i++) {
sum1 += (x[i] * x[i]);
sum2 += (Math.cos(PIx2 * x[i]));
}
return (-20.0 * Math.exp(-0.2 * Math.sqrt(sum1 / ((double) x.length))) - Math
.exp(sum2 / ((double) x.length)) + 20.0 + Math.E);
}
// Round function
// 0. Use the Matlab version for rounding numbers
static public double myRound(double x) {
return (Math.signum(x) * Math.round(Math.abs(x)));
}
// 1. "o" is provided
static public double myXRound(double x, double o) {
return ((Math.abs(x - o) < 0.5) ? x : (myRound(2.0 * x) / 2.0));
}
// 2. "o" is not provided
static public double myXRound(double x) {
return ((Math.abs(x) < 0.5) ? x : (myRound(2.0 * x) / 2.0));
}
// Rastrigin's function
static public double rastrigin(double[] x) {
double sum = 0.0;
for (int i = 0; i < x.length; i++) {
sum += (x[i] * x[i]) - (10.0 * Math.cos(PIx2 * x[i])) + 10.0;
}
return (sum);
}
// Non-Continuous Rastrigin's function
static public double rastriginNonCont(double[] x) {
double sum = 0.0;
double currX;
for (int i = 0; i < x.length; i++) {
currX = myXRound(x[i]);
sum += (currX * currX) - (10.0 * Math.cos(PIx2 * currX)) + 10.0;
}
return (sum);
}
// Weierstrass function
static public double weierstrass(double[] x) {
return (weierstrass(x, 0.5, 3.0, 20));
}
static public double weierstrass(double[] x, double a, double b, int Kmax) {
double sum1 = 0.0;
for (int i = 0; i < x.length; i++) {
for (int k = 0; k <= Kmax; k++) {
sum1 += Math.pow(a, k) * Math.cos(PIx2 * Math.pow(b, k) * (x[i] + 0.5));
}
}
double sum2 = 0.0;
for (int k = 0; k <= Kmax; k++) {
sum2 += Math.pow(a, k) * Math.cos(PIx2 * Math.pow(b, k) * (0.5));
}
return (sum1 - sum2 * ((double) (x.length)));
}
// F8F2
static public double F8F2(double[] x) {
double sum = 0.0;
for (int i = 1; i < x.length; i++) {
sum += F8(F2(x[i - 1], x[i]));
}
sum += F8(F2(x[x.length - 1], x[0]));
return (sum);
}
// Scaffer's F6 function
static public double ScafferF6(double x, double y) {
double temp1 = x * x + y * y;
double temp2 = Math.sin(Math.sqrt(temp1));
double temp3 = 1.0 + 0.001 * temp1;
return (0.5 + ((temp2 * temp2 - 0.5) / (temp3 * temp3)));
}
// Expanded Scaffer's F6 function
static public double EScafferF6(double[] x) {
double sum = 0.0;
for (int i = 1; i < x.length; i++) {
sum += ScafferF6(x[i - 1], x[i]);
}
sum += ScafferF6(x[x.length - 1], x[0]);
return (sum);
}
// Non-Continuous Expanded Scaffer's F6 function
static public double EScafferF6NonCont(double[] x) {
double sum = 0.0;
double prevX, currX;
currX = myXRound(x[0]);
for (int i = 1; i < x.length; i++) {
prevX = currX;
currX = myXRound(x[i]);
sum += ScafferF6(prevX, currX);
}
prevX = currX;
currX = myXRound(x[0]);
sum += ScafferF6(prevX, currX);
return (sum);
}
// Elliptic
static public double elliptic(double[] x) {
double sum = 0.0;
double a = 1e6;
for (int i = 0; i < x.length; i++) {
sum += Math.pow(a, (((double) i) / ((double) (x.length - 1)))) * x[i] * x[i];
}
return (sum);
}
// Hybrid composition
static public double hybrid_composition(double[] x, HCJob job) throws JMetalException {
int num_func = job.numberOfBasicFunctions;
int num_dim = job.numberOfDimensions;
// Get the raw weights
double wMax = Double.NEGATIVE_INFINITY;
for (int i = 0; i < num_func; i++) {
double sumSqr = 0.0;
shift(job.z[i], x, job.shiftGlobalOptimum[i]);
for (int j = 0; j < num_dim; j++) {
sumSqr += (job.z[i][j] * job.z[i][j]);
}
job.w[i] = Math.exp(-1.0 * sumSqr / (2.0 * num_dim * job.sigma[i] * job.sigma[i]));
if (wMax < job.w[i]) {
wMax = job.w[i];
}
}
// Modify the weights
double wSum = 0.0;
double w1mMaxPow = 1.0 - Math.pow(wMax, 10.0);
for (int i = 0; i < num_func; i++) {
if (job.w[i] != wMax) {
job.w[i] *= w1mMaxPow;
}
wSum += job.w[i];
}
// Normalize the weights
for (int i = 0; i < num_func; i++) {
job.w[i] /= wSum;
}
double sumF = 0.0;
for (int i = 0; i < num_func; i++) {
for (int j = 0; j < num_dim; j++) {
job.z[i][j] /= job.lambda[i];
}
rotate(job.zM[i], job.z[i], job.linearTransformationMatrix[i]);
sumF +=
job.w[i] *
(
job.C * job.basicFunc(i, job.zM[i]) / job.fmax[i] +
job.biases[i]
);
}
return (sumF);
}
// Shift
static public void shift(double[] results, double[] x, double[] o) {
for (int i = 0; i < x.length; i++) {
results[i] = x[i] - o[i];
}
}
// Rotate
static public void rotate(double[] results, double[] x, double[][] matrix) {
xA(results, x, matrix);
}
// (1xD) row vector * (Dx1) column vector = (1) scalar
static public double xy(double[] x, double[] y) {
double result = 0.0;
for (int i = 0; i < x.length; i++) {
result += (x[i] * y[i]);
}
return (result);
}
//
// Elementary operations
//
// (1xD) row vector * (DxD) matrix = (1xD) row vector
static public void xA(double[] result, double[] x, double[][] A) {
for (int i = 0; i < result.length; i++) {
result[i] = 0.0;
for (int j = 0; j < result.length; j++) {
result[i] += (x[j] * A[j][i]);
}
}
}
// (DxD) matrix * (Dx1) column vector = (Dx1) column vector
static public void Ax(double[] result, double[][] A, double[] x) {
for (int i = 0; i < result.length; i++) {
result[i] = 0.0;
for (int j = 0; j < result.length; j++) {
result[i] += (A[i][j] * x[j]);
}
}
}
//
// Matrix & vector operations
//
//
// Utility functions for loading data from the given text file
//
static public void loadTestDataFromFile(String file, int num_test_points, int test_dimension,
double[][] x, double[] f) throws JMetalException {
try {
JMetalLogger.logger.info("File bias: " + file);
BufferedReader brSrc = new BufferedReader(new FileReader(file));
loadMatrix(brSrc, num_test_points, test_dimension, x);
loadColumnVector(brSrc, num_test_points, f);
brSrc.close();
} catch (Exception e) {
JMetalLogger.logger.log(Level.SEVERE, "Error in Benchmark.java", e);
throw new JMetalException("Error in Benchmark.java");
}
}
static public void loadRowVectorFromFile(String file, int columns, double[] row)
throws JMetalException {
try {
BufferedReader brSrc =
new BufferedReader(
new InputStreamReader(new FileInputStream(ClassLoader.getSystemResource(file).getPath()))) ;
//BufferedReader brSrc = new BufferedReader(new FileReader(file));
loadRowVector(brSrc, columns, row);
brSrc.close();
} catch (Exception e) {
JMetalLogger.logger.log(Level.SEVERE, "Error in Benchmark.java", e);
throw new JMetalException("Error in Benchmark.java");
}
}
static public void loadRowVector(BufferedReader brSrc, int columns, double[] row)
throws Exception {
String stToken;
StringTokenizer stTokenizer = new StringTokenizer(brSrc.readLine());
for (int i = 0; i < columns; i++) {
stToken = stTokenizer.nextToken();
row[i] = Double.parseDouble(stToken);
}
}
static public void loadColumnVectorFromFile(String file, int rows, double[] column)
throws JMetalException {
try {
BufferedReader brSrc =
new BufferedReader(
new InputStreamReader(new FileInputStream(ClassLoader.getSystemResource(file).getPath()))) ;
//BufferedReader brSrc = new BufferedReader(new FileReader(file));
loadColumnVector(brSrc, rows, column);
brSrc.close();
} catch (Exception e) {
JMetalLogger.logger.log(Level.SEVERE, "Error in Benchmark.java", e);
throw new JMetalException("Error in Benchmark.java");
}
}
static public void loadColumnVector(BufferedReader brSrc, int rows, double[] column)
throws Exception {
String stToken;
for (int i = 0; i < rows; i++) {
StringTokenizer stTokenizer = new StringTokenizer(brSrc.readLine());
stToken = stTokenizer.nextToken();
column[i] = Double.parseDouble(stToken);
}
}
static public void loadNMatrixFromFile(String file, int N, int rows, int columns,
double[][][] matrix) throws JMetalException {
try {
BufferedReader brSrc =
new BufferedReader(
new InputStreamReader(new FileInputStream(ClassLoader.getSystemResource(file).getPath()))) ;
//BufferedReader brSrc = new BufferedReader(new FileReader(file));
for (int i = 0; i < N; i++) {
loadMatrix(brSrc, rows, columns, matrix[i]);
}
brSrc.close();
} catch (Exception e) {
throw new JMetalException("Error in Benchmark.java", e);
}
}
static public void loadMatrixFromFile(String file, int rows, int columns, double[][] matrix)
throws JMetalException {
try {
BufferedReader brSrc =
new BufferedReader(
new InputStreamReader(new FileInputStream(ClassLoader.getSystemResource(file).getPath()))) ;
//BufferedReader brSrc = new BufferedReader(new FileReader(file));
loadMatrix(brSrc, rows, columns, matrix);
brSrc.close();
} catch (Exception e) {
throw new JMetalException("Error in Benchmark.java", e);
}
}
static public void loadMatrix(BufferedReader brSrc, int rows, int columns, double[][] matrix)
throws Exception {
for (int i = 0; i < rows; i++) {
loadRowVector(brSrc, columns, matrix[i]);
}
}
//
// Use this function to manufacture new test function objects
//
public TestFunc testFunctionFactory(int func_num, int dimension) throws JMetalException {
TestFunc returnFunc = null;
try {
returnFunc = (TestFunc)
loader.loadClass(CEC2005Code + "." + test_func_class_names[func_num - 1])
.getConstructor(test_func_arg_types)
.newInstance(
new Object[] {
new Integer(dimension),
new Double(m_biases[func_num - 1])
}
);
} catch (Exception e) {
throw new JMetalException("Error in Benchmark.java", e);
}
return (returnFunc);
}
// Run tests on the test functions
// < 0: Error!
// = 0: On all the functions
// > 0: On the specified org.uma.test function
public void runTest() throws JMetalException {
runTest(0);
}
public void runTest(int func_num) throws JMetalException {
if (func_num == 0) {
for (int i = 1; i <= NUM_TEST_FUNC; i++) {
runTest(i);
}
} else if ((func_num < 0) || (func_num > NUM_TEST_FUNC)) {
throw new JMetalException("The specified func_num is out of range.");
} else {
// Run the org.uma.test function against the check points
int num_test_points = 10;
int test_dimension = 50;
double[] test_f = new double[num_test_points];
double[][] test_x = new double[num_test_points][test_dimension];
String file_test = "testData/test_data_func" + func_num + ".txt";
// Create the org.uma.test function object
TestFunc aFunc = testFunctionFactory(func_num, test_dimension);
JMetalLogger.logger.info("Run tests on function " + func_num +
" (" + aFunc.name() + "):");
JMetalLogger.logger.info(" " +
num_test_points + " " +
aFunc.dimension() + "-dimension check points");
loadTestDataFromFile(file_test, num_test_points, test_dimension, test_x, test_f);
for (int i = 0; i < num_test_points; i++) {
// Execute the org.uma.test function
// Collect and compare the results
double result = aFunc.f(test_x[i]);
double diff = result - test_f[i];
double ratio = Math.abs(diff / test_f[i]);
JMetalLogger.logger.info(" " +
numberFormatter.format(result) +
" - " +
numberFormatter.format(test_f[i]) +
" = " +
numberFormatter.format(diff));
JMetalLogger.logger.info(" " + " " +
"Difference ratio = " + numberFormatter.format(ratio));
if (ratio != 0.0) {
if (ratio <= 1e-12) {
JMetalLogger.logger.info(" (<= 1E-12)");
} else {
JMetalLogger.logger.info(" (> 1E-12) *****");
}
} else {
JMetalLogger.logger.info("");
}
}
}
}
}