You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2012/09/21 17:32:18 UTC

svn commit: r1388552 - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math3/optimization/direct/CMAESOptimizer.java test/java/org/apache/commons/math3/optimization/direct/CMAESOptimizerTest.java

Author: erans
Date: Fri Sep 21 15:32:18 2012
New Revision: 1388552

URL: http://svn.apache.org/viewvc?rev=1388552&view=rev
Log:
MATH-865
Early detection that overflow will occur in the variables normalization
procedure ("encode" method). Warning mentioned in the documentation.

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=1388552&r1=1388551&r2=1388552&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 Fri Sep 21 15:32:18 2012
@@ -24,8 +24,8 @@ import java.util.List;
 import org.apache.commons.math3.analysis.MultivariateFunction;
 import org.apache.commons.math3.exception.DimensionMismatchException;
 import org.apache.commons.math3.exception.MathUnsupportedOperationException;
-import org.apache.commons.math3.exception.MathIllegalStateException;
 import org.apache.commons.math3.exception.NotPositiveException;
+import org.apache.commons.math3.exception.NumberIsTooLargeException;
 import org.apache.commons.math3.exception.OutOfRangeException;
 import org.apache.commons.math3.exception.TooManyEvaluationsException;
 import org.apache.commons.math3.exception.util.LocalizedFormats;
@@ -78,6 +78,12 @@ import org.apache.commons.math3.util.Mat
  *  <li><a href="http://en.wikipedia.org/wiki/CMA-ES">Wikipedia</a></li>
  * </ul>
  *
+ * When simple constraints (boundaries) are used, care must be taken that the
+ * difference between the upper and lower bounds does not overflow; should it
+ * be the case, a {@link NumberIsTooLargeException} will be thrown by the
+ * {@link BaseAbstractMultivariateSimpleBoundsOptimizer#optimize(int,
+ * MultivariateFunction,GoalType,double[],double[],double[]) optimize} method.
+ *
  * @version $Id$
  * @since 3.0
  */
@@ -529,6 +535,21 @@ public class CMAESOptimizer
                 boundaries = new double[2][];
                 boundaries[0] = lB;
                 boundaries[1] = uB;
+
+                // Abort early if the normalization will overflow (cf. "encode" method).
+                for (int i = 0; i < lB.length; i++) {
+                    if (Double.isInfinite(boundaries[1][i] - boundaries[0][i])) {
+                        final double max = Double.MAX_VALUE + boundaries[0][i];
+                        final NumberIsTooLargeException e
+                            = new NumberIsTooLargeException(boundaries[1][i],
+                                                            max,
+                                                            true);
+                        e.getContext().addMessage(LocalizedFormats.OVERFLOW);
+                        e.getContext().addMessage(LocalizedFormats.INDEX, i);
+
+                        throw e;
+                    }
+                }
             }
         } else {
             // Convert API to internal handling of boundaries.

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=1388552&r1=1388551&r2=1388552&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 Fri Sep 21 15:32:18 2012
@@ -26,11 +26,13 @@ import org.apache.commons.math3.exceptio
 import org.apache.commons.math3.exception.NumberIsTooSmallException;
 import org.apache.commons.math3.exception.DimensionMismatchException;
 import org.apache.commons.math3.exception.MathUnsupportedOperationException;
+import org.apache.commons.math3.exception.MathIllegalStateException;
 import org.apache.commons.math3.exception.NotPositiveException;
 import org.apache.commons.math3.exception.OutOfRangeException;
 import org.apache.commons.math3.optimization.GoalType;
 import org.apache.commons.math3.optimization.PointValuePair;
 import org.apache.commons.math3.random.MersenneTwister;
+import org.apache.commons.math3.util.FastMath;
 import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -376,7 +378,6 @@ public class CMAESOptimizerTest {
     public void testMath864() {
         final CMAESOptimizer optimizer = new CMAESOptimizer();
         final MultivariateFunction fitnessFunction = new MultivariateFunction() {
-                @Override
                 public double value(double[] parameters) {
                     final double target = 1;
                     final double error = target - parameters[0];
@@ -394,6 +395,35 @@ public class CMAESOptimizerTest {
     }
 
     /**
+     * Cf. MATH-865
+     */
+    @Test(expected=NumberIsTooLargeException.class)
+    public void testBoundaryRangeTooLarge() {
+        final CMAESOptimizer optimizer = new CMAESOptimizer();
+        final MultivariateFunction fitnessFunction = new MultivariateFunction() {
+                public double value(double[] parameters) {
+                    if (Double.isNaN(parameters[0])) {
+                        throw new MathIllegalStateException();
+                    }
+                    final double target = 1;
+                    final double error = target - parameters[0];
+                    return error * error;
+                }
+            };
+
+        final double[] start = { 0 };
+
+        // The difference between upper and lower bounds is used to used
+        // normalize the variables: In case of overflow, NaN is produced.
+        final double max = Double.MAX_VALUE / 2;
+        final double tooLarge = FastMath.nextUp(max);
+        final double[] lower = { -tooLarge };
+        final double[] upper = { tooLarge };
+        final double[] result = optimizer.optimize(10000, fitnessFunction, GoalType.MINIMIZE,
+                                                   start, lower, upper).getPoint();
+    }
+
+    /**
      * @param func Function to optimize.
      * @param startPoint Starting point.
      * @param inSigma Individual input sigma.