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: 1.15 $ $Date: 2004/07/17 21:19:39 $
28 */
29 public abstract class UnivariateRealSolverImpl implements UnivariateRealSolver,
30 Serializable {
31
32 /*** Serializable version identifier */
33 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 return (f.value(lower) * f.value(upper) < 0);
269 }
270
271 /***
272 * Returns true if the arguments form a (strictly) increasing sequence
273 *
274 * @param start first number
275 * @param mid second number
276 * @param end third number
277 * @return true if the arguments form an increasing sequence
278 */
279 protected boolean isSequence(double start, double mid, double end) {
280 return (start < mid) && (mid < end);
281 }
282
283 /***
284 * Verifies that the endpoints specify an interval,
285 * throws IllegalArgumentException if not
286 *
287 * @param lower lower endpoint
288 * @param upper upper endpoint
289 * @throws IllegalArgumentException
290 */
291 protected void verifyInterval(double lower, double upper) {
292 if (lower >= upper) {
293 throw new IllegalArgumentException
294 ("Endpoints do not specify an interval: [" + lower +
295 "," + upper + "]");
296 }
297 }
298
299 /***
300 * Verifies that <code>lower < initial < upper</code>
301 * throws IllegalArgumentException if not
302 *
303 * @param lower lower endpoint
304 * @param initial initial value
305 * @param upper upper endpoint
306 * @throws IllegalArgumentException
307 */
308 protected void verifySequence(double lower, double initial, double upper) {
309 if (!isSequence(lower, initial, upper)) {
310 throw new IllegalArgumentException
311 ("Invalid interval, initial value parameters: lower=" +
312 lower + " initial=" + initial + " upper=" + upper);
313 }
314 }
315
316 /***
317 * Verifies that the endpoints specify an interval and the function takes
318 * opposite signs at the enpoints, throws IllegalArgumentException if not
319 *
320 * @param lower lower endpoint
321 * @param upper upper endpoint
322 * @param f function
323 * @throws IllegalArgumentException
324 * @throws FunctionEvaluationException if an error occurs evaluating the
325 * function at the endpoints
326 */
327 protected void verifyBracketing(double lower, double upper,
328 UnivariateRealFunction f) throws FunctionEvaluationException {
329
330 verifyInterval(lower, upper);
331 if (!isBracketing(lower, upper, f)) {
332 throw new IllegalArgumentException
333 ("Function values at endpoints do not have different signs." +
334 " Endpoints: [" + lower + "," + upper + "]" +
335 " Values: [" + f.value(lower) + "," + f.value(upper) + "]");
336 }
337 }
338 }