经典数值计算

插值问题

物理问题 \rightarrow 离散化 \rightarrow 计算机处理

离散的物理数据,但不知道实际函数\rightarrow 构造近似函数作为实际函数f(x)f(x)的逼近


插值问题的数学表述: f(x)f(x)是定义在区间[a,b][a, b]的函数,(x0,y0), (x1,y1), (x2,y2)..., (xn,yn)(x_0, y_0),\ (x_1, y_1),\ (x_2, y_2)...,\ (x_n, y_n)是该区间上n+1n+1个不同的点。我们需要构造一个便于计算的函数P(x)P(x),s.t.

P(xi)=yiP(x_i) = y_i

则称P(x)P(x)f(x)f(x)的插值函数,[a,b][a, b]是插值区间,(xi,yi)(x_i, y_i)是插值节点。同时在其他xxix \neq x_i点上,P(x)P(x)可以作为f(x)f(x)的近似。

多项式插值

Pn(x)=a0+a1x+a2x2+...+anxn,    a0,a1,...,anRP_n(x) = a_0 + a_1x + a_2x^2 + ... + a_nx^n,\;\; a_0, a_1, ..., a_n \in \mathbb{R}


定理:对于n+1n+1个互不相同的插值节点,满足插值条件的nn次多项式插值函数存在且唯一。


多项式插值方法一 —— 拉格朗日插值法

引入:线性插值

给定两个点(x0,y0)(x_0, y_0)(x1,y1)(x_1, y_1)求解

