数学模型:Python实现微分方程

文章摘要:微分方程的Python实现。
参考书籍:数学建模算法与应用(第3版)司守奎 孙玺菁。
PS1:只涉及了具体实现并不涉及底层理论。没有给出底层理论参考书籍的原因是不想做这个方向吧。所以对我只要掌握基本模型有个概念那就好了。
PS2:这里跳过两个章节直接来到微分方程那是因为:第四章节我想划归到算法学习里,因为图领域感觉挺大的并且我挺有兴趣的想好好学习下。第五章节归属数值分析范畴,我已经从底层理论完成这部分的内容,可以参考这篇文章。
文章声明:如有发现错误,还望批评指正。

文章目录

  • 微分方程的符号解
    • 参考书籍例6.6
    • 参考书籍例6.7
    • 参考书籍例6.8
  • 微分方程的数值解
    • 病毒传播模型
      • 指数传播模型
      • SI模型
      • SIS模型
      • SIR模型
    • Logistic模型

由于微分方程不在博主兴趣范畴之内,我们针对几个常见模型进行Python的实现。

微分方程的符号解

符号解就是解析解,该解十分精确。有些方程没符号解。我们这里只讨论有符号解的微分方程。

参考书籍例6.6

求解如右柯西问题 { d x d t = A x x ( 0 ) = [ 1 , 1 , 1 ] T 解,其中 x ( t ) = [ x 1 ( t ) , x 2 ( t ) , x 3 ( t ) ] T , A = [ 3 − 1 1 2 0 − 1 1 − 1 2 ] . 求解如右柯西问题\left\{\begin{matrix}\frac{d\mathbf{x}}{dt}=\mathbf{Ax}\\\mathbf{x}(0)=[1,1,1]^T\end{matrix}\right.解,其中\mathbf{x}(t)=[x_1(t),x_2(t),x_3(t)]^T,A=\begin{bmatrix}3&-1&1\\2&0&-1\\1&-1&2\end{bmatrix}. 求解如右柯西问题{dtdx=Axx(0)=[1,1,1]T解,其中x(t)=[x1(t),x2(t),x3(t)]T,A= 321101112 .

import sympy as sp
sp.var('t')
sp.var('x1:4',cls=sp.Function)
x=sp.Matrix([x1(t),x2(t),x3(t)])
A=sp.Matrix([[3,-1,1],[2,0,-1],[1,-1,2]])
eq=x.diff(t)-A@x
print(sp.dsolve(eq,ics={x1(0):1,x2(0):1,x3(0):1}))

在这里插入图片描述
PS1:代码在编译器内会显示异常,这是因为没有找到变量声明。但是能够顺利运行,因为代码底层已经声明变量。
PS2:虽然正确但是强迫症很难受。所以下面不会采用这种方法。

参考书籍例6.7

[ x 1 ′ ( t ) x 2 ′ ( t ) x 3 ′ ( t ) ] = [ 1 0 0 2 1 − 2 3 2 1 ] [ x 1 ( t ) x 2 ( t ) x 3 ( t ) ] + [ 0 0 e t c o s ( 2 t ) ] , [ x 1 ( 0 ) x 2 ( 0 ) x 3 ( 0 ) ] = [ 0 1 1 ] 。 \begin{bmatrix}x_1'(t)\\x_2'(t)\\x_3'(t)\end{bmatrix}=\begin{bmatrix}1&0&0\\2&1&-2\\3&2&1\end{bmatrix}\begin{bmatrix}x_1(t)\\x_2(t)\\x_3(t)\end{bmatrix}+\begin{bmatrix}0\\0\\e^tcos(2t)\end{bmatrix},\begin{bmatrix}x_1(0)\\x_2(0)\\x_3(0)\end{bmatrix}=\begin{bmatrix}0\\1\\1\end{bmatrix}。 x1(t)x2(t)x3(t) = 123012021 x1(t)x2(t)x3(t) + 00etcos(2t) , x1(0)x2(0)x3(0) = 011

import sympy as sp
t=sp.var('t')
x1=sp.Function('x1')(t);x2=sp.Function('x2')(t);x3=sp.Function('x3')(t)
con1=sp.Eq(x1.diff(t),x1);con2=sp.Eq(x2.diff(t),2*x1+x2-2*x3);con3=sp.Eq(x3.diff(t),3*x1+2*x2+x3+sp.exp(t)*sp.cos(2*t))
con_initial={x1.subs(t,0):0,x2.subs(t,0):0,x3.subs(t,0):0}
print(sp.dsolve((con1,con2,con3),[x1,x2,x3],ics=con_initial))

在这里插入图片描述

参考书籍例6.8

求常微分方程组 { f ′ ′ + 3 g ′ + f ′ = 1 ,边值条件 f ′ ( 1 ) = 0 , f ( 0 ) = 0 , g ( 0 ) = 0 时的解 求常微分方程组\left\{\begin{matrix}f''+3\\g'+f'=1\end{matrix}\right.,边值条件f'(1)=0,f(0)=0,g(0)=0时的解 求常微分方程组{f′′+3g+f=1,边值条件f(1)=0,f(0)=0,g(0)=0时的解

import sympy as sp
x=sp.var('x')
f=sp.Function('f')(x);g=sp.Function('g')(x)
con1=sp.Eq(f.diff(x,2)+g,3);con2=sp.Eq(f.diff(x)+g.diff(x),1)
con_initial={f.diff(x).subs(x,0):0,f.subs(x,0):0,g.subs(x,0):0}
print(sp.dsolve((con1,con2),[f,g],ics=con_initial))

在这里插入图片描述

微分方程的数值解

没有什么兴趣,所以不想去做。但是最近正在手搓数值分析。或许可以放到那里。

病毒传播模型

指数传播模型

基本假设:
1)问题研究区域封闭,一个时期人口总量基本不变。2) t t t时刻染病人数 N ( t ) N(t) N(t)连续变化并且可微。3)每个病人单位时间,有效使人致病人数为 λ \lambda λ 4)模型期间不会死亡
数学模型:
{ d N ( t ) d t = λ N ( t ) , t > 0 N ( 0 ) = N 0 \left\{\begin{matrix}\frac{dN(t)}{dt}=\lambda N(t),t>0\\N(0)=N_0\end{matrix}\right. {dtdN(t)=λN(t),t>0N(0)=N0
模型解得:
N ( t ) = N 0 e λ t N(t)=N_0e^{\lambda t} N(t)=N0eλt

import matplotlib.pyplot as plt
import math
N0=100;T=30;la=5
lt=[N0*pow(math.e,la*i) for i in range(1,T+1)]
plt.figure(figsize=(16,9));plt.grid();plt.rcParams['font.sans-serif']=['SimHei']
plt.plot([i for i in range(1,T+1)],lt,ms=10,marker="o",linewidth=5,color="black")
plt.xlabel("时间",size=15);plt.ylabel("人数",size=15);plt.show()

数学模型:Python实现微分方程_第1张图片
模型补充:
这样算的是第T天感染人数,不是总的感染人数,所以应该把前面的全加起来(小声:感觉书上错了)
结果分析:
显然指数增长那是不正确的。

SI模型

基本假设:
1)问题研究区域封闭,一个时期人口总量基本不变,总人口 N N N。2)人群分为两种健康人群患病人群,设置两种人群占全人群分别为 s ( t ) s(t) s(t) i ( t ) i(t) i(t),易 s ( t ) + i ( t ) = 1 s(t)+i(t)=1 s(t)+i(t)=1 3)日感染率为 λ \lambda λ
数学模型:
{ d i ( t ) d t = λ i ( t ) ( 1 − i ( t ) ) , t > 0 i ( 0 ) = i 0 \left\{\begin{matrix}\frac{di(t)}{dt}=\lambda i(t)(1-i(t)),t>0\\i(0)=i_0\end{matrix}\right. {dtdi(t)=λi(t)(1i(t)),t>0i(0)=i0
模型解得:
i ( t ) = 1 1 + ( 1 i 0 − 1 ) e − λ t i(t)=\frac{1}{1+(\frac{1}{i_0}-1)e^{-\lambda t}} i(t)=1+(i011)eλt1

import matplotlib.pyplot as plt
import math
i0=0.1;la=0.01;T=365*3+366
lt=[1/(1+(1/i0-1)*pow(math.e,-la*i)) for i in range(1,T+1)]
plt.figure(figsize=(16,9));plt.grid();plt.rcParams['font.sans-serif']=['SimHei']
plt.plot([i for i in range(1,T+1)],lt,marker="o",linewidth=5,color="black")
plt.xlabel("时间",size=15);plt.ylabel("比例",size=15);plt.show()

数学模型:Python实现微分方程_第2张图片

SIS模型

模型假设:
1)同SI模型2)每天治愈人数占总人数比例为u
数学模型:
{ d i ( t ) d t = λ i ( t ) ( 1 − i ( t ) ) − u i ( t ) , t > 0 i ( 0 ) = i 0 \left\{\begin{matrix}\frac{di(t)}{dt}=\lambda i(t)(1-i(t))-ui(t),t>0\\i(0)=i_0\end{matrix}\right. {dtdi(t)=λi(t)(1i(t))ui(t),t>0i(0)=i0
模型解得:
i ( t ) = { [ λ λ − u + ( 1 i 0 − λ λ − u ) e − ( λ − u ) t ] − 1 , λ ≠ u i ( 0 ) = i 0 , λ = u i(t)=\left\{\begin{matrix}[\frac{\lambda}{\lambda-u}+(\frac{1}{i_0}-\frac{\lambda}{\lambda-u})e^{-(\lambda-u)t}]^{-1},\lambda \neq u\\i(0)=i_0,\lambda=u\end{matrix}\right. i(t)={[λuλ+(i01λuλ)e(λu)t]1,λ=ui(0)=i0,λ=u

import matplotlib.pyplot as plt
import math
def func(i):
    global la,u,i0
    if la==u:
        return pow(la*i+1/i0,-1)
    return pow(la/(la-u)+(1/i0-la/(la-u))*pow(math.e,-(la-u)*i),-1)
la=0.05;u=0.05;i0=0.5;T=365*3+366
lt=[func(i) for i in range(1,T+1)]
plt.figure(figsize=(16,9));plt.grid();plt.rcParams['font.sans-serif']=['SimHei']
plt.plot([i for i in range(1,T+1)],lt,marker="o",linewidth=5,color="black")
plt.xlabel("时间",size=15);plt.ylabel("比例",size=15);plt.show()

数学模型:Python实现微分方程_第3张图片
结果分析:
我这里是 λ \lambda λ等于 u u u。可自己调。当 λ ≤ u \lambda\leq u λu所有人最后都会被治愈。当 λ > u \lambda>u λ>u最后总有一小部分的人保持健康。

SIR模型

基本假设:
1)人群分为3类A:健康人士(没有患过)B:患病人士C:健康人士(曾经患过)分别记: s ( t ) , i ( t ) , r ( t ) s(t),i(t),r(t) s(t),i(t),r(t) 2)日感染率,日治愈率记: λ , u \lambda,u λ,u 3)总人口 N N N
数学模型:
i ( t ) = { d i ( t ) d t = λ s ( t ) i ( t ) − u i ( t ) d s ( t ) d t = − λ s ( t ) i ( t ) d r ( t ) d t = u i ( t ) i ( 0 ) = i 0 , s ( 0 ) = s 0 , r ( 0 ) − 0 i(t)=\left\{\begin{matrix}\frac{di(t)}{dt}=\lambda s(t)i(t)-ui(t)\\\frac{ds(t)}{dt}=-\lambda s(t)i(t)\\\frac{dr(t)}{dt}=ui(t)\\i(0)=i_0,s(0)=s_0,r(0)-0\end{matrix}\right. i(t)= dtdi(t)=λs(t)i(t)ui(t)dtds(t)=λs(t)i(t)dtdr(t)=ui(t)i(0)=i0,s(0)=s0,r(0)0
模型求解:
这是一个常微分方程组,难以求解析解。可以用Python求数值解。

def sir_model(t,y,la,u):
    S,I,R=y[0],y[1],y[2]
    dSdt=-la*S*I;dIdt=la*S*I-u*I;dRdt=u*I
    return [dSdt,dIdt,dRdt]
S0=0.99;I0=0.01;R0=0.0;la=0.2;u=0.1;t_start=0;t_end=365*3+366;y0=(S0,I0,R0);t_span=[i for i in range(t_end+1)]
from scipy.integrate import solve_ivp
solution=solve_ivp(sir_model,[t_start,t_end],y0,args=(la,u),t_eval=t_span)
S=solution.y[0];I=solution.y[1];R=solution.y[2]
import matplotlib.pyplot as plt
plt.figure(figsize=(16,9));plt.grid();plt.rcParams['font.sans-serif']=['SimHei']
plt.plot(solution.t,S,label='A类人士')
plt.plot(solution.t,I,label='B类人士')
plt.plot(solution.t,R,label='C类人士')
plt.xlabel('时间');plt.ylabel('比例');plt.legend();plt.show()

数学模型:Python实现微分方程_第4张图片

Logistic模型

模型假设:
1)设 r ( x ) r(x) r(x) x x x线性函数,所以 r ( x ) = r − s x r(x)=r-sx r(x)=rsx。2)地球容纳最大人数为 x m x_m xm
PS:这里我们可以化 r ( x ) r(x) r(x) r ( 1 − x x m ) r(1-\frac{x}{x_m}) r(1xmx).仔细想想,不难理解
模型建立:
{ d x d t = r ( 1 − x x m ) x , x ( t 0 ) = x 0 . \left\{\begin{matrix}\frac{dx}{dt}=r(1-\frac{x}{x_m})x,\\x(t_0)=x_0.\end{matrix}\right. {dtdx=r(1xmx)x,x(t0)=x0.
PS:这里是一个可以用分离变量方法解的方程,应该不难。
模型解得:
x ( t ) = x m 1 + ( x m x 0 − 1 ) e − r ( t − t 0 ) x(t)=\frac{x_m}{1+(\frac{x_m}{x_0}-1)e^{-r(t-t_0)}} x(t)=1+(x0xm1)er(tt0)xm
这个有解析解就不写代码了。

你可能感兴趣的:(数学建模,数学建模,微分方程,python)