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.math.analysis;
18
19 import org.apache.commons.math.FunctionEvaluationException;
20 import org.apache.commons.math.MaxIterationsExceededException;
21
22 /**
23 * Implements the <a href="http://mathworld.wolfram.com/Bisection.html">
24 * bisection algorithm</a> for finding zeros of univariate real functions.
25 * <p>
26 * The function should be continuous but not necessarily smooth.</p>
27 *
28 * @version $Revision: 615734 $ $Date: 2008-01-27 23:10:03 -0700 (Sun, 27 Jan 2008) $
29 */
30 public class BisectionSolver extends UnivariateRealSolverImpl {
31
32 /** Serializable version identifier */
33 private static final long serialVersionUID = 4963578633786538912L;
34
35 /**
36 * Construct a solver for the given function.
37 *
38 * @param f function to solve.
39 */
40 public BisectionSolver(UnivariateRealFunction f) {
41 super(f, 100, 1E-6);
42 }
43
44 /**
45 * Find a zero in the given interval.
46 *
47 * @param min the lower bound for the interval.
48 * @param max the upper bound for the interval.
49 * @param initial the start value to use (ignored).
50 * @return the value where the function is zero
51 * @throws MaxIterationsExceededException the maximum iteration count is exceeded
52 * @throws FunctionEvaluationException if an error occurs evaluating
53 * the function
54 * @throws IllegalArgumentException if min is not less than max
55 */
56 public double solve(double min, double max, double initial)
57 throws MaxIterationsExceededException, FunctionEvaluationException {
58
59 return solve(min, max);
60 }
61
62 /**
63 * Find a zero root in the given interval.
64 *
65 * @param min the lower bound for the interval
66 * @param max the upper bound for the interval
67 * @return the value where the function is zero
68 * @throws MaxIterationsExceededException if the maximum iteration count is exceeded.
69 * @throws FunctionEvaluationException if an error occurs evaluating the
70 * function
71 * @throws IllegalArgumentException if min is not less than max
72 */
73 public double solve(double min, double max) throws MaxIterationsExceededException,
74 FunctionEvaluationException {
75
76 clearResult();
77 verifyInterval(min,max);
78 double m;
79 double fm;
80 double fmin;
81
82 int i = 0;
83 while (i < maximalIterationCount) {
84 m = UnivariateRealSolverUtils.midpoint(min, max);
85 fmin = f.value(min);
86 fm = f.value(m);
87
88 if (fm * fmin > 0.0) {
89 // max and m bracket the root.
90 min = m;
91 } else {
92 // min and m bracket the root.
93 max = m;
94 }
95
96 if (Math.abs(max - min) <= absoluteAccuracy) {
97 m = UnivariateRealSolverUtils.midpoint(min, max);
98 setResult(m, i);
99 return m;
100 }
101 ++i;
102 }
103
104 throw new MaxIterationsExceededException(maximalIterationCount);
105 }
106 }