You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2014/03/03 10:58:30 UTC

svn commit: r1573506 - in /commons/proper/math/trunk: pom.xml src/changes/changes.xml src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/noderiv/CMAESOptimizer.java

Author: luc
Date: Mon Mar  3 09:58:29 2014
New Revision: 1573506

URL: http://svn.apache.org/r1573506
Log:
Prevent penalties to grow multiplicatively in CMAES.

Patch provided by Bruce A Johnson.

JIRA: MATH-1107

Modified:
    commons/proper/math/trunk/pom.xml
    commons/proper/math/trunk/src/changes/changes.xml
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/noderiv/CMAESOptimizer.java

Modified: commons/proper/math/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/pom.xml?rev=1573506&r1=1573505&r2=1573506&view=diff
==============================================================================
--- commons/proper/math/trunk/pom.xml (original)
+++ commons/proper/math/trunk/pom.xml Mon Mar  3 09:58:29 2014
@@ -223,6 +223,9 @@
       <name>Curtis Jensen</name>
     </contributor>
     <contributor>
+      <name>Bruce A Johnson</name>
+    </contributor>
+    <contributor>
       <name>Ismael Juma</name>
     </contributor>
     <contributor>

Modified: commons/proper/math/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/changes/changes.xml?rev=1573506&r1=1573505&r2=1573506&view=diff
==============================================================================
--- commons/proper/math/trunk/src/changes/changes.xml (original)
+++ commons/proper/math/trunk/src/changes/changes.xml Mon Mar  3 09:58:29 2014
@@ -51,6 +51,9 @@ If the output is not quite correct, chec
   </properties>
   <body>
     <release version="3.3" date="TBD" description="TBD">
+      <action dev="luc" type="fix" issue="MATH-1107" due-to="Bruce A Johnson">
+        Prevent penalties to grow multiplicatively in CMAES for out of bounds points.
+      </action>
       <action dev="psteitz" type="update" issue="MATH-437">
         Added KolmogorovSmirnovTest class, deprecating KolmogorovSmirnovDistribution.
       </action>

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/noderiv/CMAESOptimizer.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/noderiv/CMAESOptimizer.java?rev=1573506&r1=1573505&r2=1573506&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/noderiv/CMAESOptimizer.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/noderiv/CMAESOptimizer.java Mon Mar  3 09:58:29 2014
@@ -377,7 +377,8 @@ public class CMAESOptimizer
         dimension = guess.length;
         initializeCMA(guess);
         iterations = 0;
-        double bestValue = fitfun.value(guess);
+        ValuePenaltyPair valuePenalty = fitfun.value(guess);
+        double bestValue = valuePenalty.value+valuePenalty.penalty;
         push(fitnessHistory, bestValue);
         PointValuePair optimum
             = new PointValuePair(getStartPoint(),
@@ -394,6 +395,7 @@ public class CMAESOptimizer
             final RealMatrix arz = randn1(dimension, lambda);
             final RealMatrix arx = zeros(dimension, lambda);
             final double[] fitness = new double[lambda];
+            final ValuePenaltyPair[] valuePenaltyPairs = new ValuePenaltyPair[lambda];
             // generate random offspring
             for (int k = 0; k < lambda; k++) {
                 RealMatrix arxk = null;
@@ -414,11 +416,18 @@ public class CMAESOptimizer
                 }
                 copyColumn(arxk, 0, arx, k);
                 try {
-                    fitness[k] = fitfun.value(arx.getColumn(k)); // compute fitness
+                    valuePenaltyPairs[k] = fitfun.value(arx.getColumn(k)); // compute fitness
                 } catch (TooManyEvaluationsException e) {
                     break generationLoop;
                 }
             }
+
+            // Compute fitnesses by adding value and penalty after scaling by value range.
+            double valueRange = valueRange(valuePenaltyPairs);
+            for (int iValue=0;iValue<valuePenaltyPairs.length;iValue++) {
+                 fitness[iValue] = valuePenaltyPairs[iValue].value + valuePenaltyPairs[iValue].penalty*valueRange;
+            }
+
             // Sort by fitness and compute weighted mean into xmean
             final int[] arindex = sortedIndices(fitness);
             // Calculate new xmean, this is selection and recombination
