编程实战(2)——Python解微分方程方法总结

文章目录

  • 编程实战(2)——Python解微分方程方法总结
    • 综述
    • 代码解析
      • 二阶常系数齐次微分方程的解析解
        • dsolve获取解析解
        • 检验一下
        • dsolve能解二阶非齐次微分方程吗?
      • odeint+画图求数值解
      • 求解微分方程组
        • 一阶方程组求解
        • 能解二阶方程组吗?

综述

最近有用python解微分方程的需求,然后找了网上很多的资料和帖子,然后结合个人的想法做了一些研究。

本篇博客主要讲解了二阶常系数微分方程的解析解和数值解的解法以及一阶常系数微分方程组的通解解法,并对每一个步骤做了详细的说明(网上很多帖子讲的并不是很详细),并做了一些探究性的尝试

代码解析

二阶常系数齐次微分方程的解析解

dsolve获取解析解

我们这里用到的库是sympy;

用sympy.dslove常系数齐次微分方程代码思路如下:

  • 首先我们要把需要的微分方程化成g(f(x),x)=0g(f(x),x)=0g(f(x),x)=0的形式;
  • 然后把所有的可能被求导的自变量找出来,同时确定因变量,用sympy.symbols标记自变量,用Function表示因变量;
  • 解方程并输出

例题:解微分方程f(x)′′+ω2f(x)=0f(x)''+\omega^2f(x)=0f(x)′′+ω2f(x)=0

现在对照上面的三步很简单的思路来看一个例子:

import sympy as syx = sy.symbols("x") # 标出x和ω为自变量并用符号'x'和'w'表示之
omega = sy.symbols("w")
f = sy.Function("f") # 函数因变量f(x),用f表示equation = f(x).diff(x,2) + omega**2*f(x) # 化成g(f(x),x) = 0的形式,diff是求导函数print(sy.dsolve(equation,f(x)))
sy.pprint(sy.dsolve(equation,f(x)))# 两种输出方法,前面一个是返回的真实的dsolve返回的元组,后面是sympy库自带的格式化输出解析解的字符串

输出的结果:

Eq(f(x), C1*exp(-I*w*x) + C2*exp(I*w*x))
           -ⅈ⋅w⋅x       ⅈ⋅w⋅x
f(x) = C₁⋅ℯ       + C₂⋅ℯ

这个结果可以化成对应的三角函数形式。

检验一下

