BaseAbstractUnivariateIntegrator.java

  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. import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
  19. import org.apache.commons.math4.legacy.analysis.solvers.UnivariateSolverUtils;
  20. import org.apache.commons.math4.legacy.exception.NullArgumentException;
  21. import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
  22. import org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException;
  23. import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
  24. import org.apache.commons.math4.legacy.exception.TooManyEvaluationsException;
  25. import org.apache.commons.math4.legacy.core.IntegerSequence;

  26. /**
  27.  * Provide a default implementation for several generic functions.
  28.  *
  29.  * @since 1.2
  30.  */
  31. public abstract class BaseAbstractUnivariateIntegrator implements UnivariateIntegrator {

  32.     /** Default absolute accuracy. */
  33.     public static final double DEFAULT_ABSOLUTE_ACCURACY = 1.0e-15;

  34.     /** Default relative accuracy. */
  35.     public static final double DEFAULT_RELATIVE_ACCURACY = 1.0e-6;

  36.     /** Default minimal iteration count. */
  37.     public static final int DEFAULT_MIN_ITERATIONS_COUNT = 3;

  38.     /** Default maximal iteration count. */
  39.     public static final int DEFAULT_MAX_ITERATIONS_COUNT = Integer.MAX_VALUE;

  40.     /** The iteration count. */
  41.     protected IntegerSequence.Incrementor iterations;

  42.     /** Maximum absolute error. */
  43.     private final double absoluteAccuracy;

  44.     /** Maximum relative error. */
  45.     private final double relativeAccuracy;

  46.     /** minimum number of iterations. */
  47.     private final int minimalIterationCount;
  48.     /** maximum number of iterations. */
  49.     private final int maximalIterationCount;

  50.     /** The functions evaluation count. */
  51.     private IntegerSequence.Incrementor evaluations;

  52.     /** Function to integrate. */
  53.     private UnivariateFunction function;

  54.     /** Lower bound for the interval. */
  55.     private double min;

  56.     /** Upper bound for the interval. */
  57.     private double max;

  58.     /**
  59.      * Construct an integrator with given accuracies and iteration counts.
  60.      * <p>
  61.      * The meanings of the various parameters are:
  62.      * <ul>
  63.      *   <li>relative accuracy:
  64.      *       this is used to stop iterations if the absolute accuracy can't be
  65.      *       achieved due to large values or short mantissa length. If this
  66.      *       should be the primary criterion for convergence rather then a
  67.      *       safety measure, set the absolute accuracy to a ridiculously small value,
  68.      *       like {@link org.apache.commons.numbers.core.Precision#SAFE_MIN Precision.SAFE_MIN}.</li>
  69.      *   <li>absolute accuracy:
  70.      *       The default is usually chosen so that results in the interval
  71.      *       -10..-0.1 and +0.1..+10 can be found with a reasonable accuracy. If the
  72.      *       expected absolute value of your results is of much smaller magnitude, set
  73.      *       this to a smaller value.</li>
  74.      *   <li>minimum number of iterations:
  75.      *       minimal iteration is needed to avoid false early convergence, e.g.
  76.      *       the sample points happen to be zeroes of the function. Users can
  77.      *       use the default value or choose one that they see as appropriate.</li>
  78.      *   <li>maximum number of iterations:
  79.      *       usually a high iteration count indicates convergence problems. However,
  80.      *       the "reasonable value" varies widely for different algorithms. Users are
  81.      *       advised to use the default value supplied by the algorithm.</li>
  82.      * </ul>
  83.      *
  84.      * @param relativeAccuracy relative accuracy of the result
  85.      * @param absoluteAccuracy absolute accuracy of the result
  86.      * @param minimalIterationCount minimum number of iterations
  87.      * @param maximalIterationCount maximum number of iterations
  88.      * @exception NotStrictlyPositiveException if minimal number of iterations
  89.      * is not strictly positive
  90.      * @exception NumberIsTooSmallException if maximal number of iterations
  91.      * is lesser than or equal to the minimal number of iterations
  92.      */
  93.     protected BaseAbstractUnivariateIntegrator(final double relativeAccuracy,
  94.                                                final double absoluteAccuracy,
  95.                                                final int minimalIterationCount,
  96.                                                final int maximalIterationCount) {
  97.         // accuracy settings
  98.         this.relativeAccuracy      = relativeAccuracy;
  99.         this.absoluteAccuracy      = absoluteAccuracy;

  100.         // iterations count settings
  101.         if (minimalIterationCount <= 0) {
  102.             throw new NotStrictlyPositiveException(minimalIterationCount);
  103.         }
  104.         if (maximalIterationCount <= minimalIterationCount) {
  105.             throw new NumberIsTooSmallException(maximalIterationCount, minimalIterationCount, false);
  106.         }
  107.         this.minimalIterationCount = minimalIterationCount;
  108.         this.maximalIterationCount = maximalIterationCount;
  109.     }

  110.     /**
  111.      * Construct an integrator with given accuracies.
  112.      * @param relativeAccuracy relative accuracy of the result
  113.      * @param absoluteAccuracy absolute accuracy of the result
  114.      */
  115.     protected BaseAbstractUnivariateIntegrator(final double relativeAccuracy,
  116.                                                final double absoluteAccuracy) {
  117.         this(relativeAccuracy, absoluteAccuracy,
  118.              DEFAULT_MIN_ITERATIONS_COUNT, DEFAULT_MAX_ITERATIONS_COUNT);
  119.     }

  120.     /**
  121.      * Construct an integrator with given iteration counts.
  122.      * @param minimalIterationCount minimum number of iterations
  123.      * @param maximalIterationCount maximum number of iterations
  124.      * @exception NotStrictlyPositiveException if minimal number of iterations
  125.      * is not strictly positive
  126.      * @exception NumberIsTooSmallException if maximal number of iterations
  127.      * is lesser than or equal to the minimal number of iterations
  128.      */
  129.     protected BaseAbstractUnivariateIntegrator(final int minimalIterationCount,
  130.                                                final int maximalIterationCount) {
  131.         this(DEFAULT_RELATIVE_ACCURACY, DEFAULT_ABSOLUTE_ACCURACY,
  132.              minimalIterationCount, maximalIterationCount);
  133.     }

  134.     /** {@inheritDoc} */
  135.     @Override
  136.     public double getRelativeAccuracy() {
  137.         return relativeAccuracy;
  138.     }

  139.     /** {@inheritDoc} */
  140.     @Override
  141.     public double getAbsoluteAccuracy() {
  142.         return absoluteAccuracy;
  143.     }

  144.     /** {@inheritDoc} */
  145.     @Override
  146.     public int getMinimalIterationCount() {
  147.         return minimalIterationCount;
  148.     }

  149.     /** {@inheritDoc} */
  150.     @Override
  151.     public int getMaximalIterationCount() {
  152.         return iterations.getMaximalCount();
  153.     }

  154.     /** {@inheritDoc} */
  155.     @Override
  156.     public int getEvaluations() {
  157.         return evaluations.getCount();
  158.     }

  159.     /** {@inheritDoc} */
  160.     @Override
  161.     public int getIterations() {
  162.         return iterations.getCount();
  163.     }

  164.     /**
  165.      * @return the lower bound.
  166.      */
  167.     protected double getMin() {
  168.         return min;
  169.     }
  170.     /**
  171.      * @return the upper bound.
  172.      */
  173.     protected double getMax() {
  174.         return max;
  175.     }

  176.     /**
  177.      * Compute the objective function value.
  178.      *
  179.      * @param point Point at which the objective function must be evaluated.
  180.      * @return the objective function value at specified point.
  181.      * @throws TooManyEvaluationsException if the maximal number of function
  182.      * evaluations is exceeded.
  183.      */
  184.     protected double computeObjectiveValue(final double point) {
  185.         try {
  186.             evaluations.increment();
  187.         } catch (MaxCountExceededException e) {
  188.             throw new TooManyEvaluationsException(e.getMax());
  189.         }
  190.         return function.value(point);
  191.     }

  192.     /**
  193.      * Prepare for computation.
  194.      * Subclasses must call this method if they the {@code integrate} method.
  195.      *
  196.      * @param maxEval Maximum number of evaluations.
  197.      * @param f the integrand function
  198.      * @param lower the min bound for the interval
  199.      * @param upper the upper bound for the interval
  200.      * @throws NullArgumentException if {@code f} is {@code null}.
  201.      * @throws org.apache.commons.math4.legacy.exception.MathIllegalArgumentException
  202.      * if {@code min >= max}.
  203.      */
  204.     protected void setup(final int maxEval,
  205.                          final UnivariateFunction f,
  206.                          final double lower, final double upper) {

  207.         // Checks.
  208.         NullArgumentException.check(f);
  209.         UnivariateSolverUtils.verifyInterval(lower, upper);

  210.         // Reset.
  211.         min = lower;
  212.         max = upper;
  213.         function = f;
  214.         iterations = IntegerSequence.Incrementor.create()
  215.             .withMaximalCount(maximalIterationCount);
  216.         evaluations = IntegerSequence.Incrementor.create()
  217.             .withMaximalCount(maxEval);
  218.     }

  219.     /** {@inheritDoc} */
  220.     @Override
  221.     public double integrate(final int maxEval, final UnivariateFunction f,
  222.                             final double lower, final double upper) {

  223.         // Initialization.
  224.         setup(maxEval, f, lower, upper);

  225.         // Perform computation.
  226.         return doIntegrate();
  227.     }

  228.     /**
  229.      * Method for implementing actual integration algorithms in derived
  230.      * classes.
  231.      *
  232.      * @return the root.
  233.      * @throws TooManyEvaluationsException if the maximal number of evaluations
  234.      * is exceeded.
  235.      * @throws MaxCountExceededException if the maximum iteration count is exceeded
  236.      * or the integrator detects convergence problems otherwise
  237.      */
  238.     protected abstract double doIntegrate() ;
  239. }