函数插值的python实现——拉格朗日、牛顿插值
1. 拉格朗日(Larange)插值
\qquad 拉格朗日插值,是通过构造 n + 1 n+1 n+1 个插值节点来构造 n n n 阶插值多项式。
\qquad 假设 n + 1 n+1 n+1 个插值节点为 x 0 , x 1 , ⋯ , x n x_0,x_1,\cdots,x_n x0,x1,⋯,xn,且满足函数插值条件:
L n ( x k ) = f ( x k ) = f k , k = 0 , 1 , ⋯ , n \qquad\qquad L_n(x_k)=f(x_k)=f_k\ ,\quad k=0,1,\cdots,n Ln(xk)=f(xk)=fk ,k=0,1,⋯,n
\qquad
\qquad
拉格朗日插值的
n
n
n 阶插值基函数为:
l k ( x ) = ( x − x 0 ) ⋯ ( x − x k − 1 ) ( x − x k + 1 ) ⋯ ( x − x n ) ( x k − x 0 ) ⋯ ( x k − x k − 1 ) ( x k − x k + 1 ) ⋯ ( x k − x n ) \qquad\qquad l_k(x)=\dfrac{(x-x_0)\cdots(x-x_{k-1})(x-x_{k+1})\cdots(x-x_n)}{(x_k-x_0)\cdots(x_k-x_{k-1})(x_k-x_{k+1})\cdots(x_k-x_n)} lk(x)=(xk−x0)⋯(xk−xk−1)(xk−xk+1)⋯(xk−xn)(x−x0)⋯(x−xk−1)(x−xk+1)⋯(x−xn)
\qquad
\qquad
显然,对于任意的插值节点
x
i
x_i
xi,插值基函数满足:
l k ( x i ) = { 1 , x i = x k 0 , x i ≠ x k \qquad\qquad l_k(x_i)=\left\{\begin{aligned}\ 1,\qquad x_i=x_k\\ \\ \ 0,\qquad x_i\ne x_k\end{aligned}\right. lk(xi)=⎩ ⎨ ⎧ 1,xi=xk 0,xi=xk
\qquad 因此, n n n 阶拉格朗日插值多项式就可以写为: L n ( x ) = ∑ k = 0 n f k l k ( x ) L_n(x)=\displaystyle\sum_{k=0}^nf_kl_k(x) Ln(x)=k=0∑nfklk(x)
假设 f ( n ) ( x ) f^{(n)}(x) f(n)(x) 在 [ a , b ] [a,b] [a,b] 上连续, f ( n + 1 ) ( x ) f^{(n+1)}(x) f(n+1)(x) 在 ( a , b ) (a,b) (a,b) 上存在
假设 n + 1 n+1 n+1 个插值节点 a ≤ x 0 < x 1 < ⋯ < x n ≤ b a\le x_0<x_1<\cdots<x_n\le b a≤x0<x1<⋯<xn≤b
记 n + 1 n+1 n+1 阶多项式 ω n + 1 ( x ) = ( x − x 0 ) ( x − x 1 ) ⋯ ( x − x n ) \omega_{n+1}(x)=(x-x_0)(x-x_1)\cdots(x-x_{n}) ωn+1(x)=(x−x0)(x−x1)⋯(x−xn)
插值余项
:
R n ( x ) = f ( x ) − L n ( x ) = f ( n + 1 ) ( ξ ) ( n + 1 ) ! ω n + 1 ( x ) , ξ ∈ ( a , b ) , ∀ x ∈ [ a , b ] R_n(x)=f(x)-L_n(x)=\dfrac{f^{(n+1)}(\xi)}{(n+1)!}\omega_{n+1}(x),\quad\xi\in(a,b),\ \forall x\in[a,b] Rn(x)=f(x)−Ln(x)=(n+1)!f(n+1)(ξ)ωn+1(x),ξ∈(a,b), ∀x∈[a,b]
\qquad
实现代码
import numpy as np
import matplotlib.pyplot as plt
def intLagrange(x,xcp,f):
hatf = np.zeros(len(x))
for n in range(len(x)):
for k in range(len(xcp)):
xcp1 = xcp.copy()
xcp1[k] = xcp[k] - 1
xcp2 = xcp.copy()
xcp2[k] = x[n] - 1
hatf[n] += f(xcp[k])*np.prod(x[n]-xcp2)/np.prod(xcp[k]-xcp1)
return hatf
if __name__ == '__main__':
plt.figure(figsize=(7, 4))
# parameters
cpnum = 17 # 插值节点数
xs = -9
xe = 11
x = np.arange(xs,xe,0.1) #待插值点
xcp = np.linspace(xs,xe,cpnum)
# function to be interpolated
f = lambda x: x**2 + 30*np.sin(x)
plt.plot(x,f(x))
# Lagrange
hatf = intLagrange(x,xcp,f)
plt.plot(x,hatf)
# plot control point
for i in range(len(xcp)):
plt.plot(xcp[i],f(xcp[i]),'ro',markerfacecolor='none')
plt.legend(['original','Lagrange','control point'])
plt.title('Lagrange Interpolation')
plt.show()
运行结果:
\qquad
拉格朗日插值法的主要缺点:一旦插值节点的数量 n n n 发生改变,所有的插值基函数 l k ( x ) , k = 0 , 1 , ⋯ , n l_k(x),\ k=0,1,\cdots,n lk(x), k=0,1,⋯,n 都需要重新计算。
\qquad
2. 牛顿(Larange)插值
2.1 牛顿插值多项式的基本形式
\qquad 拉格朗日插值法的主要缺点:一旦插值节点的数量 n n n 发生改变,所有的插值基函数 l k ( x ) , k = 0 , 1 , ⋯ , n l_k(x),\ k=0,1,\cdots,n lk(x), k=0,1,⋯,n 都需要重新计算。
\qquad 牛顿插值法可以克服这一缺点, n n n 阶牛顿插值多项式的形式为:
P n ( x ) = a 0 + a 1 ( x − x 0 ) + a 2 ( x − x 0 ) ( x − x 1 ) + ⋯ + a n ( x − x 0 ) ( x − x 1 ) ⋯ ( x − x n − 1 ) \qquad\qquad P_n(x)=a_0+a_1(x-x_0)+a_2(x-x_0)(x-x_1)+\cdots+a_n(x-x_0)(x-x_1)\cdots(x-x_{n-1}) Pn(x)=a0+a1(x−x0)+a2(x−x0)(x−x1)+⋯+an(x−x0)(x−x1)⋯(x−xn−1)
显然, n n n 阶牛顿插值多项式 P n ( x ) P_n(x) Pn(x) 只与 n n n 个插值节点 x 0 , x 1 , ⋯ , x n − 1 x_0,x_1,\cdots,x_{n-1} x0,x1,⋯,xn−1 有关。
\qquad
\qquad
如果增加一个新的插值节点
x
n
x_n
xn,那么新的
n
+
1
n+1
n+1 阶牛顿插值多项式
P
n
+
1
(
x
)
P_{n+1}(x)
Pn+1(x) 只需要在
P
n
(
x
)
P_n(x)
Pn(x) 后再增加一项:
P n + 1 ( x ) = P n ( x ) + \qquad\qquad P_{n+1}(x)=P_n(x)+ Pn+1(x)=Pn(x)+ a n + 1 ( x − x 0 ) ( x − x 1 ) ⋯ ( x − x n − 1 ) ( x − x n ) \ a_{n+1}(x-x_0)(x-x_1)\cdots(x-x_{n-1})(x-x_n) an+1(x−x0)(x−x1)⋯(x−xn−1)(x−xn)
\qquad
\qquad
对于
n
n
n 阶牛顿插值多项式
P
n
(
x
)
P_n(x)
Pn(x),需要求出
n
n
n 个插值系数
a
0
,
a
1
,
⋯
,
a
n
−
1
a_0,a_1,\cdots,a_{n-1}
a0,a1,⋯,an−1,并且满足函数插值条件:
P
n
(
x
i
)
=
f
(
x
i
)
,
i
=
0
,
1
,
⋯
,
n
−
1
\qquad\qquad P_n(x_i)=f(x_i),\quad i=0,1,\cdots,n-1
Pn(xi)=f(xi),i=0,1,⋯,n−1
\qquad
2.2 牛顿均差插值多项式
\qquad 将某个插值节点 x k x_k xk 的函数值记为 f k = f ( x k ) f_k=f(x_k) fk=f(xk),已知区间 [ x 0 , x n − 1 ] [x_0,x_{n-1}] [x0,xn−1] 上的 n n n 个插值节点 x 0 , x 1 , ⋯ , x n − 1 x_0,x_1,\cdots,x_{n-1} x0,x1,⋯,xn−1 的函数值 f 0 , f 1 , ⋯ , f n − 1 f_0,f_1,\cdots,f_{n-1} f0,f1,⋯,fn−1。
\qquad 分析牛顿插值多项式:
P n ( x ) = a 0 + a 1 ( x − x 0 ) + a 2 ( x − x 0 ) ( x − x 1 ) + ⋯ + a n ( x − x 0 ) ( x − x 1 ) ⋯ ( x − x n − 1 ) \qquad\qquad P_n(x)=a_0+a_1(x-x_0)+a_2(x-x_0)(x-x_1)+\cdots+a_n(x-x_0)(x-x_1)\cdots(x-x_{n-1}) Pn(x)=a0+a1(x−x0)+a2(x−x0)(x−x1)+⋯+an(x−x0)(x−x1)⋯(x−xn−1)
\qquad 可以依次求出牛顿插值多项式的各个系数:
(
1
)
\qquad(1)
(1) 当
x
=
x
0
x=x_0
x=x0 时,
P
n
(
x
0
)
=
a
0
=
f
0
P_n(x_0)=a_0=f_0
Pn(x0)=a0=f0
⟹
a
0
=
f
0
\qquad\newline\qquad\qquad\qquad\qquad\qquad\qquad\Longrightarrow a_0=f_0
⟹a0=f0
(
2
)
\qquad(2)
(2) 当
x
=
x
1
x=x_1
x=x1 时,
P
n
(
x
1
)
=
a
0
+
a
1
(
x
1
−
x
0
)
=
f
1
P_n(x_1)=a_0+a_1(x_1-x_0)=f_1
Pn(x1)=a0+a1(x1−x0)=f1
⟹
a
1
=
f
1
−
f
0
x
1
−
x
0
\qquad\newline\qquad\qquad\qquad\qquad\qquad\qquad\Longrightarrow a_1=\dfrac{f_1-f_0}{x_1-x_0}
⟹a1=x1−x0f1−f0
(
3
)
\qquad(3)
(3) 当
x
=
x
2
x=x_2
x=x2 时,
P
n
(
x
2
)
=
a
0
+
a
1
(
x
2
−
x
0
)
+
a
2
(
x
2
−
x
0
)
(
x
2
−
x
1
)
=
f
2
P_n(x_2)=a_0+a_1(x_2-x_0)+a_2(x_2-x_0)(x_2-x_1)=f_2
Pn(x2)=a0+a1(x2−x0)+a2(x2−x0)(x2−x1)=f2
⟹
a
2
=
f
2
−
f
0
x
2
−
x
0
−
f
1
−
f
0
x
1
−
x
0
x
2
−
x
1
\qquad\newline\qquad\qquad\qquad\qquad\qquad\qquad\Longrightarrow a_2=\dfrac{\dfrac{f_2-f_0}{x_2-x_0}-\dfrac{f_1-f_0}{x_1-x_0}}{x_2-x_1}
⟹a2=x2−x1x2−x0f2−f0−x1−x0f1−f0
\qquad
(
4
)
\qquad(4)
(4) 依次递推,可以求出其余系数
a
3
,
⋯
,
a
n
−
1
a_3,\cdots,a_{n-1}
a3,⋯,an−1
\qquad
(1) 均差的定义
\qquad
定义一阶均差
:
f
[
x
0
,
x
k
]
=
f
(
x
k
)
−
f
(
x
0
)
x
k
−
x
0
f[x_0,x_k]=\dfrac{f(x_k)-f(x_0)}{x_k-x_0}
f[x0,xk]=xk−x0f(xk)−f(x0)
\qquad
二阶均差
:
f
[
x
0
,
x
1
,
x
k
]
=
f
[
x
0
,
x
k
]
−
f
[
x
0
,
x
1
]
x
k
−
x
1
f[x_0,x_1,x_k]=\dfrac{f[x_0,x_k]-f[x_0,x_1]}{x_k-x_1}
f[x0,x1,xk]=xk−x1f[x0,xk]−f[x0,x1]
\qquad
以及k阶均差
:
f [ x 0 , x 1 , ⋯ , x k ] = f [ x 0 , ⋯ , x k − 2 , x k ] − f [ x 0 , x 1 , ⋯ , x k − 1 ] x k − x k − 1 \qquad\qquad f[x_0,x_1,\cdots,x_k]=\dfrac{f[x_0,\cdots,x_{k-2},x_k]-f[x_0,x_1,\cdots,x_{k-1}]}{x_k-x_{k-1}} f[x0,x1,⋯,xk]=xk−xk−1f[x0,⋯,xk−2,xk]−f[x0,x1,⋯,xk−1]
引入均差之后,显然 a 0 = f ( x 0 ) , a 1 = f [ x 0 , x 1 ] , a 2 = f [ x 0 , x 1 , x 2 ] , ⋯ a_0=f(x_0),\ a_1=f[x_0,x_1],\ a_2=f[x_0,x_1,x_2],\ \cdots a0=f(x0), a1=f[x0,x1], a2=f[x0,x1,x2], ⋯
\qquad
那么
n
n
n 阶牛顿插值多项式就可以写为:
N
n
(
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
n
]
(
x
−
x
0
)
(
x
−
x
1
)
⋯
(
x
−
x
n
−
1
)
\qquad\qquad\begin{aligned}N_n(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)\\ &\quad+\cdots+f[x_0,x_1,\cdots,x_n](x-x_0)(x-x_1)\cdots(x-x_{n-1})\end{aligned}
Nn(x)=f(x0)+f[x0,x1](x−x0)+f[x0,x1,x2](x−x0)(x−x1)+⋯+f[x0,x1,⋯,xn](x−x0)(x−x1)⋯(x−xn−1)
\qquad
(2) 均差表
\qquad
为了简化计算,可根据均差的对称性
(均差与节点的排列次序无关),将
k
k
k 阶均差的表达式写为:
f
[
x
0
,
x
1
,
⋯
,
x
k
]
=
f
[
x
1
,
x
2
,
⋯
,
x
k
]
−
f
[
x
0
,
x
1
,
⋯
,
x
k
−
1
]
x
k
−
x
0
\qquad\qquad f[x_0,x_1,\cdots,x_k]=\dfrac{f[x_1,x_2,\cdots,x_k]-f[x_0,x_1,\cdots,x_{k-1}]}{x_k-x_0}
f[x0,x1,⋯,xk]=xk−x0f[x1,x2,⋯,xk]−f[x0,x1,⋯,xk−1]
\qquad
根据该公式,就可以将
n
n
n 阶牛顿插值多项式的插值系数
a
0
,
a
1
,
⋯
,
a
n
−
1
a_0,a_1,\cdots,a_{n-1}
a0,a1,⋯,an−1 的求解过程列成均差表
:
x k x_k xk | f ( x k ) f(x_k) f(xk) | 一阶均差 | 二阶均差 | 三阶均差 |
---|---|---|---|---|
x 0 x_0 x0 | f ( x 0 ) ‾ \underline{f(x_0)} f(x0) | |||
x 1 x_1 x1 | f ( x 1 ) f(x_1) f(x1) | f [ x 0 , x 1 ] ‾ \underline{f[x_0,x_1]} f[x0,x1] | ||
x 2 x_2 x2 | f ( x 2 ) f(x_2) f(x2) | f [ x 1 , x 2 ] f[x_1,x_2] f[x1,x2] | f [ x 0 , x 1 , x 2 ] ‾ \underline{f[x_0,x_1,x_2]} f[x0,x1,x2] | |
x 3 x_3 x3 | f ( x 3 ) f(x_3) f(x3) | f [ x 2 , x 3 ] f[x_2,x_3] f[x2,x3] | f [ x 1 , x 2 , x 3 ] f[x_1,x_2,x_3] f[x1,x2,x3] | f [ x 0 , x 1 , x 2 , x 3 ] ‾ \underline{f[x_0,x_1,x_2,x_3]} f[x0,x1,x2,x3] |
⋮ \vdots ⋮ | ⋮ \vdots ⋮ | ⋮ \vdots ⋮ | ⋮ \vdots ⋮ | ⋮ \vdots ⋮ |
在均差表中,根据 k k k 阶均差公式,下划线标记的均差,均可由左侧的 2 2 2 个(左、左上)表格项求出。
\qquad
\qquad
若记
n
n
n 阶多项式
ω
n
(
x
)
=
(
x
−
x
0
)
(
x
−
x
1
)
⋯
(
x
−
x
n
−
1
)
,
n
≥
1
\omega_n(x)=(x-x_0)(x-x_1)\cdots(x-x_{n-1}),\ n\ge1
ωn(x)=(x−x0)(x−x1)⋯(x−xn−1), n≥1 ,那么
n
n
n 阶牛顿插值多项式又可表示为:
N
n
(
x
)
=
f
(
x
0
)
+
f
[
x
0
,
x
1
]
ω
1
(
x
)
+
f
[
x
0
,
x
1
,
x
2
]
ω
2
(
x
)
+
⋯
+
f
[
x
0
,
x
1
,
⋯
,
x
n
]
ω
n
(
x
)
\qquad\qquad\begin{aligned}N_n(x)&=f(x_0)+f[x_0,x_1]\omega_1(x)+f[x_0,x_1,x_2]\omega_2(x)+\cdots+f[x_0,x_1,\cdots,x_n]\omega_n(x)\end{aligned}
Nn(x)=f(x0)+f[x0,x1]ω1(x)+f[x0,x1,x2]ω2(x)+⋯+f[x0,x1,⋯,xn]ωn(x)
实现代码
import numpy as np
import matplotlib.pyplot as plt
def intNewton(x,xcp,f):
divdiff = getdivideddiff(xcp,f)
hatf = np.ones(len(x))*f(xcp[0])
for n in range(len(x)):
t0 = 1
for k in range(len(xcp)-1):
# Newton
t0 = (x[n]-xcp[k])*t0
hatf[n] += divdiff[k]*t0
return hatf
def getdivideddiff(xcp,f):
divdiff = np.zeros(len(xcp)-1)
t = f(xcp)
for k in range(len(xcp)-1):
num0 = t
num1 = np.concatenate((np.ones(1),num0[0:-1]))
k0 = k+1
den = np.concatenate((np.ones(k0),xcp[0:-k0]))
t = (num0-num1)/(xcp-den)
divdiff[k] = t[k0]
return divdiff
if __name__ == '__main__':
plt.figure(figsize=(7, 4))
# parameters
cpnum = 17 # 插值节点数
xs = -9
xe = 11
x = np.linspace(xs,xe,100) # 待插值点
xcp = np.linspace(xs,xe,cpnum) # 插值节点的函数值已知
# function to be interpolated
f = lambda x: x**2 + 30*np.sin(x)
plt.plot(x,f(x))
##Newton Interpolation
hatf = intNewton(x,xcp,f)
plt.plot(x,hatf)
# plot control point
for i in range(len(xcp)):
plt.plot(xcp[i],f(xcp[i]),'ro',markerfacecolor='none')
plt.legend(['original','Newton','control point'])
plt.title('Newton Interpolation')
plt.show()
运行结果:
\qquad
函数插值的结果,与插值节点的选择有关。为了方便,此处使用了等距插值节点。
\qquad
3. 等距插值节点的牛顿插值
(1) 差分的定义
\qquad 考虑“插值节点之间距离相等”的情况,也就是 x k = x 0 + k h , k = 0 , 1 , ⋯ , n x_k=x_0+kh,k=0,1,\cdots,n xk=x0+kh,k=0,1,⋯,n,并记 f k = f ( x k ) f_k=f(x_k) fk=f(xk),可定义
1 ) \qquad1) 1) 一阶差分: { Δ f k = f k + 1 − f k 前向 ∇ f k = f k − f k − 1 后向 \left\{\begin{aligned}\Delta f_k=f_{k+1}-f_k \qquad 前向\\ \\ \nabla f_k=f_k-f_{k-1} \qquad 后向\end{aligned}\right. ⎩ ⎨ ⎧Δfk=fk+1−fk前向∇fk=fk−fk−1后向
2 ) \qquad2) 2) 二阶差分: { Δ 2 f k = Δ f k + 1 − Δ f k 前向 ∇ 2 f k = Δ f k − Δ f k − 1 后向 \left\{\begin{aligned}\Delta^2 f_k=\Delta f_{k+1}-\Delta f_k \qquad 前向\\ \\ \nabla^2 f_k=\Delta f_k-\Delta f_{k-1} \qquad 后向\end{aligned}\right. ⎩ ⎨ ⎧Δ2fk=Δfk+1−Δfk前向∇2fk=Δfk−Δfk−1后向
\qquad 以及
3 ) \qquad3) 3) m \textbf{m} m阶差分: { Δ m f k = Δ m − 1 f k + 1 − Δ m − 1 f k 前向 ∇ m f k = Δ m − 1 f k − Δ m − 1 f k − 1 后向 \left\{\begin{aligned}\Delta^m f_k=\Delta^{m-1} f_{k+1}-\Delta^{m-1} f_k \qquad 前向\\ \\ \nabla^m f_k=\Delta^{m-1} f_k-\Delta^{m-1} f_{k-1} \qquad 后向\end{aligned}\right. ⎩ ⎨ ⎧Δmfk=Δm−1fk+1−Δm−1fk前向∇mfk=Δm−1fk−Δm−1fk−1后向
\qquad
\qquad
从而,可得到均差
与差分
之间的关系:
\qquad\qquad 一阶: f [ x k , x k + 1 ] = f k + 1 − f k x k + 1 − x k = Δ f k h f[x_k,x_{k+1}]=\dfrac{f_{k+1}-f_k}{x_{k+1}-x_k}=\dfrac{\Delta f_k}{h} f[xk,xk+1]=xk+1−xkfk+1−fk=hΔfk
\qquad\qquad 二阶: f [ x k , x k + 1 , x k + 2 ] = f [ x k + 1 , x k + 2 ] − f [ x k , x k + 1 ] x k + 2 − x k = Δ 2 f k 2 h 2 f[x_k,x_{k+1},x_{k+2}]=\dfrac{f[x_{k+1},x_{k+2}]-f[x_k,x_{k+1}]}{x_{k+2}-x_k}=\dfrac{\Delta^2 f_k}{2h^2} f[xk,xk+1,xk+2]=xk+2−xkf[xk+1,xk+2]−f[xk,xk+1]=2h2Δ2fk
⟹
\qquad\qquad\Longrightarrow\quad
⟹
m
\textbf{m}
m阶:
f
[
x
k
,
x
k
+
1
,
⋯
,
x
k
+
m
]
=
Δ
m
f
k
m
!
h
m
f[x_k,x_{k+1},\cdots,x_{k+m}]=\dfrac{\Delta^m f_k}{m!h^m}
f[xk,xk+1,⋯,xk+m]=m!hmΔmfk
\qquad
(2) 差分表
\qquad
等距插值节点的牛顿插值不再采用均差,而是采用差分。因此,
n
n
n 阶牛顿插值多项式的插值系数
a
0
,
a
1
,
⋯
,
a
n
−
1
a_0,a_1,\cdots,a_{n-1}
a0,a1,⋯,an−1 的求解过程可以列成差分表
(以
n
=
4
n=4
n=4 为例):
x k x_k xk | f k f_k fk | Δ ( ∇ ) \Delta(\nabla) Δ(∇) | Δ 2 ( ∇ 2 ) \Delta^2(\nabla^2) Δ2(∇2) | Δ 3 ( ∇ 3 ) \Delta^3(\nabla^3) Δ3(∇3) | Δ 4 ( ∇ 4 ) \Delta^4(\nabla^4) Δ4(∇4) |
---|---|---|---|---|---|
x 0 x_0 x0 | f 0 f_0 f0 | ||||
x 1 x_1 x1 | f 1 f_1 f1 | Δ f 0 ‾ ( ∇ f 1 ) \underline{\Delta f_0}(\nabla f_1) Δf0(∇f1) | |||
x 2 x_2 x2 | f 2 f_2 f2 | Δ f 1 ( ∇ f 2 ) \Delta f_1(\nabla f_2) Δf1(∇f2) | Δ 2 f 0 ‾ ( ∇ 2 f 2 ) \underline{\Delta^2f_0}(\nabla^2f_2) Δ2f0(∇2f2) | ||
x 3 x_3 x3 | f 3 f_3 f3 | Δ f 2 ( ∇ f 3 ) \Delta f_2(\nabla f_3) Δf2(∇f3) | Δ 2 f 1 ( ∇ 2 f 3 ) \Delta^2f_1(\nabla^2f_3) Δ2f1(∇2f3) | Δ 3 f 0 ‾ ( ∇ 3 f 3 ) \underline{\Delta^3f_0}(\nabla^3f_3) Δ3f0(∇3f3) | |
x 4 x_4 x4 | f 4 f_4 f4 | Δ f 3 ( ∇ f 4 ‾ ‾ ) \Delta f_3(\underline{\underline{\nabla f_4}}) Δf3(∇f4) | Δ 2 f 2 ( ∇ 2 f 4 ‾ ‾ ) \Delta^2f_2(\underline{\underline{\nabla^2f_4}}) Δ2f2(∇2f4) | Δ 3 f 1 ( ∇ 3 f 4 ‾ ‾ ) \Delta^3f_1(\underline{\underline{\nabla^3f_4}}) Δ3f1(∇3f4) | Δ 4 f 0 ‾ ( ∇ 4 f 4 ‾ ‾ ) \underline{\Delta^4f_0}(\underline{\underline{\nabla^4f_4}}) Δ4f0(∇4f4) |
在差分表中,单下划线标记的前向差分、双下划线标记的后向差分,均可由左侧的 2 2 2 个(左、左上)表格项求出,下标正好相差一位。
\qquad
(3) 前向插值
\qquad 前向插值,是从区间 [ x 0 , x n − 1 ] [x_0,x_{n-1}] [x0,xn−1] 的起点 x 0 x_0 x0 开始进行插值,任意待插值点的形式可写为 x = x 0 + t h , t ≥ 0 x=x_0+th,\ t\ge0 x=x0+th, t≥0。
\qquad 牛顿插值多项式中的 n n n 阶多项式 ω n ( x ) \omega_n(x) ωn(x) 可以写为:
ω n ( x ) = ( x − x 0 ) ( x − x 1 ) ⋯ ( x − x n − 1 ) = t ( t − 1 ) ⋯ ( t − n + 1 ) h n , t ≥ 0 \qquad\qquad\omega_n(x)=(x-x_0)(x-x_1)\cdots(x-x_{n-1})=t(t-1)\cdots(t-n+1)h^n,\ t\ge0 ωn(x)=(x−x0)(x−x1)⋯(x−xn−1)=t(t−1)⋯(t−n+1)hn, t≥0
\qquad
\qquad
等距插值节点时的
n
n
n 阶牛顿(前向)插值多项式为:
N
n
(
x
)
=
f
(
x
0
)
+
f
[
x
0
,
x
1
]
ω
1
(
x
)
+
f
[
x
0
,
x
1
,
x
2
]
ω
2
(
x
)
+
⋯
+
f
[
x
0
,
x
1
,
⋯
,
x
n
]
ω
n
(
x
)
⇓
\qquad\qquad\begin{aligned}N_n(x)&=f(x_0)+f[x_0,x_1]\omega_1(x)+f[x_0,x_1,x_2]\omega_2(x)+\cdots\ \\&\quad+f[x_0,x_1,\cdots,x_n]\omega_n(x)\\ \newline\\ \newline&\qquad\qquad\qquad\qquad\qquad\qquad\Downarrow \\ \newline\end{aligned}
Nn(x)=f(x0)+f[x0,x1]ω1(x)+f[x0,x1,x2]ω2(x)+⋯ +f[x0,x1,⋯,xn]ωn(x)⇓
N
n
(
x
0
+
t
h
)
=
f
(
x
0
)
+
Δ
f
0
h
t
h
+
Δ
2
f
0
2
h
2
t
(
t
−
1
)
h
2
+
⋯
+
Δ
n
f
0
n
!
h
n
t
(
t
−
1
)
⋯
(
t
−
n
+
1
)
h
n
\qquad\qquad\begin{aligned}N_n(x_0+th)&=f(x_0)+\dfrac{\Delta f_0}{h}th+\dfrac{\Delta^2 f_0}{2h^2}t(t-1)h^2+\cdots +\dfrac{\Delta^n f_0}{n!h^n}t(t-1)\cdots(t-n+1)h^n\end{aligned}
Nn(x0+th)=f(x0)+hΔf0th+2h2Δ2f0t(t−1)h2+⋯+n!hnΔnf0t(t−1)⋯(t−n+1)hn
=
f
0
+
t
Δ
f
0
+
t
(
t
−
1
)
2
Δ
2
f
0
+
⋯
+
t
(
t
−
1
)
⋯
(
t
−
n
+
1
)
n
!
Δ
n
f
0
\qquad\qquad\begin{aligned}\qquad\qquad\quad\ &=f_0+t\Delta f_0+\dfrac{t(t-1)}{2}\Delta^2 f_0+\cdots+\dfrac{t(t-1)\cdots(t-n+1)}{n!}\Delta^n f_0\end{aligned}
=f0+tΔf0+2t(t−1)Δ2f0+⋯+n!t(t−1)⋯(t−n+1)Δnf0
写成该表达式的目的,是为了更方便地使用“差分表”来进行实现。
\qquad
(4) 后向插值
\qquad 后向插值,正好与前向插值相反,是从区间 [ x 0 , x n − 1 ] [x_0,x_{n-1}] [x0,xn−1] 的终点 x n − 1 x_{n-1} xn−1 开始进行插值,任意待插值点的形式可写为 x = x n − 1 + t h , t ≤ 0 x=x_{n-1}+th,\ t\le0 x=xn−1+th, t≤0。为了能够利用前向插值公式,可将插值节点按照 x n − 1 , x n − 2 , ⋯ , x 1 , x 0 x_{n-1},x_{n-2},\cdots,x_1,x_0 xn−1,xn−2,⋯,x1,x0 的顺序进行倒序排列。
\qquad 倒序排列后, n n n 阶牛顿插值多项式为:
N n ( x ) = f ( x n − 1 ) + f [ x n − 1 , x n − 2 ] ( x − x n − 1 ) + f [ x n − 1 , x n − 2 , x n − 3 ] ( x − x n − 1 ) ( x − x n − 2 ) + ⋯ + f [ x 0 , x 1 , ⋯ , x n ] ( x − x n − 1 ) ( x − x n − 2 ) ⋯ ( x − x 0 ) \qquad\qquad\begin{aligned}N_n(x)&=f(x_{n-1})+f[x_{n-1},x_{n-2}](x-x_{n-1})\\ &+f[x_{n-1},x_{n-2},x_{n-3}](x-x_{n-1})(x-x_{n-2})+\cdots\ \\ &+f[x_0,x_1,\cdots,x_n](x-x_{n-1})(x-x_{n-2})\cdots(x-x_0)\end{aligned} Nn(x)=f(xn−1)+f[xn−1,xn−2](x−xn−1)+f[xn−1,xn−2,xn−3](x−xn−1)(x−xn−2)+⋯ +f[x0,x1,⋯,xn](x−xn−1)(x−xn−2)⋯(x−x0)
\qquad 同样地,可以记 n n n 阶多项式 ω n ( x ) \omega_n(x) ωn(x) 为:
ω n ( x ) = ( x − x n − 1 ) ( x − x n − 2 ) ⋯ ( x − x 0 ) = t ( t + 1 ) ⋯ ( t + n − 1 ) h n \qquad\qquad\omega_n(x)=(x-x_{n-1})(x-x_{n-2})\cdots(x-x_0)=t(t+1)\cdots(t+n-1)h^n ωn(x)=(x−xn−1)(x−xn−2)⋯(x−x0)=t(t+1)⋯(t+n−1)hn
\qquad 以及 m \textbf{m} m阶差分: f [ x k , x k − 1 , ⋯ , x k − m ] = ∇ m f k m ! h m f[x_k,x_{k-1},\cdots,x_{k-m}]=\dfrac{\nabla^m f_k}{m!h^m} f[xk,xk−1,⋯,xk−m]=m!hm∇mfk
\qquad
\qquad
因此,等距插值节点时的
n
n
n 阶牛顿(后向)插值多项式为:
N
n
(
x
)
=
f
(
x
n
−
1
)
+
f
[
x
n
−
1
,
x
n
−
2
]
ω
1
(
x
)
+
f
[
x
n
−
1
,
x
n
−
2
,
x
n
−
3
]
ω
2
(
x
)
+
⋯
+
f
[
x
n
−
1
,
x
n
−
2
,
⋯
,
x
0
]
ω
n
(
x
)
⇓
\qquad\qquad\begin{aligned}N_n(x)&=f(x_{n-1})+f[x_{n-1},x_{n-2}]\omega_1(x)+f[x_{n-1},x_{n-2},x_{n-3}]\omega_2(x)+\cdots\ \\&\quad+f[x_{n-1},x_{n-2},\cdots,x_0]\omega_n(x)\\ \newline\\ \newline&\qquad\qquad\qquad\qquad\qquad\qquad\Downarrow \\ \newline\end{aligned}
Nn(x)=f(xn−1)+f[xn−1,xn−2]ω1(x)+f[xn−1,xn−2,xn−3]ω2(x)+⋯ +f[xn−1,xn−2,⋯,x0]ωn(x)⇓
N
n
(
x
0
+
t
h
)
=
f
(
x
n
−
1
)
+
∇
f
n
−
1
h
t
h
+
∇
2
f
n
−
1
2
h
2
t
(
t
−
1
)
h
2
+
⋯
+
∇
n
f
n
−
1
n
!
h
n
t
(
t
−
1
)
⋯
(
t
−
n
+
1
)
h
n
\qquad\qquad\begin{aligned}N_n(x_0+th)&=f(x_{n-1})+\dfrac{\nabla f_{n-1}}{h}th+\dfrac{\nabla^2 f_{n-1}}{2h^2}t(t-1)h^2+\cdots +\dfrac{\nabla^n f_{n-1}}{n!h^n}t(t-1)\cdots(t-n+1)h^n\end{aligned}
Nn(x0+th)=f(xn−1)+h∇fn−1th+2h2∇2fn−1t(t−1)h2+⋯+n!hn∇nfn−1t(t−1)⋯(t−n+1)hn
=
f
n
−
1
+
t
∇
f
n
−
1
+
t
(
t
+
1
)
2
∇
2
f
n
−
1
+
⋯
+
t
(
t
+
1
)
⋯
(
t
+
n
−
1
)
n
!
∇
n
f
n
−
1
\qquad\qquad\begin{aligned}\qquad\qquad\quad\ &=f_{n-1}+t\nabla f_{n-1}+\dfrac{t(t+1)}{2}\nabla^2 f_{n-1}+\cdots+\dfrac{t(t+1)\cdots(t+n-1)}{n!}\nabla^n f_{n-1}\end{aligned}
=fn−1+t∇fn−1+2t(t+1)∇2fn−1+⋯+n!t(t+1)⋯(t+n−1)∇nfn−1
写成该表达式的目的,是为了更方便地使用“差分表”来进行实现。
\qquad
实现代码
import numpy as np
import matplotlib.pyplot as plt
# 牛顿法:等距节点插值(前插公式)
def intNewtonforw_e(x,xcp,f,h,num):
diff_forw, diff_back = getdiff(xcp,f)
hatf = np.zeros(len(x))
for i in range(len(x)):
if i%num == 0:
hatf[i] = f(x[i])
continue
t = i/num
hatf[i] = hatf[0]
tmp = 1
prodn = 1
for n in range(1,len(xcp)-1):#插值多项式阶数为n=len(xcp)-1阶,可以小于n
tmp = tmp*(t-n+1)
prodn = prodn * n
hatf[i] += tmp * diff_forw[n]/prodn
return hatf
# 牛顿法:等距节点插值(后插公式)
def intNewtonback_e(x,xcp,f,h,num):
diff_forw, diff_back = getdiff(xcp,f)
xn = len(x)-1
hatf = np.zeros(len(x))
for i in range(len(x)):
if i%num == 0:
hatf[xn-i] = f(x[xn-i])
continue
t = - i/num
hatf[xn-i] = hatf[xn]
tmp = 1
prodn = 1
for n in range(1,len(xcp)-1):#插值多项式阶数为nlen(xcp)-1阶,可以小于n
tmp = tmp*(t+n-1)
prodn = prodn * n
hatf[xn-i] += tmp * diff_back[n]/prodn
return hatf
# 获取各阶前向差分和后向差分
def getdiff(xcp,f):
# np.set_printoptions(precision=5)
diff_forw = np.zeros(len(xcp))
diff_back = np.zeros(len(xcp))
t0 = f(xcp)
diff_forw[0] = t0[0]
diff_back[0] = t0[-1]
for n in range(1,len(xcp)):
fn0 = t0
fn1 = np.concatenate((np.ones(1),fn0[0:-1]))
t1 = fn0 - fn1
diff_forw[n] = t1[1]
diff_back[n] = t1[-1]
t0 = t1[1:]
return diff_forw, diff_back
if __name__ == '__main__':
plt.figure(figsize=(7, 4))
# parameters
xs = -13
xe = 13
h = 1 # 相邻等距节点的间隔
num = 10 # 两个等距节点之间再等距划分10个点
t = h/num # 相邻节点之间的待插值点间隔
x = np.arange(xs,xe+t,t) # 等距节点之间再等分后的待插值点
xcp = np.arange(xs,xe+h,h) # 等距节点
# function to be interpolated
f = lambda x: x**2 + 30*np.sin(x)
plt.plot(x,f(x))
##Newton Interpolation
hatf = intNewtonforw_e(x,xcp,f,h,num) #前向插值
plt.plot(x,hatf)
hatf = intNewtonback_e(x,xcp,f,h,num) #后向插值
plt.plot(x,hatf)
# plot control point
for i in range(len(xcp)):
plt.plot(xcp[i],f(xcp[i]),'ro',markerfacecolor='none')
plt.legend(['original','Newton forward','Newton backward','control point'])
plt.title('Newton Interpolation')
plt.show()
运行结果:
(
1
)
(1)
(1) 前插公式
\qquad
(
2
)
(2)
(2) 后插公式
\qquad
(
3
)
(3)
(3) 将前插公式和后插公式的结果显示在同一张图
\qquad
\qquad
参考:
基于径向基函数(RBF)的函数插值
\qquad
\qquad
\qquad
\qquad