Home | History | Annotate | Download | only in solvers
      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 
     18 package org.apache.commons.math.analysis.solvers;
     19 
     20 import org.apache.commons.math.FunctionEvaluationException;
     21 import org.apache.commons.math.MathRuntimeException;
     22 import org.apache.commons.math.MaxIterationsExceededException;
     23 import org.apache.commons.math.analysis.DifferentiableUnivariateRealFunction;
     24 import org.apache.commons.math.analysis.UnivariateRealFunction;
     25 import org.apache.commons.math.exception.util.LocalizedFormats;
     26 import org.apache.commons.math.util.FastMath;
     27 
     28 /**
     29  * Implements <a href="http://mathworld.wolfram.com/NewtonsMethod.html">
     30  * Newton's Method</a> for finding zeros of real univariate functions.
     31  * <p>
     32  * The function should be continuous but not necessarily smooth.</p>
     33  *
     34  * @version $Revision: 1070725 $ $Date: 2011-02-15 02:31:12 +0100 (mar. 15 fvr. 2011) $
     35  */
     36 public class NewtonSolver extends UnivariateRealSolverImpl {
     37 
     38     /**
     39      * Construct a solver for the given function.
     40      * @param f function to solve.
     41      * @deprecated as of 2.0 the function to solve is passed as an argument
     42      * to the {@link #solve(UnivariateRealFunction, double, double)} or
     43      * {@link UnivariateRealSolverImpl#solve(UnivariateRealFunction, double, double, double)}
     44      * method.
     45      */
     46     @Deprecated
     47     public NewtonSolver(DifferentiableUnivariateRealFunction f) {
     48         super(f, 100, 1E-6);
     49     }
     50 
     51     /**
     52      * Construct a solver.
     53      * @deprecated in 2.2 (to be removed in 3.0).
     54      */
     55     @Deprecated
     56     public NewtonSolver() {
     57         super(100, 1E-6);
     58     }
     59 
     60     /** {@inheritDoc} */
     61     @Deprecated
     62     public double solve(final double min, final double max)
     63         throws MaxIterationsExceededException, FunctionEvaluationException  {
     64         return solve(f, min, max);
     65     }
     66 
     67     /** {@inheritDoc} */
     68     @Deprecated
     69     public double solve(final double min, final double max, final double startValue)
     70         throws MaxIterationsExceededException, FunctionEvaluationException  {
     71         return solve(f, min, max, startValue);
     72     }
     73 
     74     /**
     75      * Find a zero near the midpoint of <code>min</code> and <code>max</code>.
     76      *
     77      * @param f the function to solve
     78      * @param min the lower bound for the interval
     79      * @param max the upper bound for the interval
     80      * @param maxEval Maximum number of evaluations.
     81      * @return the value where the function is zero
     82      * @throws MaxIterationsExceededException if the maximum iteration count is exceeded
     83      * @throws FunctionEvaluationException if an error occurs evaluating the function or derivative
     84      * @throws IllegalArgumentException if min is not less than max
     85      */
     86     @Override
     87     public double solve(int maxEval, final UnivariateRealFunction f,
     88                         final double min, final double max)
     89         throws MaxIterationsExceededException, FunctionEvaluationException  {
     90         setMaximalIterationCount(maxEval);
     91         return solve(f, min, max);
     92     }
     93 
     94     /**
     95      * Find a zero near the midpoint of <code>min</code> and <code>max</code>.
     96      *
     97      * @param f the function to solve
     98      * @param min the lower bound for the interval
     99      * @param max the upper bound for the interval
    100      * @return the value where the function is zero
    101      * @throws MaxIterationsExceededException if the maximum iteration count is exceeded
    102      * @throws FunctionEvaluationException if an error occurs evaluating the function or derivative
    103      * @throws IllegalArgumentException if min is not less than max
    104      * @deprecated in 2.2 (to be removed in 3.0).
    105      */
    106     @Deprecated
    107     public double solve(final UnivariateRealFunction f,
    108                         final double min, final double max)
    109         throws MaxIterationsExceededException, FunctionEvaluationException  {
    110         return solve(f, min, max, UnivariateRealSolverUtils.midpoint(min, max));
    111     }
    112 
    113     /**
    114      * Find a zero near the value <code>startValue</code>.
    115      *
    116      * @param f the function to solve
    117      * @param min the lower bound for the interval (ignored).
    118      * @param max the upper bound for the interval (ignored).
    119      * @param startValue the start value to use.
    120      * @param maxEval Maximum number of evaluations.
    121      * @return the value where the function is zero
    122      * @throws MaxIterationsExceededException if the maximum iteration count is exceeded
    123      * @throws FunctionEvaluationException if an error occurs evaluating the function or derivative
    124      * @throws IllegalArgumentException if startValue is not between min and max or
    125      * if function is not a {@link DifferentiableUnivariateRealFunction} instance
    126      */
    127     @Override
    128     public double solve(int maxEval, final UnivariateRealFunction f,
    129                         final double min, final double max, final double startValue)
    130         throws MaxIterationsExceededException, FunctionEvaluationException {
    131         setMaximalIterationCount(maxEval);
    132         return solve(f, min, max, startValue);
    133     }
    134 
    135     /**
    136      * Find a zero near the value <code>startValue</code>.
    137      *
    138      * @param f the function to solve
    139      * @param min the lower bound for the interval (ignored).
    140      * @param max the upper bound for the interval (ignored).
    141      * @param startValue the start value to use.
    142      * @return the value where the function is zero
    143      * @throws MaxIterationsExceededException if the maximum iteration count is exceeded
    144      * @throws FunctionEvaluationException if an error occurs evaluating the function or derivative
    145      * @throws IllegalArgumentException if startValue is not between min and max or
    146      * if function is not a {@link DifferentiableUnivariateRealFunction} instance
    147      * @deprecated in 2.2 (to be removed in 3.0).
    148      */
    149     @Deprecated
    150     public double solve(final UnivariateRealFunction f,
    151                         final double min, final double max, final double startValue)
    152         throws MaxIterationsExceededException, FunctionEvaluationException {
    153 
    154         try {
    155 
    156             final UnivariateRealFunction derivative =
    157                 ((DifferentiableUnivariateRealFunction) f).derivative();
    158             clearResult();
    159             verifySequence(min, startValue, max);
    160 
    161             double x0 = startValue;
    162             double x1;
    163 
    164             int i = 0;
    165             while (i < maximalIterationCount) {
    166 
    167                 x1 = x0 - (f.value(x0) / derivative.value(x0));
    168                 if (FastMath.abs(x1 - x0) <= absoluteAccuracy) {
    169                     setResult(x1, i);
    170                     return x1;
    171                 }
    172 
    173                 x0 = x1;
    174                 ++i;
    175             }
    176 
    177             throw new MaxIterationsExceededException(maximalIterationCount);
    178         } catch (ClassCastException cce) {
    179             throw MathRuntimeException.createIllegalArgumentException(LocalizedFormats.FUNCTION_NOT_DIFFERENTIABLE);
    180         }
    181     }
    182 
    183 }
    184