Return-Path: X-Original-To: apmail-commons-commits-archive@minotaur.apache.org Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 08C9A776B for ; Tue, 23 Aug 2011 22:35:41 +0000 (UTC) Received: (qmail 96555 invoked by uid 500); 23 Aug 2011 22:35:40 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 96465 invoked by uid 500); 23 Aug 2011 22:35:39 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 96458 invoked by uid 99); 23 Aug 2011 22:35:39 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 23 Aug 2011 22:35:39 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 23 Aug 2011 22:35:30 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 4A5822388A56 for ; Tue, 23 Aug 2011 22:35:07 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1160914 - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math/analysis/integration/ site/xdoc/ test/java/org/apache/commons/math/analysis/integration/ Date: Tue, 23 Aug 2011 22:35:06 -0000 To: commits@commons.apache.org From: luc@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110823223507.4A5822388A56@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: luc Date: Tue Aug 23 22:35:06 2011 New Revision: 1160914 URL: http://svn.apache.org/viewvc?rev=1160914&view=rev Log: Changed integration API for consistency with solvers API. Now the main convergence parameters are set in the constructor and remain fixed, but a maximal number of function evaluation must be provided at each call to the integration method. JIRA: MATH-464 Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/LegendreGaussIntegrator.java commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/RombergIntegrator.java commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/SimpsonIntegrator.java commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/TrapezoidIntegrator.java commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/UnivariateRealIntegrator.java commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/UnivariateRealIntegratorImpl.java commons/proper/math/trunk/src/site/xdoc/changes.xml commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/LegendreGaussIntegratorTest.java commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/RombergIntegratorTest.java commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/SimpsonIntegratorTest.java commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/TrapezoidIntegratorTest.java Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/LegendreGaussIntegrator.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/LegendreGaussIntegrator.java?rev=1160914&r1=1160913&r2=1160914&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/LegendreGaussIntegrator.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/LegendreGaussIntegrator.java Tue Aug 23 22:35:06 2011 @@ -18,9 +18,9 @@ package org.apache.commons.math.analysis import org.apache.commons.math.ConvergenceException; import org.apache.commons.math.MathRuntimeException; -import org.apache.commons.math.analysis.UnivariateRealFunction; -import org.apache.commons.math.exception.MaxCountExceededException; -import org.apache.commons.math.exception.MathUserException; +import org.apache.commons.math.exception.NotStrictlyPositiveException; +import org.apache.commons.math.exception.NumberIsTooSmallException; +import org.apache.commons.math.exception.TooManyEvaluationsException; import org.apache.commons.math.exception.util.LocalizedFormats; import org.apache.commons.math.util.FastMath; @@ -119,15 +119,25 @@ public class LegendreGaussIntegrator ext /** Weights for the current method. */ private final double[] weights; - /** Build a Legendre-Gauss integrator. + /** + * Build a Legendre-Gauss integrator with given accuracies and iterations counts. * @param n number of points desired (must be between 2 and 5 inclusive) - * @param defaultMaximalIterationCount maximum number of iterations - * @exception IllegalArgumentException if the number of points is not - * in the supported range + * @param relativeAccuracy relative accuracy of the result + * @param absoluteAccuracy absolute accuracy of the result + * @param minimalIterationCount minimum number of iterations + * @param maximalIterationCount maximum number of iterations + * @exception NotStrictlyPositiveException if minimal number of iterations + * is not strictly positive + * @exception NumberIsTooSmallException if maximal number of iterations + * is lesser than or equal to the minimal number of iterations */ - public LegendreGaussIntegrator(final int n, final int defaultMaximalIterationCount) - throws IllegalArgumentException { - super(defaultMaximalIterationCount); + public LegendreGaussIntegrator(final int n, + final double relativeAccuracy, + final double absoluteAccuracy, + final int minimalIterationCount, + final int maximalIterationCount) + throws NotStrictlyPositiveException, NumberIsTooSmallException { + super(relativeAccuracy, absoluteAccuracy, minimalIterationCount, maximalIterationCount); switch(n) { case 2 : abscissas = ABSCISSAS_2; @@ -153,22 +163,48 @@ public class LegendreGaussIntegrator ext } - /** {@inheritDoc} */ - public double integrate(final UnivariateRealFunction f, final double min, final double max) - throws ConvergenceException, MathUserException, IllegalArgumentException { + /** + * Build a Legendre-Gauss integrator with given accuracies. + * @param n number of points desired (must be between 2 and 5 inclusive) + * @param relativeAccuracy relative accuracy of the result + * @param absoluteAccuracy absolute accuracy of the result + */ + public LegendreGaussIntegrator(final int n, + final double relativeAccuracy, + final double absoluteAccuracy) { + this(n, relativeAccuracy, absoluteAccuracy, + DEFAULT_MIN_ITERATIONS_COUNT, DEFAULT_MAX_ITERATIONS_COUNT); + } - clearResult(); - verifyInterval(min, max); - verifyIterationCount(); + /** + * Build a Legendre-Gauss integrator with given iteration counts. + * @param n number of points desired (must be between 2 and 5 inclusive) + * @param minimalIterationCount minimum number of iterations + * @param maximalIterationCount maximum number of iterations + * @exception NotStrictlyPositiveException if minimal number of iterations + * is not strictly positive + * @exception NumberIsTooSmallException if maximal number of iterations + * is lesser than or equal to the minimal number of iterations + */ + public LegendreGaussIntegrator(final int n, + final int minimalIterationCount, + final int maximalIterationCount) { + this(n, DEFAULT_RELATIVE_ACCURACY, DEFAULT_ABSOLUTE_ACCURACY, + minimalIterationCount, maximalIterationCount); + } + + /** {@inheritDoc} */ + protected double doIntegrate() + throws TooManyEvaluationsException, ConvergenceException { // compute first estimate with a single step - double oldt = stage(f, min, max, 1); + double oldt = stage(1); int n = 2; - for (int i = 0; i < maximalIterationCount; ++i) { + while (true) { // improve integral with a larger number of steps - final double t = stage(f, min, max, n); + final double t = stage(n); // estimate error final double delta = FastMath.abs(t - oldt); @@ -177,8 +213,8 @@ public class LegendreGaussIntegrator ext relativeAccuracy * (FastMath.abs(oldt) + FastMath.abs(t)) * 0.5); // check convergence - if ((i + 1 >= minimalIterationCount) && (delta <= limit)) { - setResult(t, i); + if ((iterations.getCount() + 1 >= minimalIterationCount) && (delta <= limit)) { + setResult(t); return result; } @@ -186,26 +222,21 @@ public class LegendreGaussIntegrator ext double ratio = FastMath.min(4, FastMath.pow(delta / limit, 0.5 / abscissas.length)); n = FastMath.max((int) (ratio * n), n + 1); oldt = t; + iterations.incrementCount(); } - throw new MaxCountExceededException(maximalIterationCount); - } /** * Compute the n-th stage integral. - * @param f the integrand function - * @param min the lower bound for the interval - * @param max the upper bound for the interval * @param n number of steps * @return the value of n-th stage integral - * @throws MathUserException if an error occurs evaluating the - * function + * @throws TooManyEvaluationsException if the maximal number of evaluations + * is exceeded. */ - private double stage(final UnivariateRealFunction f, - final double min, final double max, final int n) - throws MathUserException { + private double stage(final int n) + throws TooManyEvaluationsException { // set up the step for the current stage final double step = (max - min) / n; @@ -216,7 +247,7 @@ public class LegendreGaussIntegrator ext double sum = 0.0; for (int i = 0; i < n; ++i) { for (int j = 0; j < abscissas.length; ++j) { - sum += weights[j] * f.value(midPoint + halfStep * abscissas[j]); + sum += weights[j] * computeObjectiveValue(midPoint + halfStep * abscissas[j]); } midPoint += step; } Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/RombergIntegrator.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/RombergIntegrator.java?rev=1160914&r1=1160913&r2=1160914&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/RombergIntegrator.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/RombergIntegrator.java Tue Aug 23 22:35:06 2011 @@ -16,11 +16,11 @@ */ package org.apache.commons.math.analysis.integration; -import org.apache.commons.math.exception.MathUserException; -import org.apache.commons.math.MathRuntimeException; -import org.apache.commons.math.analysis.UnivariateRealFunction; -import org.apache.commons.math.exception.MaxCountExceededException; -import org.apache.commons.math.exception.util.LocalizedFormats; +import org.apache.commons.math.ConvergenceException; +import org.apache.commons.math.exception.NotStrictlyPositiveException; +import org.apache.commons.math.exception.NumberIsTooLargeException; +import org.apache.commons.math.exception.NumberIsTooSmallException; +import org.apache.commons.math.exception.TooManyEvaluationsException; import org.apache.commons.math.util.FastMath; /** @@ -38,36 +38,88 @@ import org.apache.commons.math.util.Fast */ public class RombergIntegrator extends UnivariateRealIntegratorImpl { + /** Maximal number of iterations for Romberg. */ + public static final int ROMBERG_MAX_ITERATIONS_COUNT = 32; + /** - * Construct an integrator. + * Build a Romberg integrator with given accuracies and iterations counts. + * @param relativeAccuracy relative accuracy of the result + * @param absoluteAccuracy absolute accuracy of the result + * @param minimalIterationCount minimum number of iterations + * @param maximalIterationCount maximum number of iterations + * (must be less than or equal to {@link #ROMBERG_MAX_ITERATIONS_COUNT}) + * @exception NotStrictlyPositiveException if minimal number of iterations + * is not strictly positive + * @exception NumberIsTooSmallException if maximal number of iterations + * is lesser than or equal to the minimal number of iterations + * @exception NumberIsTooLargeException if maximal number of iterations + * is greater than {@link #ROMBERG_MAX_ITERATIONS_COUNT} + */ + public RombergIntegrator(final double relativeAccuracy, + final double absoluteAccuracy, + final int minimalIterationCount, + final int maximalIterationCount) + throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException { + super(relativeAccuracy, absoluteAccuracy, minimalIterationCount, maximalIterationCount); + if (maximalIterationCount > ROMBERG_MAX_ITERATIONS_COUNT) { + throw new NumberIsTooLargeException(maximalIterationCount, + ROMBERG_MAX_ITERATIONS_COUNT, false); + } + } + + /** + * Build a Romberg integrator with given iteration counts. + * @param minimalIterationCount minimum number of iterations + * @param maximalIterationCount maximum number of iterations + * (must be less than or equal to {@link #ROMBERG_MAX_ITERATIONS_COUNT}) + * @exception NotStrictlyPositiveException if minimal number of iterations + * is not strictly positive + * @exception NumberIsTooSmallException if maximal number of iterations + * is lesser than or equal to the minimal number of iterations + * @exception NumberIsTooLargeException if maximal number of iterations + * is greater than {@link #ROMBERG_MAX_ITERATIONS_COUNT} + */ + public RombergIntegrator(final int minimalIterationCount, + final int maximalIterationCount) + throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException { + super(minimalIterationCount, maximalIterationCount); + if (maximalIterationCount > ROMBERG_MAX_ITERATIONS_COUNT) { + throw new NumberIsTooLargeException(maximalIterationCount, + ROMBERG_MAX_ITERATIONS_COUNT, false); + } + } + + /** + * Construct a Romberg integrator with default settings + * (max iteration count set to {@link #ROMBERG_MAX_ITERATIONS_COUNT}) */ public RombergIntegrator() { - super(32); + super(DEFAULT_MIN_ITERATIONS_COUNT, ROMBERG_MAX_ITERATIONS_COUNT); } /** {@inheritDoc} */ - public double integrate(final UnivariateRealFunction f, final double min, final double max) - throws MaxCountExceededException, MathUserException, IllegalArgumentException { + protected double doIntegrate() + throws TooManyEvaluationsException, ConvergenceException { - final int m = maximalIterationCount + 1; + final int m = iterations.getMaximalCount() + 1; double previousRow[] = new double[m]; double currentRow[] = new double[m]; - clearResult(); - verifyInterval(min, max); - verifyIterationCount(); - TrapezoidIntegrator qtrap = new TrapezoidIntegrator(); - currentRow[0] = qtrap.stage(f, min, max, 0); + currentRow[0] = qtrap.stage(this, 0); + iterations.incrementCount(); double olds = currentRow[0]; - for (int i = 1; i <= maximalIterationCount; ++i) { + while (true) { + + final int i = iterations.getCount(); // switch rows final double[] tmpRow = previousRow; previousRow = currentRow; currentRow = tmpRow; - currentRow[0] = qtrap.stage(f, min, max, i); + currentRow[0] = qtrap.stage(this, i); + iterations.incrementCount(); for (int j = 1; j <= i; j++) { // Richardson extrapolation coefficient final double r = (1L << (2 * j)) - 1; @@ -79,24 +131,13 @@ public class RombergIntegrator extends U final double delta = FastMath.abs(s - olds); final double rLimit = relativeAccuracy * (FastMath.abs(olds) + FastMath.abs(s)) * 0.5; if ((delta <= rLimit) || (delta <= absoluteAccuracy)) { - setResult(s, i); + setResult(s); return result; } } olds = s; } - throw new MaxCountExceededException(maximalIterationCount); - } - /** {@inheritDoc} */ - @Override - protected void verifyIterationCount() throws IllegalArgumentException { - super.verifyIterationCount(); - // at most 32 bisection refinements due to higher order divider - if (maximalIterationCount > 32) { - throw MathRuntimeException.createIllegalArgumentException( - LocalizedFormats.INVALID_ITERATIONS_LIMITS, - 0, 32); - } } + } Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/SimpsonIntegrator.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/SimpsonIntegrator.java?rev=1160914&r1=1160913&r2=1160914&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/SimpsonIntegrator.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/SimpsonIntegrator.java Tue Aug 23 22:35:06 2011 @@ -16,11 +16,11 @@ */ package org.apache.commons.math.analysis.integration; -import org.apache.commons.math.exception.MathUserException; -import org.apache.commons.math.MathRuntimeException; -import org.apache.commons.math.analysis.UnivariateRealFunction; -import org.apache.commons.math.exception.MaxCountExceededException; -import org.apache.commons.math.exception.util.LocalizedFormats; +import org.apache.commons.math.ConvergenceException; +import org.apache.commons.math.exception.NotStrictlyPositiveException; +import org.apache.commons.math.exception.NumberIsTooLargeException; +import org.apache.commons.math.exception.NumberIsTooSmallException; +import org.apache.commons.math.exception.TooManyEvaluationsException; import org.apache.commons.math.util.FastMath; /** @@ -37,57 +37,95 @@ import org.apache.commons.math.util.Fast */ public class SimpsonIntegrator extends UnivariateRealIntegratorImpl { + /** Maximal number of iterations for Simpson. */ + public static final int SIMPSON_MAX_ITERATIONS_COUNT = 64; + + /** + * Build a Simpson integrator with given accuracies and iterations counts. + * @param relativeAccuracy relative accuracy of the result + * @param absoluteAccuracy absolute accuracy of the result + * @param minimalIterationCount minimum number of iterations + * @param maximalIterationCount maximum number of iterations + * (must be less than or equal to {@link #SIMPSON_MAX_ITERATIONS_COUNT}) + * @exception NotStrictlyPositiveException if minimal number of iterations + * is not strictly positive + * @exception NumberIsTooSmallException if maximal number of iterations + * is lesser than or equal to the minimal number of iterations + * @exception NumberIsTooLargeException if maximal number of iterations + * is greater than {@link #SIMPSON_MAX_ITERATIONS_COUNT} + */ + public SimpsonIntegrator(final double relativeAccuracy, + final double absoluteAccuracy, + final int minimalIterationCount, + final int maximalIterationCount) + throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException { + super(relativeAccuracy, absoluteAccuracy, minimalIterationCount, maximalIterationCount); + if (maximalIterationCount > SIMPSON_MAX_ITERATIONS_COUNT) { + throw new NumberIsTooLargeException(maximalIterationCount, + SIMPSON_MAX_ITERATIONS_COUNT, false); + } + } + + /** + * Build a Simpson integrator with given iteration counts. + * @param minimalIterationCount minimum number of iterations + * @param maximalIterationCount maximum number of iterations + * (must be less than or equal to {@link #SIMPSON_MAX_ITERATIONS_COUNT}) + * @exception NotStrictlyPositiveException if minimal number of iterations + * is not strictly positive + * @exception NumberIsTooSmallException if maximal number of iterations + * is lesser than or equal to the minimal number of iterations + * @exception NumberIsTooLargeException if maximal number of iterations + * is greater than {@link #SIMPSON_MAX_ITERATIONS_COUNT} + */ + public SimpsonIntegrator(final int minimalIterationCount, + final int maximalIterationCount) + throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException { + super(minimalIterationCount, maximalIterationCount); + if (maximalIterationCount > SIMPSON_MAX_ITERATIONS_COUNT) { + throw new NumberIsTooLargeException(maximalIterationCount, + SIMPSON_MAX_ITERATIONS_COUNT, false); + } + } + /** - * Construct an integrator. + * Construct an integrator with default settings. + * (max iteration count set to {@link #SIMPSON_MAX_ITERATIONS_COUNT}) */ public SimpsonIntegrator() { - super(64); + super(DEFAULT_MIN_ITERATIONS_COUNT, SIMPSON_MAX_ITERATIONS_COUNT); } /** {@inheritDoc} */ - public double integrate(final UnivariateRealFunction f, final double min, final double max) - throws MaxCountExceededException, MathUserException, IllegalArgumentException { - - clearResult(); - verifyInterval(min, max); - verifyIterationCount(); + protected double doIntegrate() + throws TooManyEvaluationsException, ConvergenceException { TrapezoidIntegrator qtrap = new TrapezoidIntegrator(); if (minimalIterationCount == 1) { - final double s = (4 * qtrap.stage(f, min, max, 1) - qtrap.stage(f, min, max, 0)) / 3.0; - setResult(s, 1); + final double s = (4 * qtrap.stage(this, 1) - qtrap.stage(this, 0)) / 3.0; + setResult(s); return result; } // Simpson's rule requires at least two trapezoid stages. double olds = 0; - double oldt = qtrap.stage(f, min, max, 0); - for (int i = 1; i <= maximalIterationCount; ++i) { - final double t = qtrap.stage(f, min, max, i); + double oldt = qtrap.stage(this, 0); + while (true) { + final double t = qtrap.stage(this, iterations.getCount()); + iterations.incrementCount(); final double s = (4 * t - oldt) / 3.0; - if (i >= minimalIterationCount) { + if (iterations.getCount() >= minimalIterationCount) { final double delta = FastMath.abs(s - olds); final double rLimit = relativeAccuracy * (FastMath.abs(olds) + FastMath.abs(s)) * 0.5; if ((delta <= rLimit) || (delta <= absoluteAccuracy)) { - setResult(s, i); + setResult(s); return result; } } olds = s; oldt = t; } - throw new MaxCountExceededException(maximalIterationCount); - } - /** {@inheritDoc} */ - @Override - protected void verifyIterationCount() throws IllegalArgumentException { - super.verifyIterationCount(); - // at most 64 bisection refinements - if (maximalIterationCount > 64) { - throw MathRuntimeException.createIllegalArgumentException( - LocalizedFormats.INVALID_ITERATIONS_LIMITS, - 0, 64); - } } + } Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/TrapezoidIntegrator.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/TrapezoidIntegrator.java?rev=1160914&r1=1160913&r2=1160914&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/TrapezoidIntegrator.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/TrapezoidIntegrator.java Tue Aug 23 22:35:06 2011 @@ -16,11 +16,11 @@ */ package org.apache.commons.math.analysis.integration; -import org.apache.commons.math.exception.MathUserException; -import org.apache.commons.math.MathRuntimeException; -import org.apache.commons.math.analysis.UnivariateRealFunction; -import org.apache.commons.math.exception.MaxCountExceededException; -import org.apache.commons.math.exception.util.LocalizedFormats; +import org.apache.commons.math.ConvergenceException; +import org.apache.commons.math.exception.NotStrictlyPositiveException; +import org.apache.commons.math.exception.NumberIsTooLargeException; +import org.apache.commons.math.exception.NumberIsTooSmallException; +import org.apache.commons.math.exception.TooManyEvaluationsException; import org.apache.commons.math.util.FastMath; /** @@ -36,14 +36,66 @@ import org.apache.commons.math.util.Fast */ public class TrapezoidIntegrator extends UnivariateRealIntegratorImpl { + /** Maximal number of iterations for trapezoid. */ + public static final int TRAPEZOID_MAX_ITERATIONS_COUNT = 64; + /** Intermediate result. */ private double s; /** - * Construct an integrator. + * Build a trapezoid integrator with given accuracies and iterations counts. + * @param relativeAccuracy relative accuracy of the result + * @param absoluteAccuracy absolute accuracy of the result + * @param minimalIterationCount minimum number of iterations + * @param maximalIterationCount maximum number of iterations + * (must be less than or equal to {@link #TRAPEZOID_MAX_ITERATIONS_COUNT) + * @exception NotStrictlyPositiveException if minimal number of iterations + * is not strictly positive + * @exception NumberIsTooSmallException if maximal number of iterations + * is lesser than or equal to the minimal number of iterations + * @exception NumberIsTooLargeException if maximal number of iterations + * is greater than {@link #TRAPEZOID_MAX_ITERATIONS_COUNT} + */ + public TrapezoidIntegrator(final double relativeAccuracy, + final double absoluteAccuracy, + final int minimalIterationCount, + final int maximalIterationCount) + throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException { + super(relativeAccuracy, absoluteAccuracy, minimalIterationCount, maximalIterationCount); + if (maximalIterationCount > TRAPEZOID_MAX_ITERATIONS_COUNT) { + throw new NumberIsTooLargeException(maximalIterationCount, + TRAPEZOID_MAX_ITERATIONS_COUNT, false); + } + } + + /** + * Build a trapezoid integrator with given iteration counts. + * @param minimalIterationCount minimum number of iterations + * @param maximalIterationCount maximum number of iterations + * (must be less than or equal to {@link #TRAPEZOID_MAX_ITERATIONS_COUNT) + * @exception NotStrictlyPositiveException if minimal number of iterations + * is not strictly positive + * @exception NumberIsTooSmallException if maximal number of iterations + * is lesser than or equal to the minimal number of iterations + * @exception NumberIsTooLargeException if maximal number of iterations + * is greater than {@link #TRAPEZOID_MAX_ITERATIONS_COUNT} + */ + public TrapezoidIntegrator(final int minimalIterationCount, + final int maximalIterationCount) + throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException { + super(minimalIterationCount, maximalIterationCount); + if (maximalIterationCount > TRAPEZOID_MAX_ITERATIONS_COUNT) { + throw new NumberIsTooLargeException(maximalIterationCount, + TRAPEZOID_MAX_ITERATIONS_COUNT, false); + } + } + + /** + * Construct a trapezoid integrator with default settings. + * (max iteration count set to {@link #TRAPEZOID_MAX_ITERATIONS_COUNT}) */ public TrapezoidIntegrator() { - super(64); + super(DEFAULT_MIN_ITERATIONS_COUNT, TRAPEZOID_MAX_ITERATIONS_COUNT); } /** @@ -55,27 +107,28 @@ public class TrapezoidIntegrator extends * arbitrary m sections because this configuration can best utilize the * alrealy computed values.

