拉格朗日插值原理及其Julia实现

news2024/12/28 21:04:01

文章目录

    • 数学原理
    • 算法化
    • 测试

设函数 y = f ( x ) y=f(x) y=f(x)在区间 [ a , b ] [a,b] [a,b]上有定义,且在点 a ⩽ x 0 ⩽ x 1 … ⩽ x n ⩽ b a\leqslant x_0\leqslant x_1\ldots\leqslant x_n\leqslant b ax0x1xnb上的值 y 0 , y 1 … y n y_0, y_1 \ldots y_n y0,y1yn之间存在一个函数 P ( x ) P(x) P(x),使得

P ( x i ) = y i ( i = 0 , 1 , … , n ) P(x_i)=y_i (i=0,1,\ldots, n) P(xi)=yi(i=0,1,,n)

成立,则称 P ( x ) P(x) P(x) f ( x ) f(x) f(x)的插值函数,在 x 0 , x 1 , … , x n x_0, x_1,\ldots,x_n x0,x1,,xn称为插值节点,包含节点的区间称为插值区间。如果 P ( x ) P(x) P(x)是次数不超过 n n n的代数多项式,则称之为插值多项式。

数学原理

若有 n + 1 n+1 n+1组一一对应的 ( x , y ) (x,y) (x,y)点对,假设存在一多项式 L n ( x ) L_n(x) Ln(x),使之满足 L n ( x j ) = y j , j = 0 , 1 , … , n L_n(x_j)=y_j,j=0,1,\ldots,n Ln(xj)=yj,j=0,1,,n,即

