Romberg's method

From Wikipedia, the free encyclopedia

In numerical analysis, Romberg's method (Romberg 1955) generates a triangular array consisting of numerical estimates of the definite integral

 \int_a^b f(x) \, dx

by using Richardson extrapolation (Richardson 1910) repeatedly on the trapezium rule. Romberg's method evaluates the integrand at equally-spaced points. The integrand must have continuous derivatives, though fairly good results may be obtained if only a few derivatives exist. If it is possible to evaluate the integrand at unequally-spaced points, then other methods such as Gaussian quadrature and Clenshaw–Curtis quadrature are generally more accurate.

Contents

[edit] Method

The method can be defined inductively in this way:

R(0,0) = \frac{1}{2} (b-a) (f(a) + f(b))
R(n,0) = \frac{1}{2} R(n-1,0) + h_n \sum_{k=1}^{2^{n-1}} f(a + (2k-1)h_n)
R(n,m) = R(n,m-1) + \frac{1}{4^m-1} (R(n,m-1) - R(n-1,m-1))

or

R(n,m) = \frac{1}{4^m-1} ( 4^m R(n,m-1) - R(n-1,m-1))

where

 n \ge 1
 m \ge 1
 h_n = \frac{b-a}{2^n}.

In big O notation, the error for R(n,m) is:

 O\left(h_n^{2^{m+1}}\right).

The zeroeth extrapolation, R(n,0), is equivalent to the Trapezoidal Rule with n + 2 points; the first extrapolation, R(n,1), is equivalent to Simpson's rule with n + 2 points.

When function evaluations are expensive, it may be preferable to replace the polynomial interpolation of Richardson with the rational interpolation proposed by Bulirsch & Stoer (1967).

[edit] Python implementation of Romberg's method

Here is an implementation of Romberg's method in Python.

def print_row(lst):
    print ' '.join('%11.8f' % x for x in lst)
 
def romberg(f, a, b, eps = 1E-8):
    """Approximate the definite integral of f from a to b by Romberg's method.
    eps is the desired accuracy."""
    R = [[0.5 * (b - a) * (f(a) + f(b))]]  # R[0][0]
    print_row(R[0])
    n = 1
    while True:
        h = float(b-a)/2**n
        R.append((n+1)*[None])  # Add an empty row.
        R[n][0] = 0.5*R[n-1][0] + h*sum(f(a+(2*k-1)*h) for k in range(1, 2**(n-1)+1)) # for proper limits
        for m in range(1, n+1):
            R[n][m] = R[n][m-1] + (R[n][m-1] - R[n-1][m-1]) / (4**m - 1)
        print_row(R[n])
        if abs(R[n][n-1] - R[n][n]) < eps:
            return R[n][n]
        n += 1
 
from math import *
 
# In this example, the error function erf(1) is evaluated.
print romberg(lambda t: 2/sqrt(pi)*exp(-t*t), 0, 1)

[edit] Example

As an example, the Gaussian function is integrated from 0 to 1, i.e. the Error function {\rm erf}(1)\doteq 0.842700792949715. The triangular array is calculated row by row and calculation is terminated if the two last entries in the last row differ less than 1E-8.

 0.77174333
 0.82526296  0.84310283
 0.83836778  0.84273605  0.84271160
 0.84161922  0.84270304  0.84270083  0.84270066
 0.84243051  0.84270093  0.84270079  0.84270079  0.84270079

The result in the lower right corner of the triangular array is accurate to the digits shown. It is remarkable that this result is derived from the less accurate approximations obtained by the trapezium rule in the first column of the triangular array.

[edit] References

[edit] External links