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
9
* http://www.apache.org/licenses/LICENSE-2.0
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.
18
package org.apache.commons.math.analysis;
20
import java.io.Serializable;
22
import org.apache.commons.math.FunctionEvaluationException;
25
* Provide a default implementation for several functions useful to generic
28
* @version $Revision: 480440 $ $Date: 2006-11-29 00:14:12 -0700 (Wed, 29 Nov 2006) $
30
public abstract class UnivariateRealSolverImpl implements UnivariateRealSolver,
33
/** Serializable version identifier */
34
private static final long serialVersionUID = 1112491292565386596L;
36
/** Maximum absolute error. */
37
protected double absoluteAccuracy;
39
/** Maximum relative error. */
40
protected double relativeAccuracy;
42
/** Maximum error of function. */
43
protected double functionValueAccuracy;
45
/** Maximum number of iterations. */
46
protected int maximalIterationCount;
48
/** Default maximum absolute error. */
49
protected double defaultAbsoluteAccuracy;
51
/** Default maximum relative error. */
52
protected double defaultRelativeAccuracy;
54
/** Default maximum error of function. */
55
protected double defaultFunctionValueAccuracy;
57
/** Default maximum number of iterations. */
58
protected int defaultMaximalIterationCount;
60
/** Indicates where a root has been computed. */
61
protected boolean resultComputed = false;
63
/** The last computed root. */
64
protected double result;
66
// Mainly for test framework.
67
/** The last iteration count. */
68
protected int iterationCount;
70
/** The function to solve. */
71
protected UnivariateRealFunction f;
74
* Construct a solver with given iteration count and accuracy.
76
* @param f the function to solve.
77
* @param defaultAbsoluteAccuracy maximum absolute error
78
* @param defaultMaximalIterationCount maximum number of iterations
79
* @throws IllegalArgumentException if f is null or the
80
* defaultAbsoluteAccuracy is not valid
82
protected UnivariateRealSolverImpl(
83
UnivariateRealFunction f,
84
int defaultMaximalIterationCount,
85
double defaultAbsoluteAccuracy) {
90
throw new IllegalArgumentException("function can not be null.");
94
this.defaultAbsoluteAccuracy = defaultAbsoluteAccuracy;
95
this.defaultRelativeAccuracy = 1E-14;
96
this.defaultFunctionValueAccuracy = 1E-15;
97
this.absoluteAccuracy = defaultAbsoluteAccuracy;
98
this.relativeAccuracy = defaultRelativeAccuracy;
99
this.functionValueAccuracy = defaultFunctionValueAccuracy;
100
this.defaultMaximalIterationCount = defaultMaximalIterationCount;
101
this.maximalIterationCount = defaultMaximalIterationCount;
105
* Access the last computed root.
107
* @return the last computed root
108
* @throws IllegalStateException if no root has been computed
110
public double getResult() {
111
if (resultComputed) {
114
throw new IllegalStateException("No result available");
119
* Access the last iteration count.
121
* @return the last iteration count
122
* @throws IllegalStateException if no root has been computed
125
public int getIterationCount() {
126
if (resultComputed) {
127
return iterationCount;
129
throw new IllegalStateException("No result available");
134
* Convenience function for implementations.
136
* @param result the result to set
137
* @param iterationCount the iteration count to set
139
protected final void setResult(double result, int iterationCount) {
140
this.result = result;
141
this.iterationCount = iterationCount;
142
this.resultComputed = true;
146
* Convenience function for implementations.
148
protected final void clearResult() {
149
this.resultComputed = false;
153
* Set the absolute accuracy.
155
* @param accuracy the accuracy.
156
* @throws IllegalArgumentException if the accuracy can't be achieved by
157
* the solver or is otherwise deemed unreasonable.
159
public void setAbsoluteAccuracy(double accuracy) {
160
absoluteAccuracy = accuracy;
164
* Get the actual absolute accuracy.
166
* @return the accuracy
168
public double getAbsoluteAccuracy() {
169
return absoluteAccuracy;
173
* Reset the absolute accuracy to the default.
175
public void resetAbsoluteAccuracy() {
176
absoluteAccuracy = defaultAbsoluteAccuracy;
180
* Set the upper limit for the number of iterations.
182
* @param count maximum number of iterations
184
public void setMaximalIterationCount(int count) {
185
maximalIterationCount = count;
189
* Get the upper limit for the number of iterations.
191
* @return the actual upper limit
193
public int getMaximalIterationCount() {
194
return maximalIterationCount;
198
* Reset the upper limit for the number of iterations to the default.
200
public void resetMaximalIterationCount() {
201
maximalIterationCount = defaultMaximalIterationCount;
205
* Set the relative accuracy.
207
* @param accuracy the relative accuracy.
208
* @throws IllegalArgumentException if the accuracy can't be achieved by
209
* the solver or is otherwise deemed unreasonable.
211
public void setRelativeAccuracy(double accuracy) {
212
relativeAccuracy = accuracy;
216
* Get the actual relative accuracy.
217
* @return the accuracy
219
public double getRelativeAccuracy() {
220
return relativeAccuracy;
224
* Reset the relative accuracy to the default.
226
public void resetRelativeAccuracy() {
227
relativeAccuracy = defaultRelativeAccuracy;
231
* Set the function value accuracy.
233
* @param accuracy the accuracy.
234
* @throws IllegalArgumentException if the accuracy can't be achieved by
235
* the solver or is otherwise deemed unreasonable.
237
public void setFunctionValueAccuracy(double accuracy) {
238
functionValueAccuracy = accuracy;
242
* Get the actual function value accuracy.
243
* @return the accuracy
245
public double getFunctionValueAccuracy() {
246
return functionValueAccuracy;
250
* Reset the actual function accuracy to the default.
252
public void resetFunctionValueAccuracy() {
253
functionValueAccuracy = defaultFunctionValueAccuracy;
258
* Returns true iff the function takes opposite signs at the endpoints.
260
* @param lower the lower endpoint
261
* @param upper the upper endpoint
262
* @param f the function
263
* @return true if f(lower) * f(upper) < 0
264
* @throws FunctionEvaluationException if an error occurs evaluating the
265
* function at the endpoints
267
protected boolean isBracketing(double lower, double upper,
268
UnivariateRealFunction f) throws FunctionEvaluationException {
269
double f1 = f.value(lower);
270
double f2 = f.value(upper);
271
return ((f1 > 0 && f2 < 0) || (f1 < 0 && f2 > 0));
275
* Returns true if the arguments form a (strictly) increasing sequence
277
* @param start first number
278
* @param mid second number
279
* @param end third number
280
* @return true if the arguments form an increasing sequence
282
protected boolean isSequence(double start, double mid, double end) {
283
return (start < mid) && (mid < end);
287
* Verifies that the endpoints specify an interval,
288
* throws IllegalArgumentException if not
290
* @param lower lower endpoint
291
* @param upper upper endpoint
292
* @throws IllegalArgumentException
294
protected void verifyInterval(double lower, double upper) {
295
if (lower >= upper) {
296
throw new IllegalArgumentException
297
("Endpoints do not specify an interval: [" + lower +
303
* Verifies that <code>lower < initial < upper</code>
304
* throws IllegalArgumentException if not
306
* @param lower lower endpoint
307
* @param initial initial value
308
* @param upper upper endpoint
309
* @throws IllegalArgumentException
311
protected void verifySequence(double lower, double initial, double upper) {
312
if (!isSequence(lower, initial, upper)) {
313
throw new IllegalArgumentException
314
("Invalid interval, initial value parameters: lower=" +
315
lower + " initial=" + initial + " upper=" + upper);
320
* Verifies that the endpoints specify an interval and the function takes
321
* opposite signs at the enpoints, throws IllegalArgumentException if not
323
* @param lower lower endpoint
324
* @param upper upper endpoint
326
* @throws IllegalArgumentException
327
* @throws FunctionEvaluationException if an error occurs evaluating the
328
* function at the endpoints
330
protected void verifyBracketing(double lower, double upper,
331
UnivariateRealFunction f) throws FunctionEvaluationException {
333
verifyInterval(lower, upper);
334
if (!isBracketing(lower, upper, f)) {
335
throw new IllegalArgumentException
336
("Function values at endpoints do not have different signs." +
337
" Endpoints: [" + lower + "," + upper + "]" +
338
" Values: [" + f.value(lower) + "," + f.value(upper) + "]");