Python数值计算(10)——PPoly对象

news2024/11/14 14:15:00

在scipy中,scipy.interpolate下还有一个PPoly的类,用于表示插值多项式,很多插值算法的结果,都以该类的实例返回,因此有必要了解该类的使用方法。要使用该类,首先要引入相应的模块:

from scipy.interpolate import PPoly

1. 对象创建

PPoly类的构造函数为:

class PPoly(c, x, extrapolate=None, axis=0)

其中c为系数列表,需要注意的是,c是一个k×m的二维数组,c中的每一列是每个分段的系数,x表示间断点横坐标,它必须按升序或者降序方式排列,其行数必须是m+1,x[i]和x[i + 1]之间的多项式以如下形式表示:

S = sum(c[m, i] * (xp - x[i])**(k-m) for m in range(k+1))

其中k 是多项式的度。说了这么多,还是比较抽象,我们直接以一个多项式的创建为例,解释其原理。先创建一个PPoly对象,然后绘制其图形:

import numpy as np
from numpy import poly1d
from numpy.polynomial import Polynomial
from scipy.interpolate import PPoly
import matplotlib.pyplot as plt

c=np.array([[1,-2,3],[0,0,1]])
x=[0,1,2,3]
p1=PPoly(c,x)
X=np.linspace(0,3,1000)
Y=p1(X)
plt.plot(X,Y)
plt.grid()
plt.show()

所生成图形如下:

提供的系数c是一个2×3(k=2,m=3)的数组,说明多项式的度为k=2(因此最高次幂为2-1=1),提供的间断点x,第一个维度大小必须是(m+1)=4。再看看生成的分段多项式,通过简单的计算,可知三段(不含垂直线)分别是:

