001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.math4.legacy.analysis.solvers; 018 019 020/** 021 * This class implements the <a href="http://mathworld.wolfram.com/BrentsMethod.html"> 022 * Brent algorithm</a> for finding zeros of real univariate functions. 023 * The function should be continuous but not necessarily smooth. 024 * The {@code solve} method returns a zero {@code x} of the function {@code f} 025 * in the given interval {@code [a, b]} to within a tolerance 026 * {@code 2 eps abs(x) + t} where {@code eps} is the relative accuracy and 027 * {@code t} is the absolute accuracy. 028 * <p>The given interval must bracket the root.</p> 029 * <p> 030 * The reference implementation is given in chapter 4 of 031 * <blockquote> 032 * <b>Algorithms for Minimization Without Derivatives</b>, 033 * <em>Richard P. Brent</em>, 034 * Dover, 2002 035 * </blockquote> 036 * 037 * @see BaseAbstractUnivariateSolver 038 */ 039public class BrentSolver extends AbstractUnivariateSolver { 040 041 /** Default absolute accuracy. */ 042 private static final double DEFAULT_ABSOLUTE_ACCURACY = 1e-6; 043 044 /** 045 * Construct a solver with default absolute accuracy (1e-6). 046 */ 047 public BrentSolver() { 048 this(DEFAULT_ABSOLUTE_ACCURACY); 049 } 050 /** 051 * Construct a solver. 052 * 053 * @param absoluteAccuracy Absolute accuracy. 054 */ 055 public BrentSolver(double absoluteAccuracy) { 056 super(absoluteAccuracy); 057 } 058 /** 059 * Construct a solver. 060 * 061 * @param relativeAccuracy Relative accuracy. 062 * @param absoluteAccuracy Absolute accuracy. 063 */ 064 public BrentSolver(double relativeAccuracy, 065 double absoluteAccuracy) { 066 super(relativeAccuracy, absoluteAccuracy); 067 } 068 /** 069 * Construct a solver. 070 * 071 * @param relativeAccuracy Relative accuracy. 072 * @param absoluteAccuracy Absolute accuracy. 073 * @param functionValueAccuracy Function value accuracy. 074 * 075 * @see BaseAbstractUnivariateSolver#BaseAbstractUnivariateSolver(double,double,double) 076 */ 077 public BrentSolver(double relativeAccuracy, 078 double absoluteAccuracy, 079 double functionValueAccuracy) { 080 super(relativeAccuracy, absoluteAccuracy, functionValueAccuracy); 081 } 082 083 /** 084 * {@inheritDoc} 085 */ 086 @Override 087 protected double doSolve() { 088 final double min = getMin(); 089 final double max = getMax(); 090 final double initial = getStartValue(); 091 092 final org.apache.commons.numbers.rootfinder.BrentSolver rf = 093 new org.apache.commons.numbers.rootfinder.BrentSolver(getRelativeAccuracy(), 094 getAbsoluteAccuracy(), 095 getFunctionValueAccuracy()); 096 097 double root = Double.NaN; 098 try { 099 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}