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