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 }