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 * http://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 package org.apache.commons.math4.legacy.analysis.solvers; 18 19 20 /** 21 * This class implements the <a href="http://mathworld.wolfram.com/BrentsMethod.html"> 22 * Brent algorithm</a> for finding zeros of real univariate functions. 23 * The function should be continuous but not necessarily smooth. 24 * The {@code solve} method returns a zero {@code x} of the function {@code f} 25 * in the given interval {@code [a, b]} to within a tolerance 26 * {@code 2 eps abs(x) + t} where {@code eps} is the relative accuracy and 27 * {@code t} is the absolute accuracy. 28 * <p>The given interval must bracket the root.</p> 29 * <p> 30 * The reference implementation is given in chapter 4 of 31 * <blockquote> 32 * <b>Algorithms for Minimization Without Derivatives</b>, 33 * <em>Richard P. Brent</em>, 34 * Dover, 2002 35 * </blockquote> 36 * 37 * @see BaseAbstractUnivariateSolver 38 */ 39 public class BrentSolver extends AbstractUnivariateSolver { 40 41 /** Default absolute accuracy. */ 42 private static final double DEFAULT_ABSOLUTE_ACCURACY = 1e-6; 43 44 /** 45 * Construct a solver with default absolute accuracy (1e-6). 46 */ 47 public BrentSolver() { 48 this(DEFAULT_ABSOLUTE_ACCURACY); 49 } 50 /** 51 * Construct a solver. 52 * 53 * @param absoluteAccuracy Absolute accuracy. 54 */ 55 public BrentSolver(double absoluteAccuracy) { 56 super(absoluteAccuracy); 57 } 58 /** 59 * Construct a solver. 60 * 61 * @param relativeAccuracy Relative accuracy. 62 * @param absoluteAccuracy Absolute accuracy. 63 */ 64 public BrentSolver(double relativeAccuracy, 65 double absoluteAccuracy) { 66 super(relativeAccuracy, absoluteAccuracy); 67 } 68 /** 69 * Construct a solver. 70 * 71 * @param relativeAccuracy Relative accuracy. 72 * @param absoluteAccuracy Absolute accuracy. 73 * @param functionValueAccuracy Function value accuracy. 74 * 75 * @see BaseAbstractUnivariateSolver#BaseAbstractUnivariateSolver(double,double,double) 76 */ 77 public BrentSolver(double relativeAccuracy, 78 double absoluteAccuracy, 79 double functionValueAccuracy) { 80 super(relativeAccuracy, absoluteAccuracy, functionValueAccuracy); 81 } 82 83 /** 84 * {@inheritDoc} 85 */ 86 @Override 87 protected double doSolve() { 88 final double min = getMin(); 89 final double max = getMax(); 90 final double initial = getStartValue(); 91 92 final org.apache.commons.numbers.rootfinder.BrentSolver rf = 93 new org.apache.commons.numbers.rootfinder.BrentSolver(getRelativeAccuracy(), 94 getAbsoluteAccuracy(), 95 getFunctionValueAccuracy()); 96 97 double root = Double.NaN; 98 try { 99 root = rf.findRoot(arg -> computeObjectiveValue(arg), 100 min, initial, max); 101 } catch (IllegalArgumentException e) { 102 // Redundant calls in order to throw the expected exceptions. 103 verifySequence(min, initial, max); 104 verifyBracketing(min, max); 105 } 106 107 return root; 108 } 109 }