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.  *      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.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.analysis.integration;

  22. import org.hipparchus.analysis.UnivariateFunction;
  23. import org.hipparchus.analysis.solvers.UnivariateSolverUtils;
  24. import org.hipparchus.exception.LocalizedCoreFormats;
  25. import org.hipparchus.exception.MathIllegalArgumentException;
  26. import org.hipparchus.exception.MathIllegalStateException;
  27. import org.hipparchus.exception.NullArgumentException;
  28. import org.hipparchus.util.Incrementor;
  29. import org.hipparchus.util.MathUtils;

  30. /**
  31.  * Provide a default implementation for several generic functions.
  32.  *
  33.  */
  34. public abstract class BaseAbstractUnivariateIntegrator implements UnivariateIntegrator {

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

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

  39.     /** Default minimal iteration count. */
  40.     public static final int DEFAULT_MIN_ITERATIONS_COUNT = 3;

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

  43.     /** The iteration count. */
  44.     protected final Incrementor iterations;

  45.     /** Maximum absolute error. */
  46.     private final double absoluteAccuracy;

  47.     /** Maximum relative error. */
  48.     private final double relativeAccuracy;

  49.     /** minimum number of iterations */
  50.     private final int minimalIterationCount;

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

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

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

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

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

  99.         // accuracy settings
  100.         this.relativeAccuracy      = relativeAccuracy;
  101.         this.absoluteAccuracy      = absoluteAccuracy;

  102.         // iterations count settings
  103.         if (minimalIterationCount <= 0) {
  104.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL_BOUND_EXCLUDED,
  105.                                                    minimalIterationCount, 0);
  106.         }
  107.         if (maximalIterationCount <= minimalIterationCount) {
  108.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL_BOUND_EXCLUDED,
  109.                                                    maximalIterationCount, minimalIterationCount);
  110.         }
  111.         this.minimalIterationCount = minimalIterationCount;
  112.         this.iterations            = new Incrementor(maximalIterationCount);

  113.         // prepare evaluations counter, but do not set it yet
  114.         evaluations = new Incrementor();

  115.     }

  116.     /**
  117.      * Construct an integrator with given accuracies.
  118.      * @param relativeAccuracy relative accuracy of the result
  119.      * @param absoluteAccuracy absolute accuracy of the result
  120.      */
  121.     protected BaseAbstractUnivariateIntegrator(final double relativeAccuracy,
  122.                                            final double absoluteAccuracy) {
  123.         this(relativeAccuracy, absoluteAccuracy,
  124.              DEFAULT_MIN_ITERATIONS_COUNT, DEFAULT_MAX_ITERATIONS_COUNT);
  125.     }

  126.     /**
  127.      * Construct an integrator with given iteration counts.
  128.      * @param minimalIterationCount minimum number of iterations
  129.      * @param maximalIterationCount maximum number of iterations
  130.      * @exception MathIllegalArgumentException if minimal number of iterations
  131.      * is not strictly positive
  132.      * @exception MathIllegalArgumentException if maximal number of iterations
  133.      * is lesser than or equal to the minimal number of iterations
  134.      */
  135.     protected BaseAbstractUnivariateIntegrator(final int minimalIterationCount,
  136.                                            final int maximalIterationCount)
  137.         throws MathIllegalArgumentException {
  138.         this(DEFAULT_RELATIVE_ACCURACY, DEFAULT_ABSOLUTE_ACCURACY,
  139.              minimalIterationCount, maximalIterationCount);
  140.     }

  141.     /** {@inheritDoc} */
  142.     @Override
  143.     public double getRelativeAccuracy() {
  144.         return relativeAccuracy;
  145.     }

  146.     /** {@inheritDoc} */
  147.     @Override
  148.     public double getAbsoluteAccuracy() {
  149.         return absoluteAccuracy;
  150.     }

  151.     /** {@inheritDoc} */
  152.     @Override
  153.     public int getMinimalIterationCount() {
  154.         return minimalIterationCount;
  155.     }

  156.     /** {@inheritDoc} */
  157.     @Override
  158.     public int getMaximalIterationCount() {
  159.         return iterations.getMaximalCount();
  160.     }

  161.     /** {@inheritDoc} */
  162.     @Override
  163.     public int getEvaluations() {
  164.         return evaluations.getCount();
  165.     }

  166.     /** {@inheritDoc} */
  167.     @Override
  168.     public int getIterations() {
  169.         return iterations.getCount();
  170.     }

  171.     /** Get the lower bound.
  172.      * @return the lower bound.
  173.      */
  174.     protected double getMin() {
  175.         return min;
  176.     }

  177.     /** Get the upper bound.
  178.      * @return the upper bound.
  179.      */
  180.     protected double getMax() {
  181.         return max;
  182.     }

  183.     /**
  184.      * Compute the objective function value.
  185.      *
  186.      * @param point Point at which the objective function must be evaluated.
  187.      * @return the objective function value at specified point.
  188.      * @throws MathIllegalStateException if the maximal number of function
  189.      * evaluations is exceeded.
  190.      */
  191.     protected double computeObjectiveValue(final double point)
  192.         throws MathIllegalStateException {
  193.         evaluations.increment();
  194.         return function.value(point);
  195.     }

  196.     /**
  197.      * Prepare for computation.
  198.      * Subclasses must call this method if they override any of the
  199.      * {@code solve} methods.
  200.      *
  201.      * @param maxEval Maximum number of evaluations.
  202.      * @param f the integrand function
  203.      * @param lower the min bound for the interval
  204.      * @param upper the upper bound for the interval
  205.      * @throws NullArgumentException if {@code f} is {@code null}.
  206.      * @throws MathIllegalArgumentException if {@code min >= max}.
  207.      */
  208.     protected void setup(final int maxEval,
  209.                          final UnivariateFunction f,
  210.                          final double lower, final double upper)
  211.         throws MathIllegalArgumentException, NullArgumentException {

  212.         // Checks.
  213.         MathUtils.checkNotNull(f);
  214.         UnivariateSolverUtils.verifyInterval(lower, upper);

  215.         // Reset.
  216.         min = lower;
  217.         max = upper;
  218.         function = f;
  219.         evaluations = evaluations.withMaximalCount(maxEval);
  220.         iterations.reset();
  221.     }

  222.     /** {@inheritDoc} */
  223.     @Override
  224.     public double integrate(final int maxEval, final UnivariateFunction f,
  225.                             final double lower, final double upper)
  226.         throws MathIllegalArgumentException, MathIllegalStateException, NullArgumentException {

  227.         // Initialization.
  228.         setup(maxEval, f, lower, upper);

  229.         // Perform computation.
  230.         return doIntegrate();

  231.     }

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

  244. }