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.exception.LocalizedCoreFormats; 25 import org.hipparchus.exception.MathIllegalArgumentException; 26 import org.hipparchus.exception.MathIllegalStateException; 27 import org.hipparchus.util.FastMath; 28 29 /** 30 * Implements the <a href="http://en.wikipedia.org/wiki/Midpoint_method"> 31 * Midpoint Rule</a> for integration of real univariate functions. For 32 * reference, see <b>Numerical Mathematics</b>, ISBN 0387989595, 33 * chapter 9.2. 34 * <p> 35 * The function should be integrable.</p> 36 * 37 */ 38 public class MidPointIntegrator extends BaseAbstractUnivariateIntegrator { 39 40 /** Maximum number of iterations for midpoint. */ 41 public static final int MIDPOINT_MAX_ITERATIONS_COUNT = 64; 42 43 /** 44 * Build a midpoint integrator with given accuracies and iterations counts. 45 * @param relativeAccuracy relative accuracy of the result 46 * @param absoluteAccuracy absolute accuracy of the result 47 * @param minimalIterationCount minimum number of iterations 48 * @param maximalIterationCount maximum number of iterations 49 * (must be less than or equal to {@link #MIDPOINT_MAX_ITERATIONS_COUNT} 50 * @exception MathIllegalArgumentException if minimal number of iterations 51 * is not strictly positive 52 * @exception MathIllegalArgumentException if maximal number of iterations 53 * is lesser than or equal to the minimal number of iterations 54 * @exception MathIllegalArgumentException if maximal number of iterations 55 * is greater than {@link #MIDPOINT_MAX_ITERATIONS_COUNT} 56 */ 57 public MidPointIntegrator(final double relativeAccuracy, 58 final double absoluteAccuracy, 59 final int minimalIterationCount, 60 final int maximalIterationCount) 61 throws MathIllegalArgumentException { 62 super(relativeAccuracy, absoluteAccuracy, minimalIterationCount, maximalIterationCount); 63 if (maximalIterationCount > MIDPOINT_MAX_ITERATIONS_COUNT) { 64 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE_BOUND_EXCLUDED, 65 maximalIterationCount, MIDPOINT_MAX_ITERATIONS_COUNT); 66 } 67 } 68 69 /** 70 * Build a midpoint integrator with given iteration counts. 71 * @param minimalIterationCount minimum number of iterations 72 * @param maximalIterationCount maximum number of iterations 73 * (must be less than or equal to {@link #MIDPOINT_MAX_ITERATIONS_COUNT} 74 * @exception MathIllegalArgumentException if minimal number of iterations 75 * is not strictly positive 76 * @exception MathIllegalArgumentException if maximal number of iterations 77 * is lesser than or equal to the minimal number of iterations 78 * @exception MathIllegalArgumentException if maximal number of iterations 79 * is greater than {@link #MIDPOINT_MAX_ITERATIONS_COUNT} 80 */ 81 public MidPointIntegrator(final int minimalIterationCount, 82 final int maximalIterationCount) 83 throws MathIllegalArgumentException { 84 super(minimalIterationCount, maximalIterationCount); 85 if (maximalIterationCount > MIDPOINT_MAX_ITERATIONS_COUNT) { 86 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE_BOUND_EXCLUDED, 87 maximalIterationCount, MIDPOINT_MAX_ITERATIONS_COUNT); 88 } 89 } 90 91 /** 92 * Construct a midpoint integrator with default settings. 93 * (max iteration count set to {@link #MIDPOINT_MAX_ITERATIONS_COUNT}) 94 */ 95 public MidPointIntegrator() { 96 super(DEFAULT_MIN_ITERATIONS_COUNT, MIDPOINT_MAX_ITERATIONS_COUNT); 97 } 98 99 /** 100 * Compute the n-th stage integral of midpoint rule. 101 * This function should only be called by API <code>integrate()</code> in the package. 102 * To save time it does not verify arguments - caller does. 103 * <p> 104 * The interval is divided equally into 2^n sections rather than an 105 * arbitrary m sections because this configuration can best utilize the 106 * already computed values.</p> 107 * 108 * @param n the stage of 1/2 refinement. Must be larger than 0. 109 * @param previousStageResult Result from the previous call to the 110 * {@code stage} method. 111 * @param min Lower bound of the integration interval. 112 * @param diffMaxMin Difference between the lower bound and upper bound 113 * of the integration interval. 114 * @return the value of n-th stage integral 115 * @throws MathIllegalStateException if the maximal number of evaluations 116 * is exceeded. 117 */ 118 private double stage(final int n, 119 double previousStageResult, 120 double min, 121 double diffMaxMin) 122 throws MathIllegalStateException { 123 124 // number of new points in this stage 125 final long np = 1L << (n - 1); 126 double sum = 0; 127 128 // spacing between adjacent new points 129 final double spacing = diffMaxMin / np; 130 131 // the first new point 132 double x = min + 0.5 * spacing; 133 for (long i = 0; i < np; i++) { 134 sum += computeObjectiveValue(x); 135 x += spacing; 136 } 137 // add the new sum to previously calculated result 138 return 0.5 * (previousStageResult + sum * spacing); 139 } 140 141 142 /** {@inheritDoc} */ 143 @Override 144 protected double doIntegrate() 145 throws MathIllegalArgumentException, MathIllegalStateException { 146 147 final double min = getMin(); 148 final double diff = getMax() - min; 149 final double midPoint = min + 0.5 * diff; 150 151 double oldt = diff * computeObjectiveValue(midPoint); 152 153 while (true) { 154 iterations.increment(); 155 final int i = iterations.getCount(); 156 final double t = stage(i, oldt, min, diff); 157 if (i >= getMinimalIterationCount()) { 158 final double delta = FastMath.abs(t - oldt); 159 final double rLimit = 160 getRelativeAccuracy() * (FastMath.abs(oldt) + FastMath.abs(t)) * 0.5; 161 if ((delta <= rLimit) || (delta <= getAbsoluteAccuracy())) { 162 return t; 163 } 164 } 165 oldt = t; 166 } 167 168 } 169 170 }