| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.math4.optim.nonlinear.scalar; |
| |
| import org.apache.commons.math4.analysis.UnivariateFunction; |
| import org.apache.commons.math4.optim.MaxEval; |
| import org.apache.commons.math4.optim.univariate.BracketFinder; |
| import org.apache.commons.math4.optim.univariate.BrentOptimizer; |
| import org.apache.commons.math4.optim.univariate.SearchInterval; |
| import org.apache.commons.math4.optim.univariate.SimpleUnivariateValueChecker; |
| import org.apache.commons.math4.optim.univariate.UnivariateObjectiveFunction; |
| import org.apache.commons.math4.optim.univariate.UnivariateOptimizer; |
| import org.apache.commons.math4.optim.univariate.UnivariatePointValuePair; |
| |
| /** |
| * Class for finding the minimum of the objective function along a given |
| * direction. |
| * |
| * @since 3.3 |
| */ |
| public class LineSearch { |
| /** |
| * Value that will pass the precondition check for {@link BrentOptimizer} |
| * but will not pass the convergence check, so that the custom checker |
| * will always decide when to stop the line search. |
| */ |
| private static final double REL_TOL_UNUSED = 1e-15; |
| /** |
| * Value that will pass the precondition check for {@link BrentOptimizer} |
| * but will not pass the convergence check, so that the custom checker |
| * will always decide when to stop the line search. |
| */ |
| private static final double ABS_TOL_UNUSED = Double.MIN_VALUE; |
| /** |
| * Optimizer used for line search. |
| */ |
| private final UnivariateOptimizer lineOptimizer; |
| /** |
| * 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. |
| */ |
| private final MultivariateOptimizer mainOptimizer; |
| |
| /** |
| * The {@code BrentOptimizer} default stopping criterion uses the |
| * tolerances to check the domain (point) values, not the function |
| * values. |
| * The {@code relativeTolerance} and {@code absoluteTolerance} |
| * arguments are thus passed to a {@link SimpleUnivariateValueChecker |
| * custom checker} that will use the function values. |
| * |
| * @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. |
| * @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 |
| * difference between successive iterations is below 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 initialBracketingRange) { |
| mainOptimizer = optimizer; |
| lineOptimizer = new BrentOptimizer(REL_TOL_UNUSED, |
| ABS_TOL_UNUSED, |
| new SimpleUnivariateValueChecker(relativeTolerance, |
| absoluteTolerance)); |
| this.initialBracketingRange = initialBracketingRange; |
| } |
| |
| /** |
| * Finds the number {@code alpha} that optimizes |
| * {@code f(startPoint + alpha * direction)}. |
| * |
| * @param startPoint Starting point. |
| * @param direction Search direction. |
| * @return the optimum. |
| * @throws org.apache.commons.math4.exception.TooManyEvaluationsException |
| * if the number of evaluations is exceeded. |
| */ |
| public UnivariatePointValuePair search(final double[] startPoint, |
| final double[] direction) { |
| final int n = startPoint.length; |
| final UnivariateFunction f = new UnivariateFunction() { |
| /** {@inheritDoc} */ |
| @Override |
| public double value(double alpha) { |
| final double[] x = new double[n]; |
| for (int i = 0; i < n; i++) { |
| x[i] = startPoint[i] + alpha * direction[i]; |
| } |
| final double obj = mainOptimizer.computeObjectiveValue(x); |
| return obj; |
| } |
| }; |
| |
| final GoalType goal = mainOptimizer.getGoalType(); |
| 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). |
| return lineOptimizer.optimize(new MaxEval(Integer.MAX_VALUE), |
| new UnivariateObjectiveFunction(f), |
| goal, |
| new SearchInterval(bracket.getLo(), |
| bracket.getHi(), |
| bracket.getMid())); |
| } |
| } |