@@ -503,7 +512,6 @@ public class CMAESOptimizer
             }
             // store best in history
             push(fitnessHistory,bestFitness);
-            fitfun.setValueRange(worstFitness-bestFitness);
             if (generateStatistics) {
                 statisticsSigmaHistory.add(sigma);
                 statisticsFitnessHistory.add(bestFitness);
@@ -825,6 +833,25 @@ public class CMAESOptimizer
         }
         return indices;
     }
+   /**
+     * Get range of values.
+     *
+     * @param vpPairs Array of valuePenaltyPairs to get range from.
+     * @return a double equal to maximum value minus minimum value.
+     */
+    private double valueRange(final ValuePenaltyPair[] vpPairs) {
+        double max = Double.NEGATIVE_INFINITY;
+        double min = Double.MAX_VALUE;
+        for (ValuePenaltyPair vpPair:vpPairs) {
+            if (vpPair.value > max) {
+                max = vpPair.value;
+            }
+            if (vpPair.value < min) {
+                min = vpPair.value;
+            }
+        }
+        return max-min;
+    }
 
     /**
      * Used to sort fitness values. Sorting is always in lower value first
@@ -872,15 +899,31 @@ public class CMAESOptimizer
             return (int) ((1438542 ^ (bits >>> 32) ^ bits) & 0xffffffff);
         }
     }
+    /**
+     * Stores the value and penalty (for repair of out of bounds point).
+     */
+    private static class ValuePenaltyPair {
+        /** Objective function value. */
+        private double value;
+        /** Penalty value for repair of out out of bounds points. */
+        private double penalty;
+
+        /**
+         * @param value Function value.
+         * @param penalty Out-of-bounds penalty.
+        */
+        public ValuePenaltyPair(final double value, final double penalty) {
+            this.value   = value;
+            this.penalty = penalty;
+        }
+    }
+
 
     /**
      * Normalizes fitness values to the range [0,1]. Adds a penalty to the
-     * fitness value if out of range. The penalty is adjusted by calling
-     * setValueRange().
+     * fitness value if out of range.
      */
     private class FitnessFunction {
-        /** Determines the penalty for boundary violations */
-        private double valueRange;
         /**
          * Flag indicating whether the objective variables are forced into their
          * bounds if defined
@@ -890,7 +933,6 @@ public class CMAESOptimizer
         /** Simple constructor.
          */
         public FitnessFunction() {
-            valueRange = 1;
             isRepairMode = true;
         }
 
@@ -898,16 +940,19 @@ public class CMAESOptimizer
          * @param point Normalized objective variables.
          * @return the objective value + penalty for violated bounds.
          */
-        public double value(final double[] point) {
+        public ValuePenaltyPair value(final double[] point) {
             double value;
+            double penalty=0.0;
             if (isRepairMode) {
                 double[] repaired = repair(point);
-                value = CMAESOptimizer.this.computeObjectiveValue(repaired) +
-                    penalty(point, repaired);
+                value = CMAESOptimizer.this.computeObjectiveValue(repaired);
+                penalty =  penalty(point, repaired);
             } else {
                 value = CMAESOptimizer.this.computeObjectiveValue(point);
             }
-            return isMinimize ? value : -value;
+            value = isMinimize ? value : -value;
+            penalty = isMinimize ? penalty : -penalty;
+            return new ValuePenaltyPair(value,penalty);
         }
 
         /**
@@ -930,13 +975,6 @@ public class CMAESOptimizer
         }
 
         /**
-         * @param valueRange Adjusts the penalty computation.
-         */
-        public void setValueRange(double valueRange) {
-            this.valueRange = valueRange;
-        }
-
-        /**
          * @param x Normalized objective variables.
          * @return the repaired (i.e. all in bounds) objective variables.
          */
@@ -966,7 +1004,7 @@ public class CMAESOptimizer
             double penalty = 0;
             for (int i = 0; i < x.length; i++) {
                 double diff = FastMath.abs(x[i] - repaired[i]);
-                penalty += diff * valueRange;
+                penalty += diff;
             }
             return isMinimize ? penalty : -penalty;
         }