001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.math3.analysis.integration; 018 019 import org.apache.commons.math3.analysis.UnivariateFunction; 020 import org.apache.commons.math3.analysis.solvers.UnivariateSolverUtils; 021 import org.apache.commons.math3.exception.MathIllegalArgumentException; 022 import org.apache.commons.math3.exception.MaxCountExceededException; 023 import org.apache.commons.math3.exception.NotStrictlyPositiveException; 024 import org.apache.commons.math3.exception.NullArgumentException; 025 import org.apache.commons.math3.exception.NumberIsTooSmallException; 026 import org.apache.commons.math3.exception.TooManyEvaluationsException; 027 import org.apache.commons.math3.util.Incrementor; 028 import org.apache.commons.math3.util.MathUtils; 029 030 /** 031 * Provide a default implementation for several generic functions. 032 * 033 * @version $Id: BaseAbstractUnivariateIntegrator.java 1364387 2012-07-22 18:14:11Z tn $ 034 * @since 1.2 035 */ 036 public abstract class BaseAbstractUnivariateIntegrator implements UnivariateIntegrator { 037 038 /** Default absolute accuracy. */ 039 public static final double DEFAULT_ABSOLUTE_ACCURACY = 1.0e-15; 040 041 /** Default relative accuracy. */ 042 public static final double DEFAULT_RELATIVE_ACCURACY = 1.0e-6; 043 044 /** Default minimal iteration count. */ 045 public static final int DEFAULT_MIN_ITERATIONS_COUNT = 3; 046 047 /** Default maximal iteration count. */ 048 public static final int DEFAULT_MAX_ITERATIONS_COUNT = Integer.MAX_VALUE; 049 050 /** The iteration count. */ 051 protected final Incrementor iterations; 052 053 /** Maximum absolute error. */ 054 private final double absoluteAccuracy; 055 056 /** Maximum relative error. */ 057 private final double relativeAccuracy; 058 059 /** minimum number of iterations */ 060 private final int minimalIterationCount; 061 062 /** The functions evaluation count. */ 063 private final Incrementor evaluations; 064 065 /** Function to integrate. */ 066 private UnivariateFunction function; 067 068 /** Lower bound for the interval. */ 069 private double min; 070 071 /** Upper bound for the interval. */ 072 private double max; 073 074 /** 075 * Construct an integrator with given accuracies and iteration counts. 076 * <p> 077 * The meanings of the various parameters are: 078 * <ul> 079 * <li>relative accuracy: 080 * this is used to stop iterations if the absolute accuracy can't be 081 * achieved due to large values or short mantissa length. If this 082 * should be the primary criterion for convergence rather then a 083 * safety measure, set the absolute accuracy to a ridiculously small value, 084 * like {@link org.apache.commons.math3.util.Precision#SAFE_MIN Precision.SAFE_MIN}.</li> 085 * <li>absolute accuracy: 086 * The default is usually chosen so that results in the interval 087 * -10..-0.1 and +0.1..+10 can be found with a reasonable accuracy. If the 088 * expected absolute value of your results is of much smaller magnitude, set 089 * this to a smaller value.</li> 090 * <li>minimum number of iterations: 091 * minimal iteration is needed to avoid false early convergence, e.g. 092 * the sample points happen to be zeroes of the function. Users can 093 * use the default value or choose one that they see as appropriate.</li> 094 * <li>maximum number of iterations: 095 * usually a high iteration count indicates convergence problems. However, 096 * the "reasonable value" varies widely for different algorithms. Users are 097 * advised to use the default value supplied by the algorithm.</li> 098 * </ul> 099 * </p> 100 * @param relativeAccuracy relative accuracy of the result 101 * @param absoluteAccuracy absolute accuracy of the result 102 * @param minimalIterationCount minimum number of iterations 103 * @param maximalIterationCount maximum number of iterations 104 * @exception NotStrictlyPositiveException if minimal number of iterations 105 * is not strictly positive 106 * @exception NumberIsTooSmallException if maximal number of iterations 107 * is lesser than or equal to the minimal number of iterations 108 */ 109 protected BaseAbstractUnivariateIntegrator(final double relativeAccuracy, 110 final double absoluteAccuracy, 111 final int minimalIterationCount, 112 final int maximalIterationCount) 113 throws NotStrictlyPositiveException, NumberIsTooSmallException { 114 115 // accuracy settings 116 this.relativeAccuracy = relativeAccuracy; 117 this.absoluteAccuracy = absoluteAccuracy; 118 119 // iterations count settings 120 if (minimalIterationCount <= 0) { 121 throw new NotStrictlyPositiveException(minimalIterationCount); 122 } 123 if (maximalIterationCount <= minimalIterationCount) { 124 throw new NumberIsTooSmallException(maximalIterationCount, minimalIterationCount, false); 125 } 126 this.minimalIterationCount = minimalIterationCount; 127 this.iterations = new Incrementor(); 128 iterations.setMaximalCount(maximalIterationCount); 129 130 // prepare evaluations counter, but do not set it yet 131 evaluations = new Incrementor(); 132 133 } 134 135 /** 136 * Construct an integrator with given accuracies. 137 * @param relativeAccuracy relative accuracy of the result 138 * @param absoluteAccuracy absolute accuracy of the result 139 */ 140 protected BaseAbstractUnivariateIntegrator(final double relativeAccuracy, 141 final double absoluteAccuracy) { 142 this(relativeAccuracy, absoluteAccuracy, 143 DEFAULT_MIN_ITERATIONS_COUNT, DEFAULT_MAX_ITERATIONS_COUNT); 144 } 145 146 /** 147 * Construct an integrator with given iteration counts. 148 * @param minimalIterationCount minimum number of iterations 149 * @param maximalIterationCount maximum number of iterations 150 * @exception NotStrictlyPositiveException if minimal number of iterations 151 * is not strictly positive 152 * @exception NumberIsTooSmallException if maximal number of iterations 153 * is lesser than or equal to the minimal number of iterations 154 */ 155 protected BaseAbstractUnivariateIntegrator(final int minimalIterationCount, 156 final int maximalIterationCount) 157 throws NotStrictlyPositiveException, NumberIsTooSmallException { 158 this(DEFAULT_RELATIVE_ACCURACY, DEFAULT_ABSOLUTE_ACCURACY, 159 minimalIterationCount, maximalIterationCount); 160 } 161 162 /** {@inheritDoc} */ 163 public double getRelativeAccuracy() { 164 return relativeAccuracy; 165 } 166 167 /** {@inheritDoc} */ 168 public double getAbsoluteAccuracy() { 169 return absoluteAccuracy; 170 } 171 172 /** {@inheritDoc} */ 173 public int getMinimalIterationCount() { 174 return minimalIterationCount; 175 } 176 177 /** {@inheritDoc} */ 178 public int getMaximalIterationCount() { 179 return iterations.getMaximalCount(); 180 } 181 182 /** {@inheritDoc} */ 183 public int getEvaluations() { 184 return evaluations.getCount(); 185 } 186 187 /** {@inheritDoc} */ 188 public int getIterations() { 189 return iterations.getCount(); 190 } 191 192 /** 193 * @return the lower bound. 194 */ 195 protected double getMin() { 196 return min; 197 } 198 /** 199 * @return the upper bound. 200 */ 201 protected double getMax() { 202 return max; 203 } 204 205 /** 206 * Compute the objective function value. 207 * 208 * @param point Point at which the objective function must be evaluated. 209 * @return the objective function value at specified point. 210 * @throws TooManyEvaluationsException if the maximal number of function 211 * evaluations is exceeded. 212 */ 213 protected double computeObjectiveValue(final double point) 214 throws TooManyEvaluationsException { 215 try { 216 evaluations.incrementCount(); 217 } catch (MaxCountExceededException e) { 218 throw new TooManyEvaluationsException(e.getMax()); 219 } 220 return function.value(point); 221 } 222 223 /** 224 * Prepare for computation. 225 * Subclasses must call this method if they override any of the 226 * {@code solve} methods. 227 * 228 * @param maxEval Maximum number of evaluations. 229 * @param f the integrand function 230 * @param lower the min bound for the interval 231 * @param upper the upper bound for the interval 232 * @throws NullArgumentException if {@code f} is {@code null}. 233 * @throws MathIllegalArgumentException if {@code min >= max}. 234 */ 235 protected void setup(final int maxEval, 236 final UnivariateFunction f, 237 final double lower, final double upper) 238 throws NullArgumentException, MathIllegalArgumentException { 239 240 // Checks. 241 MathUtils.checkNotNull(f); 242 UnivariateSolverUtils.verifyInterval(lower, upper); 243 244 // Reset. 245 min = lower; 246 max = upper; 247 function = f; 248 evaluations.setMaximalCount(maxEval); 249 evaluations.resetCount(); 250 iterations.resetCount(); 251 252 } 253 254 /** {@inheritDoc} */ 255 public double integrate(final int maxEval, final UnivariateFunction f, 256 final double lower, final double upper) 257 throws TooManyEvaluationsException, MaxCountExceededException, 258 MathIllegalArgumentException, NullArgumentException { 259 260 // Initialization. 261 setup(maxEval, f, lower, upper); 262 263 // Perform computation. 264 return doIntegrate(); 265 266 } 267 268 /** 269 * Method for implementing actual integration algorithms in derived 270 * classes. 271 * 272 * @return the root. 273 * @throws TooManyEvaluationsException if the maximal number of evaluations 274 * is exceeded. 275 * @throws MaxCountExceededException if the maximum iteration count is exceeded 276 * or the integrator detects convergence problems otherwise 277 */ 278 protected abstract double doIntegrate() 279 throws TooManyEvaluationsException, MaxCountExceededException; 280 281 }