This is an automated email from the ASF dual-hosted git repository. erans pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-math.git
commit 2470c3ff28d5e5f378cab14838fced2b2643701e Author: Gilles Sadowski <gillese...@gmail.com> AuthorDate: Tue Jul 28 13:50:22 2020 +0200 Factor out utilities that are useful for other unit test classes too. --- .../scalar/noderiv/BOBYQAOptimizerTest.java | 417 +++------------------ .../nonlinear/scalar/noderiv/OptimTestUtils.java | 396 +++++++++++++++++++ 2 files changed, 452 insertions(+), 361 deletions(-) diff --git a/src/test/java/org/apache/commons/math4/optim/nonlinear/scalar/noderiv/BOBYQAOptimizerTest.java b/src/test/java/org/apache/commons/math4/optim/nonlinear/scalar/noderiv/BOBYQAOptimizerTest.java index a51a222..6aae6a3 100644 --- a/src/test/java/org/apache/commons/math4/optim/nonlinear/scalar/noderiv/BOBYQAOptimizerTest.java +++ b/src/test/java/org/apache/commons/math4/optim/nonlinear/scalar/noderiv/BOBYQAOptimizerTest.java @@ -40,31 +40,30 @@ import org.junit.Test; * Test for {@link BOBYQAOptimizer}. */ public class BOBYQAOptimizerTest { - - static final int DIM = 13; + private static final int DIM = 13; @Test(expected=NumberIsTooLargeException.class) public void testInitOutOfBounds() { - double[] startPoint = point(DIM, 3); + double[] startPoint = OptimTestUtils.point(DIM, 3); double[][] boundaries = boundaries(DIM, -1, 2); - doTest(new Rosen(), startPoint, boundaries, + doTest(new OptimTestUtils.Rosen(), startPoint, boundaries, GoalType.MINIMIZE, 1e-13, 1e-6, 2000, null); } @Test(expected=DimensionMismatchException.class) public void testBoundariesDimensionMismatch() { - double[] startPoint = point(DIM, 0.5); + double[] startPoint = OptimTestUtils.point(DIM, 0.5); double[][] boundaries = boundaries(DIM + 1, -1, 2); - doTest(new Rosen(), startPoint, boundaries, + doTest(new OptimTestUtils.Rosen(), startPoint, boundaries, GoalType.MINIMIZE, 1e-13, 1e-6, 2000, null); } @Test(expected=NumberIsTooSmallException.class) public void testProblemDimensionTooSmall() { - double[] startPoint = point(1, 0.5); - doTest(new Rosen(), startPoint, null, + double[] startPoint = OptimTestUtils.point(1, 0.5); + doTest(new OptimTestUtils.Rosen(), startPoint, null, GoalType.MINIMIZE, 1e-13, 1e-6, 2000, null); } @@ -72,168 +71,168 @@ public class BOBYQAOptimizerTest { @Test(expected=TooManyEvaluationsException.class) public void testMaxEvaluations() { final int lowMaxEval = 2; - double[] startPoint = point(DIM, 0.1); + double[] startPoint = OptimTestUtils.point(DIM, 0.1); double[][] boundaries = null; - doTest(new Rosen(), startPoint, boundaries, + doTest(new OptimTestUtils.Rosen(), startPoint, boundaries, GoalType.MINIMIZE, 1e-13, 1e-6, lowMaxEval, null); } @Test public void testRosen() { - double[] startPoint = point(DIM,0.1); + double[] startPoint = OptimTestUtils.point(DIM,0.1); double[][] boundaries = null; - PointValuePair expected = new PointValuePair(point(DIM,1.0),0.0); - doTest(new Rosen(), startPoint, boundaries, + PointValuePair expected = new PointValuePair(OptimTestUtils.point(DIM,1.0),0.0); + doTest(new OptimTestUtils.Rosen(), startPoint, boundaries, GoalType.MINIMIZE, 1e-13, 1e-6, 2000, expected); } @Test public void testMaximize() { - double[] startPoint = point(DIM,1.0); + double[] startPoint = OptimTestUtils.point(DIM,1.0); double[][] boundaries = null; - PointValuePair expected = new PointValuePair(point(DIM,0.0),1.0); - doTest(new MinusElli(), startPoint, boundaries, + PointValuePair expected = new PointValuePair(OptimTestUtils.point(DIM,0.0),1.0); + doTest(new OptimTestUtils.MinusElli(), startPoint, boundaries, GoalType.MAXIMIZE, 2e-10, 5e-6, 1000, expected); boundaries = boundaries(DIM,-0.3,0.3); - startPoint = point(DIM,0.1); - doTest(new MinusElli(), startPoint, boundaries, + startPoint = OptimTestUtils.point(DIM,0.1); + doTest(new OptimTestUtils.MinusElli(), startPoint, boundaries, GoalType.MAXIMIZE, 2e-10, 5e-6, 1000, expected); } @Test public void testEllipse() { - double[] startPoint = point(DIM,1.0); + double[] startPoint = OptimTestUtils.point(DIM,1.0); double[][] boundaries = null; PointValuePair expected = - new PointValuePair(point(DIM,0.0),0.0); - doTest(new Elli(), startPoint, boundaries, + new PointValuePair(OptimTestUtils.point(DIM,0.0),0.0); + doTest(new OptimTestUtils.Elli(), startPoint, boundaries, GoalType.MINIMIZE, 1e-13, 1e-6, 1000, expected); } @Test public void testElliRotated() { - double[] startPoint = point(DIM,1.0); + double[] startPoint = OptimTestUtils.point(DIM,1.0); double[][] boundaries = null; PointValuePair expected = - new PointValuePair(point(DIM,0.0),0.0); - doTest(new ElliRotated(), startPoint, boundaries, + new PointValuePair(OptimTestUtils.point(DIM,0.0),0.0); + doTest(new OptimTestUtils.ElliRotated(), startPoint, boundaries, GoalType.MINIMIZE, 1e-12, 1e-6, 10000, expected); } @Test public void testCigar() { - double[] startPoint = point(DIM,1.0); + double[] startPoint = OptimTestUtils.point(DIM,1.0); double[][] boundaries = null; PointValuePair expected = - new PointValuePair(point(DIM,0.0),0.0); - doTest(new Cigar(), startPoint, boundaries, + new PointValuePair(OptimTestUtils.point(DIM,0.0),0.0); + doTest(new OptimTestUtils.Cigar(), startPoint, boundaries, GoalType.MINIMIZE, 1e-13, 1e-6, 100, expected); } @Test public void testTwoAxes() { - double[] startPoint = point(DIM,1.0); + double[] startPoint = OptimTestUtils.point(DIM,1.0); double[][] boundaries = null; PointValuePair expected = - new PointValuePair(point(DIM,0.0),0.0); - doTest(new TwoAxes(), startPoint, boundaries, + new PointValuePair(OptimTestUtils.point(DIM,0.0),0.0); + doTest(new OptimTestUtils.TwoAxes(), startPoint, boundaries, GoalType.MINIMIZE, 2* 1e-13, 1e-6, 100, expected); } @Test public void testCigTab() { - double[] startPoint = point(DIM,1.0); + double[] startPoint = OptimTestUtils.point(DIM,1.0); double[][] boundaries = null; PointValuePair expected = - new PointValuePair(point(DIM,0.0),0.0); - doTest(new CigTab(), startPoint, boundaries, + new PointValuePair(OptimTestUtils.point(DIM,0.0),0.0); + doTest(new OptimTestUtils.CigTab(), startPoint, boundaries, GoalType.MINIMIZE, 1e-13, 5e-5, 100, expected); } @Test public void testSphere() { - double[] startPoint = point(DIM,1.0); + double[] startPoint = OptimTestUtils.point(DIM,1.0); double[][] boundaries = null; PointValuePair expected = - new PointValuePair(point(DIM,0.0),0.0); - doTest(new Sphere(), startPoint, boundaries, + new PointValuePair(OptimTestUtils.point(DIM,0.0),0.0); + doTest(new OptimTestUtils.Sphere(), startPoint, boundaries, GoalType.MINIMIZE, 1e-13, 1e-6, 100, expected); } @Test public void testTablet() { - double[] startPoint = point(DIM,1.0); + double[] startPoint = OptimTestUtils.point(DIM,1.0); double[][] boundaries = null; PointValuePair expected = - new PointValuePair(point(DIM,0.0),0.0); - doTest(new Tablet(), startPoint, boundaries, + new PointValuePair(OptimTestUtils.point(DIM,0.0),0.0); + doTest(new OptimTestUtils.Tablet(), startPoint, boundaries, GoalType.MINIMIZE, 1e-13, 1e-6, 100, expected); } @Test public void testDiffPow() { - double[] startPoint = point(DIM/2,1.0); + double[] startPoint = OptimTestUtils.point(DIM/2,1.0); double[][] boundaries = null; PointValuePair expected = - new PointValuePair(point(DIM/2,0.0),0.0); - doTest(new DiffPow(), startPoint, boundaries, + new PointValuePair(OptimTestUtils.point(DIM/2,0.0),0.0); + doTest(new OptimTestUtils.DiffPow(), startPoint, boundaries, GoalType.MINIMIZE, 1e-8, 1e-1, 21000, expected); } @Test public void testSsDiffPow() { - double[] startPoint = point(DIM/2,1.0); + double[] startPoint = OptimTestUtils.point(DIM/2,1.0); double[][] boundaries = null; PointValuePair expected = - new PointValuePair(point(DIM/2,0.0),0.0); - doTest(new SsDiffPow(), startPoint, boundaries, + new PointValuePair(OptimTestUtils.point(DIM/2,0.0),0.0); + doTest(new OptimTestUtils.SsDiffPow(), startPoint, boundaries, GoalType.MINIMIZE, 1e-2, 1.3e-1, 50000, expected); } @Test public void testAckley() { - double[] startPoint = point(DIM,0.1); + double[] startPoint = OptimTestUtils.point(DIM,0.1); double[][] boundaries = null; PointValuePair expected = - new PointValuePair(point(DIM,0.0),0.0); - doTest(new Ackley(), startPoint, boundaries, + new PointValuePair(OptimTestUtils.point(DIM,0.0),0.0); + doTest(new OptimTestUtils.Ackley(), startPoint, boundaries, GoalType.MINIMIZE, 1e-7, 1e-5, 1000, expected); } @Test public void testRastrigin() { - double[] startPoint = point(DIM,1.0); + double[] startPoint = OptimTestUtils.point(DIM,1.0); double[][] boundaries = null; PointValuePair expected = - new PointValuePair(point(DIM,0.0),0.0); - doTest(new Rastrigin(), startPoint, boundaries, + new PointValuePair(OptimTestUtils.point(DIM,0.0),0.0); + doTest(new OptimTestUtils.Rastrigin(), startPoint, boundaries, GoalType.MINIMIZE, 1e-13, 1e-6, 1000, expected); } @Test public void testConstrainedRosen() { - double[] startPoint = point(DIM,0.1); + double[] startPoint = OptimTestUtils.point(DIM,0.1); double[][] boundaries = boundaries(DIM,-1,2); PointValuePair expected = - new PointValuePair(point(DIM,1.0),0.0); - doTest(new Rosen(), startPoint, boundaries, + new PointValuePair(OptimTestUtils.point(DIM,1.0),0.0); + doTest(new OptimTestUtils.Rosen(), startPoint, boundaries, GoalType.MINIMIZE, 1e-13, 1e-6, 2000, expected); } @@ -243,9 +242,9 @@ public class BOBYQAOptimizerTest { // makes it run for several hours before completing @Ignore @Test public void testConstrainedRosenWithMoreInterpolationPoints() { - final double[] startPoint = point(DIM, 0.1); + final double[] startPoint = OptimTestUtils.point(DIM, 0.1); final double[][] boundaries = boundaries(DIM, -1, 2); - final PointValuePair expected = new PointValuePair(point(DIM, 1.0), 0.0); + final PointValuePair expected = new PointValuePair(OptimTestUtils.point(DIM, 1.0), 0.0); // This should have been 78 because in the code the hard limit is // said to be @@ -255,7 +254,7 @@ public class BOBYQAOptimizerTest { final int maxAdditionalPoints = 47; for (int num = 1; num <= maxAdditionalPoints; num++) { - doTest(new Rosen(), startPoint, boundaries, + doTest(new OptimTestUtils.Rosen(), startPoint, boundaries, GoalType.MINIMIZE, 1e-12, 1e-6, 2000, num, @@ -347,12 +346,6 @@ public class BOBYQAOptimizerTest { // System.out.println(func.getClass().getName() + " END"); // XXX } - private static double[] point(int n, double value) { - double[] ds = new double[n]; - Arrays.fill(ds, value); - return ds; - } - private static double[][] boundaries(int dim, double lower, double upper) { double[][] boundaries = new double[2][dim]; @@ -364,302 +357,4 @@ public class BOBYQAOptimizerTest { } return boundaries; } - - private static class Sphere implements MultivariateFunction { - - @Override - public double value(double[] x) { - double f = 0; - for (int i = 0; i < x.length; ++i) { - f += x[i] * x[i]; - } - return f; - } - } - - private static class Cigar implements MultivariateFunction { - private double factor; - - Cigar() { - this(1e3); - } - - Cigar(double axisratio) { - factor = axisratio * axisratio; - } - - @Override - public double value(double[] x) { - double f = x[0] * x[0]; - for (int i = 1; i < x.length; ++i) { - f += factor * x[i] * x[i]; - } - return f; - } - } - - private static class Tablet implements MultivariateFunction { - private double factor; - - Tablet() { - this(1e3); - } - - Tablet(double axisratio) { - factor = axisratio * axisratio; - } - - @Override - public double value(double[] x) { - double f = factor * x[0] * x[0]; - for (int i = 1; i < x.length; ++i) { - f += x[i] * x[i]; - } - return f; - } - } - - private static class CigTab implements MultivariateFunction { - private double factor; - - CigTab() { - this(1e4); - } - - CigTab(double axisratio) { - factor = axisratio; - } - - @Override - public double value(double[] x) { - int end = x.length - 1; - double f = x[0] * x[0] / factor + factor * x[end] * x[end]; - for (int i = 1; i < end; ++i) { - f += x[i] * x[i]; - } - return f; - } - } - - private static class TwoAxes implements MultivariateFunction { - - private double factor; - - TwoAxes() { - this(1e6); - } - - TwoAxes(double axisratio) { - factor = axisratio * axisratio; - } - - @Override - public double value(double[] x) { - double f = 0; - for (int i = 0; i < x.length; ++i) { - f += (i < x.length / 2 ? factor : 1) * x[i] * x[i]; - } - return f; - } - } - - private static class ElliRotated implements MultivariateFunction { - private Basis B = new Basis(); - private double factor; - - ElliRotated() { - this(1e3); - } - - ElliRotated(double axisratio) { - factor = axisratio * axisratio; - } - - @Override - public double value(double[] x) { - double f = 0; - x = B.Rotate(x); - for (int i = 0; i < x.length; ++i) { - f += FastMath.pow(factor, i / (x.length - 1.)) * x[i] * x[i]; - } - return f; - } - } - - private static class Elli implements MultivariateFunction { - - private double factor; - - Elli() { - this(1e3); - } - - Elli(double axisratio) { - factor = axisratio * axisratio; - } - - @Override - public double value(double[] x) { - double f = 0; - for (int i = 0; i < x.length; ++i) { - f += FastMath.pow(factor, i / (x.length - 1.)) * x[i] * x[i]; - } - return f; - } - } - - private static class MinusElli implements MultivariateFunction { - private final Elli elli = new Elli(); - @Override - public double value(double[] x) { - return 1.0 - elli.value(x); - } - } - - private static class DiffPow implements MultivariateFunction { -// private int fcount = 0; - @Override - public double value(double[] x) { - double f = 0; - for (int i = 0; i < x.length; ++i) { - f += FastMath.pow(FastMath.abs(x[i]), 2. + 10 * (double) i - / (x.length - 1.)); - } -// System.out.print("" + (fcount++) + ") "); -// for (int i = 0; i < x.length; i++) -// System.out.print(x[i] + " "); -// System.out.println(" = " + f); - return f; - } - } - - private static class SsDiffPow implements MultivariateFunction { - - @Override - public double value(double[] x) { - double f = FastMath.pow(new DiffPow().value(x), 0.25); - return f; - } - } - - private static class Rosen implements MultivariateFunction { - - @Override - public double value(double[] x) { - double f = 0; - for (int i = 0; i < x.length - 1; ++i) { - f += 1e2 * (x[i] * x[i] - x[i + 1]) * (x[i] * x[i] - x[i + 1]) - + (x[i] - 1.) * (x[i] - 1.); - } - return f; - } - } - - private static class Ackley implements MultivariateFunction { - private double axisratio; - - Ackley(double axra) { - axisratio = axra; - } - - public Ackley() { - this(1); - } - - @Override - public double value(double[] x) { - double f = 0; - double res2 = 0; - double fac = 0; - for (int i = 0; i < x.length; ++i) { - fac = FastMath.pow(axisratio, (i - 1.) / (x.length - 1.)); - f += fac * fac * x[i] * x[i]; - res2 += FastMath.cos(2. * FastMath.PI * fac * x[i]); - } - f = (20. - 20. * FastMath.exp(-0.2 * FastMath.sqrt(f / x.length)) - + FastMath.exp(1.) - FastMath.exp(res2 / x.length)); - return f; - } - } - - private static class Rastrigin implements MultivariateFunction { - - private double axisratio; - private double amplitude; - - Rastrigin() { - this(1, 10); - } - - Rastrigin(double axisratio, double amplitude) { - this.axisratio = axisratio; - this.amplitude = amplitude; - } - - @Override - public double value(double[] x) { - double f = 0; - double fac; - for (int i = 0; i < x.length; ++i) { - fac = FastMath.pow(axisratio, (i - 1.) / (x.length - 1.)); - if (i == 0 && x[i] < 0) { - fac *= 1.; - } - f += fac * fac * x[i] * x[i] + amplitude - * (1. - FastMath.cos(2. * FastMath.PI * fac * x[i])); - } - return f; - } - } - - private static class Basis { - double[][] basis; - Random rand = new Random(2); // use not always the same basis - - double[] Rotate(double[] x) { - GenBasis(x.length); - double[] y = new double[x.length]; - for (int i = 0; i < x.length; ++i) { - y[i] = 0; - for (int j = 0; j < x.length; ++j) { - y[i] += basis[i][j] * x[j]; - } - } - return y; - } - - void GenBasis(int DIM) { - if (basis != null ? basis.length == DIM : false) { - return; - } - - double sp; - int i, j, k; - - /* generate orthogonal basis */ - basis = new double[DIM][DIM]; - for (i = 0; i < DIM; ++i) { - /* sample components gaussian */ - for (j = 0; j < DIM; ++j) { - basis[i][j] = rand.nextGaussian(); - } - /* substract projection of previous vectors */ - for (j = i - 1; j >= 0; --j) { - for (sp = 0., k = 0; k < DIM; ++k) { - sp += basis[i][k] * basis[j][k]; /* scalar product */ - } - for (k = 0; k < DIM; ++k) { - basis[i][k] -= sp * basis[j][k]; /* substract */ - } - } - /* normalize */ - for (sp = 0., k = 0; k < DIM; ++k) { - sp += basis[i][k] * basis[i][k]; /* squared norm */ - } - for (k = 0; k < DIM; ++k) { - basis[i][k] /= FastMath.sqrt(sp); - } - } - } - } } diff --git a/src/test/java/org/apache/commons/math4/optim/nonlinear/scalar/noderiv/OptimTestUtils.java b/src/test/java/org/apache/commons/math4/optim/nonlinear/scalar/noderiv/OptimTestUtils.java new file mode 100644 index 0000000..df6cd1f --- /dev/null +++ b/src/test/java/org/apache/commons/math4/optim/nonlinear/scalar/noderiv/OptimTestUtils.java @@ -0,0 +1,396 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math4.optim.nonlinear.scalar.noderiv; + +import java.util.Arrays; +import java.util.Random; +import org.apache.commons.rng.UniformRandomProvider; +import org.apache.commons.rng.simple.RandomSource; +import org.apache.commons.math4.analysis.MultivariateFunction; +import org.apache.commons.math4.util.FastMath; + +/** + * Utilities for testing the optimizers. + */ +class OptimTestUtils { + + static class Sphere implements MultivariateFunction { + + @Override + public double value(double[] x) { + double f = 0; + for (int i = 0; i < x.length; ++i) { + f += x[i] * x[i]; + } + return f; + } + } + + static class Cigar implements MultivariateFunction { + private double factor; + + Cigar() { + this(1e3); + } + + Cigar(double axisratio) { + factor = axisratio * axisratio; + } + + @Override + public double value(double[] x) { + double f = x[0] * x[0]; + for (int i = 1; i < x.length; ++i) { + f += factor * x[i] * x[i]; + } + return f; + } + } + + static class Tablet implements MultivariateFunction { + private double factor; + + Tablet() { + this(1e3); + } + + Tablet(double axisratio) { + factor = axisratio * axisratio; + } + + @Override + public double value(double[] x) { + double f = factor * x[0] * x[0]; + for (int i = 1; i < x.length; ++i) { + f += x[i] * x[i]; + } + return f; + } + } + + static class CigTab implements MultivariateFunction { + private double factor; + + CigTab() { + this(1e4); + } + + CigTab(double axisratio) { + factor = axisratio; + } + + @Override + public double value(double[] x) { + int end = x.length - 1; + double f = x[0] * x[0] / factor + factor * x[end] * x[end]; + for (int i = 1; i < end; ++i) { + f += x[i] * x[i]; + } + return f; + } + } + + static class TwoAxes implements MultivariateFunction { + + private double factor; + + TwoAxes() { + this(1e6); + } + + TwoAxes(double axisratio) { + factor = axisratio * axisratio; + } + + @Override + public double value(double[] x) { + double f = 0; + for (int i = 0; i < x.length; ++i) { + f += (i < x.length / 2 ? factor : 1) * x[i] * x[i]; + } + return f; + } + } + + static class ElliRotated implements MultivariateFunction { + private Basis B = new Basis(); + private double factor; + + ElliRotated() { + this(1e3); + } + + ElliRotated(double axisratio) { + factor = axisratio * axisratio; + } + + @Override + public double value(double[] x) { + double f = 0; + x = B.Rotate(x); + for (int i = 0; i < x.length; ++i) { + f += FastMath.pow(factor, i / (x.length - 1.)) * x[i] * x[i]; + } + return f; + } + } + + static class Elli implements MultivariateFunction { + + private double factor; + + Elli() { + this(1e3); + } + + Elli(double axisratio) { + factor = axisratio * axisratio; + } + + @Override + public double value(double[] x) { + double f = 0; + for (int i = 0; i < x.length; ++i) { + f += FastMath.pow(factor, i / (x.length - 1.)) * x[i] * x[i]; + } + return f; + } + } + + static class MinusElli implements MultivariateFunction { + private final Elli elli = new Elli(); + @Override + public double value(double[] x) { + return 1.0 - elli.value(x); + } + } + + static class DiffPow implements MultivariateFunction { + @Override + public double value(double[] x) { + double f = 0; + for (int i = 0; i < x.length; ++i) { + f += FastMath.pow(FastMath.abs(x[i]), 2. + 10 * (double) i + / (x.length - 1.)); + } + return f; + } + } + + static class SsDiffPow implements MultivariateFunction { + @Override + public double value(double[] x) { + double f = FastMath.pow(new DiffPow().value(x), 0.25); + return f; + } + } + + static class Rosen implements MultivariateFunction { + @Override + public double value(double[] x) { + double f = 0; + for (int i = 0; i < x.length - 1; ++i) { + f += 1e2 * (x[i] * x[i] - x[i + 1]) * (x[i] * x[i] - x[i + 1]) + + (x[i] - 1.) * (x[i] - 1.); + } + return f; + } + } + + static class Ackley implements MultivariateFunction { + private double axisratio; + + Ackley(double axra) { + axisratio = axra; + } + + public Ackley() { + this(1); + } + + @Override + public double value(double[] x) { + double f = 0; + double res2 = 0; + double fac = 0; + for (int i = 0; i < x.length; ++i) { + fac = FastMath.pow(axisratio, (i - 1.) / (x.length - 1.)); + f += fac * fac * x[i] * x[i]; + res2 += FastMath.cos(2. * FastMath.PI * fac * x[i]); + } + f = (20. - 20. * FastMath.exp(-0.2 * FastMath.sqrt(f / x.length)) + + FastMath.exp(1.) - FastMath.exp(res2 / x.length)); + return f; + } + } + + static class Rastrigin implements MultivariateFunction { + private double axisratio; + private double amplitude; + + Rastrigin() { + this(1, 10); + } + + Rastrigin(double axisratio, double amplitude) { + this.axisratio = axisratio; + this.amplitude = amplitude; + } + + @Override + public double value(double[] x) { + double f = 0; + double fac; + for (int i = 0; i < x.length; ++i) { + fac = FastMath.pow(axisratio, (i - 1.) / (x.length - 1.)); + if (i == 0 && x[i] < 0) { + fac *= 1.; + } + f += fac * fac * x[i] * x[i] + amplitude + * (1. - FastMath.cos(2. * FastMath.PI * fac * x[i])); + } + return f; + } + } + + static class FourExtrema implements MultivariateFunction { + // The following function has 4 local extrema. + static final double xM = -3.841947088256863675365; + static final double yM = -1.391745200270734924416; + static final double xP = 0.2286682237349059125691; + static final double yP = -yM; + static final double valueXmYm = 0.2373295333134216789769; // Local maximum. + static final double valueXmYp = -valueXmYm; // Local minimum. + static final double valueXpYm = -0.7290400707055187115322; // Global minimum. + static final double valueXpYp = -valueXpYm; // Global maximum. + + @Override + public double value(double[] variables) { + final double x = variables[0]; + final double y = variables[1]; + return (x == 0 || y == 0) ? 0 : + FastMath.atan(x) * FastMath.atan(x + 2) * FastMath.atan(y) * FastMath.atan(y) / (x * y); + } + } + + static class Rosenbrock implements MultivariateFunction { + @Override + public double value(double[] x) { + double a = x[1] - x[0] * x[0]; + double b = 1.0 - x[0]; + return 100 * a * a + b * b; + } + } + + static class Powell implements MultivariateFunction { + @Override + public double value(double[] x) { + double a = x[0] + 10 * x[1]; + double b = x[2] - x[3]; + double c = x[1] - 2 * x[2]; + double d = x[0] - x[3]; + return a * a + 5 * b * b + c * c * c * c + 10 * d * d * d * d; + } + } + + static class Gaussian2D implements MultivariateFunction { + private final double[] maximumPosition; + private final double std; + + public Gaussian2D(double xOpt, double yOpt, double std) { + maximumPosition = new double[] { xOpt, yOpt }; + this.std = std; + } + + public double getMaximum() { + return value(maximumPosition); + } + + public double[] getMaximumPosition() { + return maximumPosition.clone(); + } + + @Override + public double value(double[] point) { + final double x = point[0], y = point[1]; + final double twoS2 = 2.0 * std * std; + return 1.0 / (twoS2 * FastMath.PI) * FastMath.exp(-(x * x + y * y) / twoS2); + } + } + + static double[] point(int n, double value) { + double[] ds = new double[n]; + Arrays.fill(ds, value); + return ds; + } + + /** Creates a RNG instance. */ + static UniformRandomProvider rng() { + return RandomSource.create(RandomSource.MWC_256); + } + + private static class Basis { + double[][] basis; + final Random rand = new Random(2); // use not always the same basis + + double[] Rotate(double[] x) { + GenBasis(x.length); + double[] y = new double[x.length]; + for (int i = 0; i < x.length; ++i) { + y[i] = 0; + for (int j = 0; j < x.length; ++j) { + y[i] += basis[i][j] * x[j]; + } + } + return y; + } + + void GenBasis(int DIM) { + if (basis != null ? basis.length == DIM : false) { + return; + } + + double sp; + int i, j, k; + + /* generate orthogonal basis */ + basis = new double[DIM][DIM]; + for (i = 0; i < DIM; ++i) { + /* sample components gaussian */ + for (j = 0; j < DIM; ++j) { + basis[i][j] = rand.nextGaussian(); + } + /* substract projection of previous vectors */ + for (j = i - 1; j >= 0; --j) { + for (sp = 0., k = 0; k < DIM; ++k) { + sp += basis[i][k] * basis[j][k]; /* scalar product */ + } + for (k = 0; k < DIM; ++k) { + basis[i][k] -= sp * basis[j][k]; /* substract */ + } + } + /* normalize */ + for (sp = 0., k = 0; k < DIM; ++k) { + sp += basis[i][k] * basis[i][k]; /* squared norm */ + } + for (k = 0; k < DIM; ++k) { + basis[i][k] /= FastMath.sqrt(sp); + } + } + } + } +}