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 2023/04/05 14:43:53 UTC

[commons-math] branch master updated: MATH-1657: Provide (protected) accessor to the objective function.

This is an automated email from the ASF dual-hosted git repository.

erans pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-math.git


The following commit(s) were added to refs/heads/master by this push:
     new 56844842a MATH-1657: Provide (protected) accessor to the objective function.
56844842a is described below

commit 56844842a86612c0fadd2e3ac6fc57f21e6747ae
Author: Gilles Sadowski <gi...@gmail.com>
AuthorDate: Wed Apr 5 16:41:24 2023 +0200

    MATH-1657: Provide (protected) accessor to the objective function.
    
    Deprecated method "computeObjectiveValue" (equivalent functionality).
    
    Thanks to François Laferrière for the suggestion.
---
 .../legacy/optim/nonlinear/scalar/LineSearch.java   | 10 ++++++----
 .../nonlinear/scalar/MultivariateOptimizer.java     | 21 +++++++++++++++++++--
 .../NonLinearConjugateGradientOptimizer.java        |  4 +++-
 .../nonlinear/scalar/noderiv/BOBYQAOptimizer.java   |  5 +++--
 .../nonlinear/scalar/noderiv/CMAESOptimizer.java    | 10 ++++++----
 .../nonlinear/scalar/noderiv/PowellOptimizer.java   |  6 ++++--
 .../nonlinear/scalar/noderiv/SimplexOptimizer.java  |  4 +---
 .../legacy/optim/univariate/BrentOptimizer.java     |  6 ++++--
 .../optim/univariate/UnivariateOptimizer.java       | 21 +++++++++++++++++++--
 src/changes/changes.xml                             |  4 ++++
 10 files changed, 69 insertions(+), 22 deletions(-)

diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/LineSearch.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/LineSearch.java
index 1dab36529..6e674c364 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/LineSearch.java
+++ b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/LineSearch.java
@@ -17,6 +17,7 @@
 package org.apache.commons.math4.legacy.optim.nonlinear.scalar;
 
 import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
+import org.apache.commons.math4.legacy.analysis.MultivariateFunction;
 import org.apache.commons.math4.legacy.optim.MaxEval;
 import org.apache.commons.math4.legacy.optim.univariate.BracketFinder;
 import org.apache.commons.math4.legacy.optim.univariate.BrentOptimizer;
@@ -73,9 +74,9 @@ public class LineSearch {
      *
      * @param optimizer Optimizer on behalf of which the line search
      * be performed.
-     * Its {@link MultivariateOptimizer#computeObjectiveValue(double[])
-     * computeObjectiveValue} method will be called by the
-     * {@link #search(double[],double[]) search} method.
+     * Its {@link MultivariateOptimizer#getObjectiveFunction() objective
+     * function} will be called by the {@link #search(double[],double[])
+     * search} method.
      * @param relativeTolerance Search will stop when the function relative
      * difference between successive iterations is below this value.
      * @param absoluteTolerance Search will stop when the function absolute
@@ -111,6 +112,7 @@ public class LineSearch {
     public UnivariatePointValuePair search(final double[] startPoint,
                                            final double[] direction) {
         final int n = startPoint.length;
+        final MultivariateFunction func = mainOptimizer.getObjectiveFunction();
         final UnivariateFunction f = new UnivariateFunction() {
             /** {@inheritDoc} */
             @Override
@@ -119,7 +121,7 @@ public class LineSearch {
                 for (int i = 0; i < n; i++) {
                     x[i] = startPoint[i] + alpha * direction[i];
                 }
-                return mainOptimizer.computeObjectiveValue(x);
+                return func.value(x);
             }
         };
 
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/MultivariateOptimizer.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/MultivariateOptimizer.java
index c36e95e16..2cd72d83b 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/MultivariateOptimizer.java
+++ b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/MultivariateOptimizer.java
@@ -85,7 +85,14 @@ public abstract class MultivariateOptimizer
                 continue;
             }
             if (data instanceof ObjectiveFunction) {
-                function = ((ObjectiveFunction) data).getObjectiveFunction();
+                final MultivariateFunction delegate = ((ObjectiveFunction) data).getObjectiveFunction();
+                function = new MultivariateFunction() {
+                        @Override
+                        public double value(double[] point) {
+                            incrementEvaluationCount();
+                            return delegate.value(point);
+                        }
+                    };
                 continue;
             }
         }
@@ -98,6 +105,14 @@ public abstract class MultivariateOptimizer
         return goal;
     }
 
+    /**
+     * @return a wrapper that delegates to the user-supplied function,
+     * and counts the number of evaluations.
+     */
+    protected MultivariateFunction getObjectiveFunction() {
+        return function;
+    }
+
     /**
      * Computes the objective function value.
      * This method <em>must</em> be called by subclasses to enforce the
@@ -107,9 +122,11 @@ public abstract class MultivariateOptimizer
      * @return the objective function value at the specified point.
      * @throws org.apache.commons.math4.legacy.exception.TooManyEvaluationsException
      * if the maximal number of evaluations is exceeded.
+     *
+     * @deprecated Use {@link #getObjectiveFunction()} instead.
      */
+    @Deprecated
     public double computeObjectiveValue(double[] params) {
-        super.incrementEvaluationCount();
         return function.value(params);
     }
 }
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/gradient/NonLinearConjugateGradientOptimizer.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/gradient/NonLinearConjugateGradientOptimizer.java
index 168fc72e6..f22eaf309 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/gradient/NonLinearConjugateGradientOptimizer.java
+++ b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/gradient/NonLinearConjugateGradientOptimizer.java
@@ -17,6 +17,7 @@
 
 package org.apache.commons.math4.legacy.optim.nonlinear.scalar.gradient;
 