* - * @param f the integrand function - * @param min the lower bound for the interval - * @param max the upper bound for the interval + * @param baseIntegrator integrator holdingintegration parameters * @param n the stage of 1/2 refinement, n = 0 is no refinement * @return the value of n-th stage integral - * @throws MathUserException if an error occurs evaluating the function + * @throws TooManyEvaluationsException if the maximal number of evaluations + * is exceeded. */ - double stage(final UnivariateRealFunction f, - final double min, final double max, final int n) - throws MathUserException { + double stage(final UnivariateRealIntegratorImpl baseIntegrator, final int n) + throws TooManyEvaluationsException { if (n == 0) { - s = 0.5 * (max - min) * (f.value(min) + f.value(max)); + s = 0.5 * (baseIntegrator.max - baseIntegrator.min) * + (baseIntegrator.computeObjectiveValue(baseIntegrator.min) + + baseIntegrator.computeObjectiveValue(baseIntegrator.max)); return s; } else { final long np = 1L << (n-1); // number of new points in this stage double sum = 0; - final double spacing = (max - min) / np; // spacing between adjacent new points - double x = min + 0.5 * spacing; // the first new point + // spacing between adjacent new points + final double spacing = (baseIntegrator.max - baseIntegrator.min) / np; + double x = baseIntegrator.min + 0.5 * spacing; // the first new point for (long i = 0; i < np; i++) { - sum += f.value(x); + sum += baseIntegrator.computeObjectiveValue(x); x += spacing; } // add the new sum to previously calculated result @@ -85,39 +138,27 @@ public class TrapezoidIntegrator extends } /** {@inheritDoc} */ - public double integrate(final UnivariateRealFunction f, final double min, final double max) - throws MaxCountExceededException, MathUserException, IllegalArgumentException { + protected double doIntegrate() + throws TooManyEvaluationsException, ConvergenceException { - clearResult(); - verifyInterval(min, max); - verifyIterationCount(); - - double oldt = stage(f, min, max, 0); - for (int i = 1; i <= maximalIterationCount; ++i) { - final double t = stage(f, min, max, i); + double oldt = stage(this, 0); + iterations.incrementCount(); + while (true) { + final int i = iterations.getCount(); + final double t = stage(this, i); if (i >= minimalIterationCount) { final double delta = FastMath.abs(t - oldt); final double rLimit = relativeAccuracy * (FastMath.abs(oldt) + FastMath.abs(t)) * 0.5; if ((delta <= rLimit) || (delta <= absoluteAccuracy)) { - setResult(t, i); + setResult(t); return result; } } oldt = t; + iterations.incrementCount(); } - throw new MaxCountExceededException(maximalIterationCount); - } - /** {@inheritDoc} */ - @Override - protected void verifyIterationCount() throws IllegalArgumentException { - super.verifyIterationCount(); - // at most 64 bisection refinements - if (maximalIterationCount > 64) { - throw MathRuntimeException.createIllegalArgumentException( - LocalizedFormats.INVALID_ITERATIONS_LIMITS, - 0, 64); - } } + } Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/UnivariateRealIntegrator.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/UnivariateRealIntegrator.java?rev=1160914&r1=1160913&r2=1160914&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/UnivariateRealIntegrator.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/UnivariateRealIntegrator.java Tue Aug 23 22:35:06 2011 @@ -17,8 +17,10 @@ package org.apache.commons.math.analysis.integration; import org.apache.commons.math.ConvergenceException; -import org.apache.commons.math.exception.MathUserException; import org.apache.commons.math.analysis.UnivariateRealFunction; +import org.apache.commons.math.exception.MathIllegalArgumentException; +import org.apache.commons.math.exception.NullArgumentException; +import org.apache.commons.math.exception.TooManyEvaluationsException; /** * Interface for univariate real integration algorithms. @@ -29,115 +31,51 @@ import org.apache.commons.math.analysis. public interface UnivariateRealIntegrator { /** - * Set the upper limit for the number of iterations. - *

- * Usually a high iteration count indicates convergence problems. However, - * the "reasonable value" varies widely for different algorithms. Users are - * advised to use the default value supplied by the algorithm.

- *

- * A {@link ConvergenceException} will be thrown if this number - * is exceeded.

- * - * @param count maximum number of iterations - */ - void setMaximalIterationCount(int count); - - /** - * Get the upper limit for the number of iterations. - * - * @return the actual upper limit - */ - int getMaximalIterationCount(); - - /** - * Set the absolute accuracy. - *

- * The default is usually chosen so that results in the interval - * -10..-0.1 and +0.1..+10 can be found with a reasonable accuracy. If the - * expected absolute value of your results is of much smaller magnitude, set - * this to a smaller value.

- *

- * Algorithms are advised to do a plausibility check with the relative - * accuracy, but clients should not rely on this.

- * - * @param accuracy the accuracy. - * @throws IllegalArgumentException if the accuracy can't be achieved by - * the solver or is otherwise deemed unreasonable. - */ - void setAbsoluteAccuracy(double accuracy); - - /** - * Get the actual absolute accuracy. - * - * @return the accuracy - */ - double getAbsoluteAccuracy(); - - /** - * Set the relative accuracy. - *

- * This is used to stop iterations if the absolute accuracy can't be - * achieved due to large values or short mantissa length.

- *

- * If this should be the primary criterion for convergence rather then a - * safety measure, set the absolute accuracy to a ridiculously small value, - * like {@link org.apache.commons.math.util.MathUtils#SAFE_MIN MathUtils.SAFE_MIN}.

- * - * @param accuracy the relative accuracy. - */ - void setRelativeAccuracy(double accuracy); - - /** * Get the actual relative accuracy. * @return the accuracy */ double getRelativeAccuracy(); /** - * Set the lower limit for the number of iterations. - *

- * Minimal iteration is needed to avoid false early convergence, e.g. - * the sample points happen to be zeroes of the function. Users can - * use the default value or choose one that they see as appropriate.

- *

- * A ConvergenceException will be thrown if this number - * is not met.

+ * Get the actual absolute accuracy. * - * @param count minimum number of iterations + * @return the accuracy */ - void setMinimalIterationCount(int count); + double getAbsoluteAccuracy(); /** - * Get the lower limit for the number of iterations. + * Get the min limit for the number of iterations. * - * @return the actual lower limit + * @return the actual min limit */ int getMinimalIterationCount(); /** - * Reset the lower limit for the number of iterations to the default. - *

- * The default value is supplied by the implementation.

+ * Get the upper limit for the number of iterations. * - * @see #setMinimalIterationCount(int) + * @return the actual upper limit */ - void resetMinimalIterationCount(); + int getMaximalIterationCount(); /** * Integrate the function in the given interval. * + * @param maxEval Maximum number of evaluations. * @param f the integrand function - * @param min the lower bound for the interval + * @param min the min bound for the interval * @param max the upper bound for the interval * @return the value of integral + * @throws TooManyEvaluationsException if the maximal number of evaluations + * is exceeded. * @throws ConvergenceException if the maximum iteration count is exceeded * or the integrator detects convergence problems otherwise - * @throws MathUserException if an error occurs evaluating the function - * @throws IllegalArgumentException if min > max or the endpoints do not + * @throws MathIllegalArgumentException if min > max or the endpoints do not * satisfy the requirements specified by the integrator + * @throws NullArgumentException if {@code f} is {@code null}. */ - double integrate(UnivariateRealFunction f, double min, double max) - throws ConvergenceException, MathUserException, IllegalArgumentException; + double integrate(int maxEval, UnivariateRealFunction f, double min, double max) + throws TooManyEvaluationsException, ConvergenceException, + MathIllegalArgumentException, NullArgumentException; /** * Get the result of the last run of the integrator. @@ -147,4 +85,21 @@ public interface UnivariateRealIntegrato * because no result was yet computed or the last attempt failed */ double getResult() throws IllegalStateException; + + /** + * Get the number of function evaluations of the last run of the integrator. + * @return number of function evaluations + * @throws IllegalStateException if there is no result available, either + * because no result was yet computed or the last attempt failed + */ + int getEvaluations() throws IllegalStateException; + + /** + * Get the number of iterations of the last run of the integrator. + * @return number of iterations + * @throws IllegalStateException if there is no result available, either + * because no result was yet computed or the last attempt failed + */ + int getIterations() throws IllegalStateException; + } Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/UnivariateRealIntegratorImpl.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/UnivariateRealIntegratorImpl.java?rev=1160914&r1=1160913&r2=1160914&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/UnivariateRealIntegratorImpl.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/integration/UnivariateRealIntegratorImpl.java Tue Aug 23 22:35:06 2011 @@ -16,9 +16,19 @@ */ package org.apache.commons.math.analysis.integration; +import org.apache.commons.math.ConvergenceException; import org.apache.commons.math.MathRuntimeException; -import org.apache.commons.math.exception.util.LocalizedFormats; +import org.apache.commons.math.analysis.UnivariateRealFunction; +import org.apache.commons.math.analysis.solvers.UnivariateRealSolverUtils; +import org.apache.commons.math.exception.MathIllegalArgumentException; import org.apache.commons.math.exception.MaxCountExceededException; +import org.apache.commons.math.exception.NotStrictlyPositiveException; +import org.apache.commons.math.exception.NullArgumentException; +import org.apache.commons.math.exception.NumberIsTooSmallException; +import org.apache.commons.math.exception.TooManyEvaluationsException; +import org.apache.commons.math.exception.util.LocalizedFormats; +import org.apache.commons.math.util.Incrementor; +import org.apache.commons.math.util.MathUtils; /** * Provide a default implementation for several generic functions. @@ -28,23 +38,41 @@ import org.apache.commons.math.exception */ public abstract class UnivariateRealIntegratorImpl implements UnivariateRealIntegrator { + /** Default absolute accuracy. */ + public static final double DEFAULT_ABSOLUTE_ACCURACY = 1.0e-15; + + /** Default relative accuracy. */ + public static final double DEFAULT_RELATIVE_ACCURACY = 1.0e-6; + + /** Default minimal iteration count. */ + public static final int DEFAULT_MIN_ITERATIONS_COUNT = 3; + + /** Default maximal iteration count. */ + public static final int DEFAULT_MAX_ITERATIONS_COUNT = Integer.MAX_VALUE; + /** Maximum absolute error. */ protected double absoluteAccuracy; /** Maximum relative error. */ protected double relativeAccuracy; - /** Maximum number of iterations. */ - protected int maximalIterationCount; - /** minimum number of iterations */ protected int minimalIterationCount; - /** default minimum number of iterations */ - protected int defaultMinimalIterationCount; + /** The iteration count. */ + protected Incrementor iterations; + + /** The functions evaluation count. */ + protected Incrementor evaluations; + + /** Function to integrate. */ + protected UnivariateRealFunction function; - /** The last iteration count. */ - protected int iterationCount; + /** Lower bound for the interval. */ + protected double min; + + /** Upper bound for the interval. */ + protected double max; /** indicates whether an integral has been computed */ protected boolean resultComputed = false; @@ -53,33 +81,96 @@ public abstract class UnivariateRealInte protected double result; /** - * Construct an integrator with given iteration count and accuracy. - * + * Construct an integrator with given accuracies and iteration counts. + *

+ * The meanings of the various parameters are: + *

    + *
  • relative accuracy: + * this is used to stop iterations if the absolute accuracy can't be + * achieved due to large values or short mantissa length. If this + * should be the primary criterion for convergence rather then a + * safety measure, set the absolute accuracy to a ridiculously small value, + * like {@link org.apache.commons.math.util.MathUtils#SAFE_MIN MathUtils.SAFE_MIN}.
  • + *
  • absolute accuracy: + * The default is usually chosen so that results in the interval + * -10..-0.1 and +0.1..+10 can be found with a reasonable accuracy. If the + * expected absolute value of your results is of much smaller magnitude, set + * this to a smaller value.
  • + *
  • minimum number of iterations: + * minimal iteration is needed to avoid false early convergence, e.g. + * the sample points happen to be zeroes of the function. Users can + * use the default value or choose one that they see as appropriate.
  • + *
  • maximum number of iterations: + * usually a high iteration count indicates convergence problems. However, + * the "reasonable value" varies widely for different algorithms. Users are + * advised to use the default value supplied by the algorithm.
  • + *
+ *

+ * @param relativeAccuracy relative accuracy of the result + * @param absoluteAccuracy absolute accuracy of the result + * @param minimalIterationCount minimum number of iterations * @param maximalIterationCount maximum number of iterations + * @exception NotStrictlyPositiveException if minimal number of iterations + * is not strictly positive + * @exception NumberIsTooSmallException if maximal number of iterations + * is lesser than or equal to the minimal number of iterations */ - protected UnivariateRealIntegratorImpl(final int maximalIterationCount) { + protected UnivariateRealIntegratorImpl(final double relativeAccuracy, + final double absoluteAccuracy, + final int minimalIterationCount, + final int maximalIterationCount) + throws NotStrictlyPositiveException, NumberIsTooSmallException { + + // accuracy settings + this.relativeAccuracy = relativeAccuracy; + this.absoluteAccuracy = absoluteAccuracy; + + // iterations count settings + if (minimalIterationCount <= 0) { + throw new NotStrictlyPositiveException(minimalIterationCount); + } + if (maximalIterationCount <= minimalIterationCount) { + throw new NumberIsTooSmallException(maximalIterationCount, minimalIterationCount, false); + } + this.minimalIterationCount = minimalIterationCount; + this.iterations = new Incrementor(); + iterations.setMaximalCount(maximalIterationCount); - setMaximalIterationCount(maximalIterationCount); - setAbsoluteAccuracy(1.0e-15); - setRelativeAccuracy(1.0e-6); - setMinimalIterationCount(3); + // prepare evaluations counter, but do not set it yet + evaluations = new Incrementor(); - verifyIterationCount(); } - /** {@inheritDoc} */ - public void setMaximalIterationCount(final int count) { - maximalIterationCount = count; + /** + * Construct an integrator with given accuracies. + * @param relativeAccuracy relative accuracy of the result + * @param absoluteAccuracy absolute accuracy of the result + */ + protected UnivariateRealIntegratorImpl(final double relativeAccuracy, + final double absoluteAccuracy) { + this(relativeAccuracy, absoluteAccuracy, + DEFAULT_MIN_ITERATIONS_COUNT, DEFAULT_MAX_ITERATIONS_COUNT); } - /** {@inheritDoc} */ - public int getMaximalIterationCount() { - return maximalIterationCount; + /** + * Construct an integrator with given iteration counts. + * @param minimalIterationCount minimum number of iterations + * @param maximalIterationCount maximum number of iterations + * @exception NotStrictlyPositiveException if minimal number of iterations + * is not strictly positive + * @exception NumberIsTooSmallException if maximal number of iterations + * is lesser than or equal to the minimal number of iterations + */ + protected UnivariateRealIntegratorImpl(final int minimalIterationCount, + final int maximalIterationCount) + throws NotStrictlyPositiveException, NumberIsTooSmallException { + this(DEFAULT_RELATIVE_ACCURACY, DEFAULT_ABSOLUTE_ACCURACY, + minimalIterationCount, maximalIterationCount); } /** {@inheritDoc} */ - public void setAbsoluteAccuracy(double accuracy) { - absoluteAccuracy = accuracy; + public double getRelativeAccuracy() { + return relativeAccuracy; } /** {@inheritDoc} */ @@ -88,13 +179,13 @@ public abstract class UnivariateRealInte } /** {@inheritDoc} */ - public void setRelativeAccuracy(final double accuracy) { - relativeAccuracy = accuracy; + public int getMinimalIterationCount() { + return minimalIterationCount; } /** {@inheritDoc} */ - public double getRelativeAccuracy() { - return relativeAccuracy; + public int getMaximalIterationCount() { + return iterations.getMaximalCount(); } /** {@inheritDoc} */ @@ -106,90 +197,110 @@ public abstract class UnivariateRealInte } } - /** - * Convenience function for implementations. - * - * @param newResult the result to set - * @param newCount the iteration count to set - */ - protected final void setResult(final double newResult, final int newCount) { - this.result = newResult; - this.iterationCount = newCount; - this.resultComputed = true; - } - - /** - * Convenience function for implementations. - */ - protected final void clearResult() { - this.iterationCount = 0; - this.resultComputed = false; - } - /** {@inheritDoc} */ - public void setMinimalIterationCount(final int count) { - minimalIterationCount = count; - } - - /** {@inheritDoc} */ - public int getMinimalIterationCount() { - return minimalIterationCount; + public int getEvaluations() throws IllegalStateException { + if (resultComputed) { + return evaluations.getCount(); + } else { + throw MathRuntimeException.createIllegalStateException(LocalizedFormats.NO_RESULT_AVAILABLE); + } } /** {@inheritDoc} */ - public void resetMinimalIterationCount() { - minimalIterationCount = defaultMinimalIterationCount; + public int getIterations() throws IllegalStateException { + if (resultComputed) { + return iterations.getCount(); + } else { + throw MathRuntimeException.createIllegalStateException(LocalizedFormats.NO_RESULT_AVAILABLE); + } } /** - * Verifies that the endpoints specify an interval. + * Convenience function for implementations. * - * @param lower lower endpoint - * @param upper upper endpoint - * @throws IllegalArgumentException if not interval + * @param newResult the result to set + * @param newCount the iteration count to set */ - protected void verifyInterval(final double lower, final double upper) - throws IllegalArgumentException { - if (lower >= upper) { - throw MathRuntimeException.createIllegalArgumentException( - LocalizedFormats.ENDPOINTS_NOT_AN_INTERVAL, - lower, upper); - } + protected final void setResult(final double newResult) { + result = newResult; + resultComputed = true; } /** - * Verifies that the upper and lower limits of iterations are valid. + * Compute the objective function value. * - * @throws IllegalArgumentException if not valid + * @param point Point at which the objective function must be evaluated. + * @return the objective function value at specified point. + * @throws TooManyEvaluationsException if the maximal number of evaluations + * is exceeded. */ - protected void verifyIterationCount() throws IllegalArgumentException { - if ((minimalIterationCount <= 0) || (maximalIterationCount <= minimalIterationCount)) { - throw MathRuntimeException.createIllegalArgumentException( - LocalizedFormats.INVALID_ITERATIONS_LIMITS, - minimalIterationCount, maximalIterationCount); + protected double computeObjectiveValue(final double point) + throws TooManyEvaluationsException { + try { + evaluations.incrementCount(); + } catch (MaxCountExceededException e) { + throw new TooManyEvaluationsException(e.getMax()); } + return function.value(point); } /** - * Reset the iterations counter to 0. + * Prepare for computation. + * Subclasses must call this method if they override any of the + * {@code solve} methods. * - * @since 2.2 + * @param maxEval Maximum number of evaluations. + * @param f the integrand function + * @param min the min bound for the interval + * @param upper the upper bound for the interval + * @throws NullArgumentException if {@code f} is {@code null}. + * @throws MathIllegalArgumentException if {@code min >= max}. */ - protected void resetIterationsCounter() { - iterationCount = 0; + protected void setup(final int maxEval, + final UnivariateRealFunction f, + final double min, final double max) + throws NullArgumentException, MathIllegalArgumentException { + + // Checks. + MathUtils.checkNotNull(f); + UnivariateRealSolverUtils.verifyInterval(min, max); + + // Reset. + this.min = min; + this.max = max; + function = f; + evaluations.setMaximalCount(maxEval); + evaluations.resetCount(); + iterations.resetCount(); + resultComputed = false; + + } + + /** {@inheritDoc} */ + public double integrate(final int maxEval, final UnivariateRealFunction f, + final double min, final double max) + throws TooManyEvaluationsException, ConvergenceException, + MathIllegalArgumentException, NullArgumentException { + + // Initialization. + setup(maxEval, f, min, max); + + // Perform computation. + return doIntegrate(); + } /** - * Increment the iterations counter by 1. + * Method for implementing actual integration algorithms in derived + * classes. * - * @throws MaxCountExceededException if the maximal number - * of iterations is exceeded. - * @since 2.2 - */ - protected void incrementIterationsCounter() { - if (++iterationCount > maximalIterationCount) { - throw new MaxCountExceededException(maximalIterationCount); - } - } + * @return the root. + * @throws TooManyEvaluationsException if the maximal number of evaluations + * is exceeded. + * @throws ConvergenceException if the maximum iteration count is exceeded + * or the integrator detects convergence problems otherwise + */ + protected abstract double doIntegrate() + throws TooManyEvaluationsException, ConvergenceException; } Modified: commons/proper/math/trunk/src/site/xdoc/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/changes.xml?rev=1160914&r1=1160913&r2=1160914&view=diff ============================================================================== --- commons/proper/math/trunk/src/site/xdoc/changes.xml (original) +++ commons/proper/math/trunk/src/site/xdoc/changes.xml Tue Aug 23 22:35:06 2011 @@ -52,6 +52,11 @@ The type attribute can be add,u If the output is not quite correct, check for invisible trailing spaces! --> + + Changed integration API for consistency with solvers API. Now the main convergence + parameters are set in the constructor and remain fixed, but a maximal number of function + evaluation must be provided at each call to the integration method. + Added storeless covariance implementation. Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/LegendreGaussIntegratorTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/LegendreGaussIntegratorTest.java?rev=1160914&r1=1160913&r2=1160914&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/LegendreGaussIntegratorTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/LegendreGaussIntegratorTest.java Tue Aug 23 22:35:06 2011 @@ -25,6 +25,7 @@ import org.apache.commons.math.analysis. import org.apache.commons.math.analysis.UnivariateRealFunction; import org.apache.commons.math.analysis.polynomials.PolynomialFunction; import org.apache.commons.math.exception.MathUserException; +import org.apache.commons.math.exception.TooManyEvaluationsException; import org.apache.commons.math.util.FastMath; import org.junit.Assert; import org.junit.Test; @@ -35,42 +36,43 @@ public class LegendreGaussIntegratorTest @Test public void testSinFunction() throws MathException { UnivariateRealFunction f = new SinFunction(); - UnivariateRealIntegratorImpl integrator = new LegendreGaussIntegrator(5, 64); - integrator.setAbsoluteAccuracy(1.0e-10); - integrator.setRelativeAccuracy(1.0e-14); - integrator.setMinimalIterationCount(2); - integrator.setMaximalIterationCount(15); + UnivariateRealIntegratorImpl integrator = new LegendreGaussIntegrator(5, 1.0e-14, 1.0e-10, 2, 15); double min, max, expected, result, tolerance; min = 0; max = FastMath.PI; expected = 2; tolerance = FastMath.max(integrator.getAbsoluteAccuracy(), FastMath.abs(expected * integrator.getRelativeAccuracy())); - result = integrator.integrate(f, min, max); + result = integrator.integrate(10000, f, min, max); Assert.assertEquals(expected, result, tolerance); min = -FastMath.PI/3; max = 0; expected = -0.5; tolerance = FastMath.max(integrator.getAbsoluteAccuracy(), FastMath.abs(expected * integrator.getRelativeAccuracy())); - result = integrator.integrate(f, min, max); + result = integrator.integrate(10000, f, min, max); Assert.assertEquals(expected, result, tolerance); } @Test public void testQuinticFunction() throws MathException { UnivariateRealFunction f = new QuinticFunction(); - UnivariateRealIntegrator integrator = new LegendreGaussIntegrator(3, 64); + UnivariateRealIntegrator integrator = + new LegendreGaussIntegrator(3, + UnivariateRealIntegratorImpl.DEFAULT_RELATIVE_ACCURACY, + UnivariateRealIntegratorImpl.DEFAULT_ABSOLUTE_ACCURACY, + UnivariateRealIntegratorImpl.DEFAULT_MIN_ITERATIONS_COUNT, + 64); double min, max, expected, result; min = 0; max = 1; expected = -1.0/48; - result = integrator.integrate(f, min, max); + result = integrator.integrate(10000, f, min, max); Assert.assertEquals(expected, result, 1.0e-16); min = 0; max = 0.5; expected = 11.0/768; - result = integrator.integrate(f, min, max); + result = integrator.integrate(10000, f, min, max); Assert.assertEquals(expected, result, 1.0e-16); min = -1; max = 4; expected = 2048/3.0 - 78 + 1.0/48; - result = integrator.integrate(f, min, max); + result = integrator.integrate(10000, f, min, max); Assert.assertEquals(expected, result, 1.0e-16); } @@ -80,7 +82,11 @@ public class LegendreGaussIntegratorTest Random random = new Random(86343623467878363l); for (int n = 2; n < 6; ++n) { LegendreGaussIntegrator integrator = - new LegendreGaussIntegrator(n, 64); + new LegendreGaussIntegrator(n, + UnivariateRealIntegratorImpl.DEFAULT_RELATIVE_ACCURACY, + UnivariateRealIntegratorImpl.DEFAULT_ABSOLUTE_ACCURACY, + UnivariateRealIntegratorImpl.DEFAULT_MIN_ITERATIONS_COUNT, + 64); // an n points Gauss-Legendre integrator integrates 2n-1 degree polynoms exactly for (int degree = 0; degree <= 2 * n - 1; ++degree) { @@ -90,7 +96,7 @@ public class LegendreGaussIntegratorTest coeff[k] = 2 * random.nextDouble() - 1; } PolynomialFunction p = new PolynomialFunction(coeff); - double result = integrator.integrate(p, -5.0, 15.0); + double result = integrator.integrate(10000, p, -5.0, 15.0); double reference = exactIntegration(p, -5.0, 15.0); Assert.assertEquals(n + " " + degree + " " + i, reference, result, 1.0e-12 * (1.0 + FastMath.abs(reference))); } @@ -99,6 +105,41 @@ public class LegendreGaussIntegratorTest } } + @Test + public void testIssue464() throws ConvergenceException { + final double value = 0.2; + UnivariateRealFunction f = new UnivariateRealFunction() { + public double value(double x) { + return (x >= 0 && x <= 5) ? value : 0.0; + } + }; + LegendreGaussIntegrator gauss = new LegendreGaussIntegrator(5, 3, 100); + + // due to the discontinuity, integration implies *many* calls + double maxX = 0.32462367623786328; + Assert.assertEquals(maxX * value, gauss.integrate(Integer.MAX_VALUE, f, -10, maxX), 1.0e-7); + Assert.assertTrue(gauss.getEvaluations() > 37000000); + Assert.assertTrue(gauss.getIterations() < 30); + + // setting up limits prevents such large number of calls + try { + gauss.integrate(1000, f, -10, maxX); + Assert.fail("expected TooManyEvaluationsException"); + } catch (TooManyEvaluationsException tmee) { + // expected + Assert.assertEquals(1000, tmee.getMax()); + } + + // integrating on the two sides should be simpler + double sum1 = gauss.integrate(1000, f, -10, 0); + int eval1 = gauss.getEvaluations(); + double sum2 = gauss.integrate(1000, f, 0, maxX); + int eval2 = gauss.getEvaluations(); + Assert.assertEquals(maxX * value, sum1 + sum2, 1.0e-7); + Assert.assertTrue(eval1 + eval2 < 200); + + } + private double exactIntegration(PolynomialFunction p, double a, double b) { final double[] coeffs = p.getCoefficients(); double yb = coeffs[coeffs.length - 1] / coeffs.length; Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/RombergIntegratorTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/RombergIntegratorTest.java?rev=1160914&r1=1160913&r2=1160914&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/RombergIntegratorTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/RombergIntegratorTest.java Tue Aug 23 22:35:06 2011 @@ -20,6 +20,8 @@ import org.apache.commons.math.MathExcep import org.apache.commons.math.analysis.QuinticFunction; import org.apache.commons.math.analysis.SinFunction; import org.apache.commons.math.analysis.UnivariateRealFunction; +import org.apache.commons.math.exception.NumberIsTooLargeException; +import org.apache.commons.math.exception.NumberIsTooSmallException; import org.apache.commons.math.util.FastMath; import org.junit.Assert; import org.junit.Test; @@ -47,12 +49,16 @@ public final class RombergIntegratorTest min = 0; max = FastMath.PI; expected = 2; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(100, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 50); + Assert.assertTrue(integrator.getIterations() < 10); Assert.assertEquals(expected, result, tolerance); min = -FastMath.PI/3; max = 0; expected = -0.5; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(100, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 50); + Assert.assertTrue(integrator.getIterations() < 10); Assert.assertEquals(expected, result, tolerance); } @@ -67,17 +73,23 @@ public final class RombergIntegratorTest min = 0; max = 1; expected = -1.0/48; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(100, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 10); + Assert.assertTrue(integrator.getIterations() < 5); Assert.assertEquals(expected, result, tolerance); min = 0; max = 0.5; expected = 11.0/768; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(100, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 10); + Assert.assertTrue(integrator.getIterations() < 5); Assert.assertEquals(expected, result, tolerance); min = -1; max = 4; expected = 2048/3.0 - 78 + 1.0/48; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(100, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 10); + Assert.assertTrue(integrator.getIterations() < 5); Assert.assertEquals(expected, result, tolerance); } @@ -87,31 +99,26 @@ public final class RombergIntegratorTest @Test public void testParameters() throws Exception { UnivariateRealFunction f = new SinFunction(); - UnivariateRealIntegrator integrator = new RombergIntegrator(); try { // bad interval - integrator.integrate(f, 1, -1); - Assert.fail("Expecting IllegalArgumentException - bad interval"); - } catch (IllegalArgumentException ex) { + new RombergIntegrator().integrate(1000, f, 1, -1); + Assert.fail("Expecting NumberIsTooLargeException - bad interval"); + } catch (NumberIsTooLargeException ex) { // expected } try { // bad iteration limits - integrator.setMinimalIterationCount(5); - integrator.setMaximalIterationCount(4); - integrator.integrate(f, -1, 1); - Assert.fail("Expecting IllegalArgumentException - bad iteration limits"); - } catch (IllegalArgumentException ex) { + new RombergIntegrator(5, 4); + Assert.fail("Expecting NumberIsTooSmallException - bad iteration limits"); + } catch (NumberIsTooSmallException ex) { // expected } try { // bad iteration limits - integrator.setMinimalIterationCount(10); - integrator.setMaximalIterationCount(50); - integrator.integrate(f, -1, 1); - Assert.fail("Expecting IllegalArgumentException - bad iteration limits"); - } catch (IllegalArgumentException ex) { + new RombergIntegrator(10, 50); + Assert.fail("Expecting NumberIsTooLargeException - bad iteration limits"); + } catch (NumberIsTooLargeException ex) { // expected } } Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/SimpsonIntegratorTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/SimpsonIntegratorTest.java?rev=1160914&r1=1160913&r2=1160914&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/SimpsonIntegratorTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/SimpsonIntegratorTest.java Tue Aug 23 22:35:06 2011 @@ -20,6 +20,8 @@ import org.apache.commons.math.MathExcep import org.apache.commons.math.analysis.QuinticFunction; import org.apache.commons.math.analysis.SinFunction; import org.apache.commons.math.analysis.UnivariateRealFunction; +import org.apache.commons.math.exception.NumberIsTooLargeException; +import org.apache.commons.math.exception.NumberIsTooSmallException; import org.apache.commons.math.util.FastMath; import org.junit.Assert; import org.junit.Test; @@ -46,12 +48,16 @@ public final class SimpsonIntegratorTest min = 0; max = FastMath.PI; expected = 2; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(1000, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 100); + Assert.assertTrue(integrator.getIterations() < 10); Assert.assertEquals(expected, result, tolerance); min = -FastMath.PI/3; max = 0; expected = -0.5; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(1000, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 50); + Assert.assertTrue(integrator.getIterations() < 10); Assert.assertEquals(expected, result, tolerance); } @@ -66,17 +72,23 @@ public final class SimpsonIntegratorTest min = 0; max = 1; expected = -1.0/48; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(1000, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 150); + Assert.assertTrue(integrator.getIterations() < 10); Assert.assertEquals(expected, result, tolerance); min = 0; max = 0.5; expected = 11.0/768; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(1000, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 100); + Assert.assertTrue(integrator.getIterations() < 10); Assert.assertEquals(expected, result, tolerance); min = -1; max = 4; expected = 2048/3.0 - 78 + 1.0/48; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(1000, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 150); + Assert.assertTrue(integrator.getIterations() < 10); Assert.assertEquals(expected, result, tolerance); } @@ -86,31 +98,25 @@ public final class SimpsonIntegratorTest @Test public void testParameters() throws Exception { UnivariateRealFunction f = new SinFunction(); - UnivariateRealIntegrator integrator = new SimpsonIntegrator(); - try { // bad interval - integrator.integrate(f, 1, -1); - Assert.fail("Expecting IllegalArgumentException - bad interval"); - } catch (IllegalArgumentException ex) { + new SimpsonIntegrator().integrate(1000, f, 1, -1); + Assert.fail("Expecting NumberIsTooLargeException - bad interval"); + } catch (NumberIsTooLargeException ex) { // expected } try { // bad iteration limits - integrator.setMinimalIterationCount(5); - integrator.setMaximalIterationCount(4); - integrator.integrate(f, -1, 1); - Assert.fail("Expecting IllegalArgumentException - bad iteration limits"); - } catch (IllegalArgumentException ex) { + new SimpsonIntegrator(5, 4); + Assert.fail("Expecting NumberIsTooSmallException - bad iteration limits"); + } catch (NumberIsTooSmallException ex) { // expected } try { // bad iteration limits - integrator.setMinimalIterationCount(10); - integrator.setMaximalIterationCount(99); - integrator.integrate(f, -1, 1); - Assert.fail("Expecting IllegalArgumentException - bad iteration limits"); - } catch (IllegalArgumentException ex) { + new SimpsonIntegrator(10, 99); + Assert.fail("Expecting NumberIsTooLargeException - bad iteration limits"); + } catch (NumberIsTooLargeException ex) { // expected } } Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/TrapezoidIntegratorTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/TrapezoidIntegratorTest.java?rev=1160914&r1=1160913&r2=1160914&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/TrapezoidIntegratorTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/integration/TrapezoidIntegratorTest.java Tue Aug 23 22:35:06 2011 @@ -20,6 +20,8 @@ import org.apache.commons.math.MathExcep import org.apache.commons.math.analysis.QuinticFunction; import org.apache.commons.math.analysis.SinFunction; import org.apache.commons.math.analysis.UnivariateRealFunction; +import org.apache.commons.math.exception.NumberIsTooLargeException; +import org.apache.commons.math.exception.NumberIsTooSmallException; import org.apache.commons.math.util.FastMath; import org.junit.Assert; import org.junit.Test; @@ -46,12 +48,16 @@ public final class TrapezoidIntegratorTe min = 0; max = FastMath.PI; expected = 2; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(10000, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 2500); + Assert.assertTrue(integrator.getIterations() < 15); Assert.assertEquals(expected, result, tolerance); min = -FastMath.PI/3; max = 0; expected = -0.5; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(10000, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 2500); + Assert.assertTrue(integrator.getIterations() < 15); Assert.assertEquals(expected, result, tolerance); } @@ -66,18 +72,25 @@ public final class TrapezoidIntegratorTe min = 0; max = 1; expected = -1.0/48; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(10000, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 5000); + Assert.assertTrue(integrator.getIterations() < 15); Assert.assertEquals(expected, result, tolerance); min = 0; max = 0.5; expected = 11.0/768; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(10000, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 2500); + Assert.assertTrue(integrator.getIterations() < 15); Assert.assertEquals(expected, result, tolerance); min = -1; max = 4; expected = 2048/3.0 - 78 + 1.0/48; tolerance = FastMath.abs(expected * integrator.getRelativeAccuracy()); - result = integrator.integrate(f, min, max); + result = integrator.integrate(10000, f, min, max); + Assert.assertTrue(integrator.getEvaluations() < 5000); + Assert.assertTrue(integrator.getIterations() < 15); Assert.assertEquals(expected, result, tolerance); + } /** @@ -86,31 +99,26 @@ public final class TrapezoidIntegratorTe @Test public void testParameters() throws Exception { UnivariateRealFunction f = new SinFunction(); - UnivariateRealIntegrator integrator = new TrapezoidIntegrator(); try { // bad interval - integrator.integrate(f, 1, -1); - Assert.fail("Expecting IllegalArgumentException - bad interval"); - } catch (IllegalArgumentException ex) { + new TrapezoidIntegrator().integrate(1000, f, 1, -1); + Assert.fail("Expecting NumberIsTooLargeException - bad interval"); + } catch (NumberIsTooLargeException ex) { // expected } try { // bad iteration limits - integrator.setMinimalIterationCount(5); - integrator.setMaximalIterationCount(4); - integrator.integrate(f, -1, 1); - Assert.fail("Expecting IllegalArgumentException - bad iteration limits"); - } catch (IllegalArgumentException ex) { + new TrapezoidIntegrator(5, 4); + Assert.fail("Expecting NumberIsTooSmallException - bad iteration limits"); + } catch (NumberIsTooSmallException ex) { // expected } try { // bad iteration limits - integrator.setMinimalIterationCount(10); - integrator.setMaximalIterationCount(99); - integrator.integrate(f, -1, 1); - Assert.fail("Expecting IllegalArgumentException - bad iteration limits"); - } catch (IllegalArgumentException ex) { + new TrapezoidIntegrator(10,99); + Assert.fail("Expecting NumberIsTooLargeException - bad iteration limits"); + } catch (NumberIsTooLargeException ex) { // expected } }