9.7. Improper integrals#
When the interval of integration or the integrand itself is unbounded, we say an integral is improper. Improper integrals present particular challenges to numerical computation.
Infinite interval#
When the integration domain is \((-\infty,\infty)\), the integrand has to decay as \(x \to \pm \infty\) in order for the improper integral to be finite. This fact brings up the possibility of truncating the domain:
This integral can be discretized finitely by, say, the trapezoid formula, or an adaptive integrator. However, this approach can be inefficient.
Consider the integral of \(f(x)=1/(1+x^2)\),
In this case we can easily estimate the effect of truncation on the result. For large \(M\),
The same estimate applies to the integral over \((-\infty,-M)\). To get eight digits of accuracy, for instance, we need to truncate with \(M > 2 \times 10^8\).
Double exponential transformation#
In order to do better than direct truncation, we want to encourage the function to decay faster. In practice this means a change of variable, \(x(t)\). If \(|x(t)|\) grows rapidly as \(|t| \to \infty\), then \(f(x(t))\) will decay more rapidly in \(t\) than in \(x\).
One way to accomplish this feat is to use
Noting the asymptotic behavior as \(t \rightarrow \pm\infty\) that
we find that in the same limits,
Thus, (9.7.2) is often referred to as a double exponential transformation.
By the chain rule,
The exponential terms introduced by the chain rule grow double exponentially, but the more rapid decay of \(f\) in the new variable more than makes up for this.
Consider again \(f(x)=1/(1+x^2)\) from Example 9.7.1, with \(x(t)\) given by (9.7.2). As \(t\to\infty\),
The chain rule terms in (9.7.4) become
yielding a product that is roughly
The total integrand in (9.7.4) therefore has double exponential decay in \(t\), essentially because of the squaring of \(x\) in the denominator of \(f\). The same result holds as \(t\to-\infty\).
Show code cell source
f = x -> 1/(1+x^2)
plot(f,-4,4,layout=(2,1),
xlabel=L"x",yaxis=(:log10,L"f(x)",(1e-16,2)),
title="Original integrand")
x = t -> sinh(π*sinh(t)/2)
dx_dt = t -> pi/2*cosh(t)*cosh(pi*sinh(t)/2)
g = t -> f(x(t))*dx_dt(t)
plot!(g,-4,4,subplot=2,
xlabel=L"t",yaxis=(:log10,L"f(x(t))\cdot x'(t)",(1e-16,2)),
title="Transformed integrand")
This graph suggests that we capture all of the integrand values that are larger than machine epsilon by integrating in \(t\) from \(-4\) to \(4\).
Function 9.7.3 implements double exponential integration by applying the adaptive integrator Function 5.7.2 to (9.7.4). It truncates the interval to \(-M\le t \le M\) by increasing \(M\) until the integrand is too small to matter relative to the error tolerance.
Integration of a function over \((-\infty,\infty)\)
1"""
2 intinf(f,tol)
3
4Perform adaptive doubly-exponential integration of function `f`
5over (-Inf,Inf), with error tolerance `tol`. Returns the integral
6estimate and a vector of the nodes used.
7"""
8function intinf(f,tol)
9 x = t -> sinh(sinh(t))
10 dx_dt = t -> cosh(t)*cosh(sinh(t))
11 g = t -> f(x(t))*dx_dt(t)
12
13 # Find where to truncate the integration interval.
14 M = 3
15 while (abs(g(-M)) > tol/100) || (abs(g(M)) > tol/100)
16 M += 0.5
17 if isinf(x(M))
18 @warn "Function may not decay fast enough."
19 M -= 0.5
20 break
21 end
22 end
23
24 I,t = intadapt(g,-M,M,tol)
25 return I,x.(t)
26end
About the code
The test isinf(x(M))
in line 17 checks whether \(x(M)\) is larger than the maximum double-precision value, causing it to overflow to Inf
.
We compare direct truncation in \(x\) to the double exponential method of Function 9.7.3 for \(f(x)=1/(1+x^2)\).
Show code cell source
f = x -> 1/(1+x^2)
tol = [1/10^d for d in 5:0.5:14]
err = zeros(length(tol),2)
len = zeros(Int,length(tol),2)
for (i,tol) in enumerate(tol)
I1,x1 = FNC.intadapt(f,-2/tol,2/tol,tol)
I2,x2 = FNC.intinf(f,tol)
@. err[i,:] = abs(π-[I1,I2])
@. len[i,:] = length([x1,x2])
end
plot(len,err,m=:o,label=["direct" "double exponential"])
n = [100,10000]
plot!(n,1000n.^(-4),l=:dash,label="fourth-order",
xaxis=(:log10,"number of nodes"),yaxis=(:log10,"error"),
title="Comparison of integration methods",leg=:bottomleft)
Both methods are roughly fourth-order due to Simpson’s formula in the underlying adaptive integration method. At equal numbers of evaluation nodes, however, the double exponential method is consistently 2–3 orders of magnitude more accurate.
Integrand singularity#
If \(f\) asymptotically approaches infinity as \(x\) approaches an integration endpoint, its exact integral may or may not be finite. If \(f\) is integrable, then the part of the integration interval near the singularity needs to be more finely resolved than the rest of it.
Let’s consider
where \(f\) and/or a derivative of \(f\) is unbounded at the left endpoint, zero. The change of variable
satisfies \(x(0)=1\) and \(x\to 0^+\) as \(t\to \infty\), thereby transforming the integration interval to \(t\in(0,\infty)\) and placing the singularity at infinity. The chain rule implies
Now the growth of \(f\) and \(\cosh t\) together are counteracted by the double exponential denominator, allowing easy truncation of (9.7.7). This variable transformation is paired with adaptive integration in Function 9.7.5.
Integration of a function with endpoint singularities
1"""
2 intsing(f,tol)
3
4Adaptively integrate function `f` over (0,1), where `f` may be
5singular at zero, with error tolerance `tol`. Returns the
6integral estimate and a vector of the nodes used.
7"""
8function intsing(f,tol)
9 x = t -> 2/(1+exp(2sinh(t)))
10 dx_dt = t -> cosh(t)/cosh(sinh(t))^2
11 g = t -> f(x(t))*dx_dt(t)
12
13 # Find where to truncate the integration interval.
14 M = 3
15 while abs(g(M)) > tol/100
16 M += 0.5
17 if iszero(x(M))
18 @warn "Function may grow too rapidly."
19 M -= 0.5
20 break
21 end
22 end
23
24 I,t = intadapt(g,0,M,tol)
25 return I,x.(t)
26end
About the code
The test iszero(x(M))
in line 17 checks whether \(x(M)\) is less than the smallest positive double-precision value, causing it to underflow to zero.
Let’s use Function 9.7.5 to compute
Since the integration interval is not \([0,1]\), we must first use the change of variable \(s=100t\), yielding
In order to use Function 5.7.2, we must truncate on the left to avoid evaluation at zero, where \(f\) is infinite. Since the integral from \(0\) to \(\delta\) is \(20\sqrt{\delta}\), we use \(\delta=(\epsilon/20)^2\) to achieve error tolerance \(\epsilon\).
Show code cell source
f = x -> 1/(10*sqrt(x))
tol = [1/10^d for d in 5:0.5:14]
err = zeros(length(tol),2)
len = zeros(Int,length(tol),2)
for (i,tol) in enumerate(tol)
I1,x1 = FNC.intadapt(f,(tol/20)^2,1,tol)
I2,x2 = FNC.intsing(f,tol)
@. err[i,:] = abs(0.2-[I1,I2])
@. len[i,:] = length([x1,x2])
end
plot(len,err,m=:o,label=["direct" "double exponential"])
n = [30,3000]
plot!(n,30n.^(-4),l=:dash,label="fourth-order",
xaxis=(:log10,"number of nodes"),yaxis=(:log10,"error"),
title="Comparison of integration methods",leg=:bottomleft)
As in Demo 9.7.4, the double exponential method is more accurate than direct integration by a few orders of magnitude. Equivalently, the same accuracy can be reached with many fewer nodes.
Double exponential integration is an effective general-purpose technique for improper integrals that usually outperforms interval truncation in the original variable. There are specialized methods tailored to specific singularity types that can best it, but those require more analytical work to use properly.
Exercises#
⌨ Use Function 9.7.3 to estimate the given integral with error tolerances \(10^{-3},10^{-6},10^{-9},10^{-12}\). For each result, show the actual error and the number of nodes used.
(a) \(\displaystyle\int_{-\infty}^\infty \dfrac{1}{1+x^2+x^4}\, dx = \dfrac{\pi}{\sqrt{3}}\)
(b) \(\displaystyle\int_{-\infty}^\infty e^{-x^2}\cos(x)\, dx = e^{-1/4}\sqrt{\pi}\)
(c) \(\displaystyle\int_{-\infty}^\infty (1+x^2)^{-2/3}\, dx = \dfrac{\sqrt{\pi}\,\Gamma(1/6)}{\Gamma(2/3)}\) (use
gamma()
for \(\Gamma()\))⌨ Use Function 9.7.5 to estimate the given integral, possibly after rewriting the integral into the form (9.7.5) with a left-endpoint singularity. Use error tolerances \(10^{-3},10^{-6},10^{-9},10^{-12}\), and for each result, show the actual error and the number of nodes used.
(a) \(\displaystyle\int_{0}^1 (\log x)^2\, dx = 2\)
(b) \(\displaystyle\int_{0}^{\pi/4} \sqrt{\tan(x)}\, dx = \dfrac{\pi}{\sqrt{2}}\)
(c) \(\displaystyle\int_{0}^1 \frac{1}{\sqrt{1-x^2}}\, dx = \dfrac{\pi}{2}\)
For integration on a semi-infinite interval such as \(x\in [0,\infty)\), another double exponential transformation is useful: \(x(t)=\exp\left( \sinh t \right)\).
(a) ✍ Show that \(t\in(-\infty,\infty)\) is mapped to \(x\in (0,\infty)\).
(b) ✍ Derive an analog of (9.7.4) for the chain rule on \(\int_0^\infty f(x)\,dx\).
(c) ✍ Show that truncation of \(t\) to \([-M,M]\) will truncate \(x\) to \([1/\mu,\mu]\) for some positive \(\mu\).
(d) ⌨ Write a function
intsemi(f,tol)
for the semi-infinite integration problem. Test it on the integral\[ \displaystyle\int_0^\infty \frac{e^{-x}}{\sqrt{x}}\,dx = \sqrt{\pi}. \]