分段三次hermit插值

这篇具有很好参考价值的文章主要介绍了分段三次hermit插值。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、算法实现

一、插值函数建立

设函数 y = F ( x ) y=F(x) y=F(x)在区间 [ a , b ] [a,b] [a,b]上有定义,且已知在离散点 a = x 0 < x 1 < . . . < x n = b a=x_0<x_1<...<x_n = b a=x0<x1<...<xn=b上的值 y 0 , y 1 , . . . y n , y_0,y_1,...y_n, y0,y1,...yn f ( x ) f(x) f(x) [ x j , x j + 1 ] [x_j,x_{j+1}] [xj,xj+1]分段区间内可表示为
f ( x ) = a ( x − x j ) 3 + b ( x − x j ) 2 + c ( x − x j ) + d f(x) = a(x-x_j)^3 +b(x-x_j)^2 + c(x-x_j) + d f(x)=a(xxj)3+b(xxj)2+c(xxj)+d
f ′ ( x ) f'(x) f(x)是一阶导数,则
f ′ ( x ) = 3 a ( x − x j ) 2 + 2 b ( x − x j ) + c f'(x) = 3a(x-x_j)^2 + 2b(x-x_j) + c f(x)=3a(xxj)2+2b(xxj)+c
将端点处 f ( x j ) = y j f(x_j) = y_j f(xj)=yj f ( x j + 1 ) = y j + 1 f(x_{j+1}) = y_{j+1} f(xj+1)=yj+1 带入得
{ f ( x j ) =   d f ′ ( x j ) =   c f ( x j + 1 ) =   a ( x j + 1 − x j ) 3 + b ( x j + 1 − x j ) 2 + c ( x j + 1 − x j ) f ′ ( x j + 1 ) =   3 a ( x j + 1 − x j ) 2 + 2 b ( x j + 1 − x j ) + c \left\{ \begin{aligned} f(x_j) & = \ d \\ f'(x_j) & = \ c \\ f(x_{j+1}) & = \ a(x_{j+1}-x_j)^3 + b(x_{j+1}- x_j)^2 + c(x_{j+1} - x_j) \\ f'(x_{j+1}) & = \ 3a(x_{j+1}-x_j)^2 + 2b(x_{j+1}- x_j) + c \end{aligned} \right. f(xj)f(xj)f(xj+1)f(xj+1)= d= c= a(xj+1xj)3+b(xj+1xj)2+c(xj+1xj)= 3a(xj+1xj)2+2b(xj+1xj)+c
可得关于 a , b a,b a,b 的方程为
{ a ( x j + 1 − x j ) 3 + b ( x j + 1 − x j ) 2 = f ( x j + 1 ) − f ( x j ) − f ′ ( x j ) − f ′ ( x j ) ( x j + 1 − x j ) 3 a ( x j + 1 − x j ) 2 + 2 b ( x j + 1 − x j ) = f ′ ( x j + 1 ) − f ′ ( x j ) \left\{ \begin{aligned} a(x_{j+1} - x_j)^3 + b(x_{j+1}-x_j)^2 & = f(x_{j+1}) -f(x_j) - f'(x_j)- f'(x_j)(x_{j+1}-x_{j}) \\ 3a(x_{j+1}-x_j)^2 + 2b(x_{j+1} - x_j) & = f'(x_{j+1}) - f'(x_j) \end{aligned} \right. {a(xj+1xj)3+b(xj+1xj)23a(xj+1xj)2+2b(xj+1xj)=f(xj+1)f(xj)f(xj)f(xj)(xj+1xj)=f(xj+1)f(xj)
x j x_j xj 处的差商 δ j = f ( x j + 1 ) − f ( x j ) x j + 1 − x j \delta_j = \frac{f(x_{j+1}) - f(x_j)}{x_{j+1}-x_j} δj=xj+1xjf(xj+1)f(xj) x j x_j xj 处的一阶导 d j = f ′ ( x j ) d_j = f'(x_j) dj=f(xj) d z z d x = δ j − d j x j + 1 − x j , d z d x d x = d j + 1 − δ j x j + 1 − x j dzzdx = \frac{δ_j - d_j}{x_{j+1} - x_j},dzdxdx = \frac{d_{j+1} - δ_j}{x_{j+1}-x_{j}} dzzdx=xj+1xjδjdjdzdxdx=xj+1xjdj+1δj,上式可表示为
{ a ( x j + 1 − x j ) + b = d z z d x 3 a ( x j + 1 − x j ) + 2 b = d z d x d x + d z z d x \left\{ \begin{aligned} a(x_{j+1} - x_j) + b & = dzzdx\\ 3a(x_{j+1} - x_j ) +2b & = dzdxdx + dzzdx \end{aligned} \right. {a(xj+1xj)+b3a(xj+1xj)+2b=dzzdx=dzdxdx+dzzdx
解方程组得
{ a = d z d x d x − d z z d x x j + 1 − x j b = 2 d z z d x − d z d x d x \left\{ \begin{aligned} a & = \frac{dzdxdx - dzzdx}{x_{j+1} - x_j} \\ b & = 2dzzdx - dzdxdx \end{aligned} \right. ab=xj+1xjdzdxdxdzzdx=2dzzdxdzdxdx

h j = x j + 1 − x j h_j = x_{j+_1} - x_j hj=xj+1xj,最终得出
{ a = d j + 1 + d j − 2 δ j h j 2 b = − d j + 1 − 2 d j + 3 δ j h j c = f ′ ( x j ) = d j d = f ( x j ) = y j \left\{ \begin{aligned} a & = \frac{d_{j+1} + d_j - 2\delta_j}{{h_j} ^2} \\ b & = \frac{-d_{j+1} - 2d_j + 3\delta_j}{h_j} \\ c & = f'(x_j) = d_j \\ d & = f(x_j) = y_j \end{aligned} \right. abcd=hj2dj+1+dj2δj=hjdj+12dj+3δj=f(xj)=dj=f(xj)=yj
其中 h j 、 δ j 、 y j h_j、\delta_j、y_j hjδjyj 均已知,求出 x j 、 x j + 1 x_j、x_{j+1} xjxj+1 处的导数 d j 、 d j + 1 d_j、d_{j+1} djdj+1 方程得解

二、一阶导数求法

1.内点处的导数求法

内点处的一阶导数有以下规则:

  1. 如果第 k k k 个节点附近的差商 δ k − 1 δ_{k-1} δk1 δ k δ_{k} δk 符号相反,或者其中一个为0,则该点处的一阶导数 d k = 0 d_k = 0 dk=0
  2. 如果第 k k k 个节点附近的差商 δ k − 1 δ_{k-1} δk1 δ k δ_{k} δk 符号相同,则改点处的导数
    d k + 1 = δ m i n k w 1 k δ k δ m a x k + w 2 k δ k + 1 δ m a x k d_{k+1} = \frac {\delta min_k }{w1_k \frac{\delta_k}{\delta max_k} + w2_k \frac{\delta_{k+1}}{\delta max_k}} dk+1=w1kδmaxkδk+w2kδmaxkδk+1δmink
    其中 h k = ( x k + 1 − x k ) , h s k = h k + h k + 1 , δ k = y k + 1 − y k x k + 1 − x k , δ m i n k = m i n ( δ k , δ k + 1 ) , δ m a x k = m a x ( δ k , δ k + 1 ) , w 1 k = h k + h s k 3 h s k , w 2 k = h k + 1 + h s k 3 h s k 其中 h_k = (x_{k+1}-x_k),hs_k = h_k + h_{k+1}, \delta_k = \frac{y_{k+1} - y_k}{x_{k+1} - x_{k}},\delta min_k = min(\delta_{k},\delta_{k+1}),\delta max_k = max(\delta_{k},\delta_{k+1}) ,w1_k = \frac{h_k + hs_k}{3hs_k},w2_k = \frac{h_{k+1} + hs_k}{3hs_k} 其中hk=(xk+1xk)hsk=hk+hk+1δk=xk+1xkyk+1ykδmink=min(δk,δk+1)δmaxk=max(δk,δk+1)w1k=3hskhk+hskw2k=3hskhk+1+hsk
2.端点处的导数求法

{ d 0 = ( 2 h 0 + h 1 ) δ 0 − h 0 δ 1 ( h 0 + h 1 ) d n = ( 2 h n − 1 + h n − 2 ) δ n − 1 − h n − 1 δ n − 2 ( h n − 2 + h n − 1 ) \left\{ \begin{aligned} d_0 & = \frac{(2h_0 + h_1)\delta_0 - h_0\delta_1}{(h_0+h_1)} \\ d_n & = \frac{(2h_{n-1}+h_{n-2})\delta_{n-1} - h_{n-1}\delta_{n-2}}{(h_{n-2}+h_{n-1})} \end{aligned} \right. d0dn=(h0+h1)(2h0+h1)δ0h0δ1=(hn2+hn1)(2hn1+hn2)δn1hn1δn2

二、实验仿真

# -*- encoding: utf-8 -*-
'''
@File    :   pchip.py
@Time    :   2023/03/01 11:40:41
@Author  :   answer
'''

# here put the import lib
import numpy as np
from matplotlib import pyplot as plt
from scipy import interpolate

def find_0point(delta):
    k = []
    for i in range(len(delta)-1):
        if delta[i] * delta[i+1] > 0:
            k.append(i)
    return k

# 三次分段hermit函数
def pchip_spline(x, y, frequence):
    # x,y差分
    x_diff = []
    y_diff = []
    delta = []
    for i in range(len(x)-1):
        x_diff.append(x[i+1] - x[i])
        y_diff.append(y[i+1] - y[i])
        delta.append(y_diff[i]/x_diff[i])
    # 节点导数
    n = len(x)
    slope = [0 for i in range(n)]
    if n == 2:
        slope = [delta[0] for i in range(n)]
    else:
        k = find_0point(delta)
        for i in range(len(k)):
            index = k[i]
            dx_diff = x_diff[index] + x_diff[index + 1]
            w1 = (x_diff[index] + dx_diff) / (3 * dx_diff)
            w2 = (x_diff[index + 1] + dx_diff) / (3 * dx_diff)
            dmax = max(abs(delta[index]), abs(delta[index+1]))
            dmin = min(abs(delta[index]), abs(delta[index+1]))
            slope[index + 1] = dmin / \
                (w1*delta[index]/dmax + w2*delta[index+1]/dmax)
        slope[0] = 0

    # 库函数默认端点导数不为0 interpolate.pchip_interpolate(x, y, x_pchip)
    # slope[0] = ((2 * x_diff[0] + x_diff[1]) * delta[0] -
    #             x_diff[0] * delta[1]) / (x_diff[0] + x_diff[1])
    # if slope[0] * delta[0] < 0:
    #     slope[0] = 0
    # elif (delta[0] * delta[1] < 0) & (abs(slope[0]) > 3 * abs(delta[0])):
    #     slope[0] = 3 * delta[0]
    # print(slope)

    # slope[n - 1] = ((2 * x_diff[n - 2] + x_diff[n - 3]) * delta[n - 2] -
    #                 x_diff[n - 2] * delta[n - 3]) / (x_diff[n - 3] + x_diff[n - 2])
    # if delta[n - 2] * slope[n - 1] < 0:
    #     slope[n - 1] = 0
    # elif (delta[n - 2] * delta[n - 3] < 0) & (abs(slope[n - 1]) > 3 * abs(delta[n - 2])):
    #     slope[n - 1] = 3 * delta[n - 2]
    # print(slope)

    # hermit spline
    x_hermit = []
    y_hermit = []
    for i in range(n - 1):
        # 计算多项式系数
        a = (slope[i + 1] + slope[i] - 2 * delta[i]) / (x_diff[i]**2)
        b = (3 * delta[i] - 2 * slope[i] - slope[i + 1]) / x_diff[i]
        c = slope[i]
        d = y[i]

        # 计算插值点
        for j in range(frequence):
            x_inter = x[i] + j * (x[i+1] - x[i]) / frequence
            x_hermit.append(x_inter)
            y_hermit.append(
                a * (x_inter - x[i])**3 + b * (x_inter - x[i])**2 + c * (x_inter - x[i]) + d)
    x_hermit.append(x[n-1])
    y_hermit.append(y[n-1])
    return x_hermit, y_hermit

if __name__ == '__main__':
    frequence = 10
    x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
    y = [0, 1.5, 0, 0, 0.5, 0.4, 1.2, 1.2,
         0.1, 0, 0.3, 0.6]
    x_pchip, y_pchip = pchip_spline(x, y, frequence)

    y_ = interpolate.pchip_interpolate(x, y, x_pchip)
    y_1 = interpolate.splrep(x, y)
    y_1 = interpolate.splev(x_pchip, y_1)
    y_2 = interpolate.Akima1DInterpolator(x, y)
    y_2 = y_2(x_pchip)
    y_3 = interpolate.interp1d(x, y, 'cubic')
    y_3 = y_3(x_pchip)

    plt.subplot(2, 2, 1)
    plt.plot(x, y, "o", label='sample point')
    plt.plot(x_pchip, y_, linewidth=3.0, label="scipy_pchip")
    plt.plot(x_pchip, y_1, color='lime', label="spline")
    plt.legend()

    plt.subplot(2, 2, 2)
    plt.plot(x, y, "o", label='sample point')
    plt.plot(x_pchip, y_, linewidth=3.0, label="scipy_pchip")
    plt.plot(x_pchip, y_3, color='blueviolet', label="cubic")
    plt.legend()

    plt.subplot(2, 2, 3)
    plt.plot(x, y, "o", label='sample point')
    plt.plot(x_pchip, y_, linewidth=3.0, label="scipy_pchip")
    plt.plot(x_pchip, y_2, color='dodgerblue', label="akima")
    plt.legend()

    plt.subplot(2, 2, 4)
    plt.plot(x, y, "o", label='sample point')
    plt.plot(x_pchip, y_, linewidth=3.0, label="pchip_scipy")
    plt.plot(x_pchip, y_pchip, color='gray', label="pchip d_point=0")
    plt.legend()

    plt.subplots_adjust(left=0.04, bottom=0.05, right=0.98,
                        top=0.98, wspace=0.08, hspace=0.1)
    plt.show()

  1. ( 0 , 4 ) , ( 1 , 3 ) , ( 2 , 4 ) , ( 3 , 6 ) , ( 5 , 7 ) , ( 6 , 5 ) , ( 8 , 8 ) , ( 11 , 1 ) (0,4),(1,3),(2,4),(3,6),(5,7),(6,5),(8,8),(11,1) (0,4)(1,3)(2,4)(3,6)(5,7)(6,5)(8,8)(11,1) 作为节点,每点之间插十次
    分段三次hermit插值,python,插值算法

  2. 对阶跃信号进行插值
    分段三次hermit插值,python,插值算法文章来源地址https://www.toymoban.com/news/detail-680398.html

到了这里,关于分段三次hermit插值的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深度学习基础知识 最近邻插值法、双线性插值法、双三次插值算法

    最邻近插值:将每个目标像素找到距离它最近的原图像素点,然后将该像素的值直接赋值给目标像素 优点 :实现简单,计算速度快 缺点 :插值结果缺乏连续性,可能会产生锯齿状的边缘,对于图像质量影响较大,因此当处理精度要求较高的图像时,通常会采用更加精细的插

    2024年02月03日
    浏览(53)
  • 传统图片超分算法——双三次插值 (Bicubic)、附C++源码

    呼,花了一个下午,终于是写完加调试完了所有的代码。 双三次插值介绍 之前我写的这篇博客中讲了什么是超分,并实现了单线性插值算法和双线性插值算法。在这里将再介绍一种插值算法——双三次插值算法。 首先,双三次插值法需要参考16个点(4x4),因此插值效果会

    2024年02月07日
    浏览(40)
  • 基于MATLAB的三维数据插值拟合与三次样条拟合算法(附完整代码)

    目录 一. 三维插值 例题1 二. 高维度插值拟合 格式一 格式二 格式三 格式四 格式五 例题2 三. 单变量三次样条插值 例题3 例题4 四. 多变量三次样条插值 例题6 首先三维网格生成是利用 meshgrid() 函数,在MATLAB中调用格式如下: 三维插值运算,主要利用griddata()函数与interp()函数

    2024年02月14日
    浏览(43)
  • 【运动规划算法项目实战】如何实现三次样条插值(附ROS C++代码)

    三次样条插值是一种广泛应用于数据拟合和插值的方法。它通过使用三次多项式在给定的一组数据点之间进行插值,以实现平滑的拟合效果。三次样条插值的优点是可以平滑地拟合给定的数据点,而不会产生震荡或振荡现象。 三次样条插值是机器人路径规划中常用的一

    2024年02月14日
    浏览(50)
  • 三次样条插值(python完美实现,三种形式都有!)

    使用的是公式法迭代,没有用牛顿,我认为更加精准,牛顿只是方便手算误差自然大。 ----以上为个人思考与见解,有误请指点,有想法也可联系交流!                ~~~~~~~~~~~~~~                             谢谢观看!

    2024年02月08日
    浏览(38)
  • 数值分析(四) Hermite(埃尔米特)插值法及matlab代码

      本篇为 插值法专栏 第四篇内容讲述,此章主要讲述 Hermite(埃尔米特)插值法 及matlab代码,其中也给出详细的例子让大家更好的理解Hermite插值法 提示 之前已经介绍 牛顿插值法 和 三次样条插值 ,如果没看过前两篇的可以点击以下链接阅读 数值分析(一)牛顿插值法

    2024年02月10日
    浏览(57)
  • 三次样条样条:Bézier样条和Hermite样条

    总结 What is the Difference Between Natural Cubic Spline, Hermite Spline, Bézier Spline and B-spline? 1.多项式拟合中的 Runge Phenomenon 找到一条通过N+1个点的多项式曲线 ,需要N次曲线。通过两个点的多项式曲线为一次,三个点的多项式曲线为二次。当点数较多时,曲线阶数增高,在端点处易出现

    2024年02月04日
    浏览(43)
  • 基于Matlab的插值问题(Lagrange插值法、三次插值多项式)

    要求 1、 利用Lagrange插值公式 L n ( x ) = ∑ k = 0 n ( ∏ i = 0 , i ≠ k n x − x i x k − x i ) y k {L_n}(x) = sumlimits_{k = 0}^n {left( {prodlimits_{i = 0,i ne k}^n {frac{{x - {x_i}}}{{{x_k} - {x_i}}}} } right)} {y_k} L n ​ ( x ) = k = 0 ∑ n ​ ( i = 0 , i  = k ∏ n ​ x k ​ − x i ​ x − x i ​ ​ ) y k ​ 编写出

    2024年02月07日
    浏览(44)
  • 三次样条插值——三弯矩方法

             三次样条插值方法,是将一个曲线函数分成多段,每相邻的两个标准点就是一个三次多项式函数.也就是说,n+1个标准点,共有 n 个三次函数.求解分段时共有4*n个未知系数  其相邻的分段函数之间连续,一阶导连续,二阶导也连续。 因此  每个分段三次样条函数要

    2024年01月23日
    浏览(37)
  • 牛顿插值法、拉格朗日插值法、三次插值、牛顿插值多项式、拉格朗日插值多项式

    两点式线性插值 调用Matlab库函数 拉格朗日二次插值: 牛顿二次插值 结果分析:通过对比不同插值方法,可以看到在一定范围内(高次会出现龙格现象),插值次数越高,截断误差越小(插值结果越接近于真实函数值);同时,对于相同次数的插值,由于不同的插值方法它们

    2024年02月11日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包