1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.math.analysis;
18
19 import java.io.Serializable;
20
21 import org.apache.commons.math.FunctionEvaluationException;
22
23 /**
24 * Provide a default implementation for several functions useful to generic
25 * solvers.
26 *
27 * @version $Revision: 348888 $ $Date: 2005-11-24 23:21:25 -0700 (Thu, 24 Nov 2005) $
28 */
29 public abstract class UnivariateRealSolverImpl implements UnivariateRealSolver,
30 Serializable {
31
32 /** Serializable version identifier */
33 private static final long serialVersionUID = 1112491292565386596L;
34
35 /** Maximum absolute error. */
36 protected double absoluteAccuracy;
37
38 /** Maximum relative error. */
39 protected double relativeAccuracy;
40
41 /** Maximum error of function. */
42 protected double functionValueAccuracy;
43
44 /** Maximum number of iterations. */
45 protected int maximalIterationCount;
46
47 /** Default maximum absolute error. */
48 protected double defaultAbsoluteAccuracy;
49
50 /** Default maximum relative error. */
51 protected double defaultRelativeAccuracy;
52
53 /** Default maximum error of function. */
54 protected double defaultFunctionValueAccuracy;
55
56 /** Default maximum number of iterations. */
57 protected int defaultMaximalIterationCount;
58
59 /** Indicates where a root has been computed. */
60 protected boolean resultComputed = false;
61
62 /** The last computed root. */
63 protected double result;
64
65
66 /** The last iteration count. */
67 protected int iterationCount;
68
69 /** The function to solve. */
70 protected UnivariateRealFunction f;
71
72 /**
73 * Construct a solver with given iteration count and accuracy.
74 *
75 * @param f the function to solve.
76 * @param defaultAbsoluteAccuracy maximum absolute error
77 * @param defaultMaximalIterationCount maximum number of iterations
78 * @throws IllegalArgumentException if f is null or the
79 * defaultAbsoluteAccuracy is not valid
80 */
81 protected UnivariateRealSolverImpl(
82 UnivariateRealFunction f,
83 int defaultMaximalIterationCount,
84 double defaultAbsoluteAccuracy) {
85
86 super();
87
88 if (f == null) {
89 throw new IllegalArgumentException("function can not be null.");
90 }
91
92 this.f = f;
93 this.defaultAbsoluteAccuracy = defaultAbsoluteAccuracy;
94 this.defaultRelativeAccuracy = 1E-14;
95 this.defaultFunctionValueAccuracy = 1E-15;
96 this.absoluteAccuracy = defaultAbsoluteAccuracy;
97 this.relativeAccuracy = defaultRelativeAccuracy;
98 this.functionValueAccuracy = defaultFunctionValueAccuracy;
99 this.defaultMaximalIterationCount = defaultMaximalIterationCount;
100 this.maximalIterationCount = defaultMaximalIterationCount;
101 }
102
103 /**
104 * Access the last computed root.
105 *
106 * @return the last computed root
107 * @throws IllegalStateException if no root has been computed
108 */
109 public double getResult() {
110 if (resultComputed) {
111 return result;
112 } else {
113 throw new IllegalStateException("No result available");
114 }
115 }
116
117 /**
118 * Access the last iteration count.
119 *
120 * @return the last iteration count
121 * @throws IllegalStateException if no root has been computed
122 *
123 */
124 public int getIterationCount() {
125 if (resultComputed) {
126 return iterationCount;
127 } else {
128 throw new IllegalStateException("No result available");
129 }
130 }
131
132 /**
133 * Convenience function for implementations.
134 *
135 * @param result the result to set
136 * @param iterationCount the iteration count to set
137 */
138 protected final void setResult(double result, int iterationCount) {
139 this.result = result;
140 this.iterationCount = iterationCount;
141 this.resultComputed = true;
142 }
143
144 /**
145 * Convenience function for implementations.
146 */
147 protected final void clearResult() {
148 this.resultComputed = false;
149 }
150
151 /**
152 * Set the absolute accuracy.
153 *
154 * @param accuracy the accuracy.
155 * @throws IllegalArgumentException if the accuracy can't be achieved by
156 * the solver or is otherwise deemed unreasonable.
157 */
158 public void setAbsoluteAccuracy(double accuracy) {
159 absoluteAccuracy = accuracy;
160 }
161
162 /**
163 * Get the actual absolute accuracy.
164 *
165 * @return the accuracy
166 */
167 public double getAbsoluteAccuracy() {
168 return absoluteAccuracy;
169 }
170
171 /**
172 * Reset the absolute accuracy to the default.
173 */
174 public void resetAbsoluteAccuracy() {
175 absoluteAccuracy = defaultAbsoluteAccuracy;
176 }
177
178 /**
179 * Set the upper limit for the number of iterations.
180 *
181 * @param count maximum number of iterations
182 */
183 public void setMaximalIterationCount(int count) {
184 maximalIterationCount = count;
185 }
186
187 /**
188 * Get the upper limit for the number of iterations.
189 *
190 * @return the actual upper limit
191 */
192 public int getMaximalIterationCount() {
193 return maximalIterationCount;
194 }
195
196 /**
197 * Reset the upper limit for the number of iterations to the default.
198 */
199 public void resetMaximalIterationCount() {
200 maximalIterationCount = defaultMaximalIterationCount;
201 }
202
203 /**
204 * Set the relative accuracy.
205 *
206 * @param accuracy the relative accuracy.
207 * @throws IllegalArgumentException if the accuracy can't be achieved by
208 * the solver or is otherwise deemed unreasonable.
209 */
210 public void setRelativeAccuracy(double accuracy) {
211 relativeAccuracy = accuracy;
212 }
213
214 /**
215 * Get the actual relative accuracy.
216 * @return the accuracy
217 */
218 public double getRelativeAccuracy() {
219 return relativeAccuracy;
220 }
221
222 /**
223 * Reset the relative accuracy to the default.
224 */
225 public void resetRelativeAccuracy() {
226 relativeAccuracy = defaultRelativeAccuracy;
227 }
228
229 /**
230 * Set the function value accuracy.
231 *
232 * @param accuracy the accuracy.
233 * @throws IllegalArgumentException if the accuracy can't be achieved by
234 * the solver or is otherwise deemed unreasonable.
235 */
236 public void setFunctionValueAccuracy(double accuracy) {
237 functionValueAccuracy = accuracy;
238 }
239
240 /**
241 * Get the actual function value accuracy.
242 * @return the accuracy
243 */
244 public double getFunctionValueAccuracy() {
245 return functionValueAccuracy;
246 }
247
248 /**
249 * Reset the actual function accuracy to the default.
250 */
251 public void resetFunctionValueAccuracy() {
252 functionValueAccuracy = defaultFunctionValueAccuracy;
253 }
254
255
256 /**
257 * Returns true iff the function takes opposite signs at the endpoints.
258 *
259 * @param lower the lower endpoint
260 * @param upper the upper endpoint
261 * @param f the function
262 * @return true if f(lower) * f(upper) < 0
263 * @throws FunctionEvaluationException if an error occurs evaluating the
264 * function at the endpoints
265 */
266 protected boolean isBracketing(double lower, double upper,
267 UnivariateRealFunction f) throws FunctionEvaluationException {
268 double f1 = f.value(lower);
269 double f2 = f.value(upper);
270 return ((f1 > 0 && f2 < 0) || (f1 < 0 && f2 > 0));
271 }
272
273 /**
274 * Returns true if the arguments form a (strictly) increasing sequence
275 *
276 * @param start first number
277 * @param mid second number
278 * @param end third number
279 * @return true if the arguments form an increasing sequence
280 */
281 protected boolean isSequence(double start, double mid, double end) {
282 return (start < mid) && (mid < end);
283 }
284
285 /**
286 * Verifies that the endpoints specify an interval,
287 * throws IllegalArgumentException if not
288 *
289 * @param lower lower endpoint
290 * @param upper upper endpoint
291 * @throws IllegalArgumentException
292 */
293 protected void verifyInterval(double lower, double upper) {
294 if (lower >= upper) {
295 throw new IllegalArgumentException
296 ("Endpoints do not specify an interval: [" + lower +
297 "," + upper + "]");
298 }
299 }
300
301 /**
302 * Verifies that <code>lower < initial < upper</code>
303 * throws IllegalArgumentException if not
304 *
305 * @param lower lower endpoint
306 * @param initial initial value
307 * @param upper upper endpoint
308 * @throws IllegalArgumentException
309 */
310 protected void verifySequence(double lower, double initial, double upper) {
311 if (!isSequence(lower, initial, upper)) {
312 throw new IllegalArgumentException
313 ("Invalid interval, initial value parameters: lower=" +
314 lower + " initial=" + initial + " upper=" + upper);
315 }
316 }
317
318 /**
319 * Verifies that the endpoints specify an interval and the function takes
320 * opposite signs at the enpoints, throws IllegalArgumentException if not
321 *
322 * @param lower lower endpoint
323 * @param upper upper endpoint
324 * @param f function
325 * @throws IllegalArgumentException
326 * @throws FunctionEvaluationException if an error occurs evaluating the
327 * function at the endpoints
328 */
329 protected void verifyBracketing(double lower, double upper,
330 UnivariateRealFunction f) throws FunctionEvaluationException {
331
332 verifyInterval(lower, upper);
333 if (!isBracketing(lower, upper, f)) {
334 throw new IllegalArgumentException
335 ("Function values at endpoints do not have different signs." +
336 " Endpoints: [" + lower + "," + upper + "]" +
337 " Values: [" + f.value(lower) + "," + f.value(upper) + "]");
338 }
339 }
340 }