Author: erans
Date: Sun Feb 19 00:01:22 2012
New Revision: 1290909
URL: http://svn.apache.org/viewvc?rev=1290909&view=rev
Log:
MATH-698
Made "CMAESOptimizer" a subclass of
"BaseAbstractMultivariateSimpleBoundsOptimizer".
The original code does not support mixing finite and infinite bounds (no
constraints)
on the variables; a check for this incompatibility is thus performed, throwing a
"MathUnsuppportedException" if failing.
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/direct/CMAESOptimizer.java
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/direct/CMAESOptimizerTest.java
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/direct/CMAESOptimizer.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/direct/CMAESOptimizer.java?rev=1290909&r1=1290908&r2=1290909&view=diff
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/direct/CMAESOptimizer.java
(original)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/direct/CMAESOptimizer.java
Sun Feb 19 00:01:22 2012
@@ -23,7 +23,7 @@ import java.util.List;
import org.apache.commons.math3.analysis.MultivariateFunction;
import org.apache.commons.math3.exception.DimensionMismatchException;
-import org.apache.commons.math3.exception.NoDataException;
+import org.apache.commons.math3.exception.MathUnsupportedOperationException;
import org.apache.commons.math3.exception.NotPositiveException;
import org.apache.commons.math3.exception.OutOfRangeException;
import org.apache.commons.math3.exception.TooManyEvaluationsException;
@@ -81,7 +81,7 @@ import org.apache.commons.math3.util.Mat
*/
public class CMAESOptimizer
- extends BaseAbstractMultivariateOptimizer<MultivariateFunction>
+ extends BaseAbstractMultivariateSimpleBoundsOptimizer<MultivariateFunction>
implements MultivariateOptimizer {
/** Default value for {@link #checkFeasableCount}: {@value}. */
public static final int DEFAULT_CHECKFEASABLECOUNT = 0;
@@ -242,7 +242,7 @@ public class CMAESOptimizer
* @param lambda Population size.
*/
public CMAESOptimizer(int lambda) {
- this(lambda, null, null, DEFAULT_MAXITERATIONS, DEFAULT_STOPFITNESS,
+ this(lambda, null, DEFAULT_MAXITERATIONS, DEFAULT_STOPFITNESS,
DEFAULT_ISACTIVECMA, DEFAULT_DIAGONALONLY,
DEFAULT_CHECKFEASABLECOUNT, DEFAULT_RANDOMGENERATOR, false);
}
@@ -250,11 +250,9 @@ public class CMAESOptimizer
/**
* @param lambda Population size.
* @param inputSigma Initial search volume; sigma of offspring objective
variables.
- * @param boundaries Boundaries for objective variables.
*/
- public CMAESOptimizer(int lambda, double[] inputSigma,
- double[][] boundaries) {
- this(lambda, inputSigma, boundaries, DEFAULT_MAXITERATIONS,
DEFAULT_STOPFITNESS,
+ public CMAESOptimizer(int lambda, double[] inputSigma) {
+ this(lambda, inputSigma, DEFAULT_MAXITERATIONS, DEFAULT_STOPFITNESS,
DEFAULT_ISACTIVECMA, DEFAULT_DIAGONALONLY,
DEFAULT_CHECKFEASABLECOUNT, DEFAULT_RANDOMGENERATOR, false);
}
@@ -262,7 +260,6 @@ public class CMAESOptimizer
/**
* @param lambda Population size.
* @param inputSigma Initial search volume; sigma of offspring objective
variables.
- * @param boundaries Boundaries for objective variables.
* @param maxIterations Maximal number of iterations.
* @param stopFitness Whether to stop if objective function value is
smaller than
* {@code stopFitness}.
@@ -275,10 +272,10 @@ public class CMAESOptimizer
* @param generateStatistics Whether statistic data is collected.
*/
public CMAESOptimizer(int lambda, double[] inputSigma,
- double[][] boundaries, int maxIterations, double
stopFitness,
+ int maxIterations, double stopFitness,
boolean isActiveCMA, int diagonalOnly, int
checkFeasableCount,
RandomGenerator random, boolean generateStatistics) {
- this(lambda, inputSigma, boundaries, maxIterations, stopFitness,
isActiveCMA,
+ this(lambda, inputSigma, maxIterations, stopFitness, isActiveCMA,
diagonalOnly, checkFeasableCount, random, generateStatistics,
new SimpleValueChecker());
}
@@ -286,7 +283,6 @@ public class CMAESOptimizer
/**
* @param lambda Population size.
* @param inputSigma Initial search volume; sigma of offspring objective
variables.
- * @param boundaries Boundaries for objective variables.
* @param maxIterations Maximal number of iterations.
* @param stopFitness Whether to stop if objective function value is
smaller than
* {@code stopFitness}.
@@ -300,23 +296,13 @@ public class CMAESOptimizer
* @param checker Convergence checker.
*/
public CMAESOptimizer(int lambda, double[] inputSigma,
- double[][] boundaries, int maxIterations, double
stopFitness,
+ int maxIterations, double stopFitness,
boolean isActiveCMA, int diagonalOnly, int
checkFeasableCount,
RandomGenerator random, boolean generateStatistics,
ConvergenceChecker<PointValuePair> checker) {
super(checker);
this.lambda = lambda;
this.inputSigma = inputSigma == null ? null : (double[])
inputSigma.clone();
- if (boundaries == null) {
- this.boundaries = null;
- } else {
- final int len = boundaries.length;
- this.boundaries = new double[len][];
- for (int i = 0; i < len; i++) {
- this.boundaries[i] =
- boundaries[i] == null ? null : (double[])
boundaries[i].clone();
- }
- }
this.maxIterations = maxIterations;
this.stopFitness = stopFitness;
this.isActiveCMA = isActiveCMA;
@@ -506,27 +492,45 @@ public class CMAESOptimizer
* Checks dimensions and values of boundaries and inputSigma if defined.
*/
private void checkParameters() {
- double[] init = getStartPoint();
- if (boundaries != null) {
- if (boundaries.length != 2) {
- throw new DimensionMismatchException(boundaries.length, 2);
- }
- if (boundaries[0] == null || boundaries[1] == null) {
- throw new NoDataException();
- }
- if (boundaries[0].length != init.length) {
- throw new DimensionMismatchException(boundaries[0].length,
init.length);
- }
- if (boundaries[1].length != init.length) {
- throw new DimensionMismatchException(boundaries[1].length,
init.length);
- }
- for (int i = 0; i < init.length; i++) {
- if (boundaries[0][i] > init[i] || boundaries[1][i] < init[i]) {
- throw new OutOfRangeException(init[i], boundaries[0][i],
- boundaries[1][i]);
+ final double[] init = getStartPoint();
+ final double[] lB = getLowerBound();
+ final double[] uB = getUpperBound();
+
+ // Checks whether there is at least one finite bound value.
+ boolean hasFiniteBounds = false;
+ for (int i = 0; i < lB.length; i++) {
+ if (!Double.isInfinite(lB[i]) ||
+ !Double.isInfinite(uB[i])) {
+ hasFiniteBounds = true;
+ break;
+ }
+ }
+ // Checks whether there is at least one infinite bound value.
+ boolean hasInfiniteBounds = false;
+ if (hasFiniteBounds) {
+ for (int i = 0; i < lB.length; i++) {
+ if (Double.isInfinite(lB[i]) ||
+ Double.isInfinite(uB[i])) {
+ hasInfiniteBounds = true;
+ break;
}
}
+
+ if (hasInfiniteBounds) {
+ // If there is at least one finite bound, none can be infinite,
+ // because mixed cases are not supported by the current code.
+ throw new MathUnsupportedOperationException();
+ } else {
+ // Convert API to internal handling of boundaries.
+ boundaries = new double[2][];
+ boundaries[0] = lB;
+ boundaries[1] = uB;
+ }
+ } else {
+ // Convert API to internal handling of boundaries.
+ boundaries = null;
}
+
if (inputSigma != null) {
if (inputSigma.length != init.length) {
throw new DimensionMismatchException(inputSigma.length,
init.length);
Modified:
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/direct/CMAESOptimizerTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/direct/CMAESOptimizerTest.java?rev=1290909&r1=1290908&r2=1290909&view=diff
==============================================================================
---
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/direct/CMAESOptimizerTest.java
(original)
+++
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/direct/CMAESOptimizerTest.java
Sun Feb 19 00:01:22 2012
@@ -22,8 +22,10 @@ import java.util.Random;
import org.apache.commons.math3.Retry;
import org.apache.commons.math3.RetryRunner;
import org.apache.commons.math3.analysis.MultivariateFunction;
+import org.apache.commons.math3.exception.NumberIsTooLargeException;
+import org.apache.commons.math3.exception.NumberIsTooSmallException;
import org.apache.commons.math3.exception.DimensionMismatchException;
-import org.apache.commons.math3.exception.NoDataException;
+import org.apache.commons.math3.exception.MathUnsupportedOperationException;
import org.apache.commons.math3.exception.NotPositiveException;
import org.apache.commons.math3.exception.OutOfRangeException;
import org.apache.commons.math3.optimization.GoalType;
@@ -43,8 +45,8 @@ public class CMAESOptimizerTest {
static final int DIM = 13;
static final int LAMBDA = 4 + (int)(3.*Math.log(DIM));
- @Test(expected = OutOfRangeException.class)
- public void testInitOutofbounds() {
+ @Test(expected = NumberIsTooLargeException.class)
+ public void testInitOutofbounds1() {
double[] startPoint = point(DIM,3);
double[] insigma = null;
double[][] boundaries = boundaries(DIM,-1,2);
@@ -54,6 +56,17 @@ public class CMAESOptimizerTest {
GoalType.MINIMIZE, LAMBDA, true, 0, 1e-13,
1e-13, 1e-6, 100000, expected);
}
+ @Test(expected = NumberIsTooSmallException.class)
+ public void testInitOutofbounds2() {
+ double[] startPoint = point(DIM, -2);
+ double[] insigma = null;
+ double[][] boundaries = boundaries(DIM,-1,2);
+ PointValuePair expected =
+ new PointValuePair(point(DIM,1.0),0.0);
+ doTest(new Rosen(), startPoint, insigma, boundaries,
+ GoalType.MINIMIZE, LAMBDA, true, 0, 1e-13,
+ 1e-13, 1e-6, 100000, expected);
+ }
@Test(expected = DimensionMismatchException.class)
public void testBoundariesDimensionMismatch() {
@@ -67,12 +80,27 @@ public class CMAESOptimizerTest {
1e-13, 1e-6, 100000, expected);
}
- @Test(expected = NoDataException.class)
- public void testBoundariesNoData() {
+ @Test(expected = MathUnsupportedOperationException.class)
+ public void testUnsupportedBoundaries1() {
double[] startPoint = point(DIM,0.5);
double[] insigma = null;
- double[][] boundaries = boundaries(DIM,-1,2);
- boundaries[1] = null;
+ double[][] boundaries = boundaries(DIM,-1, Double.POSITIVE_INFINITY);
+ PointValuePair expected =
+ new PointValuePair(point(DIM,1.0),0.0);
+ doTest(new Rosen(), startPoint, insigma, boundaries,
+ GoalType.MINIMIZE, LAMBDA, true, 0, 1e-13,
+ 1e-13, 1e-6, 100000, expected);
+ }
+
+ @Test(expected = MathUnsupportedOperationException.class)
+ public void testUnsupportedBoundaries2() {
+ double[] startPoint = point(DIM, 0.5);
+ double[] insigma = null;
+ final double[] lB = new double[] { -1, -1, -1, -1, -1,
Double.NEGATIVE_INFINITY, -1, -1, -1, -1, -1, -1, -1 };
+ final double[] uB = new double[] { 2, 2, 2, Double.POSITIVE_INFINITY,
2, 2, 2, 2, 2, 2, 2, 2, 2 };
+ double[][] boundaries = new double[2][];
+ boundaries[0] = lB;
+ boundaries[1] = uB;
PointValuePair expected =
new PointValuePair(point(DIM,1.0),0.0);
doTest(new Rosen(), startPoint, insigma, boundaries,
@@ -375,11 +403,12 @@ public class CMAESOptimizerTest {
PointValuePair expected) {
int dim = startPoint.length;
// test diagonalOnly = 0 - slow but normally fewer feval#
- MultivariateOptimizer optim =
- new CMAESOptimizer(
- lambda, inSigma, boundaries, 30000,
- stopValue, isActive, diagonalOnly, 0, new
MersenneTwister(),false);
- PointValuePair result = optim.optimize(maxEvaluations, func, goal,
startPoint);
+ CMAESOptimizer optim = new CMAESOptimizer( lambda, inSigma, 30000,
+ stopValue, isActive,
diagonalOnly,
+ 0, new MersenneTwister(),
false);
+ final double[] lB = boundaries == null ? null : boundaries[0];
+ final double[] uB = boundaries == null ? null : boundaries[1];
+ PointValuePair result = optim.optimize(maxEvaluations, func, goal,
startPoint, lB, uB);
Assert.assertEquals(expected.getValue(),
result.getValue(), fTol);
for (int i = 0; i < dim; i++) {