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 <gillese...@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>