View Javadoc
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 }