diff --git a/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/LineSearch.java b/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/LineSearch.java index 310af671a..7763e7788 100644 --- a/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/LineSearch.java +++ b/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/LineSearch.java @@ -54,6 +54,11 @@ public class LineSearch { * Automatic bracketing. */ private final BracketFinder bracket = new BracketFinder(); + /** + * Extent of the initial interval used to find an interval that + * brackets the optimum. + */ + private final double initialBracketingRange; /** * Optimizer on behalf of which the line search must be performed. */ @@ -70,23 +75,33 @@ 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 this class's + * computeObjectiveValue} method will be called by the * {@link #search(double[],double[]) search} method. - * @param relativeTolerance Relative threshold. - * @param absoluteTolerance Absolute threshold. + * @param relativeTolerance Search will stop when the function relative + * difference between successive iterations is smaller than this value. + * @param absoluteTolerance Search will stop when the function absolute + * difference between successive iterations is smaller than this value. + * @param initialBracketingRange Extent of the initial interval used to + * find an interval that brackets the optimum. + * If the optimized function varies a lot in the vicinity of the optimum, + * it may be necessary to provide a value lower than the distance between + * successive local minima. */ public LineSearch(MultivariateOptimizer optimizer, double relativeTolerance, - double absoluteTolerance) { + double absoluteTolerance, + double initialBracketingRange) { mainOptimizer = optimizer; lineOptimizer = new BrentOptimizer(REL_TOL_UNUSED, ABS_TOL_UNUSED, new SimpleUnivariateValueChecker(relativeTolerance, absoluteTolerance)); + this.initialBracketingRange = initialBracketingRange; } /** - * Find the minimum of the function {@code f(p + alpha * d)}. + * Finds the number {@code alpha} that optimizes + * {@code f(startPoint + alpha * direction)}. * * @param startPoint Starting point. * @param direction Search direction. @@ -109,7 +124,7 @@ public class LineSearch { }; final GoalType goal = mainOptimizer.getGoalType(); - bracket.search(f, goal, 0, 1); + bracket.search(f, goal, 0, initialBracketingRange); // Passing "MAX_VALUE" as a dummy value because it is the enclosing // class that counts the number of evaluations (and will eventually // generate the exception). diff --git a/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/gradient/NonLinearConjugateGradientOptimizer.java b/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/gradient/NonLinearConjugateGradientOptimizer.java index 3790436f1..5cdb838b3 100644 --- a/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/gradient/NonLinearConjugateGradientOptimizer.java +++ b/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/gradient/NonLinearConjugateGradientOptimizer.java @@ -86,7 +86,9 @@ public class NonLinearConjugateGradientOptimizer * search. * * @since 3.1 - * @deprecated As of v3.3, class is not used anymore. + * @deprecated As of v3.3, this class is not used anymore. + * This setting is replaced by the {@code initialBracketingRange} + * argument to the new constructors. */ @Deprecated public static class BracketingStep implements OptimizationData { @@ -125,6 +127,7 @@ public class NonLinearConjugateGradientOptimizer checker, 1e-8, 1e-8, + 1e-8, new IdentityPreconditioner()); } @@ -137,7 +140,7 @@ public class NonLinearConjugateGradientOptimizer * @param checker Convergence checker. * @param lineSearchSolver Solver to use during line search. * @deprecated as of 3.3. Please use - * {@link #NonLinearConjugateGradientOptimizer(Formula,ConvergenceChecker,double,double)} instead. + * {@link #NonLinearConjugateGradientOptimizer(Formula,ConvergenceChecker,double,double,double)} instead. */ @Deprecated public NonLinearConjugateGradientOptimizer(final Formula updateFormula, @@ -158,17 +161,23 @@ public class NonLinearConjugateGradientOptimizer * @param checker Convergence checker. * @param relativeTolerance Relative threshold for line search. * @param absoluteTolerance Absolute threshold for line search. + * @param initialBracketingRange Extent of the initial interval used to + * find an interval that brackets the optimum in order to perform the + * line search. * - * @see LineSearch#LineSearch(MultivariateOptimizer,double,double) + * @see LineSearch#LineSearch(MultivariateOptimizer,double,double,double) + * @since 3.3 */ public NonLinearConjugateGradientOptimizer(final Formula updateFormula, ConvergenceChecker checker, double relativeTolerance, - double absoluteTolerance) { + double absoluteTolerance, + double initialBracketingRange) { this(updateFormula, checker, relativeTolerance, absoluteTolerance, + initialBracketingRange, new IdentityPreconditioner()); } @@ -180,7 +189,7 @@ public class NonLinearConjugateGradientOptimizer * @param lineSearchSolver Solver to use during line search. * @param preconditioner Preconditioner. * @deprecated as of 3.3. Please use - * {@link #NonLinearConjugateGradientOptimizer(Formula,ConvergenceChecker,double,double,Preconditioner)} instead. + * {@link #NonLinearConjugateGradientOptimizer(Formula,ConvergenceChecker,double,double,double,Preconditioner)} instead. */ @Deprecated public NonLinearConjugateGradientOptimizer(final Formula updateFormula, @@ -191,6 +200,7 @@ public class NonLinearConjugateGradientOptimizer checker, lineSearchSolver.getRelativeAccuracy(), lineSearchSolver.getAbsoluteAccuracy(), + lineSearchSolver.getAbsoluteAccuracy(), preconditioner); } @@ -202,13 +212,18 @@ public class NonLinearConjugateGradientOptimizer * @param preconditioner Preconditioner. * @param relativeTolerance Relative threshold for line search. * @param absoluteTolerance Absolute threshold for line search. + * @param initialBracketingRange Extent of the initial interval used to + * find an interval that brackets the optimum in order to perform the + * line search. * - * @see LineSearch#LineSearch(MultivariateOptimizer,double,double) + * @see LineSearch#LineSearch(MultivariateOptimizer,double,double,double) + * @since 3.3 */ public NonLinearConjugateGradientOptimizer(final Formula updateFormula, ConvergenceChecker checker, double relativeTolerance, double absoluteTolerance, + double initialBracketingRange, final Preconditioner preconditioner) { super(checker); @@ -216,7 +231,8 @@ public class NonLinearConjugateGradientOptimizer this.preconditioner = preconditioner; line = new LineSearch(this, relativeTolerance, - absoluteTolerance); + absoluteTolerance, + initialBracketingRange); } /** diff --git a/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/noderiv/PowellOptimizer.java b/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/noderiv/PowellOptimizer.java index 475fe4ef7..16d5253ff 100644 --- a/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/noderiv/PowellOptimizer.java +++ b/src/main/java/org/apache/commons/math3/optim/nonlinear/scalar/noderiv/PowellOptimizer.java @@ -127,7 +127,8 @@ public class PowellOptimizer // Create the line search optimizer. line = new LineSearch(this, lineRel, - lineAbs); + lineAbs, + 1d); } /** diff --git a/src/main/java/org/apache/commons/math3/optim/univariate/BracketFinder.java b/src/main/java/org/apache/commons/math3/optim/univariate/BracketFinder.java index ef2af5267..f83031ba5 100644 --- a/src/main/java/org/apache/commons/math3/optim/univariate/BracketFinder.java +++ b/src/main/java/org/apache/commons/math3/optim/univariate/BracketFinder.java @@ -110,7 +110,10 @@ public class BracketFinder { * @throws TooManyEvaluationsException if the maximum number of evaluations * is exceeded. */ - public void search(UnivariateFunction func, GoalType goal, double xA, double xB) { + public void search(UnivariateFunction func, + GoalType goal, + double xA, + double xB) { evaluations.resetCount(); final boolean isMinim = goal == GoalType.MINIMIZE; diff --git a/src/test/java/org/apache/commons/math3/optim/nonlinear/scalar/gradient/NonLinearConjugateGradientOptimizerTest.java b/src/test/java/org/apache/commons/math3/optim/nonlinear/scalar/gradient/NonLinearConjugateGradientOptimizerTest.java index 6307c89c3..66733683d 100644 --- a/src/test/java/org/apache/commons/math3/optim/nonlinear/scalar/gradient/NonLinearConjugateGradientOptimizerTest.java +++ b/src/test/java/org/apache/commons/math3/optim/nonlinear/scalar/gradient/NonLinearConjugateGradientOptimizerTest.java @@ -105,7 +105,7 @@ public class NonLinearConjugateGradientOptimizerTest { NonLinearConjugateGradientOptimizer optimizer = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE, new SimpleValueChecker(1e-6, 1e-6), - 1e-3, 1e-3); + 1e-3, 1e-3, 1); optimizer.optimize(new MaxEval(100), problem.getObjectiveFunction(), problem.getObjectiveFunctionGradient(), @@ -122,7 +122,7 @@ public class NonLinearConjugateGradientOptimizerTest { NonLinearConjugateGradientOptimizer optimizer = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE, new SimpleValueChecker(1e-6, 1e-6), - 1e-3, 1e-3); + 1e-3, 1e-3, 1); PointValuePair optimum = optimizer.optimize(new MaxEval(100), problem.getObjectiveFunction(), @@ -145,7 +145,7 @@ public class NonLinearConjugateGradientOptimizerTest { NonLinearConjugateGradientOptimizer optimizer = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE, new SimpleValueChecker(1e-6, 1e-6), - 1e-3, 1e-3); + 1e-3, 1e-3, 1); PointValuePair optimum = optimizer.optimize(new MaxEval(100), problem.getObjectiveFunction(), @@ -171,7 +171,7 @@ public class NonLinearConjugateGradientOptimizerTest { NonLinearConjugateGradientOptimizer optimizer = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE, new SimpleValueChecker(1e-6, 1e-6), - 1e-3, 1e-3); + 1e-3, 1e-3, 1); PointValuePair optimum = optimizer.optimize(new MaxEval(100), problem.getObjectiveFunction(), @@ -193,7 +193,7 @@ public class NonLinearConjugateGradientOptimizerTest { NonLinearConjugateGradientOptimizer optimizer = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE, new SimpleValueChecker(1e-6, 1e-6), - 1e-3, 1e-3); + 1e-3, 1e-3, 1); PointValuePair optimum = optimizer.optimize(new MaxEval(100), problem.getObjectiveFunction(), @@ -235,7 +235,7 @@ public class NonLinearConjugateGradientOptimizerTest { NonLinearConjugateGradientOptimizer optimizer = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE, new SimpleValueChecker(1e-13, 1e-13), - 1e-7, 1e-7, + 1e-7, 1e-7, 1, preconditioner); PointValuePair optimum @@ -267,7 +267,7 @@ public class NonLinearConjugateGradientOptimizerTest { NonLinearConjugateGradientOptimizer optimizer = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE, new SimpleValueChecker(1e-6, 1e-6), - 1e-3, 1e-3); + 1e-3, 1e-3, 1); PointValuePair optimum = optimizer.optimize(new MaxEval(100), problem.getObjectiveFunction(), @@ -288,7 +288,7 @@ public class NonLinearConjugateGradientOptimizerTest { NonLinearConjugateGradientOptimizer optimizer = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE, new SimpleValueChecker(1e-13, 1e-13), - 1e-15, 1e-15); + 1e-15, 1e-15, 1); PointValuePair optimum1 = optimizer.optimize(new MaxEval(200), problem1.getObjectiveFunction(), @@ -333,7 +333,7 @@ public class NonLinearConjugateGradientOptimizerTest { NonLinearConjugateGradientOptimizer optimizer = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE, new SimpleValueChecker(1e-6, 1e-6), - 1e-3, 1e-3); + 1e-3, 1e-3, 1); PointValuePair optimum = optimizer.optimize(new MaxEval(100), problem.getObjectiveFunction(), @@ -356,7 +356,7 @@ public class NonLinearConjugateGradientOptimizerTest { NonLinearConjugateGradientOptimizer optimizer = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE, new SimpleValueChecker(1e-6, 1e-6), - 1e-3, 1e-3); + 1e-3, 1e-3, 1); PointValuePair optimum = optimizer.optimize(new MaxEval(100), problem.getObjectiveFunction(), @@ -377,7 +377,7 @@ public class NonLinearConjugateGradientOptimizerTest { NonLinearConjugateGradientOptimizer optimizer = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE, new SimpleValueChecker(1e-6, 1e-6), - 1e-3, 1e-3); + 1e-3, 1e-3, 1); PointValuePair optimum = optimizer.optimize(new MaxEval(100), problem.getObjectiveFunction(), @@ -400,7 +400,7 @@ public class NonLinearConjugateGradientOptimizerTest { NonLinearConjugateGradientOptimizer optimizer = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE, new SimpleValueChecker(1e-6, 1e-6), - 1e-3, 1e-3); + 1e-3, 1e-3, 1); PointValuePair optimum = optimizer.optimize(new MaxEval(100), problem.getObjectiveFunction(), @@ -422,7 +422,7 @@ public class NonLinearConjugateGradientOptimizerTest { NonLinearConjugateGradientOptimizer optimizer = new NonLinearConjugateGradientOptimizer(NonLinearConjugateGradientOptimizer.Formula.POLAK_RIBIERE, new SimpleValueChecker(1e-30, 1e-30), - 1e-15, 1e-13); + 1e-15, 1e-13, 1); PointValuePair optimum = optimizer.optimize(new MaxEval(100), problem.getObjectiveFunction(),