计算方法——三次样条插值

1、理论知识

1)三次样条插值的提法

给定 y =f(x) 的函数表( 如表 所示) ,构造函数s(x)  满足条件:
①在[x_i,x_{i+1}](i=0,1,...,n-1) 上为不超过三次的代数多项式;
s(x_i) = y_i (i=0,1,...,n)
s(x)\epsilon C^2[a,b],其中a = x_0,b=x_n
其中s(x)称为三次样条插值函数.

xx_0x_1...x_n
y =f(x)y_0y_1...y_n

s(x) 在点x_i(i=0,1,...,n) 处的微商为m_i(i=0,1,...,n),则s(x) 在每个小
区间[x_i,x_{i+1}]上有
s(x_i) = y_i    s'(x_i) = m_i  s(x_{i+1}) = y_{i+1}        s'(x_{i+1}) = m_{i+1}

2)三次样条插值的解法思路

1)

s(x) 是不超过3次的插值函数,多段的s(x) 组成了f(x)

[x_i,x_{i+1}](i=0,1,...,n-1) 所以总共有n-1个分段,也就是说要求解的参数有 4(n-1) 个

由表的信息,我们可以列出:

条件方程个数
函数值相等n
函数值连续n-2
一阶导数连续n-2
二阶导数连续

n-2

由此还需补充两个边界条件才能凑足4(n-1)个方程去求解4(n-1)个未知数

2)边界条件

而边界条件一般有如下两种情形:
(1) 已 知 被 插 值 函 数 y=f(x) 在 两 个 端 点x_0x_n处 的 微 商 值, 即 给 定
f'(x_0) = m_0 和 f'(x_n) = m_n ,相应要求s'(x_0) = m_0s'(x_n) = m_n
(2) 已知被插值函数y=f(x)  在两个端点 x0 和 xn 处的二阶微商值为 0,即给
f''(x_0) = 0f''(x_n) = 0,相应要求 s''(x_0) = 0 和 s''(x_n) = 0

3)大致的推导流程

1)先根据“函数值相等”、“函数值连续”,“一阶导连续”,设:

【参考hermite插值】

2)目标——“求解m_i 的表达式"

① 化简 h_i = x_{i+1}-x_i,代入(2.41)

② 求二阶导

2.4.2直接表现的是[x_i,x_{i+1}] 中的二阶导,从中可以获取s''(x_i^+)

③ 将2.4.2中的i替换为i-1,得到的是[x_{i-1},x_{i}] 中的二阶导,从中可以获取 s''(x_i^-)

④ 令 s''(x_i^-) = s''(x_i^+) 整理得到

\alpha_i = \frac{h_{i-1}}{h_{i-1}+h_i},上式变化为

令 \beta_i = 3[\frac{1-\alpha_i}{h_{i-1}}(y_i-y_{i-1})+\frac{\alpha_i}{h_i}(y_{i+1}-y_i)]

得到

⑦ 分别令 i = 1,2,...,n-1 可以得到n-1个等式组成的方程组

⑧ 补充条件后,有公式

分别整理得到:

2、编程计算

1)矩阵构造

根据大致推导流程,我们需要编写函数计算如下式子:

h_i = x_{i+1}-x_i

\alpha_i = \frac{h_{i-1}}{h_{i-1}+h_i}

\beta_i = 3[\frac{1-\alpha_i}{h_{i-1}}(y_i-y_{i-1})+\frac{\alpha_i}{h_i}(y_{i+1}-y_i)]

def calhi(X):
  H = []
  # len(X) = n+1
  for i in range(len(X)-1):
    H.append(X[i+1]-X[i])
  return H

def calalphai(H):
  # len(H) n  0——n-1
  # 只当 A0 = 0
  A = [0]
  for i in range(1,len(H)):
    A.append((H[i-1]/(H[i-1]+H[i])))
  return A

def calbetai(A,H,Y):
  # len(A) = n 实际有效的alpha在[1:]范围内
  # Y n+1  0——n
  B = [0]
  for i in range(1,len(A)):
    tmp1 = (1-A[i])/H[i-1]*(Y[i]-Y[i-1])
    tmp2 = A[i]/H[i]*(Y[i+1]-Y[i])
    B.append(3*(tmp1+tmp2))
  return B

根据以下式子,编写函数构造矩阵

2m_0+m_1 = \frac{3}{h_0}(y_1-y_0)

m_{n-1}+2m_n = 3\frac{y_n-y_{n-1}}{h_{n-1}}

# 构造相应的矩阵
# 先构造补充条件的list
import numpy as np

