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.math4.legacy.analysis.integration;
18
19 import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
20 import org.apache.commons.math4.legacy.analysis.solvers.UnivariateSolverUtils;
21 import org.apache.commons.math4.legacy.exception.NullArgumentException;
22 import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
23 import org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException;
24 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
25 import org.apache.commons.math4.legacy.exception.TooManyEvaluationsException;
26 import org.apache.commons.math4.legacy.core.IntegerSequence;
27
28 /**
29 * Provide a default implementation for several generic functions.
30 *
31 * @since 1.2
32 */
33 public abstract class BaseAbstractUnivariateIntegrator implements UnivariateIntegrator {
34
35 /** Default absolute accuracy. */
36 public static final double DEFAULT_ABSOLUTE_ACCURACY = 1.0e-15;
37
38 /** Default relative accuracy. */
39 public static final double DEFAULT_RELATIVE_ACCURACY = 1.0e-6;
40
41 /** Default minimal iteration count. */
42 public static final int DEFAULT_MIN_ITERATIONS_COUNT = 3;
43
44 /** Default maximal iteration count. */
45 public static final int DEFAULT_MAX_ITERATIONS_COUNT = Integer.MAX_VALUE;
46
47 /** The iteration count. */
48 protected IntegerSequence.Incrementor iterations;
49
50 /** Maximum absolute error. */
51 private final double absoluteAccuracy;
52
53 /** Maximum relative error. */
54 private final double relativeAccuracy;
55
56 /** minimum number of iterations. */
57 private final int minimalIterationCount;
58 /** maximum number of iterations. */
59 private final int maximalIterationCount;
60
61 /** The functions evaluation count. */
62 private IntegerSequence.Incrementor evaluations;
63
64 /** Function to integrate. */
65 private UnivariateFunction function;
66
67 /** Lower bound for the interval. */
68 private double min;
69
70 /** Upper bound for the interval. */
71 private double max;
72
73 /**
74 * Construct an integrator with given accuracies and iteration counts.
75 * <p>
76 * The meanings of the various parameters are:
77 * <ul>
78 * <li>relative accuracy:
79 * this is used to stop iterations if the absolute accuracy can't be
80 * achieved due to large values or short mantissa length. If this
81 * should be the primary criterion for convergence rather then a
82 * safety measure, set the absolute accuracy to a ridiculously small value,
83 * like {@link org.apache.commons.numbers.core.Precision#SAFE_MIN Precision.SAFE_MIN}.</li>
84 * <li>absolute accuracy:
85 * The default is usually chosen so that results in the interval
86 * -10..-0.1 and +0.1..+10 can be found with a reasonable accuracy. If the
87 * expected absolute value of your results is of much smaller magnitude, set
88 * this to a smaller value.</li>
89 * <li>minimum number of iterations:
90 * minimal iteration is needed to avoid false early convergence, e.g.
91 * the sample points happen to be zeroes of the function. Users can
92 * use the default value or choose one that they see as appropriate.</li>
93 * <li>maximum number of iterations:
94 * usually a high iteration count indicates convergence problems. However,
95 * the "reasonable value" varies widely for different algorithms. Users are
96 * advised to use the default value supplied by the algorithm.</li>
97 * </ul>
98 *
99 * @param relativeAccuracy relative accuracy of the result
100 * @param absoluteAccuracy absolute accuracy of the result
101 * @param minimalIterationCount minimum number of iterations
102 * @param maximalIterationCount maximum number of iterations
103 * @exception NotStrictlyPositiveException if minimal number of iterations
104 * is not strictly positive
105 * @exception NumberIsTooSmallException if maximal number of iterations
106 * is lesser than or equal to the minimal number of iterations
107 */
108 protected BaseAbstractUnivariateIntegrator(final double relativeAccuracy,
109 final double absoluteAccuracy,
110 final int minimalIterationCount,
111 final int maximalIterationCount) {
112 // accuracy settings
113 this.relativeAccuracy = relativeAccuracy;
114 this.absoluteAccuracy = absoluteAccuracy;
115
116 // iterations count settings
117 if (minimalIterationCount <= 0) {
118 throw new NotStrictlyPositiveException(minimalIterationCount);
119 }
120 if (maximalIterationCount <= minimalIterationCount) {
121 throw new NumberIsTooSmallException(maximalIterationCount, minimalIterationCount, false);
122 }
123 this.minimalIterationCount = minimalIterationCount;
124 this.maximalIterationCount = maximalIterationCount;
125 }
126
127 /**
128 * Construct an integrator with given accuracies.
129 * @param relativeAccuracy relative accuracy of the result
130 * @param absoluteAccuracy absolute accuracy of the result
131 */
132 protected BaseAbstractUnivariateIntegrator(final double relativeAccuracy,
133 final double absoluteAccuracy) {
134 this(relativeAccuracy, absoluteAccuracy,
135 DEFAULT_MIN_ITERATIONS_COUNT, DEFAULT_MAX_ITERATIONS_COUNT);
136 }
137
138 /**
139 * Construct an integrator with given iteration counts.
140 * @param minimalIterationCount minimum number of iterations
141 * @param maximalIterationCount maximum number of iterations
142 * @exception NotStrictlyPositiveException if minimal number of iterations
143 * is not strictly positive
144 * @exception NumberIsTooSmallException if maximal number of iterations
145 * is lesser than or equal to the minimal number of iterations
146 */
147 protected BaseAbstractUnivariateIntegrator(final int minimalIterationCount,
148 final int maximalIterationCount) {
149 this(DEFAULT_RELATIVE_ACCURACY, DEFAULT_ABSOLUTE_ACCURACY,
150 minimalIterationCount, maximalIterationCount);
151 }
152
153 /** {@inheritDoc} */
154 @Override
155 public double getRelativeAccuracy() {
156 return relativeAccuracy;
157 }
158
159 /** {@inheritDoc} */
160 @Override
161 public double getAbsoluteAccuracy() {
162 return absoluteAccuracy;
163 }
164
165 /** {@inheritDoc} */
166 @Override
167 public int getMinimalIterationCount() {
168 return minimalIterationCount;
169 }
170
171 /** {@inheritDoc} */
172 @Override
173 public int getMaximalIterationCount() {
174 return iterations.getMaximalCount();
175 }
176
177 /** {@inheritDoc} */
178 @Override
179 public int getEvaluations() {
180 return evaluations.getCount();
181 }
182
183 /** {@inheritDoc} */
184 @Override
185 public int getIterations() {
186 return iterations.getCount();
187 }
188
189 /**
190 * @return the lower bound.
191 */
192 protected double getMin() {
193 return min;
194 }
195 /**
196 * @return the upper bound.
197 */
198 protected double getMax() {
199 return max;
200 }
201
202 /**
203 * Compute the objective function value.
204 *
205 * @param point Point at which the objective function must be evaluated.
206 * @return the objective function value at specified point.
207 * @throws TooManyEvaluationsException if the maximal number of function
208 * evaluations is exceeded.
209 */
210 protected double computeObjectiveValue(final double point) {
211 try {
212 evaluations.increment();
213 } catch (MaxCountExceededException e) {
214 throw new TooManyEvaluationsException(e.getMax());
215 }
216 return function.value(point);
217 }
218
219 /**
220 * Prepare for computation.
221 * Subclasses must call this method if they the {@code integrate} method.
222 *
223 * @param maxEval Maximum number of evaluations.
224 * @param f the integrand function
225 * @param lower the min bound for the interval
226 * @param upper the upper bound for the interval
227 * @throws NullArgumentException if {@code f} is {@code null}.
228 * @throws org.apache.commons.math4.legacy.exception.MathIllegalArgumentException
229 * if {@code min >= max}.
230 */
231 protected void setup(final int maxEval,
232 final UnivariateFunction f,
233 final double lower, final double upper) {
234
235 // Checks.
236 NullArgumentException.check(f);
237 UnivariateSolverUtils.verifyInterval(lower, upper);
238
239 // Reset.
240 min = lower;
241 max = upper;
242 function = f;
243 iterations = IntegerSequence.Incrementor.create()
244 .withMaximalCount(maximalIterationCount);
245 evaluations = IntegerSequence.Incrementor.create()
246 .withMaximalCount(maxEval);
247 }
248
249 /** {@inheritDoc} */
250 @Override
251 public double integrate(final int maxEval, final UnivariateFunction f,
252 final double lower, final double upper) {
253
254 // Initialization.
255 setup(maxEval, f, lower, upper);
256
257 // Perform computation.
258 return doIntegrate();
259 }
260
261 /**
262 * Method for implementing actual integration algorithms in derived
263 * classes.
264 *
265 * @return the root.
266 * @throws TooManyEvaluationsException if the maximal number of evaluations
267 * is exceeded.
268 * @throws MaxCountExceededException if the maximum iteration count is exceeded
269 * or the integrator detects convergence problems otherwise
270 */
271 protected abstract double doIntegrate() ;
272 }