+import org.apache.commons.math4.legacy.analysis.MultivariateFunction;
 import org.apache.commons.math4.legacy.exception.MathInternalError;
 import org.apache.commons.math4.legacy.exception.MathUnsupportedOperationException;
 import org.apache.commons.math4.legacy.exception.TooManyEvaluationsException;
@@ -171,6 +172,7 @@ public class NonLinearConjugateGradientOptimizer
         final ConvergenceChecker<PointValuePair> checker = getConvergenceChecker();
         final double[] point = getStartPoint();
         final GoalType goal = getGoalType();
+        final MultivariateFunction func = getObjectiveFunction();
         final int n = point.length;
         double[] r = computeObjectiveGradient(point);
         if (goal == GoalType.MINIMIZE) {
@@ -192,7 +194,7 @@ public class NonLinearConjugateGradientOptimizer
         while (true) {
             incrementIterationCount();
 
-            final double objective = computeObjectiveValue(point);
+            final double objective = func.value(point);
             PointValuePair previous = current;
             current = new PointValuePair(point, objective);
             if (previous != null && checker.converged(getIterations(), previous, current)) {
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/BOBYQAOptimizer.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/BOBYQAOptimizer.java
index 87515e94c..593f0f663 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/BOBYQAOptimizer.java
+++ b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/BOBYQAOptimizer.java
@@ -17,6 +17,7 @@
 // CHECKSTYLE: stop all
 package org.apache.commons.math4.legacy.optim.nonlinear.scalar.noderiv;
 
+import org.apache.commons.math4.legacy.analysis.MultivariateFunction;
 import org.apache.commons.math4.legacy.exception.MathIllegalStateException;
 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
 import org.apache.commons.math4.legacy.exception.OutOfRangeException;
@@ -826,7 +827,7 @@ public class BOBYQAOptimizer
                 }
             }
 
-            f = computeObjectiveValue(currentBest.toArray());
+            f = getObjectiveFunction().value(currentBest.toArray());
 
             if (!isMinimize) {
                 f = -f;
@@ -1682,7 +1683,7 @@ public class BOBYQAOptimizer
                 }
             }
 
-            final double objectiveValue = computeObjectiveValue(currentBest.toArray());
+            final double objectiveValue = getObjectiveFunction().value(currentBest.toArray());
             final double f = isMinimize ? objectiveValue : -objectiveValue;
             final int numEval = getEvaluations(); // nfm + 1
             fAtInterpolationPoints.setEntry(nfm, f);
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/CMAESOptimizer.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/CMAESOptimizer.java
index 1a6bf5c04..c50498a45 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/CMAESOptimizer.java
+++ b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/CMAESOptimizer.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import org.apache.commons.math4.legacy.analysis.MultivariateFunction;
 import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
 import org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException;
 import org.apache.commons.math4.legacy.exception.OutOfRangeException;