def RowForSupplement(n):
  RowsFS = np.zeros(shape=(2,n+1))
  RowsFS[0][0] = 2
  RowsFS[0][1] = 1
  RowsFS[1][n-1] = 1
  RowsFS[1][n] = 2
  return RowsFS

# 构造原先的n-1个条件的方程
def Row(A):
  n = len(A)
  Rows = np.zeros(shape=(n-1,n+1))
  for i in range(1,n):
    Rows[i-1][i-1] = 1-A[i]
    Rows[i-1][i] = 2
    Rows[i-1][i+1] = A[i]
  return Rows

# 合并左侧矩阵
def Concat(Rows,RowsFS,n):
  C = np.zeros(shape=(n+1,n+1))
  C[:n-1,:] = Rows
  C[n-1:,:] = RowsFS
  return C

# 构造β矩阵
def Beta(B,Y,H):
  n = len(Y)-1
  l1 = 3*(Y[1]-Y[0])/H[0]
  l2 = 3*(Y[n]-Y[n-1])/H[n-1]
  Beta = np.zeros(shape=(n+1,))
  for i in range(1,n):
    Beta[i-1] = B[i]
  Beta[n-1] = l1
  Beta[n] = l2
  return Beta

# 解线性方程
def solve(X,Y):
  H = calhi(X)
  A = calalphai(H)
  B = calbetai(A,H,Y)
  RowsFS = RowForSupplement(len(Y)-1)
  Rows = Row(A)
  Left = Concat(Rows,RowsFS,len(Y)-1)
  beta = Beta(B,Y,H)
  M = np.linalg.solve(Left,beta)
  print(M)
  return M

2)预测函数

到solve为止,只是解出了m_0,m_1...m_n,我们还可以编写预测函数,直接获取对于x插值函数s(x)的预测值

# 预测代码
def predict(targetX,X,Y):
  M = solve(X,Y)
  n = len(Y)
  # 确定targetX所在的区间
  st = 0
  for i in range(n-1):
    if targetX >= X[i] and targetX <= X[i+1]:
      st = i
      break
  tmp1 = (1+2*(targetX-X[st])/(X[st+1]-X[st]))*pow(((targetX-X[st+1])/(X[st]-X[st+1])),2)
  tmp2 = (1+2*(targetX-X[st+1])/(X[st]-X[st+1]))*pow(((targetX-X[st])/(X[st+1]-X[st])),2)

  tmp3 = (targetX-X[st])*pow(((targetX-X[st+1])/(X[st]-X[st+1])),2)
  tmp4 = (targetX-X[st+1])*pow(((targetX-X[st])/(X[st+1]-X[st])),2)

  return tmp1*Y[st]+tmp2*Y[st+1]+tmp3*M[st]+tmp4*M[st+1]
  

3)验证

1)输入了一个例题的参数,结果预测是正确的

2)对比内置的库函数CubicSpline:

自己的函数:

内置库函数:

  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
三次样条插值法是一种常用的插值方法,它可以通过给定的数据点,构造出一个光滑的函数曲线,从而对数据进行插值和拟合。但是,在实际应用中,三次样条插值法可能会面临一些问题,需要进行改进。 以下是三次样条插值法可能面临的若干问题以及改进方法: 1. 插值误差问题:由于三次样条插值法是通过多项式曲线拟合数据点,因此在数据点之间进行插值时,可能会产生插值误差,导致插值结果不准确。解决方法是增加插值节点,即增加数据点的数量,或者采用其他插值方法,如分段线性插值、拉格朗日插值等。 2. 边界条件问题:三次样条插值法需要指定边界条件,如一阶导数、二阶导数等。如果边界条件不合适,可能会导致插值结果不光滑或不连续。解决方法是选择合适的边界条件,例如自然边界条件、弯曲边界条件等。 3. 大数据量问题:当数据点数量非常大时,三次样条插值法的计算量会非常大,导致插值速度变慢。解决方法是采用更高阶的样条插值方法,如五次样条插值法或七次样条插值法,或者采用其他的插值方法,如Kriging插值、径向基函数插值等。 4. 插值函数平滑度问题:三次样条插值法可以构造出光滑的函数曲线,但有时插值函数的平滑度可能不够好,导致插值结果不理想。解决方法是采用其他的插值方法,如样条插值法与小波插值法的结合,或者采用其他的光滑函数,如B样条函数、NURBS曲线等。 总之,三次样条插值法是一种非常实用的插值方法,但在实际应用中可能会面临一些问题,需要根据具体情况选择合适的改进方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值