【数学建模笔记 09-1】数学建模的插值

09-1. 插值

定义

插值:求过已知有限个数据点的近似函数。

插值方法

拉格朗日插值

用多项式作为插值工具,称代数插值。

已知函数 f ( x ) f(x) f(x) 在区间 [ a , b ] [a,b] [a,b] n + 1 n+1 n+1 个不同点 x 0 , x 1 , … , x n x_0,x_1,\dots,x_n x0,x1,,xn 处的函数值 y i = f ( x i ) , i = 0 , 1 , … , n y_i=f(x_i),i=0,1,\dots,n yi=f(xi),i=0,1,,n,求一个至多 n n n 次多项式
φ n ( x ) = a 0 + a 1 x + ⋯ + a n x n \varphi_n(x)=a_0+a_1x+\dots+a_nx^n φn(x)=a0+a1x++anxn
使其在给定点处与 f ( x ) f(x) f(x) 同值,即
φ n ( x i ) = f ( x i ) = y i , i = 0 , 1 , … , n . \varphi_n(x_i)=f(x_i)=y_i,i=0,1,\dots,n. φn(xi)=f(xi)=yi,i=0,1,,n.
根据插值条件,构造方程组
{ a 0 + a 1 x 0 + a 2 x 0 2 + ⋯ + a n x 0 n = y 0 , a 0 + a 1 x 2 + a 2 x 2 2 + ⋯ + a n x 2 n = y 2 , ⋮ a 0 + a 1 x n + a 2 x n 2 + ⋯ + a n x n n = y n . \left\{\begin{aligned} &a_0+a_1x_0+a_2x_0^2+\dots+a_nx_0^n=y_0,\\ &a_0+a_1x_2+a_2x_2^2+\dots+a_nx_2^n=y_2,\\ &\vdots\\ &a_0+a_1x_n+a_2x_n^2+\dots+a_nx_n^n=y_n. \end{aligned}\right. a0+a1x0+a2x02++anx0n=y0,a0+a1x2+a2x22++anx2n=y2,a0+a1xn+a2xn2++anxnn=yn.
记变量矩阵为 A A A,则
det ( A ) = ∣ 1 x 0 x 0 2 … x 0 n 1 x 1 x 1 2 … x 1 n ⋮ ⋮ ⋮ ⋱ ⋮ 1 x n x n 2 … x n n ∣ \text{det}(A)=\begin{vmatrix} 1&x_0&x_0^2&\dots&x_0^n\\ 1&x_1&x_1^2&\dots&x_1^n\\ \vdots&\vdots&\vdots&\ddots&\vdots\\ 1&x_n&x_n^2&\dots&x_n^n\\ \end{vmatrix} det(A)=111x0x1xnx02x12xn2x0nx1nxnn
是范德蒙特行列式。当 x 0 , x 1 , … , x n x_0,x_1,\dots,x_n x0,x1,,xn 互不相同时,值不为 0,因此方程组有唯一解。

构造基函数
l i ( x ) = ( x − x 0 ) … ( x − x i − 1 ) ( x − x i + 1 ) … ( x − x n ) ( x i − x 0 ) … ( x i − x i − 1 ) ( x i − x i + 1 ) … ( x i − x n ) l_i(x)=\frac{(x-x_0)\dots(x-x_{i-1})(x-x_{i+1})\dots(x-x_n)}{(x_i-x_0)\dots(x_i-x_{i-1})(x_i-x_{i+1})\dots(x_i-x_n)} li(x)=(xix0)(xixi1)(xixi+1)(xixn)(xx0)(xxi1)(xxi+1)(xxn)

= ∏ j = 0 , j ≠ i n x − x j x i − x j , i = 0 , 1 , … , n . =\prod_{j=0,j\ne i}^n\frac{x-x_j}{x_i-x_j},i=0,1,\dots,n. =j=0,j=inxixjxxj,i=0,1,,n.

满足
l i ( x j ) = { 1 , j = i , 0 , j ≠ i . l_i(x_j)=\left\{\begin{aligned} &1,j=i,\\ &0,j\ne i. \end{aligned}\right. li(xj)={1,j=i,0,j=i.
这意味着, l i ( x j ) l_i(x_j) li(xj) x j x_j xj 上值为 1,在其他点上值都为 0。

于是有 y i l i ( x j ) y_il_i(x_j) yili(xj) x j x_j xj​ 上值为 y j y_j yj,在其他点上值都为 0。

因此有多项式
L n ( x ) = ∑ i = 0 n y i l i ( x ) = ∑ i = 0 n y i ( ∏ j = 0 , j ≠ i n x − x j x i − x j ) L_n(x)=\sum_{i=0}^ny_il_i(x)=\sum_{i=0}^ny_i(\prod_{j=0,j\ne i}^n\frac{x-x_j}{x_i-x_j}) Ln(x)=i=0nyili(x)=i=0nyi(j=0,j=inxixjxxj)
满足
L n ( x j ) = 0 + 0 + ⋯ + y j + ⋯ + 0 = y j . L_n(x_j)=0+0+\dots+y_j+\dots+0=y_j. Ln(xj)=0+0++yj++0=yj.
这意味着多项式 L n ( x ) L_n(x) Ln(x) x 0 , x 1 , … , x n x_0,x_1,\dots,x_n x0,x1,,xn 各点上,都有 L n ( x j ) = y j L_n(x_j)=y_j Ln(xj)=yj,满足唯一的多项式插值条件。

例子

已知有某个二次多项式函数 f f f,在三个点上的取值为:

  • f ( 4 ) = 10 , f(4)=10, f(4)=10,
  • f ( 5 ) = 5.25 , f(5)=5.25, f(5)=5.25,
  • f ( 6 ) = 1 , f(6)=1, f(6)=1,

f ( 18 ) f(18) f(18) 的值。

首先写出基函数
l 0 ( x ) = ( x − 5 ) ( x − 6 ) ( 4 − 5 ) ( 4 − 6 ) , l_0(x)=\frac{(x-5)(x-6)}{(4-5)(4-6)}, l0(x)=(45)(46)(x5)(x6),

l 1 ( x ) = ( x − 4 ) ( x − 6 ) ( 5 − 4 ) ( 4 − 6 ) , l_1(x)=\frac{(x-4)(x-6)}{(5-4)(4-6)}, l1(x)=(54)(46)(x4)(x6),

l 2 ( x ) = ( x − 4 ) ( x − 5 ) ( 6 − 4 ) ( 6 − 5 ) . l_2(x)=\frac{(x-4)(x-5)}{(6-4)(6-5)}. l2(x)=(64)(65)(x4)(x5).

于是有
L ( x ) = f ( 4 ) l 0 ( x ) + f ( 5 ) l 1 ( x ) + f 6 l 2 ( x ) L(x)=f(4)l_0(x)+f(5)l_1(x)+f_6l_2(x) L(x)=f(4)l0(x)+f(5)l1(x)+f6l2(x)

= 1 4 ( x 2 − 28 x + 136 ) . =\frac14(x^2-28x+136). =41(x228x+136).

f ( 18 ) = L ( 18 ) = − 11 f(18)=L(18)=-11 f(18)=L(18)=11

分段线性插值

即用折线代替曲线,多项式为
P 1 ( x ) = x − x i x i + 1 − x i y i + 1 + x − x i + 1 x i − x i + 1 , P_1(x)=\frac{x-x_i}{x_{i+1}-x_i}y_{i+1}+\frac{x-x_{i+1}}{x_i-x_{i+1}}, P1(x)=xi+1xixxiyi+1+xixi+1xxi+1,

x ∈ [ x i , x i + 1 ] , i = 0 , 1 , … , n − 1. x\in[x_i,x_{i+1}],i=0,1,\dots,n-1. x[xi,xi+1],i=0,1,,n1.

分段二次插值

即用抛物线代替曲线,多项式为
P 2 ( x ) = ( x − x 2 i + 1 ) ( x − x 2 i + 2 ) ( x 2 i − x 2 i + 1 ) ( x 2 i − x 2 i + 2 ) y 2 i P_2(x)=\frac{(x-x_{2i+1})(x-x_{2i+2})}{(x_{2i}-x_{2i+1})(x_{2i}-x_{2i+2})}y_{2i} P2(x)=(x2ix2i+1)(x2ix2i+2)(xx2i+1)(xx2i+2)y2i

+ ( x − x 2 i ) ( x − x 2 i + 2 ) ( x 2 i + 1 − x 2 i ) ( x 2 i + 1 − x 2 i + 2 ) y 2 i + 1 +\frac{(x-x_{2i})(x-x_{2i+2})}{(x_{2i+1}-x_{2i})(x_{2i+1}-x_{2i+2})}y_{2i+1} +(x2i+1x2i)(x2i+1x2i+2)(xx2i)(xx2i+2)y2i+1

+ ( x − x 2 i ) ( x − x 2 i + 1 ) ( x 2 i + 2 − x 2 i + 1 ) ( x 2 i + 2 − x 2 i + 1 ) y 2 i + 2 , +\frac{(x-x_{2i})(x-x_{2i+1})}{(x_{2i+2}-x_{2i+1})(x_{2i+2}-x_{2i+1})}y_{2i+2}, +(x2i+2x2i+1)(x2i+2x2i+1)(xx2i)(xx2i+1)y2i+2,

x ∈ [ x 2 i , x 2 i + 2 ] , i = 0 , 1 , 2 , … , n − 1. x\in[x_{2i},x_{2i+2}],i=0,1,2,\dots,n-1. x[x2i,x2i+2],i=0,1,2,,n1.

牛顿插值

设函数 f ( x ) f(x) f(x) 的一系列相异的结点 x 0 ≤ x 1 ≤ ⋯ ≤ x n x_0\le x_1\le\dots\le x_n x0x1xn,则称
f ( x i ) − f ( x j ) x i − x j , i ≠ j \frac{f(x_i)-f(x_j)}{x_i-x_j},i\ne j xixjf(xi)f(xj),i=j
f ( x ) f(x) f(x) 关于 x i , x j x_i,x_j xi,xj 的一阶差商,记 f [ x i , x j ] f[x_i,x_j] f[xi,xj]

同样的,称一阶差商的差商
f [ x i , x j ] − f [ x j , x k ] x i − x k \frac{f[x_i,x_j]-f[x_j,x_k]}{x_i-x_k} xixkf[xi,xj]f[xj,xk]
f ( x ) f(x) f(x)​ 关于 x i , x j , x k x_i,x_j,x_k xi,xj,xk 的二阶差商,记 f [ x i , x j , x k ] f[x_i,x_j,x_k] f[xi,xj,xk]

同样有
f [ x 0 , x 1 , … , x k ] = f [ x 0 , … , x k − 1 ] − f [ x 1 , … , x k ] x 0 − x k f[x_0,x_1,\dots,x_k]=\frac{f[x_0,\dots,x_{k-1}]-f[x_1,\dots,x_k]}{x_0-x_k} f[x0,x1,,xk]=x0xkf[x0,,xk1]f[x1,,xk]
f ( x ) f(x) f(x) 关于 x 0 , x 1 , … , x k x_0,x_1,\dots,x_k x0,x1,,xk k k k 阶差商。

根据差商定义,有
f ( x ) = f ( x 0 ) + ( x − x 0 ) f [ x , x 0 ] , f(x)=f(x_0)+(x-x_0)f[x,x_0], f(x)=f(x0)+(xx0)f[x,x0],

f [ x , x 0 ] = f [ x 0 , x 1 ] + ( x − x 1 ) f [ x , x 0 , x 1 ] , f[x,x_0]=f[x_0,x_1]+(x-x_1)f[x,x_0,x_1], f[x,x0]=f[x0,x1]+(xx1)f[x,x0,x1],

f [ x , x 0 , x 1 ] = f [ x 0 , x 1 , x 2 ] + ( x − x 2 ) f [ x , x 0 , x 1 , x 2 ] , f[x,x_0,x_1]=f[x_0,x_1,x_2]+(x-x_2)f[x,x_0,x_1,x_2], f[x,x0,x1]=f[x0,x1,x2]+(xx2)f[x,x0,x1,x2],

… \dots

f [ x , x 0 , … , x n − 1 ] = f [ x 0 , … , x n ] + ( x − x n ) f [ x , … , x n ] f[x,x_0,\dots,x_{n-1}]=f[x_0,\dots,x_n]+(x-x_n)f[x,\dots,x_n] f[x,x0,,xn1]=f[x0,,xn]+(xxn)f[x,,xn]

即得
f ( x ) = f ( x 0 ) + ( x − x 0 ) f [ x 0 , x 1 ] + … f(x)=f(x_0)+(x-x_0)f[x_0,x_1]+\dots f(x)=f(x0)+(xx0)f[x0,x1]+

+ ( x − x 0 ) ( x − x 1 ) … ( x − x n − 1 ) f [ x 0 , … , x n ] +(x-x_0)(x-x_1)\dots(x-x_{n-1})f[x_0,\dots,x_n] +(xx0)(xx1)(xxn1)f[x0,,xn]

+ ( x − x 0 ) ( x − x 1 ) … ( x − x n ) f [ x , x 0 , … , x n ] . +(x-x_0)(x-x_1)\dots(x-x_n)f[x,x_0,\dots,x_n]. +(xx0)(xx1)(xxn)f[x,x0,,xn].


N n ( x ) = f ( x 0 ) + ( x − x 0 ) f [ x 0 , x 1 ] + … N_n(x)=f(x_0)+(x-x_0)f[x_0,x_1]+\dots Nn(x)=f(x0)+(xx0)f[x0,x1]+

+ ( x − x 0 ) ( x − x 1 ) … ( x − x n − 1 ) f [ x 0 , … , x n ] , +(x-x_0)(x-x_1)\dots(x-x_{n-1})f[x_0,\dots,x_n], +(xx0)(xx1)(xxn1)f[x0,,xn],

R n ( x ) = ( x − x 0 ) ( x − x 1 ) … ( x − x n ) f [ x , x 0 , … , x n ] . R_n(x)=(x-x_0)(x-x_1)\dots(x-x_n)f[x,x_0,\dots,x_n]. Rn(x)=(xx0)(xx1)(xxn)f[x,x0,,xn].

N n ( x ) N_n(x) Nn(x) f ( x ) f(x) f(x) n n n 次插值多项式, R n ( x ) R_n(x) Rn(x) 称牛顿插值余项。

三次样条插值

三次样条方程 S ( x ) S(x) S(x) 满足以下条件:

  • 在每个分段小区间 [ x i , x i + 1 ] [x_i,x_{i+1}] [xi,xi+1]​ 上, S ( x ) = S i ( x ) S(x)=S_i(x) S(x)=Si(x) 都是一个三次方程;
  • 满足插值条件,即 S ( x i ) = y i , i = 0 , 1 , … , n S(x_i)=y_i,i=0,1,\dots,n S(xi)=yi,i=0,1,,n
  • 曲线光滑,即 S ( x ) , S ′ ( x ) , S ′ ′ ( x ) S(x),S'(x),S''(x) S(x),S(x),S(x) 连续。

则对于第 i i i 个小区间 [ x i , x i + 1 ] [x_i,x_{i+1}] [xi,xi+1]
S i ( x ) = a i + b i x + c i x 2 + d i x 3 , S_i(x)=a_i+b_ix+c_ix^2+d_ix^3, Si(x)=ai+bix+cix2+dix3,
包含 a i , b i , c i , d i a_i,b_i,c_i,d_i ai,bi,ci,di 4 个未知数。

有对于点 x 0 , x 1 , … , x n x_0,x_1,\dots,x_n x0,x1,,xn,有 n n n​ 个小区间,因此要找出 4 n 4n 4n 个方程求解 4 n 4n 4n 个未知数。

为满足插值条件,除两个端点外,所有内部点都满足
S i ( x i + 1 ) = y i + 1 , S i + 1 ( x i + 1 ) = y i + 1 , S_i(x_{i+1})=y_{i+1},S_{i+1}(x_{i+1})=y_{i+1}, Si(xi+1)=yi+1,Si+1(xi+1)=yi+1,

i = 0 , 1 , 2 , … , n − 2 , i=0,1,2,\dots,n-2, i=0,1,2,,n2,

2 ( n − 1 ) 2(n-1) 2(n1)​ 个方程,

加上两个端点
S 0 ( x 0 ) = y 0 , S n − 1 ( x n ) = y n , S_0(x_0)=y_0,S_{n-1}(x_n)=y_n, S0(x0)=y0,Sn1(xn)=yn,
2 n 2n 2n 个方程。

为满足连续条件,有每个内部点对应两个方程的一阶导数和二阶导数相等,即
S i ′ ( x i + 1 ) = S i + 1 ′ ( x i + 1 ) , S i ′ ′ ( x i + 1 ) = S i + 1 ′ ′ ( x i + 1 ) S_i'(x_{i+1})=S_{i+1}'(x_{i+1}),S_i''(x_{i+1})=S_{i+1}''(x_{i+1}) Si(xi+1)=Si+1(xi+1),Si(xi+1)=Si+1(xi+1)

i = 0 , 1 , 2 , … , n − 2 , i=0,1,2,\dots,n-2, i=0,1,2,,n2,

2 n − 2 2n-2 2n2 个方程,总共 4 n − 2 4n-2 4n2 个方程,还差两个。

最后两个方程通过边界条件得到:

  • 自然边界: S 0 ′ ′ ( x 0 ) = S n − 1 ′ ′ ( x n ) = 0 S_0''(x_0)=S_{n-1}''(x_n)=0 S0(x0)=Sn1(xn)=0​​;
  • 固定边界: S 0 ′ ′ ( x 0 ) = A , S n − 1 ′ ′ ( x n ) = B S_0''(x_0)=A,S_{n-1}''(x_n)=B S0(x0)=A,Sn1(xn)=B​​;
  • 非扭结边界: S 0 ′ ′ ′ ( x 0 ) = S 1 ′ ′ ′ ( x 1 ) , S n − 1 ′ ′ ′ ( x n ) = S n − 2 ′ ′ ′ ( x n − 1 ) S_0'''(x_0)=S_1'''(x_1),S_{n-1}'''(x_n)=S_{n-2}'''(x_{n-1}) S0(x0)=S1(x1),Sn1(xn)=Sn2(xn1)

选一种边界条件即可。

若选用自然条件,则构成方程组
{ S i ( x i ) = y i , i = 0 , 1 , … , n , S i ( x i + 1 ) = S i + 1 ( x i + 1 ) , i = 0 , 1 , … , n − 2 , S i ′ ( x i + 1 ) = S i + 1 ′ ( x i + 1 ) , i = 0 , 1 , … , n − 2 , S i ′ ′ ( x i + 1 ) = S i + 1 ′ ′ ( x i + 1 ) , i = 0 , 1 , … , n − 2 , S 0 ′ ′ ( x 0 ) = S n − 1 ′ ′ ( x n ) = 0. \left\{\begin{aligned} &S_i(x_i)=y_i,i=0,1,\dots,n,\\ &S_i(x_i+1)=S_{i+1}(x_{i+1}),i=0,1,\dots,n-2,\\ &S_i'(x_i+1)=S_{i+1}'(x_{i+1}),i=0,1,\dots,n-2,\\ &S_i''(x_i+1)=S_{i+1}''(x_{i+1}),i=0,1,\dots,n-2,\\ &S_0''(x_0)=S_{n-1}''(x_n)=0. \end{aligned}\right. Si(xi)=yi,i=0,1,,n,Si(xi+1)=Si+1(xi+1),i=0,1,,n2,Si(xi+1)=Si+1(xi+1),i=0,1,,n2,Si(xi+1)=Si+1(xi+1),i=0,1,,n2,S0(x0)=Sn1(xn)=0.
对方程组求解即可。

求解方程组的过程较繁琐,思路是将方程组转化为线性形式,此处不过多赘述,大致思路为,令
S j ( x ) = a j + b j ( x − x j ) + c j ( x − x j ) 2 + d j ( x − x 3 ) 3 S_j(x)=a_j+b_j(x-x_j)+c_j(x-x_j)^2+d_j(x-x_3)^3 Sj(x)=aj+bj(xxj)+cj(xxj)2+dj(xx3)3
a j + 1 = S j ( x j + 1 ) = S j + 1 ( x j 1 ) a_{j+1}=S_j(x_{j+1})=S_{j+1}(x_{j_1}) aj+1=Sj(xj+1)=Sj+1(xj1)​。

h j = x j + 1 − x j h_j=x_{j+1}-x_j hj=xj+1xj,​​


a j + 1 = a j + b j h j + c j h j 2 + d j h j 3 , a_{j+1}=a_j+b_jh_j+c_jh_j^2+d_jh_j^3, aj+1=aj+bjhj+cjhj2+djhj3,
于是有
b j + 1 = b j + 2 c j h j + 3 d j h j 2 , b_{j+1}=b_j+2c_jh_j+3d_jh_j^2, bj+1=bj+2cjhj+3djhj2,

c j + 1 = c j + 3 d j h j . c_{j+1}=c_j+3d_jh_j. cj+1=cj+3djhj.

得到线性方程组,求解即可。

Python 代码

拉格朗日插值

使用 scipy 对上述例题进行拉格朗日插值,代码如下:

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# @ author: Koorye
# @ date: 2021-7-25
# @ function: 使用 scipy 包进行拉格朗日插值

# %%

import numpy as np
from scipy.interpolate import lagrange

# %%

x = np.array([4, 5, 6])
y = np.array([10, 5.25, 1])

poly = lagrange(x, y)
res = poly(18)

# %%

print('poly =\n', poly)
print('res =', res)

# %%

import matplotlib.pyplot as plt

x1 = [i for i in range(-5,20)]
y1 = []
for each in x1:
	y1.append(poly(each))

plt.plot(x1, y1)
plt.scatter(x,y)
plt.scatter(18, res)

输出如下:

poly =
       2
0.25 x - 7 x + 34
res = -11.0

可以看出,结果为
f ( x ) = 0.25 x 2 − 7 x + 34 , f ( 18 ) = − 11. f(x)=0.25x^2-7x+34,f(18)=-11. f(x)=0.25x27x+34,f(18)=11.
并在图上标注出来。

样条插值

使用 scipy 对 (1,4), (2,3), (5,7), (8,11), (9,5), (12,3), (15,13), (17,10) 进行一次、二次、三次样条插值,代码如下:

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# @ author: Koorye
# @ date: 2021-7-25
# @ function: 使用 scipy 包进行样条插值

# %%

import numpy as np
from scipy.interpolate import interp1d

# %%

x = np.array([1, 2, 5, 8, 9, 12, 15, 17])
y = np.array([4, 3, 7, 11, 5, 3, 13, 10])

p1 = interp1d(x, y, kind='linear')
p2 = interp1d(x, y, kind='quadratic')
p3 = interp1d(x, y, kind='cubic')

# %%

x1 = np.linspace(1, 17, 100)
y1 = p1(x1)
y2 = p2(x1)
y3 = p3(x1)

import matplotlib.pyplot as plt

plt.scatter(x,y)
plt.plot(x1,y1, label='linear')
plt.plot(x1,y2, label='quadratic')
plt.plot(x1,y3, label='cubic')
plt.legend()

输出如下:

其中蓝线、黄线、绿线分别对应一次、二次、三次样条插值。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值