/*
 * 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.math3.optim.nonlinear.scalar;

import org.apache.commons.math3.optim.univariate.UnivariateOptimizer;
import org.apache.commons.math3.optim.univariate.BrentOptimizer;
import org.apache.commons.math3.optim.univariate.BracketFinder;
import org.apache.commons.math3.optim.univariate.UnivariatePointValuePair;
import org.apache.commons.math3.optim.univariate.SimpleUnivariateValueChecker;
import org.apache.commons.math3.optim.univariate.SearchInterval;
import org.apache.commons.math3.optim.univariate.UnivariateObjectiveFunction;
import org.apache.commons.math3.analysis.UnivariateFunction;
import org.apache.commons.math3.optim.MaxEval;

Class for finding the minimum of the objective function along a given direction.
Since:3.3
/** * 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 BrentOptimizer but will not pass the convergence check, so that the custom checker will always decide when to stop the line search.
/** * 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 BrentOptimizer but will not pass the convergence check, so that the custom checker will always decide when to stop the line search.
/** * 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.
/** * Optimizer used for line search. */
private final UnivariateOptimizer lineOptimizer;
Automatic bracketing.
/** * Automatic bracketing. */
private final BracketFinder bracket = new BracketFinder();
Extent of the initial interval used to find an interval that brackets the optimum.
/** * 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.
/** * Optimizer on behalf of which the line search must be performed. */
private final MultivariateOptimizer mainOptimizer;
The BrentOptimizer default stopping criterion uses the tolerances to check the domain (point) values, not the function values. The relativeTolerance and absoluteTolerance arguments are thus passed to a custom checker that will use the function values.
Params:
  • optimizer – Optimizer on behalf of which the line search be performed. Its computeObjectiveValue method will be called by the search method.
  • relativeTolerance – Search will stop when the function relative difference between successive iterations is below this value.
  • absoluteTolerance – Search will stop when the function absolute difference between successive iterations is below this value.
  • 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.
/** * 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 alpha that optimizes f(startPoint + alpha * direction).
Params:
  • startPoint – Starting point.
  • direction – Search direction.
Throws:
Returns:the optimum.
/** * 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.math3.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}
/** {@inheritDoc} */
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())); } }