{ a 0 + a 1 x 0 + … + a n x 0 n = y 0 a 0 + a 1 x 1 + … + a n x 1 n = y 1 ⋮ a 0 + a 1 x n + … + a n x n n = y n \left\{\begin{aligned} a_0+a_1x_0+\ldots+a_nx_0^n&=&y_0\\ a_0+a_1x_1+\ldots+a_nx_1^n&=&y_1\\ &\vdots&\\ a_0+a_1x_n+\ldots+a_nx_n^n&=&y_n\\ \end{aligned}\right. a0+a1x0++anx0na0+a1x1++anx1na0+a1xn++anxnn===y0y1yn

L n L_n Ln即为该组数据的插值多项式。对于任意 j = 0 , 1 , … , n j=0,1,\ldots,n j=0,1,,n,有 L n ( x j ) = y j L_n(x_j)=y_j Ln(xj)=yj,则可令

L n ( x ) = ∑ k = 0 y k l k ( x ) L_n(x)=\displaystyle\sum_{k=0}y_kl_k(x) Ln(x)=k=0yklk(x)

其中,

l k ( x j ) = δ j k = { 1 , k = j 0 , k ≠ j ( j , k = 0 , 1 , … , n ) l_k(x_j)=\delta_{jk}=\left\{\begin{aligned} 1, k=j\\ 0, k\not=j \end{aligned}\right. (j,k=0,1,\ldots,n) lk(xj)=δjk={1,k=j0,k=j(j,k=0,1,,n)

则可满足 L n ( x j ) = ∑ k = 0 n y k l k ( x j ) = y j L_n(x_j)=\displaystyle\sum_{k=0}^ny_kl_k(x_j)=y_j Ln(xj)=k=0nyklk(xj)=yj,其中 l k l_k lk被称为基函数。根据其所满足的要求,易得基函数的表达式为

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 ) l_k(x)=\frac{(x-x_0)\ldots(x-x_{k-1})(x-x_{k+1})\ldots(x-x_n)}{(x_k-x_0)\ldots(x_k-x_{k-1})(x_k-x_{k+1})\ldots(x_k-x_n)} lk(x)=(xkx0)(xkxk1)(xkxk+1)(xkxn)(xx0)(xxk1)(xxk+1)(xxn)

自此,就得到了Lagrange插值多项式。该式简洁明了,其插值基函数规律明显,能使人过目不忘。若记

ω n + 1 ( x ) = ( x − x 0 ) ( x − x 1 ) … ( x − x n ) \omega_{n+1}(x)=(x-x_0)(x-x_1)\ldots(x-x_n) ωn+1(x)=(xx0)(xx1)(xxn)

ω n + 1 ′ ( x k ) = ( x k − x 0 ) … ( x k − x k − 1 ) ( x k − x k + 1 ) … ( x k − x n ) \omega'_{n+1}(x_k)=(x_k-x_0)\ldots(x_k-x_{k-1})(x_k-x_{k+1})\ldots(x_k-x_n) ωn+1(xk)=(xkx0)(xkxk1)(xkxk+1)(xkxn)

那么Lagrange插值公式可写为

L n ( x ) = ∑ k = 0 n y k ω n + 1 ( x ) ( x − x k ) ω n + 1 ′ ( x k ) L_n(x)=\displaystyle\sum_{k=0}^ny_k\frac{\omega_{n+1}(x)}{(x-x_k)\omega'_{n+1}(x_k)} Ln(x)=k=0nyk(xxk)ωn+1(xk)ωn+1(x)

特别地,对于两点而言,Lagrange插值退化为线性插值,即

L 2 ( x ) = y 1 x − x 2 x 1 − x 2 + y 2 x − x 1 x 2 − x 1 L_2(x)=y_1\frac{x-x_2}{x_1-x_2}+y_2\frac{x-x_1}{x_2-x_1} L2(x)=y1x1x2xx2+y2x2x1xx1

算法化

在Lagrange插值公式中, ω n + 1 ( x ) \omega_{n+1}(x) ωn+1(x)为多项式乘法。Julia中虽然对函数式编程有着良好的支持,但如果将函数本身作为输出,则函数实现细节将被隐藏,因此并不能得到真正的拟合参数。故需对多项式进行抽象,即将其简化为数组的形式,其表现形式为[a_0,a_1,...,a_n],代表 a 0 + a 1 x + … + a n x n a_0+a_1x+\ldots+a_nx^n a0+a1x++anxn

那么多项式乘法可以通过进位的方式实现。对于常数项而言,并不会改变多项式的幂数;对于一阶项来说,乘以多项式数组,则将该数组向高位移一位。其实现方法为

# 多项式乘法,形式为an*x^n,建议a[1]为最低位常数项
function polyMulti(a,b)
    na = length(a); nb = length(b)
    c = zeros(na+nb-1)
    for i = 1:na
        c[i:i+nb-1] += a[i]*b
    end
    return c
end

Lagrange插值公式亦涉及到多项式除法,其实现方法与乘法类似,但运算顺序要从高位开始,并且被除多项式的阶数要不小于除数多项式。

Julia对象采用地址引用,在传参之后如果直接改变数组内容,将穿透作用域,使得函数之外的数组也发生变化,故而需要深拷贝。

function polyDiv(a,b)
    a = copy(a)         #此为余数
    na = length(a); nb = length(b)
    nc = na-nb+1
    c = zeros(nc)
    for i = 0:nc-1
        c[nc-i] = a[end-i] ÷ b[end]
        a[nc-i:end-i] += -c[nc-i]*b[1:end]
    end
    return c, a
end

此外,Lagrange插值需要频繁地进行连乘计算,其中,分子中的连乘为多项式连乘,分母中的多项式为值连乘,所以可建立连乘函数。

# 连乘函数,输入为数组,输出为数组中所有数的乘积
function sumMulti(x)
    return length(x) == 1 ? x : x[1]*sumMulti(x[2:end])
end

Lagrange插值公式中的多项式连乘形式单一,相比之下更像是多项式的两种表示形式的转换,所以再建立针对Lagrange插值公式的多项式转化函数

#将(x-x1)(x-x2)...(x-xn)化成an*x^n形式,A[1]为最低位(常数项)
#输入为[x1,x2,...,xn]输出为[a1,a2,...,an]
function polySimplify(x)
    if length(x) == 1
        return [-x[1],1]
    else
        return polyMulti([-x[1],1],polySimplify(x[2:end]))
    end
end

至此,可以创建Lagrange插值函数。

# Language插值函数
# x y: 维度相同的列变量
# A: 多项式系数,A[1]为最低位
using LinearAlgebra         #建立单位矩阵需要使用线性代数包
function Lagrange(x,y)
    n = length(x)
    xMat = x .- x' + Matrix{Float64}(I,n,n)
    polyMat = polySimplify(x)
    A = zeros(n)
    for i = 1:n
        quot = polyDiv(polyMat,[-x[i],1])[1]
        A += y[i] * quot ./ sumMulti(xMat[i,:])
    end 
    return A
end

函数中的xMat为矩阵

[ 1 x 1 − x 0 … x n − x 0 x 0 − x 1 1 … x n − x 1 ⋮ x 0 − x n x 1 − x n … 0 ] \begin{bmatrix} 1 & x_1-x_0 & \ldots & x_n-x_0\\ x_0-x_1 & 1 & \ldots & x_n-x_1\\ & & \vdots & \\ x_0-x_n & x_1-x_n & \ldots & 0\\ \end{bmatrix} 1x0x1x0xnx1x01x1xnxnx0xnx10

polyMat为多项式 ω n + 1 ( x ) \omega_{n+1}(x) ωn+1(x)

测试

在命令行中调用得

julia> include("interpolation.jl")
Lagrange (generic function with 1 method)

julia> x = [i for i = 1:9];

julia> y = x.^8 + x.^6 + x.^2 .+ 1;

julia> a = Lagrange(x,y)
9-element Array{Float64,1}:
  1.0
  4.470348358154297e-8
  0.9999999850988388
 -1.4901161193847656e-8
 -7.450580596923828e-9
  2.7939677238464355e-9
  1.0
  0.0
  1.0

结果表明,其8次项、6次项、2次项和0次项分别为1或者接近于1,其他项分别为0或者接近于0,可见拟合结果尚可。通过Plots包对原始数据和拟合结果进行比较

julia> using Plots
julia> y1 = y;
julia> y2 = [sum([a[i]*x[j]^(i-1) for i=1:9]) for j = 1:9];
julia> plot(x,[y1,y2],st=[:scatter :line])
julia> savefig("Lagrange.png")

在这里插入图片描述

可见插值结果能够符合原始数据的趋势。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/194503.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

规则引擎-drools-3.2-drl文件构成-rule部分-属性Attribute

文章目录drl文件构成-rule部分rule示例rule nameAttribute全部属性说明no-loop 和 lock-on-activeactivation-group 和 agenda-groupdrl文件构成-rule部分 drl文件构成,位于官网的第5章位置,也是drools作为规则引擎应用的最核心部分。 其中rule模块&…

谷歌浏览器无法翻译此网页,解决方法?(谷歌浏览器无法翻译成中文,谷歌翻译,最新方法)

谷歌浏览器自带的翻译功能,对我们来说用处很大,但有的时候突然就会变成“无法翻译此网页”,针对此问题这里提供几种解决方案(翻译插件),如下: 方法1: 蓝奏云文件https://wwot.lanzouw.com/iFc7d0hmrtpg 访问密码:slee 方法2: 脚本之家

分布式事务的4种模式

分布式事务理论基础 解决分布式事务,也有相应的规范和协议。分布式事务相关的协议有2PC、3PC。 由于三阶段提交协议3PC非常难实现,目前市面主流的分布式事务解决方案都是2PC协议。 有些文章分析2PC时,几乎都会用TCC两阶段的例子&#xff0…

Java开发基础入门之Java基础中的Stack类及其常用方法

一、Stack类 1.Stack是Vector的一个子类,它实现标准的后进先出堆栈。Stack只定义了创建空堆栈的默认构造方法。 Stack() 2.Stack类里面主要实现的有以下的几个方法: (1)boolean empty( )方法是判断堆栈是否为空。 (2)Object peek( )方法是返回栈顶端…

一夜爆火的现象级产品ChatGPT,是AI突破还是昙花乍现?

导语 | 编写代码、翻译小说、参加考试……2022 年末,人工智能聊天机器人 ChatGPT 风靡全网。自 2016 年 AlphaGo 击败围棋世界冠军李世石后,ChatGPT 再次掀起了人工智能发展应用的高潮。它将会给我们带来哪些影响?人工智能的颠覆性应用是否即…

MyBatis 二级缓存整合Redis【学习记录】

二级缓存整合Redis 上篇文章介绍了MyBatis自带的二级缓存,但是这个缓存是单服务器工作,无法实现分布式缓存。那么什么是分布式缓存呢?假设现在有两个服务器1和2,用户访问的时候访问了服务器1,查询后的缓存就会放在服务…

酒店预订订单的分析与建模【决策树、xgboost】

酒店预订订单的分析与建模【决策树、xgboost】 本项目包含 1.数据处理 2.数据探索性分析 3.网格搜索对决策树、xgboost进行模型参数调优 4.基于五折交叉验证的决策树、xgboost模型预测 专栏和往期项目 👉往期文章可以关注我的专栏 下巴同学的数据加油小站 会不…

《神经网络与深度学习》 邱希鹏 学习笔记(二)

正则化 所有损害优化的方法都是正则化。增加优化约束,干扰优化过程 优化约束包括 L1/L2约束,数据增强 干扰优化包括 随机梯度下降 权重衰减 提前停止 在上式中 y(n)为样本n,其展开形式为y^{(n)}为样本n,其展开形式为y(n)为样本…

【Axure教程】低代码可视化编辑器

低代码是一组数字技术工具平台,基于图形化拖拽、参数化配置等更为高效的方式,通过少量代码或不用代码实现数字化转型中的场景应用创新。例如在业务系统中,如果企业新增了一项业务,以往往往需要对系统继续开发和升级,但…

【Python学习笔记】9. Python3 解释器

前言 Linux/Unix的系统上,一般默认的 python 版本为 2.x,我们可以将 python3.x 安装在 /usr/local/python3 目录中。 Python3 解释器 Linux/Unix的系统上,一般默认的 python 版本为 2.x,我们可以将 python3.x 安装在 /usr/loca…

IDEA 常用插件跟配置提升开发效率

工欲善其事必先利其器 安装好 IntelliJ IDEA 后,进行如下的初始化操作,工作效率提升50倍。 一、插件 1. Codota 代码智能提示插件 只要打出首字母就能联想出一整条语句,这也太智能了,还显示了每条语句使用频率。原因是它学习了…

最全的视频转换器工具清单,这18款免费视频格式转换器记得收藏

审查和比较具有功能和定价的最佳视频转换器软件。从这个顶级付费和免费在线视频转换器工具列表中选择,以快速轻松地转换任何视频: 什么是视频转换器? 视频转换工具允许您将视频从一种格式转换为另一种格式。第一个商业上成功的视频格式是 Q…

11.1-股票基金历年收益率计算

文章目录1. 计算目标2. 关键问题3. 获取交易日历4. 逻辑编写1. 计算目标 我们想知道,一只股票标的,在之前的几年中,每一年的年化收益率是多少? 如果将每年的年化收益率进行求和汇总,截止到今年,总共年化收…

五、Mybatis详细教程

Mybatis概述 1 Mybatis概念 MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发 MyBatis 本是 Apache 的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github 官网&am…

Qt OpenGL(三十五)——Qt OpenGL 核心模式-点云(斯坦福兔子)

提示:本系列文章的索引目录在下面文章的链接里(点击下面可以跳转查看): Qt OpenGL 核心模式版本文章目录 Qt OpenGL(三十五)——Qt OpenGL 核心模式-点云(斯坦福兔子) 一、场景 我们在平时的项目中,有的时候会遇到,激光雷达等这些设置采集的数据集,不管是在机器人、…

【微服务】分布式缓存Redis

分布式缓存Redis基于Redis集群解决单机Redis存在的问题1.Redis持久化1.1.RDB持久化1.1.1.执行时机1.1.2.RDB原理1.1.3.小结1.2.AOF持久化1.2.1.AOF原理1.2.2.AOF配置1.2.3.AOF文件重写1.3.RDB与AOF对比2.Redis主从2.1.搭建主从架构2.2.主从数据同步原理2.2.1.全量同步2.2.2.增量…

UVM实战(张强)--- UART实例代码详细注解

目录一、整体的设计结构图二、各个组件代码详解2.1 DUT2.2 my_driver2.3 my_transaction2.4 my_env2.5 my_monitor2.6 my_agent2.7 my_model2.8 my_scoreboard2.9 my_sequencer2.10 base_test2.11 my_case02.12 my_case1一、整体的设计结构图 各个模块的基础介绍: &…

Spring核心——面向切面编程(AOP)

Spring核心——AOP(Aspect-oriented programming)一、概念二、作用三、AOP核心概念1.连接点(JoinPoint)2.切入点(Pointcut)3.通知(Advice)4.通知类5.切面(Aspect&#xf…

c语言 结构体 动态内存 动态内存管理 模拟实现atoi 找单身狗 文件操作程序编译和链接 预处理 交换奇偶位 offsetof宏的实现 习题

结构体大小 【题目名称】 在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是( C ) 对齐数是取其较小值 struct A {int a;short b;int c;char d; }; struct B {int a;short b;char c;int d; };【题目内容】 A. 1…

小程序项目学习--第五章:项目实战一

第五章:项目实战一、 01_(了解)音乐小程序的项目介绍 坑关于Vant Weapp中组件引入未找到的解决方案 [ pages/main-music/main-music.json 文件内容错误] pages/main-music/main-music.json: [“usingComponents”][“van-search”]: “vant/weapp/search/index”…