SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
RootFinder.java
1/*
2 * Class: RootFinder
3 * Description: Provides methods to solve non-linear equations.
4 * Environment: Java
5 * Software: SSJ
6 * Copyright (C) 2001 Pierre L'Ecuyer and Universite de Montreal
7 * Organization: DIRO, Universite de Montreal
8 * @author
9 * @since
10 *
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 */
25package umontreal.ssj.util;
26
27import umontreal.ssj.functions.MathFunction;
28
34public class RootFinder {
35 private static final double MINVAL = 5.0e-308;
36
37 private RootFinder() {
38 }
39
52 public static double brentDekker(double a, double b, MathFunction f, double tol) {
53 final double EPS = 0.5E-15;
54 final int MAXITER = 120; // Maximum number of iterations
55 double c, d, e;
56 double fa, fb, fc;
57 final boolean DEBUG = false;
58
59 // Special case I = [b, a]
60 if (b < a) {
61 double ctemp = a;
62 a = b;
63 b = ctemp;
64 }
65
66 // Initialization
67 fa = f.evaluate(a);
68 if (Math.abs(fa) <= MINVAL)
69 return a;
70
71 fb = f.evaluate(b);
72 if (Math.abs(fb) <= MINVAL)
73 return b;
74
75 c = a;
76 fc = fa;
77 d = e = b - a;
78 tol += EPS + Num.DBL_EPSILON; // in case tol is too small
79
80 if (Math.abs(fc) < Math.abs(fb)) {
81 a = b;
82 b = c;
83 c = a;
84 fa = fb;
85 fb = fc;
86 fc = fa;
87 }
88
89 int i;
90 for (i = 0; i < MAXITER; i++) {
91 double s, p, q, r;
92 double tol1 = tol + 4.0 * Num.DBL_EPSILON * Math.abs(b);
93 double xm = 0.5 * (c - b);
94 if (DEBUG) {
95 double err = Math.abs(fa - fb);
96 System.out.printf("[a, b] = [%g, %g] fa = %g, fb = %g |fa - fb| = %.2g%n", a, b, fa, fb, err);
97 }
98
99 if (Math.abs(fb) <= MINVAL) {
100 return b;
101 }
102 if (Math.abs(xm) <= tol1) {
103 if (Math.abs(b) > MINVAL)
104 return b;
105 else
106 return 0;
107 }
108
109 if ((Math.abs(e) >= tol1) && (Math.abs(fa) > Math.abs(fb))) {
110 if (a != c) {
111 // Inverse quadratic interpolation
112 q = fa / fc;
113 r = fb / fc;
114 s = fb / fa;
115 p = s * (2.0 * xm * q * (q - r) - (b - a) * (r - 1.0));
116 q = (q - 1.0) * (r - 1.0) * (s - 1.0);
117 } else {
118 // Linear interpolation
119 s = fb / fa;
120 p = 2.0 * xm * s;
121 q = 1.0 - s;
122 }
123
124 // Adjust signs
125 if (p > 0.0)
126 q = -q;
127 p = Math.abs(p);
128
129 // Is interpolation acceptable ?
130 if (((2.0 * p) >= (3.0 * xm * q - Math.abs(tol1 * q))) || (p >= Math.abs(0.5 * e * q))) {
131 d = xm;
132 e = d;
133 } else {
134 e = d;
135 d = p / q;
136 }
137 } else {
138 // Bisection necessary
139 d = xm;
140 e = d;
141 }
142
143 a = b;
144 fa = fb;
145 if (Math.abs(d) > tol1)
146 b += d;
147 else if (xm < 0.0)
148 b -= tol1;
149 else
150 b += tol1;
151 fb = f.evaluate(b);
152 if (fb * (Math.signum(fc)) > 0.0) {
153 c = a;
154 fc = fa;
155 d = e = b - a;
156 } else {
157 a = b;
158 b = c;
159 c = a;
160 fa = fb;
161 fb = fc;
162 fc = fa;
163 }
164 }
165
166 if (i >= MAXITER)
167 System.err.println(" WARNING: root finding does not converge");
168 return b;
169 }
170
183 public static double bisection(double a, double b, MathFunction f, double tol) {
184 // Case I = [b, a]
185 if (b < a) {
186 double ctemp = a;
187 a = b;
188 b = ctemp;
189 }
190 double xa = a;
191 double xb = b;
192 double yb = f.evaluate(b);
193 // do preliminary checks on the bounds
194 if (Math.abs(yb) <= MINVAL)
195 return b;
196 double ya = f.evaluate(a);
197 if (Math.abs(ya) <= MINVAL)
198 return a;
199
200 double x = 0, y = 0;
201 final int MAXITER = 1200; // Maximum number of iterations
202 final boolean DEBUG = false;
203 tol += Num.DBL_EPSILON; // in case tol is too small
204
205 if (DEBUG)
206 System.out.println("\niter xa xb f(x)");
207
208 boolean fini = false;
209 int i = 0;
210 while (!fini) {
211 x = (xa + xb) / 2.0;
212 y = f.evaluate(x);
213 if ((Math.abs(y) <= MINVAL) || (Math.abs(xb - xa) <= tol * Math.abs(x)) || (Math.abs(xb - xa) <= MINVAL)) {
214 if (Math.abs(x) > MINVAL)
215 return x;
216 else
217 return 0;
218 }
219 if (y * ya < 0.0)
220 xb = x;
221 else
222 xa = x;
223 ++i;
224 if (DEBUG)
225 System.out.printf("%3d %18.12g %18.12g %14.4g%n", i, xa, xb, y);
226 if (i > MAXITER) {
227 System.out.println("***** bisection: SEARCH DOES NOT CONVERGE");
228 fini = true;
229 }
230 }
231 return x;
232 }
233
234}
This class provides various constants and methods to compute numerical quantities such as factorials,...
Definition Num.java:35
static final double DBL_EPSILON
Difference between 1.0 and the smallest double greater than 1.0.
Definition Num.java:90
static double brentDekker(double a, double b, MathFunction f, double tol)
Computes a root of the function in f using the Brent-Dekker method.
static double bisection(double a, double b, MathFunction f, double tol)
Computes a root of the function in f using the bisection method.
This interface should be implemented by classes which represent univariate mathematical functions.
double evaluate(double x)
Returns the value of the function evaluated at .