Gaussian Quadrature

适用于积分区间内平滑的积分.

Computes the sample points and weights for Gauss-Legendre quadrature. The sample points are the roots of the n-th degree Legendre polynomial . These sample points and weights correctly integrate polynomials of degree or less over the interval with weight function .

$$\begin{align} \int_{-1}^1 f(x)\mathrm{d}x = \sum_{i=1}^n w_i f(x_i) \end{align}$$

其中 $x_i$ 是 $n$ 阶 Legendre 多项式的根. $x_i$ 和权重 $w_i$ 可以由 scipy.special.roots_ legendre 生成:

Computes the sample points and weights for Gauss-Legendre quadrature. The sample points are the roots of the n-th degree Legendre polynomial . These sample points and weights correctly integrate polynomials of degree or less over the interval with weight function .

积分区间不在 $[-1, 1]$ , 可以通过换换元来转换

$$\begin{align} \int_a^b f(x) \mathrm{d}x = \frac{b-a}{2}\int_{-1}^1 f(\frac{b-a}{2}t + \frac{b+a}{2})\mathrm{d}t \end{align}$$
  from scipy.special import roots_legendre as leg
  def gauquad(f, a, b, n=50):
      '''
      定义 Gaussian quadrature 积分
      函数 f 的积分区间为 [a,b]
      取 n 个 Legendre 的根
      def Gaussian quadrature integration
      integrate function f from a to b
      take n Legendre roots
      '''
      ft = lambda t: f( (b-a)*t/2 +(a+b)/2 ) * (b-a)/2
      x, w = leg(n)
      I = 0
      for i in range(n):
          I = I + w[i]*ft(x[i])
      err = 0                     # 为了与 scipy.integrate 中积分函数的输出一致, 多一个 err 参数.
      return I,err

Cauchy Principal Value (CPV) Gaussian Quadrature

CPV 用 Gaussian quadrature 时不能给出正确的结果. 这时可以将函数的积部 分和偶部分分开算.

计算积分

$$\begin{align} \mathcal{P}\int_{-a}^af(x) \mathrm{d}x = \lim_{r\to 0^+}\left[ \int_{-a}^{-r} f(x)\mathrm{d}x +\int_{r}^af(x)\mathrm{d}x \right] \end{align}$$

其中 $0$ 为奇点.

关于奇点的 Odd 部分

$$\begin{align} g(x) = \frac{1}{2}\left[ f(x)-f(-x) \right] \end{align}$$

Even 部分

$$\begin{align} h(x) = \frac{1}{2}\left[ f(x) + f(-x)\right] \end{align}$$

总的积分

$$\begin{align} \mathcal{P}\int_{-a}^a f(x) \mathrm{d}x = \lim_{r\to 0^+} \int_r^a \left[ f(x) + f(-x)\right] \mathrm{d}x \end{align}$$

如果奇点不是 $0$ , 也可以通过换元转化成上式的形式.

code

from scipy import integrate
from scipy.integrate import fixed_quad
def sgq(f, a, b, sp, n=10):
    """带有主值积分的积分.
    Singular Gaussian quadrature."""
    diffa = sp - a
    diffb = b - sp
    def ff(t):
        ff = f(t+sp) + f(-t+sp)
        return ff
    if diffa<diffb:
        sgq1, err = gauquad(ff, 0, sp-a, n=rootNum)
        sgq2, err = gauquad(f, 2*sp-a, b, n=rootNum)
    else:
        sgq1, err = gauquad(ff, 0, b-sp, n=rootNum)
        sgq2, err = gauquad(f, a, 2*sp-b, n=rootNum)
    sgq = sgq1 + sgq2
    return sgq, err

Tanh-Sinh Quadrature

对于端点发散的情况, 可以用 Tanh-Sinh quadrature (Double Exponential) 方法. 对于积分

$$\begin{align} \int_{-1}^1 f(x)\mathrm{d}x \end{align}$$

通过换元

$$\begin{align} x = \tanh \left( \frac{1}{2}\pi \sinh t \right) \end{align}$$

将积分区间 $x\in [-1, 1]$ 换为 $t\in (-\infty, +\infty)$ .

$$\begin{align} \int_{-1}^1 f(x)\mathrm{d}x = \int_{-\infty}^{+\infty}f[x(t)] w(t)\mathrm{d}t \end{align}$$

其中

$$\begin{align} w(t) = \frac{\mathrm{d}}{\mathrm{d}t}x(t) =\frac{ \frac{1}{2}\pi \cosh t}{\cosh^2\left( \frac{1}{2}\pi \sinh t \right)} \end{align}$$

权重 $w(t)$ 是一个以原点为中心的钟形函数, 因此可以抵消原来在端点的发散.

然后将积分离散化, 将积分区间作适当截断, 做数值计算.

def ts(f, a, b, n=51):
    """Tanh-sinh quadrature 方法.
    适用于端点发散的情况."""
    up = 4
    h = 2*up / (n-1)
    t = np.linspace(-up, up, n, endpoint=True)
    x = np.tanh(1/2*np.pi*np.sinh(t))
    w = 1/2*h*np.pi*np.cosh(t)
    w = w/(np.cosh(1/2*np.pi*np.sinh(t))**2)
    gc = 0
    for i in range(n):
        p = (x[i]*(b-a) + a + b)/2
        gc = gc + f(p)*w[i]
    err = 0
    gc = gc * (b-a)/2
    return gc, err

Reference

https://www.win.tue.nl/casa/meetings/seminar/previous/_abstract021106_files/Improper_integral1.pdf