\left\{\begin{matrix} y=x,0 \leqslant x<1\\ y=-2x+2,1\leqslant x < 2\\ y=3x-5, 2\leqslant x \leqslant 3 \end{matrix}\right.

可以看到各段的最高次系数与c的第0列相同,但是第二列就不一样了,原因在哪里呢?PPoly的coefs中的多项式系数是每个区间的本地系数,它的起点是按x_i为基础的,上面的函数关系修改为:

\left\{\begin{matrix} y=1(x-0)+0,0 \leqslant x<1\\ y=-2(x-1)+0,1\leqslant x < 2\\ y=3(x-2)+1, 2\leqslant x \leqslant 3 \end{matrix}\right.

就可以发现,各段的系数与之保持一致了,且采用了降幂方式排列。

通过上面的过程,验证一下该分段多项式:

c=np.array([[1,-2,3],[0,0,1]])
x=[0,1,2]
p1=PPoly(c.T,x)

注意这里c使用了转置,x也去掉了中断点3,因此k=3,m=2,函数最高次为k-1=2,函数将会分2段,各段的函数应该是:

y=1(x-0)^2-2\ast(x-0)^1+3=x^2-2x+3,\ 0\le x\le1

y=0(x-1)^2+0\ast(x-1)^1+1=1,\ 1\le x\le2

绘制的图形如下:

当然,如果只有一个函数(不分段),例如常见的多项式,px=2x^3-3x^2-4x+1,可以表示为:

x=np.array([[2,-3,-4,1]]).T
y=np.array([0,1])
p=PPoly(x,y)

和比较常用的Numpy下的Polynomial对比一下:

from numpy.polynomial import Polynomial
from scipy.interpolate import PPoly
import matplotlib.pyplot as plt

x=np.array([[2,-3,-4,1]]).T
y=np.array([0,1])
p=PPoly(x,y)

X=np.linspace(-1,1,50)
Y=p(X)
p1=Polynomial([1,-4,-3,2])
Y1=p1(X)
plt.plot(X,Y,'r')
plt.plot(X,Y1,'g*')
plt.grid()
plt.show()

运行效果为:

上面的例子先通过现有数据构造PPoly对象p,然后根据p生成点对(X,Y)并上绘制其图形(红色实线),然后构造一个Polynomial对象p2绘制图形(绿色点),可见两者是完全相符的。此外,注意到我们的分段曲线p是在[0,1]上生成的,但是在区间[-1,1]上都是可以正常使用的。

2. 对象属性

通过c和x可以获取其系数以及间断点。例如,通过CubicSpline对数据进行拟合:

x=np.array([0,1,2,3,4])
y=np.array([0,2,-1,1,0])

cs=CubicSpline(x,y)
print(cs.c)
'''
[[ 2.41666667  2.41666667 -2.08333333 -2.08333333]
 [-9.75       -2.5         4.75       -1.5       ]
 [ 9.33333333 -2.91666667 -0.66666667  2.58333333]
 [ 0.          2.         -1.          1.        ]]
'''
print(cs.x) # [0. 1. 2. 3. 4.]

其中x属性很容易理解,就是间断点,c返回的是一个列表,每一列就是每一段的系数,对于分段三次样条曲线而言,分别表示:

y=2.41666667(x-0)^3-9.75(x-0)^2+9.33333333(x-0)+0,0\le x<1\\ y=2.41666667(x-1)^3-2.5(x-1)^2-2.91666667(x-1)+2,1\le x<2\\ y=-2.08333333(x-2)^3+4.75(x-2)^2-0.66666667(x-2)-1,2\le x<3\\ y=-2.08333333(x-3)^3-1.5(x-3)^2+2.58333333(x-3)+1,3\le x\le4

3. 数值计算

3.1 单点值

向PPoly对象提供一个标量或者数组,就和函数调用一样,可以计算对应的函数值,以上面的分段三次样条曲线为例:

X=np.linspace(0,4,50)
Y=cs(X)

绘制该曲线如下:

3.2 区间定积分

通过integrate计算PPoly函数在给定区间的积分值,例如,上面的分段多项式在[0.5,1.5]之间的积分:

fint=cs.integrate(0.5,1.5)
print(fint) # 1.791666666666667

3.3 求根

通过solve方法,可以求解方程f(x)=y的根,其中y作为solve的参数,依旧以上述分段多项式为例,在区间[0,4]上找到y=3时对应的x的值,从图形中可知,应该有4个根:

cs=CubicSpline(x,y)
rts=cs.solve(1)
print(rts) # [0.12229237 1.29076033 3. 3.81029911]

测试确实将4个根都找到了。

对于一般的f(x)=0的求根,也可以使用roots方法,等效于solve(0):

cs=CubicSpline(x,y)
rts=cs.roots()
print(rts) # [0. 1.5620559  2.64950957 4.]

3.4 多项式的运算

和Poly1d和Polynomial不同,分段多项式由于其断点的存在,因此不支持一般意义上的多项式四则运算,但是仍旧可以对他进行积分和微分运算。

3.4.1 微分

对PPoly对象进行微分,可以使用PPoly. derivative方法,默认为一阶导数,也可以通过参数指定其他阶导数,返回值仍旧是一个PPoly对象,例如对前面的分段三次样条曲线:

x=np.array([0,1,2,3,4])
y=np.array([0,2,-1,1,0])

cs=CubicSpline(x,y)
X=np.linspace(0,4,50)
Y=cs(X)
csd1=cs.derivative()#一阶导
csd2=cs.derivative(2)#二阶导
plt.plot(X,Y,'r')
plt.plot(X,csd1(X),'g')
plt.plot(X,csd2(X),'b')
plt.grid()
plt.show()

效果如下:

可以看到一阶导数(绿色)是连续可导的,二阶导数(蓝色)是连续的。

3.4.2 积分

对分段多项式进行多项式积分,并不是integrate函数,该函数在前面介绍过,它实际上的功能是数值积分,实际完成多项式积分的是antiderive函数,该函数是原分段函数的不定积分,测试如下:

x=np.array([0,1,2,3,4])
y=np.array([0,2,-1,1,0])

cs=CubicSpline(x,y)
X=np.linspace(0,4,50)
Y=cs(X)
csd1=cs.derivative()#一阶导
csd1i=csd1.antiderivative()
plt.plot(X,Y,'r')
plt.plot(X,csd1i(X),'g*')
plt.grid()
plt.show()

效果如下:

测试代码先计算其导函数csd1,然后又对其进行积分得到csd1i,并将原函数cs和csd1i绘图对比,如果给derive方法提供负整数,其起到的效果和antiderive是一样的。

4. 额外的问题

最后一个问题是,如何通过PPoly对象,构造一个Polynomial对象?

例如,有个这样的分段函数:

c=np.array([[3,1],[0,1],[-2,0],[1,-1]])
x=np.array([0,1,2])
p=PPoly(c,x)

按PPoly的定义,其表达式为:

y=3(x-0)^3+0(x-0)^2-2(x-0)^1+1=3x^3-2x+1,0\le x<1

y=1(x-1)^3+1(x-1)^2+0(x-1)^1-1=x^3-2x^2+x+1,1\le x\le2

编写转换的函数如下:

def ppolyCoff_to_normal(p:PPoly):
    '''
    由于 PPoly的coefs中的多项式系数是每个区间的本地系数,
    因此必须减去对应节点区间的较低端点,以使用传统多项式方程中的系数。
    即对于区间 [x1,x2] 上的系数 [a,b,c,d],对应的多项式为
    f(x)=a*(x−x1)**3+b*(x−x1)**2+c*(x−x1)+d .
    此外,PPoly采用的降幂排列,而返回的系数中,
    按Numpy中的Polynomial组织形式升幂排列
    '''
    ppoly_coef=p.c
    x=p.x
    k,m=ppoly_coef.shape
    p_coef=np.zeros((k,m))
    for c in range(m):
        S=P([0])
        for r in range(k):
            S+=ppoly_coef[r,c]*P([-x[c],1])**(k-r-1)
            p_coef[:,c]=S.coef
return p_coef,p.x

测试代码:

c=np.array([[3,1],[0,1],[-2,0],[1,-1]])
x=np.array([0,1,2])
p=PPoly(c,x)
pc,px=ppolyCoff_to_normal(p)
print(pc)
‘’’
[[ 1. -1.]
 [-2.  1.]
 [ 0. -2.]
 [ 3.  1.]]
‘’’

print(px) # [0. 1. 2.]

函数返回系数和间断点,每一列表示每个区间段的多项式,并按升幂排列,绘制上述函数返回的多项式图形:

c=np.array([[3,1],[0,1],[-2,0],[1,-1]])
x=np.array([0,1,2])
p=PPoly(c,x)
pc,px=ppolyCoff_to_normal(p)

X=np.linspace(0,2,100)
Y=p(X)
plt.plot(X,Y,'r')
r,c=pc.shape
for i in range(c):
    p=Polynomial(pc[:,i])
    X=np.linspace(px[i],px[i+1],20)
    Y=p(X)
    plt.plot(X,Y,'b*')
plt.grid()
plt.show()

结果如下图所示:

PPoly对象使用红色的实线绘制,而通过转换后获得的多项式系数构造的多项式,绘制图形用蓝色点标识,可以看到两者是相符合的。

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

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

相关文章

基于docker的 nacos安装部署

一、拉取镜像 拉取nacos官方镜像&#xff0c;这里使用默认命令 docker pull nacos/nacos-server二、创建挂载目录 创建本地的映射文件application.properties mkdir -p /home/docker/nacos/conf /home/docker/nacos/logstouch /home/docker/nacos/conf/application.propert…

举个栗子!Tableau 技巧(280):创建点象限图( Dot Quadrant Chart )

之前分享过 &#x1f330; &#xff1a;四象限图 和 葡萄干布丁图。今天&#xff0c;我们将两者的呈现方式结合起来&#xff0c;创建如下的点象限图( Dot Quadrant Chart )&#xff0c;可以帮助数据粉在有限的看板区域内展示更多的数据信息。 那么&#xff0c;如何在 Tableau 中…

一文弄清Java的四大引用及其两大传递

开场白 Hello大家好呀&#xff0c;我是CodeCodeBond✊最近在复习很多很多的基础知识&#xff0c;有了很多新的感悟~ 话不多说&#xff0c;直接发车✈ 四大引用 问题切入点 在学习 Thread线程利用ThreadLocalMap实现线程的本地内存&#xff08;变量副本&#xff09;的时候&…

简单的docker学习 第1章 docker 概述

Docker 学习笔记 本文是b站动力节点docker学习视频的笔记整理&#xff0c;主要用于自己学习复习使用&#xff0c;视频具体地址为 : 动力节点docker 第一章 docker 概述 1.1 课程引人入 1.1.1 开发/运维互掐 ​ 开发与测试和运维间的矛盾&#xff0c;主要是由于环境的不同而…

flutter 做代码混淆

第一种、手动混淆 修改代码中出现次数多的 类目 方法 。修改静态资源的名字&#xff0c;转静态资源为webp 第二种、使用flutter 自带的命令行工具进行混淆 混淆 Dart 代码 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 使用pragma(vm:entry-point) 装饰器修改方…

【界面开发实战】使用DevEco Studio编写支付宝首页

效果展示 知识点 层叠布局 上一篇文章已经介绍了&#xff0c;这篇文章中不再赘述&#xff0c;如果想了解的话可以去看上一篇文章&#xff0c;链接如下&#xff1a; http://t.csdnimg.cn/CnBZMhttp://t.csdnimg.cn/CnBZM 弹性布局 作用&#xff1a;提供更加有效的方式对容器…

YOLOV5 改进:替换backbone为MobileVIT

1. 介绍 yolov5替换主干网络的步骤如下,依旧和之前的一样 2. 更改common文件 将下面代码加入common最下面即可: from einops import rearrange import torch import torch.nn as nn# Transformer Attention模块定义 class TAttention(nn.Module):def __init__(self, dim, …

string的底层简单实现(造轮子)

文件&#xff1a;String.h ----- 头文件 String.cpp ----- 源文件 Test.cpp ----- 源文件 实现细节&#xff1a; 实现带参构造&#xff1a; 在实现带参构造建议不使用初始化列表&#xff0c;初始化去写不太好&#xff1a; :_str(new char[strlen(str)1]) 用初始化列表要在…

如何在 Jupyter Notebook 中直接设置全局随机种子的方法及易错地方、notebook和pycharm中设置随机种子的区别

结论&#xff1a; 在 Jupyter Notebook 中直接设置全局随机种子的方法是确保每个单独的代码块中都调用相同的 set_seed 函数。这是最简单且有效的方法。在每个代码块开头设置随机种子&#xff0c;确保代码在每次执行时具有相同的随机数生成顺序。 易错地方&#xff1a; …

mac配置git的sshkey

在MAC中配置Git的SSH Key&#xff1a; 1.打开终端 2.生成SSH密钥&#xff0c;输入以下命令&#xff1a; ssh-keygen -t rsa -b 4096 -C “你自己的账号电子邮件地址” 按回车键后&#xff0c;系统会提示你输入文件保存路径&#xff0c;默认为~/.ssh/id_rsa直接按回车键使用默…

数据结构初阶之排序(上)

排序的概念及其应用 排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使⼀串记录&#xff0c;按照其中的某个或某些关键字的⼤⼩&#xff0c;递增或递减的排列起来的操作。 排序的应用 如下图&#xff1a; 样例数组 下面我们给出一组乱序的数组&#xff0c;接下来的算…

程序员进阶架构知识体系、开发运维工具使用、Java体系知识扩展、前后端分离流程详解、设计模式开发实例汇总专栏分享

场景 作为一名开发者&#xff0c;势必经历过从入门到自学、从基础到进阶、从学习到强化的过程。 当经历过几年企业级开发的磨炼&#xff0c;再回头看之前的开发过程、成长阶段发现确实是走了好多的弯路。 作为一名终身学习的信奉者&#xff0c;秉承持续学习、持续优化的信念…

GitHub推出全新AI模型平台:简化开发者体验

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

《计算机网络》(第8版)第8章 互联网上的音频/视频服务 复习笔记

第 8 章 互联网上的音频/视频服务 一、概述 1 多媒体信息的特点 多媒体信息&#xff08;包括声音和图像信息&#xff09;最主要的两个特点如下&#xff1a; &#xff08;1&#xff09;多媒体信息的信息量往往很大&#xff1b; &#xff08;2&#xff09;在传输多媒体数据时&a…

【网络】TCP协议——TCP连接相关、TCP连接状态相关、TCP数据传输与控制相关、TCP数据处理和异常、基于TCP应用层协议

文章目录 Linux网络1. TCP协议1.1 TCP连接相关1.1.1 TCP协议段格式1.1.2 确定应答(ACK)机制1.1.3 超时重传机制 1.2 TCP连接状态相关1.2.1 TIME_WAIT状态1.2.2 CLOSE_WAIT 状态 1.3 TCP数据传输与控制相关1.3.1 滑动窗口1.3.2 流量控制1.3.3 拥塞控制1.3.4 延迟应答1.3.5 捎带应…

草的渲染理论

Unity引擎提供了基础的terrain工具&#xff0c;可以制作地形&#xff0c;在上面刷树刷草。对于树&#xff0c;Unity是支持带LOD的Prefab&#xff0c;不同距离显示不同细节的模型&#xff0c;效果还不错。对于草&#xff0c;Unity支持两种方式来刷草&#xff0c;一种是Add Grass…

汇凯金业:解读区块链概念、类型与独特优势

区块链作为一种具有革命性的创新技术&#xff0c;正在逐渐改变我们的生活和商业模式。它的去中心化、安全可靠、不可篡改等特性&#xff0c;为解决许多传统领域中的问题提供了新的思路和方法。 一、区块链的基本概念 区块链是一种具有创新性的计算机技术应用模式&#xff0c;…

C#复习之类和对象

知识点一&#xff1a;什么是类 基本概念&#xff1a; 具有相同特征 具有相同行为 一类事物的抽象 类是对象的模板 可以通过类创建出对象 类的关键字 Class 知识点二&#xff1a;类声明在哪里 类一般声明在namespace语句块中 知识点三&#xff1a;类声明的语法 知识点四&#xf…

html+css 实现文字滚动的按钮

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽效果&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 文…