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