View Javadoc
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 }