BrentSolver.java

  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.  * This class implements the <a href="http://mathworld.wolfram.com/BrentsMethod.html">
  20.  * Brent algorithm</a> for finding zeros of real univariate functions.
  21.  * The function should be continuous but not necessarily smooth.
  22.  * The {@code solve} method returns a zero {@code x} of the function {@code f}
  23.  * in the given interval {@code [a, b]} to within a tolerance
  24.  * {@code 2 eps abs(x) + t} where {@code eps} is the relative accuracy and
  25.  * {@code t} is the absolute accuracy.
  26.  * <p>The given interval must bracket the root.</p>
  27.  * <p>
  28.  *  The reference implementation is given in chapter 4 of
  29.  *  <blockquote>
  30.  *   <b>Algorithms for Minimization Without Derivatives</b>,
  31.  *   <em>Richard P. Brent</em>,
  32.  *   Dover, 2002
  33.  *  </blockquote>
  34.  *
  35.  * @see BaseAbstractUnivariateSolver
  36.  */
  37. public class BrentSolver extends AbstractUnivariateSolver {

  38.     /** Default absolute accuracy. */
  39.     private static final double DEFAULT_ABSOLUTE_ACCURACY = 1e-6;

  40.     /**
  41.      * Construct a solver with default absolute accuracy (1e-6).
  42.      */
  43.     public BrentSolver() {
  44.         this(DEFAULT_ABSOLUTE_ACCURACY);
  45.     }
  46.     /**
  47.      * Construct a solver.
  48.      *
  49.      * @param absoluteAccuracy Absolute accuracy.
  50.      */
  51.     public BrentSolver(double absoluteAccuracy) {
  52.         super(absoluteAccuracy);
  53.     }
  54.     /**
  55.      * Construct a solver.
  56.      *
  57.      * @param relativeAccuracy Relative accuracy.
  58.      * @param absoluteAccuracy Absolute accuracy.
  59.      */
  60.     public BrentSolver(double relativeAccuracy,
  61.                        double absoluteAccuracy) {
  62.         super(relativeAccuracy, absoluteAccuracy);
  63.     }
  64.     /**
  65.      * Construct a solver.
  66.      *
  67.      * @param relativeAccuracy Relative accuracy.
  68.      * @param absoluteAccuracy Absolute accuracy.
  69.      * @param functionValueAccuracy Function value accuracy.
  70.      *
  71.      * @see BaseAbstractUnivariateSolver#BaseAbstractUnivariateSolver(double,double,double)
  72.      */
  73.     public BrentSolver(double relativeAccuracy,
  74.                        double absoluteAccuracy,
  75.                        double functionValueAccuracy) {
  76.         super(relativeAccuracy, absoluteAccuracy, functionValueAccuracy);
  77.     }

  78.     /**
  79.      * {@inheritDoc}
  80.      */
  81.     @Override
  82.     protected double doSolve() {
  83.         final double min = getMin();
  84.         final double max = getMax();
  85.         final double initial = getStartValue();

  86.         final org.apache.commons.numbers.rootfinder.BrentSolver rf =
  87.             new org.apache.commons.numbers.rootfinder.BrentSolver(getRelativeAccuracy(),
  88.                                                                   getAbsoluteAccuracy(),
  89.                                                                   getFunctionValueAccuracy());

  90.         double root = Double.NaN;
  91.         try {
  92.             root = rf.findRoot(arg -> computeObjectiveValue(arg),
  93.                                min, initial, max);
  94.         } catch (IllegalArgumentException e) {
  95.             // Redundant calls in order to throw the expected exceptions.
  96.             verifySequence(min, initial, max);
  97.             verifyBracketing(min, max);
  98.         }

  99.         return root;
  100.     }
  101. }