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 }