我们拿同济高数书上第346页上的一道例题来检验一下:求方程 y(4)−2y′′′+5y′′=0y^{(4)}-2y'''+5y''=0y(4)−2y′′′+5y′′=0的通解。

代码:

import sympy as syx = sy.symbols("x")
y = sy.Function("y")equation = y(x).diff(x,4)-2*y(x).diff(x,3)+5*y(x).diff(x,2)print(sy.dsolve(equation, y(x)))
sy.pprint(sy.dsolve(equation, y(x)))

输出:

Eq(y(x), C1 + C2*x + (C3*sin(2*x) + C4*cos(2*x))*exp(x))x
y(x) = C₁ + C₂⋅x + (C₃⋅sin(2⋅x) + C₄⋅cos(2⋅x))⋅ℯ

对照书上的答案,是正确的。

dsolve能解二阶非齐次微分方程吗?

我们还是拿同济高数书来检验一道例题:求方程通解 y′′−5y′+6y=xe2xy''-5y'+6y=xe^{2x}y′′−5y′+6y=xe2x

代码:

import sympy as sy
from math import ex = sy.symbols("x")
y = sy.Function("y")equation = y(x).diff(x,2)-5*y(x).diff(x,1)+6*y(x)-x*e**(2*x)print(sy.dsolve(equation, y(x)))
sy.pprint(sy.dsolve(equation, y(x)))

输出结果:

Eq(y(x), -0.5*7.38905609893065**x*x**2 - 1.0*7.38905609893065**x*x + C1*exp(2*x) + C2*exp(3*x))x  2                       x         2⋅x       3⋅
y(x) = - 0.5⋅7.38905609893065 ⋅x  - 1.0⋅7.38905609893065 ⋅x + C₁⋅ℯ    + C₂⋅ℯ  x

谜一般的输出,只有C1∗exp(2∗x)+C2∗exp(3∗x)C1*exp(2*x) + C2*exp(3*x)C1∗exp(2∗x)+C2∗exp(3∗x)这一部分是跟答案相同的,其他长长的数字就很莫名其妙了。

之所以会有前面那堆奇怪的数字可能跟算法有关系,这里就不再深究了,只能说用dslove解非齐次方程并不是很好使。

odeint+画图求数值解

这里我们用到求数值解的库叫做scipy;

scipy.odeint解数值解的思路是这样:

  • 如果是二阶方程,需要化成两个一阶方程组成的方程组,如果是一阶则跳过该步骤;
  • 把每个得到的方程组化成y′=f(x,y)y'=f(x,y)y′=f(x,y)形式,这里的x和y是相对每个方程而言的,后面会详细讲;
  • 因为要求的是数值解,所以需要确定好参数值和初始条件,在odeint中默认输入y=0y=0y=0的时因变量的值;
  • 确定自变量范围并解方程,绘制图像;

下面还是看一个例子(scipy官网文档中的例子):解微分方程 y′′+b∗y′+c∗siny=0y''+b*y'+c*siny = 0y′′+b∗y′+c∗siny=0,其中b,c是参数,对t求导;

按照上面的思路,首先化成两个一阶方程:
y′(t)=z(t)(1)y'(t)=z(t) \tag 1 y′(t)=z(t)(1)

z′(t)=−b∗z(t)−c∗sin(y(t))(2)z'(t)=-b*z(t)-c*sin(y(t)) \tag 2 z′(t)=−b∗z(t)−c∗sin(y(t))(2)

上面的第二步中说的x和y是相对方程而言,拿方程(2)来讲就是将z‘(t)当作y’,z(t)当作y,t当作x,其他的当作参数,化为y′=f(x,y)y'=f(x,y)y′=f(x,y)的形式,以便这个odeint解方程使用;

接下来看代码和注释,注释只解释基本方法:

import matplotlib.pyplot as plt
import scipy.integrate as sp
import numpy as np#设定参数b,c初值,其实这个方程是物理学中跟钟摆重力角和摩擦力有关的一个微分方程
b = 0.25
c = 5.0def function(t, y):#设定两个参数,约定第一个为自变量t,第二个为相对每个方程的因变量yyt, zt = y #规定每个方程的因变量return [zt, -b * zt - c * np.sin(yt)]#返回一个向量,每一项分别是每个方程的右半部分t = np.linspace(0, 10, 100)#规定数值解的范围
init_x = [np.pi - 0.1, 0]#规定初值,传入的是一个向量,分别是每个方程的y=0时t的取值
result = sp.odeint(function, init_x, t, tfirst=True)#解方程,注意第一个参数只填函数名不要写括号,tfirst是指是否把求导自变量作为函数第一个参数#画图部分
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = Falseplt.xlabel('t')
plt.ylabel('f(t)')
plt.plot(t, result[:, 0], label='f:yt')#原函数数值解
plt.plot(t, result[:, 1], label='f:zt')#一阶导
plt.legend()
plt.show()

接下来我参考了一下说明文档,对代码中一些关键部分做一个详细的说明。

  • 首先是我们的自定义函数,这个函数要作为odeint的必要参数,我们在调用odeint的时候,odeint会自动调用我们定义好的这个函数;
  • 自定义函数的返回值是一个数组向量,第一项表示原函数(方程的解)一阶导的表示(这里我们用另一个符号zt表示),第二项就表示原函数二阶导表示(即上面的方程(2)),以此类推…
  • 由于我们是求数值解,所以我们需要为每个方程规定一个初值,向量的第一项是第一个方程的初值,以此类推。在这里odeint默认初值为0,可以通过h0参数修改一下,详见https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.odeint.html

得到的方程数值解可视化结果如下:

对照官网的答案可知是正确的。

求解微分方程组

一阶方程组求解

我们还是用dsolve来,整个过程跟解一个方程是差不多的,所以直接上例子:

我们还是用高数书上的例题来验证(357页):

求微分方程组:
{x′(t)=3∗x(t)−2∗y(t)y′(t)=2∗z(t)−y(t)\begin{cases} x'(t)=3*x(t)- 2*y(t) \\ y'(t)=2*z(t)-y(t) \end{cases} {x′(t)=3∗x(t)−2∗y(t)y′(t)=2∗z(t)−y(t)​
代码:

import sympy as syt = sy.symbols("t")
x = sy.Function("x")
y = sy.Function("y")equation = x(t).diff(t,1)-3*x(t)+2*y(t)
equation2 = y(t).diff(t,1)-2*x(t)+y(t)print(sy.dsolve([equation,equation2], [x(t),y(t)]))
sy.pprint(sy.dsolve([equation,equation2], [x(t),y(t)]))

只是多加了一个函数关系和一个方程,然后解方程的时候需要把两个方程和两个因变量写成一个数组传进对应的位置,依葫芦画瓢即可,最后得到的结果是这样的:

[Eq(x(t), (2*C1 + 2*C2*t + C2)*exp(t)), Eq(y(t), (2*C1 + 2*C2*t)*exp(t))]
⎡                             t                          t⎤
⎣x(t) = (2⋅C₁ + 2⋅C₂⋅t + C₂)⋅ℯ , y(t) = (2⋅C₁ + 2⋅C₂⋅t)⋅ℯ ⎦

跟书上答案有略微差别但是仔细看一下就会发现是等价的。

能解二阶方程组吗?

直接看高数书358页例题2:

import sympy as sy
from math import et = sy.symbols("t")
x = sy.Function("x")
y = sy.Function("y")equation = x(t).diff(t,2)+y(t).diff(t,1)-x(t)-e**t
equation2 = y(t).diff(t,2)+x(t).diff(t,1)+y(t)print(sy.dsolve([equation,equation2], [y(t),x(t)]))
sy.pprint(sy.dsolve([equation,equation2], [y(t),x(t)]))

发现这段代码会报错:

File "D:\Anaconda3\Anaconda\lib\site-packages\sympy\solvers\ode\ode.py", line 599, in dsolveraise NotImplementedError
NotImplementedError

它说没有实现hhh,翻看了一下ode.py文件,查看他能做到的求解微分方程的种类:

allhints = ("factorable","nth_algebraic","separable","1st_exact","1st_linear","Bernoulli","Riccati_special_minus2","1st_homogeneous_coeff_best","1st_homogeneous_coeff_subs_indep_div_dep","1st_homogeneous_coeff_subs_dep_div_indep","almost_linear","linear_coefficients","separable_reduced","1st_power_series","lie_group","nth_linear_constant_coeff_homogeneous","nth_linear_euler_eq_homogeneous","nth_linear_constant_coeff_undetermined_coefficients","nth_linear_euler_eq_nonhomogeneous_undetermined_coefficients","nth_linear_constant_coeff_variation_of_parameters","nth_linear_euler_eq_nonhomogeneous_variation_of_parameters","Liouville","2nd_linear_airy","2nd_linear_bessel","2nd_hypergeometric","2nd_hypergeometric_Integral","nth_order_reducible","2nd_power_series_ordinary","2nd_power_series_regular","nth_algebraic_Integral","separable_Integral","1st_exact_Integral","1st_linear_Integral","Bernoulli_Integral","1st_homogeneous_coeff_subs_indep_div_dep_Integral","1st_homogeneous_coeff_subs_dep_div_indep_Integral","almost_linear_Integral","linear_coefficients_Integral","separable_reduced_Integral","nth_linear_constant_coeff_variation_of_parameters_Integral","nth_linear_euler_eq_nonhomogeneous_variation_of_parameters_Integral","Liouville_Integral",)

确实没有二阶常系数微分方程组这个类别,我的sympy是1.6.2版本的,不知道新版会不会增加这个功能。

总结:python解微分方程比较方便,可以满足绝大部分基础的需求(简单的数学建模方程基本都ok),如果需要更加高级的求解的话,建议转matlab。。。

编程实战(2)——Python解微分方程方法总结相关推荐

  1. python求解析解,Python解微分方程

    Python解微分方程 微分方程回顾 微分方程:python 解析解(SymPy) 微分方程:python数值解(SciPY) 微分方程组:python数值解 微分方程回顾 微分方程是用来描述某一类函 ...

  2. python从菜鸟到高手李宁pdf_尹成学院-Python从菜鸟到高手编程实战【已完结 28G】...

    带你步入 python 语言的殿堂,讲课生动风趣.深入浅出,全套视频内容充实,整个教程以 python语言为核心,完整精彩的演练了数据结构.算法.设计模式.数据库.大数据高并发检索.文件重定向.多线程 ...

  3. 《Python数据可视化编程实战》——5.5 用OpenGL制作动画

    本节书摘来异步社区<Python数据可视化编程实战>一书中的第5章,第5.5节,作者:[爱尔兰]Igor Milovanović,更多章节内容可以访问云栖社区"异步社区" ...

  4. python编程语法大全-Python编程入门——基础语法详解

    今天小编给大家带来Python编程入门--基础语法详解. 关于怎么快速学python,可以加下小编的python学习群:611+530+101,不管你是小白还是大牛,小编我都欢迎,不定期分享干货 每天 ...

  5. python编程if语法-Python编程入门基础语法详解经典

    原标题:Python编程入门基础语法详解经典 一.基本概念 1.内置的变量类型: Python是有变量类型的,而且会强制检查变量类型.内置的变量类型有如下几种: #浮点 float_number = ...

  6. 《Python数据可视化编程实战》—— 1.6 安装图像处理工具:Python图像库(PIL)...

    本节书摘来异步社区<Python数据可视化编程实战>一书中的第1章,第1.6节,作者:[爱尔兰]Igor Milovanović,更多章节内容可以访问云栖社区"异步社区" ...

  7. python 读取鼠标选中文本_木辛老师的编程课堂:Python和Qt之页面布局实战篇(一)...

    通过前几节课的学习,我们已经基本上掌握了使用Qt Designer完成简单的布局管理.通过这些知识的学习,我们算是对PyQt进行了初步的了解,也算是入门了! 但是仅仅掌握这些知识还是远远不够的: 高深 ...

  8. pyqt 界面关闭信号_木辛老师的编程课堂之Python和Qt实战慕课软件开发:增加关闭按钮...

    软件实战开始,快速提供编程能力:通过实战,分析产品需求,梳理设计需求,提升项目分析和架构的能力.快点跟着木辛老师一起学习吧! 请点击右上角"关注"按钮关注我们哟:跟着木辛老师学习P ...

  9. python硬件编程_Python学习日记_《Python硬件编程实战》笔记_Mr_Ouyang

    书名: Python硬件编程实战 作者: 李茂 出版社: 机械工业出版社 [此处需要插入图片 Python封面] 笔者简评:不太适宜购买,全书大篇幅在用图片来解释极简单的细节,对于那些需要作者去深挖. ...

  10. 《Python数据可视化编程实战》—— 1.2 安装matplotlib、Numpy和Scipy库

    本节书摘来异步社区<Python数据可视化编程实战>一书中的第1章,第1.2节,作者:[爱尔兰]Igor Milovanović,更多章节内容可以访问云栖社区"异步社区" ...

最新文章

  1. linux io重定向指令,Linux基础知识之 IO重定向
  2. 一位全加器的结构描述vhdl_小学数学结构化学习的评价实践探索
  3. 大数据开发实战:数据流图及相关数据技术
  4. 删库造成损失 0.87 亿,微盟程序员被判6年!
  5. Xamarin.Forms弹出对话框插件
  6. java多线程区别_Java中实现多线程的两种方式之间的区别
  7. [Unity]限制两个物体之间的距离
  8. (王道408考研操作系统)第一章计算机系统概述-第一节3:操作系统的运行机制与体系结构
  9. html评论和回复评论_佟丽娅“挑衅”贾玲,评论区晒刘德华合照,贾玲高情商回复佩服...
  10. termux安装python2_termux怎么安装python
  11. 虹科工业树莓派在激光雕刻中的应用
  12. 红米开发版刷机教程_红米手机稳定版刷机教程(Recovery卡刷)的具体操作方法
  13. 开源音乐播放器_测试4个开源音乐播放器等
  14. 微信号注册人工服务器,怎么设置微信公众号接入人工客服?
  15. 一文读懂《医疗器械定期风险评价报告》撰写要点
  16. 图片指纹技术检测图片相似度
  17. 找回Windows 10安全通知图标
  18. macOS 与 iOS 中的 Tagged Pointer
  19. C# 特性Description的值的获取
  20. BarManage --- 菜单

热门文章

  1. index.highlight.max_analyzed_offset
  2. 九、Redis三种集群模式
  3. IBus拼音无法选择候选词故障
  4. 计算机一级IF函数应用,计算机一级if函数怎么用
  5. 洪湖市计算机软件学校,湖北省教育厅关于公布“第十届湖北省中小学电脑制作作品评选”暨“第四届湖北省中小学信息技术创新与实践活动”获奖名单的通知...
  6. 【qq机器人】不良语言撤回
  7. 程序员被裁员失业有哪些软件众包外包平台可以接单?
  8. 世界杯要来了,先跟梅西来个热身吧_数字体验_新浪博客
  9. Flutter 2.8 release 发布,快来看看新特性吧
  10. 杂项-公司:Apple