improved consistency between solvers/integrators

by providing the integrand function as a parameter to integrate
rather that at construction, thus allowing reuse of a configured integrator
Jira: MATH-218

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@735545 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2009-01-18 21:06:15 +00:00
parent 217fe6de71
commit 56e7606e9a
9 changed files with 162 additions and 61 deletions

View File

@ -36,21 +36,39 @@ import org.apache.commons.math.analysis.UnivariateRealFunction;
*/
public class RombergIntegrator extends UnivariateRealIntegratorImpl {
/** serializable version identifier */
private static final long serialVersionUID = -1058849527738180243L;
/** Serializable version identifier. */
private static final long serialVersionUID = 4616482344304576900L;
/**
* Construct an integrator for the given function.
*
* @param f function to integrate
* @deprecated as of 2.0 the integrand function is passed as an argument
* to the {@link #integrate(UnivariateRealFunction, double, double)}method.
*/
@Deprecated
public RombergIntegrator(UnivariateRealFunction f) {
super(f, 32);
}
/**
* Construct an integrator.
*/
public RombergIntegrator() {
super(32);
}
/** {@inheritDoc} */
public double integrate(double min, double max) throws MaxIterationsExceededException,
FunctionEvaluationException, IllegalArgumentException {
@Deprecated
public double integrate(final double min, final double max)
throws MaxIterationsExceededException, FunctionEvaluationException, IllegalArgumentException {
return integrate(f, min, max);
}
/** {@inheritDoc} */
public double integrate(final UnivariateRealFunction f,
final double min, final double max)
throws MaxIterationsExceededException, FunctionEvaluationException, IllegalArgumentException {
int i = 1, j, m = maximalIterationCount + 1;
// Array structure here can be improved for better space
@ -61,11 +79,11 @@ public class RombergIntegrator extends UnivariateRealIntegratorImpl {
verifyInterval(min, max);
verifyIterationCount();
TrapezoidIntegrator qtrap = new TrapezoidIntegrator(this.f);
t[0][0] = qtrap.stage(min, max, 0);
TrapezoidIntegrator qtrap = new TrapezoidIntegrator();
t[0][0] = qtrap.stage(f, min, max, 0);
olds = t[0][0];
while (i <= maximalIterationCount) {
t[i][0] = qtrap.stage(min, max, i);
t[i][0] = qtrap.stage(f, min, max, i);
for (j = 1; j <= i; j++) {
// Richardson extrapolation coefficient
r = (1L << (2 * j)) -1;

View File

@ -35,21 +35,39 @@ import org.apache.commons.math.analysis.UnivariateRealFunction;
*/
public class SimpsonIntegrator extends UnivariateRealIntegratorImpl {
/** serializable version identifier */
private static final long serialVersionUID = 3405465123320678216L;
/** Serializable version identifier. */
private static final long serialVersionUID = 2535890386567281329L;
/**
* Construct an integrator for the given function.
*
* @param f function to integrate
* @deprecated as of 2.0 the integrand function is passed as an argument
* to the {@link #integrate(UnivariateRealFunction, double, double)}method.
*/
@Deprecated
public SimpsonIntegrator(UnivariateRealFunction f) {
super(f, 64);
}
/**
* Construct an integrator.
*/
public SimpsonIntegrator() {
super(64);
}
/** {@inheritDoc} */
public double integrate(double min, double max) throws MaxIterationsExceededException,
FunctionEvaluationException, IllegalArgumentException {
@Deprecated
public double integrate(final double min, final double max)
throws MaxIterationsExceededException, FunctionEvaluationException, IllegalArgumentException {
return integrate(f, min, max);
}
/** {@inheritDoc} */
public double integrate(final UnivariateRealFunction f,
final double min, final double max)
throws MaxIterationsExceededException, FunctionEvaluationException, IllegalArgumentException {
int i = 1;
double s, olds, t, oldt;
@ -58,17 +76,17 @@ public class SimpsonIntegrator extends UnivariateRealIntegratorImpl {
verifyInterval(min, max);
verifyIterationCount();
TrapezoidIntegrator qtrap = new TrapezoidIntegrator(this.f);
TrapezoidIntegrator qtrap = new TrapezoidIntegrator();
if (minimalIterationCount == 1) {
s = (4 * qtrap.stage(min, max, 1) - qtrap.stage(min, max, 0)) / 3.0;
s = (4 * qtrap.stage(f, min, max, 1) - qtrap.stage(f, min, max, 0)) / 3.0;
setResult(s, 1);
return result;
}
// Simpson's rule requires at least two trapezoid stages.
olds = 0;
oldt = qtrap.stage(min, max, 0);
oldt = qtrap.stage(f, min, max, 0);
while (i <= maximalIterationCount) {
t = qtrap.stage(min, max, i);
t = qtrap.stage(f, min, max, i);
s = (4 * t - oldt) / 3.0;
if (i >= minimalIterationCount) {
final double delta = Math.abs(s - olds);

View File

@ -34,21 +34,31 @@ import org.apache.commons.math.analysis.UnivariateRealFunction;
*/
public class TrapezoidIntegrator extends UnivariateRealIntegratorImpl {
/** serializable version identifier */
private static final long serialVersionUID = 4978222553983172543L;
/** Serializable version identifier. */
private static final long serialVersionUID = 6963842845860399200L;
/** intermediate result */
/** Intermediate result. */
private double s;
/**
* Construct an integrator for the given function.
*
* @param f function to integrate
* @deprecated as of 2.0 the integrand function is passed as an argument
* to the {@link #integrate(UnivariateRealFunction, double, double)}method.
*/
@Deprecated
public TrapezoidIntegrator(UnivariateRealFunction f) {
super(f, 64);
}
/**
* Construct an integrator.
*/
public TrapezoidIntegrator() {
super(64);
}
/**
* Compute the n-th stage integral of trapezoid rule. This function
* should only be called by API <code>integrate()</code> in the package.
@ -58,6 +68,7 @@ public class TrapezoidIntegrator extends UnivariateRealIntegratorImpl {
* arbitrary m sections because this configuration can best utilize the
* alrealy computed values.</p>
*
* @param f the integrand function
* @param min the lower bound for the interval
* @param max the upper bound for the interval
* @param n the stage of 1/2 refinement, n = 0 is no refinement
@ -65,8 +76,9 @@ public class TrapezoidIntegrator extends UnivariateRealIntegratorImpl {
* @throws FunctionEvaluationException if an error occurs evaluating the
* function
*/
double stage(double min, double max, int n) throws
FunctionEvaluationException {
double stage(final UnivariateRealFunction f,
final double min, final double max, final int n)
throws FunctionEvaluationException {
long i, np;
double x, spacing, sum = 0;
@ -89,8 +101,16 @@ public class TrapezoidIntegrator extends UnivariateRealIntegratorImpl {
}
/** {@inheritDoc} */
public double integrate(double min, double max) throws MaxIterationsExceededException,
FunctionEvaluationException, IllegalArgumentException {
@Deprecated
public double integrate(final double min, final double max)
throws MaxIterationsExceededException, FunctionEvaluationException, IllegalArgumentException {
return integrate(f, min, max);
}
/** {@inheritDoc} */
public double integrate(final UnivariateRealFunction f,
final double min, final double max)
throws MaxIterationsExceededException, FunctionEvaluationException, IllegalArgumentException {
int i = 1;
double t, oldt;
@ -99,9 +119,9 @@ public class TrapezoidIntegrator extends UnivariateRealIntegratorImpl {
verifyInterval(min, max);
verifyIterationCount();
oldt = stage(min, max, 0);
oldt = stage(f, min, max, 0);
while (i <= maximalIterationCount) {
t = stage(min, max, i);
t = stage(f, min, max, i);
if (i >= minimalIterationCount) {
final double delta = Math.abs(t - oldt);
final double rLimit =

View File

@ -19,6 +19,7 @@ package org.apache.commons.math.analysis.integration;
import org.apache.commons.math.ConvergenceException;
import org.apache.commons.math.ConvergingAlgorithm;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
/**
* Interface for univariate real integration algorithms.
@ -70,10 +71,29 @@ public interface UnivariateRealIntegrator extends ConvergingAlgorithm {
* function
* @throws IllegalArgumentException if min > max or the endpoints do not
* satisfy the requirements specified by the integrator
* @deprecated replaced by {@link #integrate(UnivariateRealFunction, double, double)}
* since 2.0
*/
@Deprecated
double integrate(double min, double max) throws ConvergenceException,
FunctionEvaluationException, IllegalArgumentException;
/**
* Integrate the function in the given interval.
*
* @param min the lower bound for the interval
* @param max the upper bound for the interval
* @return the value of integral
* @throws ConvergenceException if the maximum iteration count is exceeded
* or the integrator detects convergence problems otherwise
* @throws FunctionEvaluationException if an error occurs evaluating the
* function
* @throws IllegalArgumentException if min > max or the endpoints do not
* satisfy the requirements specified by the integrator
*/
double integrate(UnivariateRealFunction f, double min, double max) throws ConvergenceException,
FunctionEvaluationException, IllegalArgumentException;
/**
* Get the result of the last run of the integrator.
*

View File

@ -44,7 +44,10 @@ public abstract class UnivariateRealIntegratorImpl
/** the last computed integral */
protected double result;
/** the integrand function */
/** The integrand functione.
* @deprecated as of 2.0 the integrand function is passed as an argument
* to the {@link #integrate(UnivariateRealFunction, double, double)}method. */
@Deprecated
protected UnivariateRealFunction f;
/**
@ -54,7 +57,10 @@ public abstract class UnivariateRealIntegratorImpl
* @param defaultMaximalIterationCount maximum number of iterations
* @throws IllegalArgumentException if f is null or the iteration
* limits are not valid
* @deprecated as of 2.0 the integrand function is passed as an argument
* to the {@link #integrate(UnivariateRealFunction, double, double)}method.
*/
@Deprecated
protected UnivariateRealIntegratorImpl(final UnivariateRealFunction f,
final int defaultMaximalIterationCount)
throws IllegalArgumentException {
@ -73,6 +79,25 @@ public abstract class UnivariateRealIntegratorImpl
verifyIterationCount();
}
/**
* Construct an integrator with given iteration count and accuracy.
*
* @param defaultMaximalIterationCount maximum number of iterations
* @throws IllegalArgumentException if f is null or the iteration
* limits are not valid
*/
protected UnivariateRealIntegratorImpl(final int defaultMaximalIterationCount)
throws IllegalArgumentException {
super(defaultMaximalIterationCount, 1.0e-15);
// parameters that are problem specific
setRelativeAccuracy(1.0e-6);
this.defaultMinimalIterationCount = 3;
this.minimalIterationCount = defaultMinimalIterationCount;
verifyIterationCount();
}
/**
* Access the last computed integral.
*

View File

@ -76,9 +76,9 @@ The <action> type attribute can be add,update,fix,remove.
Added support for multi-dimensional Fourier transform.
</action>
<action dev="luc" type="update" issue="MATH-218" >
The root solvers now take the function to solve as a parameter to
the solve methods, thus allowing to reuse the same solver for different
functions.
The root solvers and the integrators now take the function to solve as a
parameter to the solve/integrate methods, thus allowing to reuse the same
solver/integrator for different functions.
</action>
<action dev="luc" type="add" issue="MATH-234" >
Added setter methods for rows and columns in matrices.

View File

@ -39,17 +39,17 @@ public final class RombergIntegratorTest extends TestCase {
*/
public void testSinFunction() throws MathException {
UnivariateRealFunction f = new SinFunction();
UnivariateRealIntegrator integrator = new RombergIntegrator(f);
UnivariateRealIntegrator integrator = new RombergIntegrator();
double min, max, expected, result, tolerance;
min = 0; max = Math.PI; expected = 2;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
min = -Math.PI/3; max = 0; expected = -0.5;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
}
@ -58,22 +58,22 @@ public final class RombergIntegratorTest extends TestCase {
*/
public void testQuinticFunction() throws MathException {
UnivariateRealFunction f = new QuinticFunction();
UnivariateRealIntegrator integrator = new RombergIntegrator(f);
UnivariateRealIntegrator integrator = new RombergIntegrator();
double min, max, expected, result, tolerance;
min = 0; max = 1; expected = -1.0/48;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
min = 0; max = 0.5; expected = 11.0/768;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
min = -1; max = 4; expected = 2048/3.0 - 78 + 1.0/48;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
}
@ -82,11 +82,11 @@ public final class RombergIntegratorTest extends TestCase {
*/
public void testParameters() throws Exception {
UnivariateRealFunction f = new SinFunction();
UnivariateRealIntegrator integrator = new RombergIntegrator(f);
UnivariateRealIntegrator integrator = new RombergIntegrator();
try {
// bad interval
integrator.integrate(1, -1);
integrator.integrate(f, 1, -1);
fail("Expecting IllegalArgumentException - bad interval");
} catch (IllegalArgumentException ex) {
// expected
@ -95,7 +95,7 @@ public final class RombergIntegratorTest extends TestCase {
// bad iteration limits
integrator.setMinimalIterationCount(5);
integrator.setMaximalIterationCount(4);
integrator.integrate(-1, 1);
integrator.integrate(f, -1, 1);
fail("Expecting IllegalArgumentException - bad iteration limits");
} catch (IllegalArgumentException ex) {
// expected
@ -104,7 +104,7 @@ public final class RombergIntegratorTest extends TestCase {
// bad iteration limits
integrator.setMinimalIterationCount(10);
integrator.setMaximalIterationCount(50);
integrator.integrate(-1, 1);
integrator.integrate(f, -1, 1);
fail("Expecting IllegalArgumentException - bad iteration limits");
} catch (IllegalArgumentException ex) {
// expected

View File

@ -38,17 +38,17 @@ public final class SimpsonIntegratorTest extends TestCase {
*/
public void testSinFunction() throws MathException {
UnivariateRealFunction f = new SinFunction();
UnivariateRealIntegrator integrator = new SimpsonIntegrator(f);
UnivariateRealIntegrator integrator = new SimpsonIntegrator();
double min, max, expected, result, tolerance;
min = 0; max = Math.PI; expected = 2;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
min = -Math.PI/3; max = 0; expected = -0.5;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
}
@ -57,22 +57,22 @@ public final class SimpsonIntegratorTest extends TestCase {
*/
public void testQuinticFunction() throws MathException {
UnivariateRealFunction f = new QuinticFunction();
UnivariateRealIntegrator integrator = new SimpsonIntegrator(f);
UnivariateRealIntegrator integrator = new SimpsonIntegrator();
double min, max, expected, result, tolerance;
min = 0; max = 1; expected = -1.0/48;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
min = 0; max = 0.5; expected = 11.0/768;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
min = -1; max = 4; expected = 2048/3.0 - 78 + 1.0/48;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
}
@ -81,11 +81,11 @@ public final class SimpsonIntegratorTest extends TestCase {
*/
public void testParameters() throws Exception {
UnivariateRealFunction f = new SinFunction();
UnivariateRealIntegrator integrator = new SimpsonIntegrator(f);
UnivariateRealIntegrator integrator = new SimpsonIntegrator();
try {
// bad interval
integrator.integrate(1, -1);
integrator.integrate(f, 1, -1);
fail("Expecting IllegalArgumentException - bad interval");
} catch (IllegalArgumentException ex) {
// expected
@ -94,7 +94,7 @@ public final class SimpsonIntegratorTest extends TestCase {
// bad iteration limits
integrator.setMinimalIterationCount(5);
integrator.setMaximalIterationCount(4);
integrator.integrate(-1, 1);
integrator.integrate(f, -1, 1);
fail("Expecting IllegalArgumentException - bad iteration limits");
} catch (IllegalArgumentException ex) {
// expected
@ -103,7 +103,7 @@ public final class SimpsonIntegratorTest extends TestCase {
// bad iteration limits
integrator.setMinimalIterationCount(10);
integrator.setMaximalIterationCount(99);
integrator.integrate(-1, 1);
integrator.integrate(f, -1, 1);
fail("Expecting IllegalArgumentException - bad iteration limits");
} catch (IllegalArgumentException ex) {
// expected

View File

@ -38,17 +38,17 @@ public final class TrapezoidIntegratorTest extends TestCase {
*/
public void testSinFunction() throws MathException {
UnivariateRealFunction f = new SinFunction();
UnivariateRealIntegrator integrator = new TrapezoidIntegrator(f);
UnivariateRealIntegrator integrator = new TrapezoidIntegrator();
double min, max, expected, result, tolerance;
min = 0; max = Math.PI; expected = 2;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
min = -Math.PI/3; max = 0; expected = -0.5;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
}
@ -57,22 +57,22 @@ public final class TrapezoidIntegratorTest extends TestCase {
*/
public void testQuinticFunction() throws MathException {
UnivariateRealFunction f = new QuinticFunction();
UnivariateRealIntegrator integrator = new TrapezoidIntegrator(f);
UnivariateRealIntegrator integrator = new TrapezoidIntegrator();
double min, max, expected, result, tolerance;
min = 0; max = 1; expected = -1.0/48;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
min = 0; max = 0.5; expected = 11.0/768;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
min = -1; max = 4; expected = 2048/3.0 - 78 + 1.0/48;
tolerance = Math.abs(expected * integrator.getRelativeAccuracy());
result = integrator.integrate(min, max);
result = integrator.integrate(f, min, max);
assertEquals(expected, result, tolerance);
}
@ -81,11 +81,11 @@ public final class TrapezoidIntegratorTest extends TestCase {
*/
public void testParameters() throws Exception {
UnivariateRealFunction f = new SinFunction();
UnivariateRealIntegrator integrator = new TrapezoidIntegrator(f);
UnivariateRealIntegrator integrator = new TrapezoidIntegrator();
try {
// bad interval
integrator.integrate(1, -1);
integrator.integrate(f, 1, -1);
fail("Expecting IllegalArgumentException - bad interval");
} catch (IllegalArgumentException ex) {
// expected
@ -94,7 +94,7 @@ public final class TrapezoidIntegratorTest extends TestCase {
// bad iteration limits
integrator.setMinimalIterationCount(5);
integrator.setMaximalIterationCount(4);
integrator.integrate(-1, 1);
integrator.integrate(f, -1, 1);
fail("Expecting IllegalArgumentException - bad iteration limits");
} catch (IllegalArgumentException ex) {
// expected
@ -103,7 +103,7 @@ public final class TrapezoidIntegratorTest extends TestCase {
// bad iteration limits
integrator.setMinimalIterationCount(10);
integrator.setMaximalIterationCount(99);
integrator.integrate(-1, 1);
integrator.integrate(f, -1, 1);
fail("Expecting IllegalArgumentException - bad iteration limits");
} catch (IllegalArgumentException ex) {
// expected