blob: ba88c705fe72df48630a8c77af17f72db05f6f44 [file] [log] [blame]
<?xml version="1.0"?>
<!--
Copyright 2003-2005 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?xml-stylesheet type="text/xsl" href="./xdoc.xsl"?>
<!-- $Revision$ $Date$ -->
<document url="analysis.html">
<properties>
<title>The Commons Math User Guide - Numerical Analysis</title>
</properties>
<body>
<section name="4 Numerical Analysis">
<subsection name="4.1 Overview" href="overview">
<p>
The analysis package provides numerical root-finding and interpolation
implementations for real-valued functions of one real variable.
</p>
<p>
Possible future additions may include numerical differentation,
integration and optimization.
</p>
</subsection>
<subsection name="4.2 Root-finding" href="rootfinding">
<p>
A <a href="../apidocs/org/apache/commons/math/analysis/UnivariateRealSolver.html">
org.apache.commons.math.analysis.UnivariateRealSolver.</a>
provides the means to find roots of univariate real-valued functions.
A root is the value where the function takes the value 0. Commons-Math
includes implementations of the following root-finding algorithms: <ul>
<li><a href="../apidocs/org/apache/commons/math/analysis/BisectionSolver.html">
Bisection</a></li>
<li><a href="../apidocs/org/apache/commons/math/analysis/BrentSolver.html">
Brent-Dekker</a></li>
<li><a href="../apidocs/org/apache/commons/math/analysis/NewtonSolver.html">
Newton's Method</a></li>
<li><a href="../apidocs/org/apache/commons/math/analysis/SecantSolver.html">
Secant Method</a></li>
</ul>
</p>
<p>
There are numerous non-obvious traps and pitfalls in root finding.
First, the usual disclaimers due to the way real world computers
calculate values apply. If the computation of the function provides
numerical instabilities, for example due to bit cancellation, the root
finding algorithms may behave badly and fail to converge or even
return bogus values. There will not necessarily be an indication that
the computed root is way off the true value. Secondly, the root finding
problem itself may be inherently ill-conditioned. There is a
"domain of indeterminacy", the interval for which the function has
near zero absolute values around the true root, which may be large.
Even worse, small problems like roundoff error may cause the function
value to "numerically oscillate" between negative and positive values.
This may again result in roots way off the true value, without
indication. There is not much a generic algorithm can do if
ill-conditioned problems are met. A way around this is to transform
the problem in order to get a better conditioned function. Proper
selection of a root-finding algorithm and its configuration parameters
requires knowledge of the analytical properties of the function under
analysis and numerical analysis techniques. Users are encouraged
to consult a numerical analysis text (or a numerical analyst) when
selecting and configuring a solver.
</p>
<p>
In order to use the root-finding features, first a solver object must
be created. It is encouraged that all solver object creation occurs
via the <code>org.apache.commons.math.analysis.UnivariateRealSolverFactory</code>
class. <code>UnivariateRealSolverFactory</code> is a simple factory
used to create all of the solver objects supported by Commons-Math.
The typical usage of <code>UnivariateRealSolverFactory</code>
to create a solver object would be:</p>
<source>UnivariateRealFunction function = // some user defined function object
UnivariateRealSolverFactory factory = UnivariateRealSolverFactory.newInstance();
UnivariateRealSolver solver = factory.newDefaultSolver(function);</source>
<p>
The solvers that can be instantiated via the
<code>UnivariateRealSolverFactory</code> are detailed below:
<table>
<tr><th>Solver</th><th>Factory Method</th><th>Notes on Use</th></tr>
<tr><td>Bisection</td><td>newBisectionSolver</td><td><div>Root must be bracketted.</div><div>Linear, guaranteed convergence</div></td></tr>
<tr><td>Brent</td><td>newBrentSolver</td><td><div>Root must be bracketted.</div><div>Super-linear, guaranteed convergence</div></td></tr>
<tr><td>Newton</td><td>newNewtonSolver</td><td><div>Uses single value for initialization.</div><div>Super-linear, non-guaranteed convergence</div><div>Function must be differentiable</div></td></tr>
<tr><td>Secant</td><td>newSecantSolver</td><td><div>Root must be bracketted.</div><div>Super-linear, non-guaranteed convergence</div></td></tr>
</table>
</p>
<p>
Using a solver object, roots of functions are easily found using the <code>solve</code>
methods. For a function <code>f</code>, and two domain values, <code>min</code> and
<code>max</code>, <code>solve</code> computes a value <code>c</code> such that:
<ul>
<li><code>f(c) = 0.0</code> (see "function value accuracy")</li>
<li><code>min &lt;= c &lt;= max</code></li>
</ul>
</p>
<p>
Typical usage:
</p>
<source>UnivariateRealFunction function = // some user defined function object
UnivariateRealSolverFactory factory = UnivariateRealSolverFactory.newInstance();
UnivariateRealSolver solver = factory.newBisectionSolver(function);
double c = solver.solve(1.0, 5.0);</source>
<p>
The <code>BrentSolve</code> uses the Brent-Dekker algorithm which is
fast and robust. This algorithm is recommended for most users and the
<code>BrentSolver</code> is the default solver provided by the
<code>UnivariateRealSolverFactory</code>. If there are multiple roots
in the interval, or there is a large domain of indeterminacy, the
algorithm will converge to a random root in the interval without
indication that there are problems. Interestingly, the examined text
book implementations all disagree in details of the convergence
criteria. Also each implementation had problems for one of the test
cases, so the expressions had to be fudged further. Don't expect to
get exactly the same root values as for other implementations of this
algorithm.
</p>
<p>
The <code>SecantSolver</code> uses a variant of the well known secant
algorithm. It may be a bit faster than the Brent solver for a class
of well-behaved functions.
</p>
<p>
The <code>BisectionSolver</code> is included for completeness and for
establishing a fall back in cases of emergency. The algorithm is
simple, most likely bug free and guaranteed to converge even in very
adverse circumstances which might cause other algorithms to
malfunction. The drawback is of course that it is also guaranteed
to be slow.
</p>
<p>
The <code>UnivariateRealSolver</code> interface exposes many
properties to control the convergence of a solver. For the most part,
these properties should not have to change from their default values
to produce good results. In the circumstances where changing these
property values is needed, it is easily done through getter and setter
methods on <code>UnivariateRealSolver</code>:
<table>
<tr><th>Property</th><th>Methods</th><th>Purpose</th></tr>
<tr>
<td>Absolute accuracy</td>
<td>
<div>getAbsoluteAccuracy</div>
<div>resetAbsoluteAccuracy</div>
<div>setAbsoluteAccuracy</div>
</td>
<td>
The Absolute Accuracy is (estimated) maximal difference between
the computed root and the true root of the function. This is
what most people think of as "accuracy" intuitively. The default
value is choosen as a sane value for most real world problems,
for roots in the range from -100 to +100. For accurate
computation of roots near zero, in the range form -0.0001 to
+0.0001, the value may be decreased. For computing roots
much larger in absolute value than 100, the default absolute
accuracy may never be reached because the given relative
accuracy is reached first.
</td>
</tr>
<tr>
<td>Relative accuracy</td>
<td>
<div>getRelativeAccuracy</div>
<div>resetRelativeAccuracy</div>
<div>setRelativeAccuracy</div>
</td>
<td>
The Relative Accuracy is the maximal difference between the
computed root and the true root, divided by the maximum of the
absolute values of the numbers. This accuracy measurement is
better suited for numerical calculations with computers, due to
the way floating point numbers are represented. The default
value is choosen so that algorithms will get a result even for
roots with large absolute values, even while it may be
impossible to reach the given absolute accuracy.
</td>
</tr>
<tr>
<td>Function value accuracy</td>
<td>
<div>getFunctionValueAccuracy</div>
<div>resetFunctionValueAccuracy</div>
<div>setFunctionValueAccuracy</div>
</td>
<td>
This value is used by some algorithms in order to prevent
numerical instabilities. If the function is evaluated to an
absolute value smaller than the Function Value Accuracy, the
algorithms assume they hit a root and return the value
immediately. The default value is a "very small value". If the
goal is to get a near zero function value rather than an accurate
root, computation may be sped up by setting this value
appropriately.
</td>
</tr>
<tr>
<td>Maximum iteration count</td>
<td>
<div>getMaximumIterationCount</div>
<div>resetMaximumIterationCount</div>
<div>setMaximumIterationCount</div>
</td>
<td>
This is the maximal number of iterations the algorithm will try.
If this number is exceeded, non-convergence is assumed and a
<code>ConvergenceException</code> exception is thrown. The
default value is 100, which should be plenty, given that a
bisection algorithm can't get any more accurate after 52
iterations because of the number of mantissa bits in a double
precision floating point number. If a number of ill-conditioned
problems is to be solved, this number can be decreased in order
to avoid wasting time.
</td>
</tr>
</table>
</p>
</subsection>
<subsection name="4.3 Interpolation" href="interpolation">
<p>
A <a href="../apidocs/org/apache/commons/math/analysis/UnivariateRealInterpolator.html">
org.apache.commons.math.analysis.UnivariateRealInterpolator</a>
is used to find a univariate real-valued function <code>f</code> which
for a given set of ordered pairs
(<code>x<sub>i</sub></code>,<code>y<sub>i</sub></code>) yields
<code>f(x<sub>i</sub>)=y<sub>i</sub></code> to the best accuracy possible.
Currently, only an interpolator for generating natural cubic splines is available. There is
no interpolator factory, mainly because the interpolation algorithm is more determined
by the kind of the interpolated function rather than the set of points to interpolate.
There aren't currently any accuracy controls either, as interpolation
accuracy is in general determined by the algorithm.
</p>
<p>Typical usage:</p>
<source>double x[]={ 0.0, 1.0, 2.0 };
double y[]={ 1.0, -1.0, 2.0);
UnivariateRealInterpolator interpolator = SplineInterpolator();
UnivariateRealFunction function = interpolator.interpolate();
double x=0.5;
double y=function.evaluate(x);
System.out println("f("+x+")="+y);</source>
<p>
A natural cubic spline is a function consisting of a polynominal of
third degree for each subinterval determined by the x-coordinates of the
interpolated points. A function interpolating <code>N</code>
value pairs consists of <code>N-1</code> polynominals. The function
is continuous, smooth and can be differentiated twice. The second
derivative is continuous but not smooth. The x values passed to the
interpolator must be ordered in ascending order. It is not valid to
evaluate the function for values outside the range
<code>x<sub>0</sub></code>..<code>x<sub>N</sub></code>.
</p>
</subsection>
</section>
</body>
</document>