{a0+a1x0=y0a0+a1x1=y1\begin{cases} a_0+ a_1x_0 = y_0\\ a_0+ a_1x_1 = y_1 \end{cases}

可得

P1(x)=a0+a1x=xx1x0x1y0+xx0x1x0y1P_1(x) = a_0+ a_1x = \frac{x-x_1}{x_0 - x_1}y_0 + \frac{x-x_0}{x_1 - x_0}y_1

推广:拉格朗日插值

Pn(x)=k=0nlk(x)yk,lk(x)=jkxxjxkxj P_n(x) = \sum_{k=0}^n l_k(x) \cdot y_k, \quad l_k(x) = \prod_{j \neq k} \frac{x - x_j}{x_k - x_j}

其中lk(x)l_k(x)被称作基函数。

拉格朗日插值基函数满足以下性质:

  • 归一性:lk(xi)={1i=k0o/wl_k(x_i) = \begin{cases} 1 \quad i = k\\ 0 \quad o/w \end{cases}
  • 多项式次数:每个lkl_knn次多项式。

举例理解

上面的线性插值已经是一个例子。现在看n=2n = 2

对于(x0,x1,x2)(x_0,x_1,x_2)

l0(x)=(xx1)(xx2)(x0x1)(x0x2)l1(x)=(xx0)(xx2)(x1x0)(x1x2)l2(x)=(xx0)(xx1)(x2x0)(x2x1)\begin{aligned} l_0(x) &= \frac{(x-x_1)(x-x_2)}{(x_0-x_1)(x_0-x_2)} \\ l_1(x) &= \frac{(x-x_0)(x-x_2)}{(x_1-x_0)(x_1-x_2)} \\ l_2(x) &= \frac{(x-x_0)(x-x_1)}{(x_2-x_0)(x_2-x_1)} \end{aligned}

线性插值误差


定理:设 f(x)f(x) 一阶连续可导,且 f(x)f''(x) 在区间 (a,b)(a, b) 上存在,则对任意 x[a,b]x \in [a, b],存在 ξ[a,b]\xi \in [a, b] 使得:

R(x)=f(x)P1(x)=f(ξ)2(xx0)(xx1)R(x) = f(x) - P_1(x) = \frac{f''(\xi)}{2}(x-x_0)(x-x_1)


证明过程:

定义误差函数:

R(x)=f(x)P1(x)=k(x)(xx0)(xx1)R(x) = f(x) - P_1(x) = k(x)(x-x_0)(x-x_1)

构造辅助函数:

ϕ(t)=f(t)P1(t)k(x)(tx0)(tx1)\phi(t) = f(t) - P_1(t) - k(x)(t-x_0)(t-x_1)

ϕ(t)\phi(t)x0,x,x1x_0,x,x_1 处有零点,且ϕ(t)\phi'(t)(ξ1,ξ2)(\xi_1,\xi_2) 有零点

\therefore 应用Rolle定理:ϕ(ξ)=0\phi''(\xi) = 0 \Rightarrow f(ξ)=2k(x)f''(\xi) = 2k(x)

一般形式的误差估计: 对于 nn 次插值多项式 Pn(x)P_n(x)

Rn(x)=f(x)Pn(x)=f(n+1)(ξ)(n+1)!ωn+1(x)R_n(x) = f(x) - P_n(x) = \frac{f^{(n+1)}(\xi)}{(n+1)!}\omega_{n+1}(x)

其中:

ωn+1(x)=i=0n(xxi)\omega_{n+1}(x) = \prod_{i=0}^n (x-x_i)

\therefore

  1. 误差与高阶导数 f(n+1)f^{(n+1)} 成正比
  2. 节点越密集 ((xxi)(x-x_i) 越小),误差越小
  3. 增加节点数 nn 可提高精度

很多情况下,f(n+1)f^{(n+1)} 未知,可采用以下方法估计:

使用 n+2n+2 个数据点进行两次插值运算:前 n+1n+1 点构造 Pn(x)P_n(x);后 n+1n+1 点构造 P^n(x)\hat{P}_n(x)。整理可得误差关系式:

f(x)Pn(x)xx0x0xn+1(Pn(x)P^n(x))f(x) - P_n(x) \approx \frac{x-x_0}{x_0-x_{n+1}}(P_n(x)-\hat{P}_n(x))

拉格朗日插值法的优点/缺点:

  • 优点:
    • 显示公式:无需解线性方程组,直接构造多项式。
    • 理论直观
  • 缺点:
    • 计算效率低:新增节点需重新计算所有基函数。
    • 数值不稳定:高次插值时可能因舍入误差放大失效。

多项式插值方法二——牛顿插值法

引入

避开了拉格朗日插值法“新增节点需重新计算所有基函数”这一问题。

由数学知识可知任何一个多项式都可以表示为:

Nn(x)=a0+k=1naki=0k1(xxi)N_n(x) = a_0 + \sum_{k=1}^n a_k \prod_{i=0}^{k-1} (x - x_i)

在牛顿形式下,我们可以认为此时aka_k对应的基函数是kk的多项式i=0k1(xxi)\prod_{i=0}^{k-1} (x - x_i),它们相互独立。因此有更高阶数加入的时候只需计算相应新的多项式系数即可。

计算步骤

将插值条件P(xi)=yiP(x_i) = y_i写成线性方程组的形式:

{y0=a0=f(x0)y1=y0+a1(x1x0)=f(x1)y2=y0+a1(x2x0)+a2(x2x0)(x2x1)=f(x2)...yn=y0+a1(xnx0)+a2(xnx0)(xnx1)+...+an(xnx0)(xnx1)...(xnxn1)=f(xn)\begin{cases} y_0 = a_0 = f(x_0)\\ y_1 = y_0 +a_1 (x_1-x_0) = f(x_1)\\ y_2 = y_0 + a_1 (x_2-x_0) + a_2(x_2-x_0)(x_2-x_1) = f(x_2)\\ ...\\ y_n = y_0 + a_1 (x_n-x_0) + a_2(x_n-x_0)(x_n-x_1) + ... + a_n(x_n-x_0)(x_n-x_1)...(x_n-x_{n-1}) = f(x_n) \end{cases}
引入差商的概念:
(y0,y1)(y_0, y_1)我们引入一阶差商

F(x0,x1)=f(x1)f(x0)x1x0F(x_0, x_1) = \frac{f(x_1) - f(x_0)}{x_1 - x_0}

类似可得更高阶的差商公式:

F(x2,x1)=f(x2)f(x1)x2x1F(x0,x1,x2)=F(x2,x1)F(x0,x1)x2x0...F(x0,...,xn)=F(x1,...,xn)F(x0,...,xn1)xnx0F(x_2, x_1) = \frac{f(x_2) - f(x_1)}{x_2 - x_1}\\ F(x_0, x_1,x_2) = \frac{F(x_2, x_1)-F(x_0, x_1)}{x_2-x_0}\\ ...\\ F(x_0,...,x_n) = \frac{F(x_1,...,x_n)-F(x_0,...,x_{n-1})}{x_n-x_0}

根据以上公式我们可以改写差商形式的牛顿插值多项式:

Pn(x)=F(x0)+k=1nF(x0,...,xk)i=0k1(xxi)P_n(x) = F(x_0) + \sum_{k=1}^n F(x_0,...,x_k) \cdot \prod_{i=0}^{k-1}(x-x_i)

示例

P3(x)=F(x0)+F(x0,x1)(xx0)+F(x0,x1,x2)(xx0)(xx1)+F(x0,x1,x2,x3)(xx0)(xx1)(xx2)\begin{aligned} P_3(x) = & F(x_0)+ F(x_0,x_1)(x-x_0) \\ & + F(x_0,x_1,x_2)(x-x_0)(x-x_1) \\ & + F(x_0,x_1,x_2,x_3)(x-x_0)(x-x_1)(x-x_2) \end{aligned}

牛顿差商的性质

  1. 线性性:
    h(x)=αf(x)+βg(x)h(x) = \alpha f(x) + \beta g(x),则:

H(x0,...,xn)=αF(x0,...,xn)+βG(x0,...,xn)H(x_0,...,x_n) = \alpha F(x_0,...,x_n) + \beta G(x_0,...,x_n)

  1. 对称性
    差商值与节点排列顺序无关:

F(x0,x1,...,xn)=F(xσ(0),xσ(1),...,xσ(n))F(x_0,x_1,...,x_n) = F(x_{\sigma(0)},x_{\sigma(1)},...,x_{\sigma(n)})

其中σ\sigma是任意排列

  1. 差商和导数关系:
    f(x)Cn[a,b]f(x)\in C^n[a,b],则存在ξ(a,b)\xi\in(a,b)使得:

  2. 差商表可加性:
    新增节点xn+1x_{n+1}时:

F(x0,...,xn+1)=F(x1,...,xn+1)F(x0,...,xn)xn+1x0F(x_0,...,x_{n+1}) = \frac{F(x_1,...,x_{n+1}) - F(x_0,...,x_n)}{x_{n+1}-x_0}

F(x0,...,xn)=f(n)(ξ)n!F(x_0,...,x_n) = \frac{f^{(n)}(\xi)}{n!}

荣格(Runge)现象

指在高次多项式插值中,随着插值节点数量的增加,插值结果在区间端点附近出现剧烈振荡的现象。这种现象由德国数学家Carl Runge在研究多项式插值时首次发现。

解决方法:多次线性插值

将插值区间划分为若干子区间,在每个子区间上用线性多项式进行插值的方法。给定节点(x0,y0),(x1,y1),...,(xn,yn)(x_0,y_0),(x_1,y_1),...,(x_n,y_n),我们构造的插值函数应该满足:

  • S(xi)=yiS(x_i) = y_i (通过所有节点)
  • S(x)S(x)在每个[xi,xi+1][x_i,x_{i+1}]上是线性函数
  • 整体函数连续(C0C^0连续)

具体实现步骤:

  1. 找到待插值点xx及其所在的区间[xk,xk+1][x_k,x_{k+1}]
  2. 计算:$ P_1(x) = \frac{x-x_{k+1}}{x_k - x_{k+1}}y_k + \frac{x-x_k}{x_{k+1} - x_k}y_{k+1} $

缺陷:C1C^1不连续

样条插值

样条插值(Spline Interpolation)是一种分段低次多项式插值方法,通过强制拼接点处的光滑条件来保证整体曲线的平滑性。

插值函数需要满足:

  • Si(xi)=yiS_i(x_i)=y_i, Si(xi+1)=yi+1S_i(x_{i+1})=y_{i+1}(插值条件)
  • 连续性:
    • C0C^0: Si1(xi)=Si(xi)S_{i-1}(x_i) = S_i(x_i)
    • C1C^1: Si1(xi)=Si(xi)S'_{i-1}(x_i) = S'_i(x_i)
    • C2C^2: Si1(xi)=Si(xi)S''_{i-1}(x_i) = S''_i(x_i)

最常用:三次样条插值函数,即在每段[xi,xi+1][x_i,x_{i+1}]上构造:

Si(x)=ai+bi(xxi)+ci(xxi)2+di(xxi)3S_i(x) = a_i + b_i(x-x_i) + c_i(x-x_i)^2 + d_i(x-x_i)^3

n+1n+1个插值点,总共有nn个区间,那么总参数有4n4n个。

约束条件:

  • 插值条件:提供 n+1n+1
  • 连续性:提供 3(n1)3(n-1)
  • 边界条件:提供n个

对于x[xk,xk+1)x \in [x_k, x_{k+1})

Sk(x)=ak+bkh+ckh2+dkh3(h=xxk)Sk(x)=bk+2ckh+3dkh2Sk(x)=2ck+6dkh\begin{aligned} S_k(x) &= a_k + b_k h + c_k h^2 + d_k h^3 \quad (h = x-x_k) \\ S'_k(x) &= b_k + 2c_k h + 3d_k h^2 \\ S''_k(x) &= 2c_k + 6d_k h \end{aligned}

应满足条件:

  • Sk(xk)=ykak=ykS_k(x_k) = y_k \Rightarrow a_k = y_k
  • $ S_k(x_{k+1}) = y_{k+1} \Rightarrow a_k + h_k b_k + h_k^2 c_k + h_k^3 d_k = y_{k+1} $ (其中 hk=xk+1xkh_k = x_{k+1}-x_k
  • $ b_k + 2h_k c_k + 3h_k^2 d_k = b_{k+1} $
  • $ 2c_k + 6h_k d_k = 2c_{k+1} $

求解该方程组:
mk=2ckm_k = 2c_k,则:

  1. 由二阶导数连续条件:

    dk=mk+1mk6hkd_k = \frac{m_{k+1}-m_k}{6h_k}

  2. 代入插值方程得:

    bk=yk+1ykhkhk2mkhk6(mk+1mk)b_k = \frac{y_{k+1}-y_k}{h_k} - \frac{h_k}{2}m_k - \frac{h_k}{6}(m_{k+1}-m_k)

  3. 将系数代入一阶导数连续条件,得到:

hkmk+2(hk+hk+1)mk+1+hk+1mk+2=6(yk+2yk+1hk+1yk+1ykhk)h_k m_k + 2(h_k+h_{k+1})m_{k+1} + h_{k+1}m_{k+2} = 6\left(\frac{y_{k+2}-y_{k+1}}{h_{k+1}} - \frac{y_{k+1}-y_k}{h_k}\right)

  1. 将上两个边界条件的约束 \Rightarrow 建立起线性方程组即可求解。

数据拟合

数据拟合是通过数学模型近似描述离散数据点的方法,与插值的区别在于:

  • 插值:强制通过所有数据点
  • 拟合:允许存在偏差,追求整体趋势匹配

最小二乘法拟合

数学原理:最小化残差平方和:

mini=1n(yif(xi))2\min \sum_{i=1}^n (y_i - f(x_i))^2

线性拟合:

考虑f(x)=a+bxf(x) = a + bx
残差平方和:$$Q(a,b) = \sum_{i=1}^n (f(x_i) - y_i)^2 = \sum_{i=1}^n (a + b x_i - y_i)^2$$
Q(a,b)Q(a, b)最小,需满足:

{Qa=2i=1n(a+bxiyi)=0Qb=2i=1n(a+bxiyi)xi=0\begin{cases} \frac{\partial Q}{\partial a} = 2\sum_{i=1}^n (a + b x_i - y_i) = 0\\ \frac{\partial Q}{\partial b} = 2\sum_{i=1}^n (a + b x_i - y_i)x_i = 0 \end{cases}

将方程组整理为矩阵形式:

[nxixixi2][ab]=[yixiyi]\begin{bmatrix} n & \sum x_i \\ \sum x_i & \sum x_i^2 \end{bmatrix} \begin{bmatrix} a \\ b \end{bmatrix} = \begin{bmatrix} \sum y_i \\ \sum x_i y_i \end{bmatrix}

求解(a,b)(a, b)即可。

多项式拟合

k次多项式模型:

f(x)=j=0kajxjf(x) = \sum_{j=0}^k a_j x^j

残差平方和:

{a01+a1xi++amxim=yia0xi+a1xi2++amxim+1=xiyia0xim+a1xim+1++amxi2m=ximyi\begin{cases} a_0 \sum 1 + a_1 \sum x_i + \cdots + a_m \sum x_i^m = \sum y_i \\ a_0 \sum x_i + a_1 \sum x_i^2 + \cdots + a_m \sum x_i^{m+1} = \sum x_i y_i \\ \vdots \\ a_0 \sum x_i^m + a_1 \sum x_i^{m+1} + \cdots + a_m \sum x_i^{2m} = \sum x_i^m y_i \end{cases}

整理成矩阵形式:

[nxiximxixi2xim+1ximxim+1xi2m][a0a1am]=[yixiyiximyi]\begin{bmatrix} n & \sum x_i & \cdots & \sum x_i^m \\ \sum x_i & \sum x_i^2 & \cdots & \sum x_i^{m+1} \\ \vdots & \vdots & \ddots & \vdots \\ \sum x_i^m & \sum x_i^{m+1} & \cdots & \sum x_i^{2m} \end{bmatrix} \begin{bmatrix} a_0 \\ a_1 \\ \vdots \\ a_m \end{bmatrix} = \begin{bmatrix} \sum y_i \\ \sum x_i y_i \\ \vdots \\ \sum x_i^m y_i \end{bmatrix}

求解即可。

非线性拟合

模型类型 变换方法 线性形式
指数模型 y=aebxy=ae^{bx} 取对数 lny=lna+bx\ln y = \ln a + bx
幂函数 y=axby=ax^b 取对数 lny=lna+blnx\ln y = \ln a + b\ln x
对数模型 y=alnx+by=a\ln x + b - 直接拟合
倒数模型 y=xa+bxy = \frac{x}{a+bx} 取倒数 1y=ax+b\frac{1}{y} = \frac{a}{x} + b

容易出现的问题:欠拟合&过拟合。

数值微分

用离散点进行数值微分:

假设数据点均匀分布,xi=x0+ihx_i = x_0 + i \cdot h,在xi1x_{i-1}xix_ixi+1x_{i+1}附近Taylor展开:

fi+1=fi+hfi+h22fi+h36fi+O(h4)f_{i+1} = f_i + h f'_i + \frac{h^2}{2} f''_i + \frac{h^3}{6} f'''_i + O(h^4)

fi1=fihfi+h22fih36fi+O(h4)f_{i-1} = f_i - h f'_i + \frac{h^2}{2} f''_i - \frac{h^3}{6} f'''_i + O(h^4)

就可以得到以下公式:

类型 公式 误差阶
前向差分 f(x)f(x+h)f(x)hf'(x) \approx \frac{f(x+h)-f(x)}{h} O(h)O(h)
后向差分 f(x)f(x)f(xh)hf'(x) \approx \frac{f(x)-f(x-h)}{h} O(h)O(h)
中心差分 f(x)f(x+h)f(xh)2hf'(x) \approx \frac{f(x+h)-f(x-h)}{2h} O(h2)O(h^2)

再在xi2x_{i-2}xi+2x_{i+2}处展开:

fi+2=fi+2hfi+4h22!fi+8h33!fi+...f_{i+2} = f_i + 2h \cdot f_i' + \frac{4h^2}{2!} f_i'' + \frac{8h^3}{3!} f_i'''+...

fi2=fi2hfi+4h22!fi8h33!fi+...f_{i-2} = f_i - 2h \cdot f_i' + \frac{4h^2}{2!} f_i'' - \frac{8h^3}{3!} f_i'''+...

\because

fi+1=fi+hfi+h22fi+h36fi+O(h4)f_{i+1} = f_i + h f'_i + \frac{h^2}{2} f''_i + \frac{h^3}{6} f'''_i + O(h^4)

fi1=fihfi+h22fih36fi+O(h4)f_{i-1} = f_i - h f'_i + \frac{h^2}{2} f''_i - \frac{h^3}{6} f'''_i + O(h^4)

消去fif_i''',可得:

数值积分

数据滤波