1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * https://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* 19 * This is not the original file distributed by the Apache Software Foundation 20 * It has been modified by the Hipparchus project 21 */ 22 package org.hipparchus.optim.nonlinear.scalar; 23 24 import org.hipparchus.analysis.UnivariateFunction; 25 import org.hipparchus.optim.MaxEval; 26 import org.hipparchus.optim.univariate.BracketFinder; 27 import org.hipparchus.optim.univariate.BrentOptimizer; 28 import org.hipparchus.optim.univariate.SearchInterval; 29 import org.hipparchus.optim.univariate.SimpleUnivariateValueChecker; 30 import org.hipparchus.optim.univariate.UnivariateObjectiveFunction; 31 import org.hipparchus.optim.univariate.UnivariateOptimizer; 32 import org.hipparchus.optim.univariate.UnivariatePointValuePair; 33 34 /** 35 * Class for finding the minimum of the objective function along a given 36 * direction. 37 * 38 */ 39 public class LineSearch { 40 /** 41 * Value that will pass the precondition check for {@link BrentOptimizer} 42 * but will not pass the convergence check, so that the custom checker 43 * will always decide when to stop the line search. 44 */ 45 private static final double REL_TOL_UNUSED = 1e-15; 46 /** 47 * Value that will pass the precondition check for {@link BrentOptimizer} 48 * but will not pass the convergence check, so that the custom checker 49 * will always decide when to stop the line search. 50 */ 51 private static final double ABS_TOL_UNUSED = Double.MIN_VALUE; 52 /** 53 * Optimizer used for line search. 54 */ 55 private final UnivariateOptimizer lineOptimizer; 56 /** 57 * Automatic bracketing. 58 */ 59 private final BracketFinder bracket = new BracketFinder(); 60 /** 61 * Extent of the initial interval used to find an interval that 62 * brackets the optimum. 63 */ 64 private final double initialBracketingRange; 65 /** 66 * Optimizer on behalf of which the line search must be performed. 67 */ 68 private final MultivariateOptimizer mainOptimizer; 69 70 /** 71 * The {@code BrentOptimizer} default stopping criterion uses the 72 * tolerances to check the domain (point) values, not the function 73 * values. 74 * The {@code relativeTolerance} and {@code absoluteTolerance} 75 * arguments are thus passed to a {@link SimpleUnivariateValueChecker 76 * custom checker} that will use the function values. 77 * 78 * @param optimizer Optimizer on behalf of which the line search 79 * be performed. 80 * Its {@link MultivariateOptimizer#computeObjectiveValue(double[]) 81 * computeObjectiveValue} method will be called by the 82 * {@link #search(double[],double[]) search} method. 83 * @param relativeTolerance Search will stop when the function relative 84 * difference between successive iterations is below this value. 85 * @param absoluteTolerance Search will stop when the function absolute 86 * difference between successive iterations is below this value. 87 * @param initialBracketingRange Extent of the initial interval used to 88 * find an interval that brackets the optimum. 89 * If the optimized function varies a lot in the vicinity of the optimum, 90 * it may be necessary to provide a value lower than the distance between 91 * successive local minima. 92 */ 93 public LineSearch(MultivariateOptimizer optimizer, 94 double relativeTolerance, 95 double absoluteTolerance, 96 double initialBracketingRange) { 97 mainOptimizer = optimizer; 98 lineOptimizer = new BrentOptimizer(REL_TOL_UNUSED, 99 ABS_TOL_UNUSED, 100 new SimpleUnivariateValueChecker(relativeTolerance, 101 absoluteTolerance)); 102 this.initialBracketingRange = initialBracketingRange; 103 } 104 105 /** 106 * Finds the number {@code alpha} that optimizes 107 * {@code f(startPoint + alpha * direction)}. 108 * 109 * @param startPoint Starting point. 110 * @param direction Search direction. 111 * @return the optimum. 112 * @throws org.hipparchus.exception.MathIllegalStateException 113 * if the number of evaluations is exceeded. 114 */ 115 public UnivariatePointValuePair search(final double[] startPoint, 116 final double[] direction) { 117 final int n = startPoint.length; 118 final UnivariateFunction f = new UnivariateFunction() { 119 /** {@inheritDoc} */ 120 @Override 121 public double value(double alpha) { 122 final double[] x = new double[n]; 123 for (int i = 0; i < n; i++) { 124 x[i] = startPoint[i] + alpha * direction[i]; 125 } 126 return mainOptimizer.computeObjectiveValue(x); 127 } 128 }; 129 130 final GoalType goal = mainOptimizer.getGoalType(); 131 bracket.search(f, goal, 0, initialBracketingRange); 132 // Passing "MAX_VALUE" as a dummy value because it is the enclosing 133 // class that counts the number of evaluations (and will eventually 134 // generate the exception). 135 return lineOptimizer.optimize(new MaxEval(Integer.MAX_VALUE), 136 new UnivariateObjectiveFunction(f), 137 goal, 138 new SearchInterval(bracket.getLo(), 139 bracket.getHi(), 140 bracket.getMid())); 141 } 142 }