@@ -885,14 +886,15 @@ public class CMAESOptimizer
          * @return the objective value + penalty for violated bounds.
          */
         public ValuePenaltyPair value(final double[] point) {
+            final MultivariateFunction func = CMAESOptimizer.this.getObjectiveFunction();
             double value;
-            double penalty=0.0;
+            double penalty = 0;
             if (isRepairMode) {
                 double[] repaired = repair(point);
-                value = CMAESOptimizer.this.computeObjectiveValue(repaired);
-                penalty =  penalty(point, repaired);
+                value = func.value(repaired);
+                penalty = penalty(point, repaired);
             } else {
-                value = CMAESOptimizer.this.computeObjectiveValue(point);
+                value = func.value(point);
             }
             value = isMinimize ? value : -value;
             penalty = isMinimize ? penalty : -penalty;
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/PowellOptimizer.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/PowellOptimizer.java
index b09032f99..405c70349 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/PowellOptimizer.java
+++ b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/PowellOptimizer.java
@@ -17,6 +17,7 @@
 package org.apache.commons.math4.legacy.optim.nonlinear.scalar.noderiv;
 
 import java.util.Arrays;
+import org.apache.commons.math4.legacy.analysis.MultivariateFunction;
 import org.apache.commons.math4.legacy.exception.MathUnsupportedOperationException;
 import org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException;
 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
@@ -169,6 +170,7 @@ public class PowellOptimizer
 
         final GoalType goal = getGoalType();
         final double[] guess = getStartPoint();
+        final MultivariateFunction func = getObjectiveFunction();
         final int n = guess.length;
 
         final double[][] direc = new double[n][n];
@@ -180,7 +182,7 @@ public class PowellOptimizer
             = getConvergenceChecker();
 
         double[] x = guess;
-        double fVal = computeObjectiveValue(x);
+        double fVal = func.value(x);
         double[] x1 = x.clone();
         while (true) {
             incrementIterationCount();
@@ -234,7 +236,7 @@ public class PowellOptimizer
             }
 
             x1 = x.clone();
-            fX2 = computeObjectiveValue(x2);
+            fX2 = func.value(x2);
 
             if (fX > fX2) {
                 double t = 2 * (fX + fX2 - 2 * fVal);
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/SimplexOptimizer.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/SimplexOptimizer.java
index 20d5eee8a..1916ab625 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/SimplexOptimizer.java
+++ b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/nonlinear/scalar/noderiv/SimplexOptimizer.java
@@ -174,9 +174,7 @@ public class SimplexOptimizer extends MultivariateOptimizer {
     protected PointValuePair doOptimize() {
         checkParameters();
 
-        // Indirect call to "computeObjectiveValue" in order to update the
-        // evaluations counter.
-        final MultivariateFunction evalFunc = this::computeObjectiveValue;
+        final MultivariateFunction evalFunc = getObjectiveFunction();
 
         final boolean isMinim = getGoalType() == GoalType.MINIMIZE;
         final Comparator<PointValuePair> comparator = (o1, o2) -> {
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/univariate/BrentOptimizer.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/univariate/BrentOptimizer.java
index 7ed3e5e1e..602719393 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/univariate/BrentOptimizer.java
+++ b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/univariate/BrentOptimizer.java
@@ -16,6 +16,7 @@
  */
 package org.apache.commons.math4.legacy.optim.univariate;
 
+import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
 import org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException;
 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
 import org.apache.commons.math4.legacy.optim.ConvergenceChecker;
@@ -116,6 +117,7 @@ public class BrentOptimizer extends UnivariateOptimizer {
         final double lo = getMin();
         final double mid = getStartValue();
         final double hi = getMax();
+        final UnivariateFunction func = getObjectiveFunction();
 
         // Optional additional convergence criteria.
         final ConvergenceChecker<UnivariatePointValuePair> checker
@@ -136,7 +138,7 @@ public class BrentOptimizer extends UnivariateOptimizer {
         double w = x;
         double d = 0;
         double e = 0;
-        double fx = computeObjectiveValue(x);
+        double fx = func.value(x);
         if (!isMinim) {
             fx = -fx;
         }
@@ -222,7 +224,7 @@ public class BrentOptimizer extends UnivariateOptimizer {
                     u = x + d;
                 }
 
-                double fu = computeObjectiveValue(u);
+                double fu = func.value(u);
                 if (!isMinim) {
                     fu = -fu;
                 }
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/univariate/UnivariateOptimizer.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/univariate/UnivariateOptimizer.java
index ca6110f01..1b170adfa 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/univariate/UnivariateOptimizer.java
+++ b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/optim/univariate/UnivariateOptimizer.java
@@ -105,7 +105,14 @@ public abstract class UnivariateOptimizer
                 continue;
             }
             if (data instanceof UnivariateObjectiveFunction) {
-                function = ((UnivariateObjectiveFunction) data).getObjectiveFunction();
+                final UnivariateFunction delegate = ((UnivariateObjectiveFunction) data).getObjectiveFunction();
+                function = new UnivariateFunction() {
+                        @Override
+                        public double value(double point) {
+                            incrementEvaluationCount();
+                            return delegate.value(point);
+                        }
+                    };
                 continue;
             }
             if (data instanceof GoalType) {
@@ -134,6 +141,14 @@ public abstract class UnivariateOptimizer
         return max;
     }
 
+    /**
+     * @return a wrapper that delegates to the user-supplied function,
+     * and counts the number of evaluations.
+     */
+    protected UnivariateFunction getObjectiveFunction() {
+        return function;
+    }
+
     /**
      * Computes the objective function value.
      * This method <em>must</em> be called by subclasses to enforce the
@@ -143,9 +158,11 @@ public abstract class UnivariateOptimizer
      * @return the objective function value at the specified point.
      * @throws TooManyEvaluationsException if the maximal number of
      * evaluations is exceeded.
+     *
+     * @deprecated Use {@link #getObjectiveFunction()} instead.
      */
+    @Deprecated
     protected double computeObjectiveValue(double x) {
-        super.incrementEvaluationCount();
         return function.value(x);
     }
 }
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 54a6a0d00..c93cfa424 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -96,6 +96,10 @@ Caveat:
  to support the whole codebase (it was one of the main reasons for
  creating more focused components).
 ">
+      <action dev="erans" type="update" issue="MATH-1657" due-to="François Laferrière">
+        Small refactoring of the "evaluation counter" in optimizers' base class:
+        Provide (protected) accessor (to replace method "computeObjectiveValue").
+      </action>
       <action dev="erans" type="update" issue="MATH-1654" due-to="Cyril de Catheu">
         "Array2DRowRealMatrix": Performance enhancement ("getEntry").
       </action>