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++) {


Reply via email to