Note
Go to the end to download the full example code.
Tanh-sinh quadrature: integrating endpoint singularities#
Integrates 1/sqrt(x) and log(x) over [0, 1], whose integrands blow up at 0. The tanh-sinh substitution crowds nodes toward the endpoints with double-exponentially small weights, and converges far faster than Gauss-Legendre quadrature on these integrands.
import matplotlib.pyplot as plt
import numpy as np
from mathematicskit.calculus import GaussianQuadrature, TanhSinhQuadrature
Where the nodes go#
tanh-sinh nodes on [0, 1] (h = 0.5):
2.15e-14, 5.56e-09, 1.13e-05, 0.00124, 0.0243, 0.163, 0.5, 0.837, 0.976, 0.999, 1, 1, 1
Convergence on singular integrands#
cases = {r"$1/\sqrt{x}$": (lambda x: 1 / np.sqrt(x), 2.0), r"$\log x$": (np.log, -1.0)}
hs = [1.0, 0.5, 0.25, 0.125, 0.0625]
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
for ax, (name, (f, exact)) in zip(axes, cases.items()):
evals, errors = [], []
for h in hs:
result = TanhSinhQuadrature(h=h).integrate(f, 0.0, 1.0)
evals.append(result.n_evaluations)
errors.append(max(abs(result.value - exact), 1e-17))
gauss_n = [4, 8, 16, 32, 64, 128]
gauss = [abs(GaussianQuadrature(n).integrate(f, 0.0, 1.0).value - exact) for n in gauss_n]
ax.loglog(evals, errors, "o-", label="tanh-sinh")
ax.loglog(gauss_n, gauss, "s-", label="Gauss-Legendre")
ax.set_xlabel("function evaluations")
ax.set_title(name)
ax.legend()
axes[0].set_ylabel("|error|")

Text(70.72222222222221, 0.5, '|error|')
Total running time of the script: (0 minutes 0.078 seconds)