From 681943d4f2fac25a5c0bce2f2f7c34171b162471 Mon Sep 17 00:00:00 2001
From: Gilles Sadowski
Date: Thu, 1 Sep 2011 23:37:36 +0000
Subject: [PATCH] MATH-413 Convergence checker passed in the constructor.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1164300 13f79535-47bb-0310-9956-ffa450edef68
---
.../optimization/direct/SimplexOptimizer.java | 18 ++--
.../SimplexOptimizerMultiDirectionalTest.java | 101 ++++++++++-------
.../SimplexOptimizerNelderMeadTest.java | 102 +++++++++++-------
3 files changed, 136 insertions(+), 85 deletions(-)
diff --git a/src/main/java/org/apache/commons/math/optimization/direct/SimplexOptimizer.java b/src/main/java/org/apache/commons/math/optimization/direct/SimplexOptimizer.java
index bff63ef8c..ef87f0656 100644
--- a/src/main/java/org/apache/commons/math/optimization/direct/SimplexOptimizer.java
+++ b/src/main/java/org/apache/commons/math/optimization/direct/SimplexOptimizer.java
@@ -63,10 +63,6 @@ import org.apache.commons.math.optimization.MultivariateRealOptimizer;
* re-initialized to one with the appropriate dimensions.
*
*
- * If {@link #setConvergenceChecker(ConvergenceChecker)} is not called,
- * a default {@link SimpleScalarValueChecker} is used.
- *
- *
* Convergence is checked by providing the worst points of
* previous and current simplex to the convergence checker, not the best
* ones.
@@ -83,10 +79,18 @@ public class SimplexOptimizer
private AbstractSimplex simplex;
/**
- * Default constructor.
+ * Constructor using a default {@link SimpleScalarValueChecker convergence
+ * checker}.
*/
public SimplexOptimizer() {
- setConvergenceChecker(new SimpleScalarValueChecker());
+ this(new SimpleScalarValueChecker());
+ }
+
+ /**
+ * @param checker Convergence checker.
+ */
+ public SimplexOptimizer(ConvergenceChecker checker) {
+ super(checker);
}
/**
@@ -94,7 +98,7 @@ public class SimplexOptimizer
* @param abs Absolute threshold.
*/
public SimplexOptimizer(double rel, double abs) {
- setConvergenceChecker(new SimpleScalarValueChecker(rel, abs));
+ this(new SimpleScalarValueChecker(rel, abs));
}
/**
diff --git a/src/test/java/org/apache/commons/math/optimization/direct/SimplexOptimizerMultiDirectionalTest.java b/src/test/java/org/apache/commons/math/optimization/direct/SimplexOptimizerMultiDirectionalTest.java
index 044a601c0..86ac26dc8 100644
--- a/src/test/java/org/apache/commons/math/optimization/direct/SimplexOptimizerMultiDirectionalTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/direct/SimplexOptimizerMultiDirectionalTest.java
@@ -27,57 +27,61 @@ import org.junit.Test;
public class SimplexOptimizerMultiDirectionalTest {
@Test
- public void testMinimizeMaximize() {
- // the following function has 4 local extrema:
- final double xM = -3.841947088256863675365;
- final double yM = -1.391745200270734924416;
- final double xP = 0.2286682237349059125691;
- final double yP = -yM;
- final double valueXmYm = 0.2373295333134216789769; // local maximum
- final double valueXmYp = -valueXmYm; // local minimum
- final double valueXpYm = -0.7290400707055187115322; // global minimum
- final double valueXpYp = -valueXpYm; // global maximum
- MultivariateRealFunction fourExtrema = new MultivariateRealFunction() {
- 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));
- }
- };
-
+ public void testMinimize1() {
SimplexOptimizer optimizer = new SimplexOptimizer(1e-11, 1e-30);
optimizer.setSimplex(new MultiDirectionalSimplex(new double[] { 0.2, 0.2 }));
- RealPointValuePair optimum;
+ final FourExtrema fourExtrema = new FourExtrema();
- // minimization
- optimum = optimizer.optimize(200, fourExtrema, GoalType.MINIMIZE, new double[] { -3, 0 });
- Assert.assertEquals(xM, optimum.getPoint()[0], 4e-6);
- Assert.assertEquals(yP, optimum.getPoint()[1], 3e-6);
- Assert.assertEquals(valueXmYp, optimum.getValue(), 8e-13);
+ final RealPointValuePair optimum
+ = optimizer.optimize(200, fourExtrema, GoalType.MINIMIZE, new double[] { -3, 0 });
+ Assert.assertEquals(fourExtrema.xM, optimum.getPoint()[0], 4e-6);
+ Assert.assertEquals(fourExtrema.yP, optimum.getPoint()[1], 3e-6);
+ Assert.assertEquals(fourExtrema.valueXmYp, optimum.getValue(), 8e-13);
Assert.assertTrue(optimizer.getEvaluations() > 120);
Assert.assertTrue(optimizer.getEvaluations() < 150);
+ }
- optimum = optimizer.optimize(200, fourExtrema, GoalType.MINIMIZE, new double[] { 1, 0 });
- Assert.assertEquals(xP, optimum.getPoint()[0], 2e-8);
- Assert.assertEquals(yM, optimum.getPoint()[1], 3e-6);
- Assert.assertEquals(valueXpYm, optimum.getValue(), 2e-12);
+ @Test
+ public void testMinimize2() {
+ SimplexOptimizer optimizer = new SimplexOptimizer(1e-11, 1e-30);
+ optimizer.setSimplex(new MultiDirectionalSimplex(new double[] { 0.2, 0.2 }));
+ final FourExtrema fourExtrema = new FourExtrema();
+
+ final RealPointValuePair optimum
+ = optimizer.optimize(200, fourExtrema, GoalType.MINIMIZE, new double[] { 1, 0 });
+ Assert.assertEquals(fourExtrema.xP, optimum.getPoint()[0], 2e-8);
+ Assert.assertEquals(fourExtrema.yM, optimum.getPoint()[1], 3e-6);
+ Assert.assertEquals(fourExtrema.valueXpYm, optimum.getValue(), 2e-12);
Assert.assertTrue(optimizer.getEvaluations() > 120);
Assert.assertTrue(optimizer.getEvaluations() < 150);
+ }
- // maximization
- optimum = optimizer.optimize(200, fourExtrema, GoalType.MAXIMIZE, new double[] { -3.0, 0.0 });
- Assert.assertEquals(xM, optimum.getPoint()[0], 7e-7);
- Assert.assertEquals(yM, optimum.getPoint()[1], 3e-7);
- Assert.assertEquals(valueXmYm, optimum.getValue(), 2e-14);
+ @Test
+ public void testMaximize1() {
+ SimplexOptimizer optimizer = new SimplexOptimizer(1e-11, 1e-30);
+ optimizer.setSimplex(new MultiDirectionalSimplex(new double[] { 0.2, 0.2 }));
+ final FourExtrema fourExtrema = new FourExtrema();
+
+ final RealPointValuePair optimum
+ = optimizer.optimize(200, fourExtrema, GoalType.MAXIMIZE, new double[] { -3.0, 0.0 });
+ Assert.assertEquals(fourExtrema.xM, optimum.getPoint()[0], 7e-7);
+ Assert.assertEquals(fourExtrema.yM, optimum.getPoint()[1], 3e-7);
+ Assert.assertEquals(fourExtrema.valueXmYm, optimum.getValue(), 2e-14);
Assert.assertTrue(optimizer.getEvaluations() > 120);
Assert.assertTrue(optimizer.getEvaluations() < 150);
+ }
- optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1e-15, 1e-30));
- optimum = optimizer.optimize(200, fourExtrema, GoalType.MAXIMIZE, new double[] { 1, 0 });
- Assert.assertEquals(xP, optimum.getPoint()[0], 2e-8);
- Assert.assertEquals(yP, optimum.getPoint()[1], 3e-6);
- Assert.assertEquals(valueXpYp, optimum.getValue(), 2e-12);
+ @Test
+ public void testMaximize2() {
+ SimplexOptimizer optimizer = new SimplexOptimizer(new SimpleScalarValueChecker(1e-15, 1e-30));
+ optimizer.setSimplex(new MultiDirectionalSimplex(new double[] { 0.2, 0.2 }));
+ final FourExtrema fourExtrema = new FourExtrema();
+
+ final RealPointValuePair optimum
+ = optimizer.optimize(200, fourExtrema, GoalType.MAXIMIZE, new double[] { 1, 0 });
+ Assert.assertEquals(fourExtrema.xP, optimum.getPoint()[0], 2e-8);
+ Assert.assertEquals(fourExtrema.yP, optimum.getPoint()[1], 3e-6);
+ Assert.assertEquals(fourExtrema.valueXpYp, optimum.getValue(), 2e-12);
Assert.assertTrue(optimizer.getEvaluations() > 180);
Assert.assertTrue(optimizer.getEvaluations() < 220);
}
@@ -153,6 +157,25 @@ public class SimplexOptimizerMultiDirectionalTest {
Assert.assertEquals(expectedPosition[1], actualPosition[1], EPSILON );
}
+ private static class FourExtrema implements MultivariateRealFunction {
+ // The following function has 4 local extrema.
+ final double xM = -3.841947088256863675365;
+ final double yM = -1.391745200270734924416;
+ final double xP = 0.2286682237349059125691;
+ final double yP = -yM;
+ final double valueXmYm = 0.2373295333134216789769; // Local maximum.
+ final double valueXmYp = -valueXmYm; // Local minimum.
+ final double valueXpYm = -0.7290400707055187115322; // Global minimum.
+ final double valueXpYp = -valueXpYm; // Global maximum.
+
+ 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);
+ }
+ }
+
private static class Gaussian2D implements MultivariateRealFunction {
private final double[] maximumPosition;
private final double std;
diff --git a/src/test/java/org/apache/commons/math/optimization/direct/SimplexOptimizerNelderMeadTest.java b/src/test/java/org/apache/commons/math/optimization/direct/SimplexOptimizerNelderMeadTest.java
index e8dee3a0c..e9bb98476 100644
--- a/src/test/java/org/apache/commons/math/optimization/direct/SimplexOptimizerNelderMeadTest.java
+++ b/src/test/java/org/apache/commons/math/optimization/direct/SimplexOptimizerNelderMeadTest.java
@@ -26,62 +26,67 @@ import org.apache.commons.math.linear.RealMatrix;
import org.apache.commons.math.optimization.GoalType;
import org.apache.commons.math.optimization.LeastSquaresConverter;
import org.apache.commons.math.optimization.RealPointValuePair;
+import org.apache.commons.math.util.FastMath;
import org.junit.Assert;
import org.junit.Test;
public class SimplexOptimizerNelderMeadTest {
@Test
- public void testMinimizeMaximize() {
-
- // the following function has 4 local extrema:
- final double xM = -3.841947088256863675365;
- final double yM = -1.391745200270734924416;
- final double xP = 0.2286682237349059125691;
- final double yP = -yM;
- final double valueXmYm = 0.2373295333134216789769; // local maximum
- final double valueXmYp = -valueXmYm; // local minimum
- final double valueXpYm = -0.7290400707055187115322; // global minimum
- final double valueXpYp = -valueXpYm; // global maximum
- MultivariateRealFunction fourExtrema = new MultivariateRealFunction() {
- public double value(double[] variables) {
- final double x = variables[0];
- final double y = variables[1];
- return (x == 0 || y == 0) ? 0 :
- (Math.atan(x) * Math.atan(x + 2) * Math.atan(y) * Math.atan(y) / (x * y));
- }
- };
-
+ public void testMinimize1() {
SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
optimizer.setSimplex(new NelderMeadSimplex(new double[] { 0.2, 0.2 }));
- RealPointValuePair optimum;
+ final FourExtrema fourExtrema = new FourExtrema();
- // minimization
- optimum = optimizer.optimize(100, fourExtrema, GoalType.MINIMIZE, new double[] { -3, 0 });
- Assert.assertEquals(xM, optimum.getPoint()[0], 2e-7);
- Assert.assertEquals(yP, optimum.getPoint()[1], 2e-5);
- Assert.assertEquals(valueXmYp, optimum.getValue(), 6e-12);
+ final RealPointValuePair optimum
+ = optimizer.optimize(100, fourExtrema, GoalType.MINIMIZE, new double[] { -3, 0 });
+ Assert.assertEquals(fourExtrema.xM, optimum.getPoint()[0], 2e-7);
+ Assert.assertEquals(fourExtrema.yP, optimum.getPoint()[1], 2e-5);
+ Assert.assertEquals(fourExtrema.valueXmYp, optimum.getValue(), 6e-12);
Assert.assertTrue(optimizer.getEvaluations() > 60);
Assert.assertTrue(optimizer.getEvaluations() < 90);
+ }
- optimum = optimizer.optimize(100, fourExtrema, GoalType.MINIMIZE, new double[] { 1, 0 });
- Assert.assertEquals(xP, optimum.getPoint()[0], 5e-6);
- Assert.assertEquals(yM, optimum.getPoint()[1], 6e-6);
- Assert.assertEquals(valueXpYm, optimum.getValue(), 1e-11);
+ @Test
+ public void testMinimize2() {
+ SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
+ optimizer.setSimplex(new NelderMeadSimplex(new double[] { 0.2, 0.2 }));
+ final FourExtrema fourExtrema = new FourExtrema();
+
+ final RealPointValuePair optimum
+ = optimizer.optimize(100, fourExtrema, GoalType.MINIMIZE, new double[] { 1, 0 });
+ Assert.assertEquals(fourExtrema.xP, optimum.getPoint()[0], 5e-6);
+ Assert.assertEquals(fourExtrema.yM, optimum.getPoint()[1], 6e-6);
+ Assert.assertEquals(fourExtrema.valueXpYm, optimum.getValue(), 1e-11);
Assert.assertTrue(optimizer.getEvaluations() > 60);
Assert.assertTrue(optimizer.getEvaluations() < 90);
+ }
- // maximization
- optimum = optimizer.optimize(100, fourExtrema, GoalType.MAXIMIZE, new double[] { -3, 0 });
- Assert.assertEquals(xM, optimum.getPoint()[0], 1e-5);
- Assert.assertEquals(yM, optimum.getPoint()[1], 3e-6);
- Assert.assertEquals(valueXmYm, optimum.getValue(), 3e-12);
+ @Test
+ public void testMaximize1() {
+ SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
+ optimizer.setSimplex(new NelderMeadSimplex(new double[] { 0.2, 0.2 }));
+ final FourExtrema fourExtrema = new FourExtrema();
+
+ final RealPointValuePair optimum
+ = optimizer.optimize(100, fourExtrema, GoalType.MAXIMIZE, new double[] { -3, 0 });
+ Assert.assertEquals(fourExtrema.xM, optimum.getPoint()[0], 1e-5);
+ Assert.assertEquals(fourExtrema.yM, optimum.getPoint()[1], 3e-6);
+ Assert.assertEquals(fourExtrema.valueXmYm, optimum.getValue(), 3e-12);
Assert.assertTrue(optimizer.getEvaluations() > 60);
Assert.assertTrue(optimizer.getEvaluations() < 90);
+ }
- optimum = optimizer.optimize(100, fourExtrema, GoalType.MAXIMIZE, new double[] { 1, 0 });
- Assert.assertEquals(xP, optimum.getPoint()[0], 4e-6);
- Assert.assertEquals(yP, optimum.getPoint()[1], 5e-6);
- Assert.assertEquals(valueXpYp, optimum.getValue(), 7e-12);
+ @Test
+ public void testMaximize2() {
+ SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
+ optimizer.setSimplex(new NelderMeadSimplex(new double[] { 0.2, 0.2 }));
+ final FourExtrema fourExtrema = new FourExtrema();
+
+ final RealPointValuePair optimum
+ = optimizer.optimize(100, fourExtrema, GoalType.MAXIMIZE, new double[] { 1, 0 });
+ Assert.assertEquals(fourExtrema.xP, optimum.getPoint()[0], 4e-6);
+ Assert.assertEquals(fourExtrema.yP, optimum.getPoint()[1], 5e-6);
+ Assert.assertEquals(fourExtrema.valueXpYp, optimum.getValue(), 7e-12);
Assert.assertTrue(optimizer.getEvaluations() > 60);
Assert.assertTrue(optimizer.getEvaluations() < 90);
}
@@ -199,6 +204,25 @@ public class SimplexOptimizerNelderMeadTest {
optimizer.optimize(20, powell, GoalType.MINIMIZE, new double[] { 3, -1, 0, 1 });
}
+ private static class FourExtrema implements MultivariateRealFunction {
+ // The following function has 4 local extrema.
+ final double xM = -3.841947088256863675365;
+ final double yM = -1.391745200270734924416;
+ final double xP = 0.2286682237349059125691;
+ final double yP = -yM;
+ final double valueXmYm = 0.2373295333134216789769; // Local maximum.
+ final double valueXmYp = -valueXmYm; // Local minimum.
+ final double valueXpYm = -0.7290400707055187115322; // Global minimum.
+ final double valueXpYp = -valueXpYm; // Global maximum.
+
+ 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);
+ }
+ }
+
private static class Rosenbrock implements MultivariateRealFunction {
private int count;