5 P& {9 a& z. E7 L" X j% U* a. q; T* V * j4 s1 C: L O( w) z; R4 R% W2. 疫情传播 SI 模型3 B; U7 |& ^' r0 b4 C
2.1 SI 模型的适用范围 " l0 q0 ~# i% WSI 模型适用于只有易感者和患病者两类人群,且无法治愈的疾病,例如 T型病、僵尸。 0 Z" [/ e" z- f. W/ B4 u ; }+ G; Z7 |" w2 x) f% R7 p4 {% e9 P" J6 F( ^
* m, U& |. H- C8 P* A% {
5 z6 I" l+ Z3 \. ]
2.2 SI 模型的假设 6 b+ m- L8 x9 b' Q3 K, P考察地区的总人数 N 不变,即不考虑生死或迁移; 9 c! K: w! C6 N7 @) n人群分为易感者(S类)和患病者(I类)两类;6 q2 [+ J' u' C% ~' d6 i4 \7 u- b
易感者(S类)与患病者(I类)有效接触即被感染,变为患病者,无潜伏期、无治愈情况、无免疫力; - B6 e; r8 @* b7 B- A每个患病者每天有效接触的易感者的平均人数(日接触数)是 λ \lambdaλ,称为日接触率; + E+ S( A. U# Y. a# ^2 L将第 t 天时 S类、I 类人群的占比记为 s ( t ) s(t)s(t)、i ( t ) i(t)i(t),数量为 S ( t ) S(t)S(t)、I ( t ) I(t)I(t);初始日期 t = 0 t=0t=0 时, S类、I 类人群占比的初值为 s 0 s_0s 4 e6 B, z) X2 H' s
0 - I' P1 b8 ^7 D+ P) a# v 0 ?7 h, u8 W c6 h7 }# A! S0 p 、i 0 i_0i " g" d3 ]; s9 E5 a- b: C
0 7 }" _* ~+ F2 ?8 I / b- x8 }: L0 H+ g9 a* Q1 _. C 。% W% z2 T- ]! D# U) J+ m5 ?
2.3 SI 模型的微分方程 ( }1 P" h( N$ C2 O- U由 / I) P- c7 X. U8 o* `1 I; pN d i d t = N λ s i N\frac{di}{dt} = N\lambda s i ! ?' ~. ?+ D l( M u! bN * x$ P5 _1 H0 b* Bdt3 @+ }3 Z3 v1 H3 T5 I. C" c$ H) {
di5 _9 s/ w& k6 s" o; t U
, v* t* o2 S# n0 H =Nλsi; {; x9 z) Z2 W" @
* B: m" Y. t5 t% q+ X
6 L, l% x' h% O. P, g# ~% H
得: : V. d4 F( I4 ]3 Z& z" v t) Jd i d t = λ i ( 1 − i ) , i ( 0 ) = i 0 \frac{di}{dt} = \lambda i (1-i),\ i(0) = i_0$ Z2 u: } A! {2 y; L' j( A
dt 9 r6 q& b' J5 sdi 3 m. P0 k$ e* h+ O " j3 @0 z# W3 I+ I0 v5 S, G h: |. ]% J
=λi(1−i), i(0)=i : R: _9 k) o& K H" |& M0- \% ?" P- r* c7 W! d8 l$ t0 W6 |, v
9 \: u: `# p' S0 F$ Z/ D ; r5 b8 N& C: b- R7 {
- u5 F3 U/ L) O- J$ r2 e) w$ [5 ]
. F7 Q8 O4 K5 l, `; L
这是 Logistic 模型,用分离变量法可以求出其解析解为: / m. x# {# o) r( T) V! A+ @i ( t ) = 1 1 + ( 1 / i 0 − 1 ) e − λ t I ( t ) = N i ( t ) i(t)=\frac{1}{1+(1/i_0 - 1)\ e^{-\lambda t}}\\ I(t)= N\ i(t) - `; P" q. a9 O- ei(t)= " [& j, q$ j, N6 L* l# ~& ~1+(1/i 8 f4 N! Q( ^+ i4 z. V8 ` [+ v0 ' Y5 H# f) Y7 H2 G 1 w" y( y0 I1 Q1 W, Q −1) e $ Q' Q) p8 H3 O: t
−λt ! A; ^7 m) b$ G* }! c; e7 k! f9 u # }, r( Y& Q& V3 i1 t: |. C: C' M* t3 _ ) k; K# s+ N% ]. c+ ?+ q8 [/ J ' T* p) U* ]1 L8 G( mI(t)=N i(t) / r1 Q# e" m3 Y+ s5 ^ - `/ C9 ^$ `! ^# }. x2 T ) i) F6 [3 A9 n( [, P! u1 w3 w+ z8 y$ X ( Q: g2 r1 O, L0 Q' ?- ]0 s) }9 g6 w/ i# P5 m
3. SI 模型的 Python 编程2 R( F9 l+ p( R" w
3.1 SI 模型的解析解 4 ~0 Y, @. g5 T; G( `上文已经得到 SI 模型的解析解,对此很容易通过 Python 编程实现,详见本文例程。! f+ U1 @9 A) o4 {
6 s) d: ~- r8 ?
2 \& R) C$ R! @) \
虽然 SI 模型的解析解并不复杂,而且解的精度当然是最好的,但我们仍然不鼓励用解析解的方法。原因在于,一是对于小白求解析解的过程相对复杂困难,而且可能出错,二是对于更复杂的模型是没有解析解的,即便大神也只能用数值方法求解。既然如此,不如从一开始就学习、掌握数值求解方法,熟悉数值解法的编程实现。 a1 f' W2 U% N' K/ b" L! x( e) k! [
8 j- w- h: c/ M2 A$ t* F. E" _3.2 SI 模型的数值解 , M N- F/ @ U2 t7 F4 G( ]$ {SI 模型是常微分方程初值问题,可以使用 Scipy 工具包的 scipy.integrate.odeint() 函数求数值解,具体方法可以参考前文《Python小白的数学建模课-09 微分方程模型》。# @0 |2 x/ x) l0 g8 T8 m6 ]
/ _ `6 N' T2 Y$ C* Y3 V# _6 [& ~( X ; W }/ S& L% F+ E0 g+ dscipy.integrate.odeint(func, y0, t, args=())- Q. D) i8 X0 ^
1+ X$ @5 a$ l0 J! \& k0 O. h
**scipy.integrate.odeint()**是求解微分方程的具体方法,通过数值积分来求解常微分方程组。) F, ?; B. j% L* e$ [
0 a! i1 j! x, Q/ e/ ?# a, S5 k# U( q' h# q2 D) f2 D# u
odeint() 的主要参数:+ _+ L/ z. K5 M; }* Z( J, F6 t
+ E2 X" n! \5 j: j# S3 i& Z. [$ [8 i1 U' _8 n. I
func: callable(y, t, …) 导数函数 f ( y , t ) f(y,t)f(y,t) ,即 y 在 t 处的导数,以函数的形式表示3 L7 x: j5 v4 T3 K
y0: array: 初始条件 y 0 y_0y 5 k( t2 S" X5 d Z0 % \% ~' E( o0 F- S% I * \* `+ {& \0 O2 y* Z) S* ~- r2 z
,对于常微分方程组 y 0 y_0y " x5 Q2 G& t5 P8 h4 _7 O- Z
0; D2 v' @ e) L2 k
9 D: h( W. _$ U: Q# S
则为数组向量 # F" j6 g! j9 s5 ht: array: 求解函数值对应的时间点的序列。序列的第一个元素是与初始条件 y 0 y_0y , Q3 I( C# N' K5 M4 r
0# v' Y- ~7 Q M0 ^8 Z+ l9 n7 S
+ D6 _1 g* s; E" n* J& [3 n 对应的初始时间 t 0 t_0t 9 ^6 v! G, P8 ^- r b0 i+ R+ `2 M) G
0 9 w+ F% P5 U. U. L, Z, Q7 q : V% C N, P- E: P( ]) O ;时间序列必须是单调递增或单调递减的,允许重复值。 . ^& d' h8 i0 X" V" b3 Zargs: 向导数函数 func 传递参数。当导数函数 f ( y , t , p 1 , p 2 , . . ) f(y,t,p1,p2,..)f(y,t,p1,p2,..) 包括可变参数 p1,p2… 时,通过 args =(p1,p2,…) 可以将参数p1,p2… 传递给导数函数 func。 ' V$ K* F% c3 y( P* aodeint() 的返回值:0 ^2 k' U# F" A5 D# l! e0 [
+ U( B: b! o b5 A$ L
5 K) M2 c. J% Z% `* Z
y: array 数组,形状为 (len(t),len(y0),给出时间序列 t 中每个时刻的 y 值。8 ^+ k0 K5 J$ Q1 h
odeint() 的编程步骤: 7 q9 e, h' c6 X. d 9 z n( i1 ^$ Y5 _5 D/ q: K$ w' d * x4 x4 w K9 N7 B, X! N导入 scipy、numpy、matplotlib 包;7 p7 Q; S+ f' S+ \* A& e# p
定义导数函数 f ( i , t ) = λ i ( 1 − i ) f(i,t)=\lambda i (1-i)f(i,t)=λi(1−i) ;: c: C i: \6 ?# r) [% ?& v9 m
定义初值 i 0 i_0i " N& z: c7 t' @# E0 Z
0 ' [( a! _* U0 a; D7 n + X/ P U; W9 m8 _4 \/ D' W# I
和 i ii 的定义区间 [ t 0 , t ] [t_0,\ t][t + H# u% p; U8 A% T( L
0 * L0 d) F4 p8 N # I2 f8 H9 y$ _, t) \$ J , t];( Z. q2 H4 r0 y: O0 e
调用 odeint() 求 i ii 在定义区间 [ t 0 , t ] [t_0,\ t][t 4 F6 B- U; o- a1 M% o6 O
0 + ]* D1 q9 _ n! A3 x' P : |) h3 S* U0 Y , t] 的数值解。 v( M% _# B- C+ C4 e2 J
0 K- @% \- L2 w$ a; e3 z2 A# F
1 t1 j5 n& y" `4 w& w8 x8 f5 {
3.3 Python例程:SI 模型的解析解与数值解 % m# B: I+ w4 x/ R% O2 `: p# 1. SI 模型,常微分非常,解析解与数值解的比较5 `) m$ I3 x6 W7 ^& U; O
from scipy.integrate import odeint # 导入 scipy.integrate 模块0 }- i3 ~; [8 p K& Y/ }% `4 z
import numpy as np # 导入 numpy包5 B) W. T9 E3 Y" R' f) m1 [
import matplotlib.pyplot as plt # 导入 matplotlib包 8 h0 V! \% s$ r9 }0 b* Z / v2 f5 T: T& k0 W6 _9 b3 N+ Y! ` y8 N( i& a
def dy_dt(y, t, lamda, mu): # 定义导数函数 f(y,t)7 _) m6 c; P9 b' T
dy_dt = lamda*y*(1-y) # di/dt = lamda*i*(1-i)/ b9 M3 m3 L# n4 D! ?
return dy_dt $ d: k1 a; c _+ o" n- q9 Y4 U3 c# k 5 ~# ]0 {2 T1 S% j6 F& Q ! m6 J4 k8 h" w& e( F# 设置模型参数 p* |5 A1 h5 z( inumber = 1e7 # 总人数 9 r4 q8 C- ]) S0 E( u6 e" b# clamda = 1.0 # 日接触率, 患病者每天有效接触的易感者的平均人数8 D- m, N7 ]+ `- o
mu1 = 0.5 # 日治愈率, 每天被治愈的患病者人数占患病者总数的比例 # I6 W) R) H- Y# f. xy0 = i0 = 1e-6 # 患病者比例的初值 9 O; ]4 v) ?$ `! mtEnd = 50 # 预测日期长度) j( c! d5 B8 ^3 B2 `7 K0 v) P, A
t = np.arange(0.0,tEnd,1) # (start,stop,step) ' [: P; D+ i2 w1 y u' y- E# s3 y/ Q' l/ \, _* C; d, X9 \( p6 |
; j: E1 ^+ d( I+ B6 d/ A
yAnaly = 1/(1+(1/i0-1)*np.exp(-lamda*t)) # 微分方程的解析解 ' Q' T5 K- i5 JyInteg = odeint(dy_dt, y0, t, args=(lamda,mu1)) # 求解微分方程初值问题6 I; ?- g A) M& Q+ r: T; z, S' i
yDeriv = lamda * yInteg *(1-yInteg) ; A5 m1 j, A, l* t7 ?" }- d 2 h) t: a0 {+ |8 b% l$ n3 E" L& z
# 绘图 5 u! T# x' X9 ~7 B! q" lplt.plot(t, yAnaly, '-ob', label='analytic') ; Z' a/ a; j* [, hplt.plot(t, yInteg, ':.r', label='numerical')7 j l1 \4 ^/ \6 Q1 V
plt.plot(t, yDeriv, '-g', label='dy_dt') 8 v% q! A. S, L$ mplt.title("Comparison between analytic and numerical solutions")' s: _8 q; Z" \4 g, D) I
plt.legend(loc='right')- w0 Y0 {' N! {& Y: e
plt.axis([0, 50, -0.1, 1.1])$ z- u. b% ?5 X, x6 S: b: c
plt.show() - i5 H* p3 Y6 ?' r% A1 5 }- @$ V# i. E9 c$ z Y2 + l4 e% G8 Q+ w4 g4 J& U3 }4 }3 |3 3 z6 V0 x$ z6 d0 U6 p3 g5 U4 - x2 u( Y9 [$ K% @: s4 m/ U5 5 u& S. q7 n2 _. j# ]6) I$ X, m( O; p2 ^
7 / `- r+ _* ?: ~) s! t% ]" \88 M3 J7 f. D- h- e; c: q5 o9 q
9# y6 w1 r8 S- {# @% N
10 F+ I/ _" c4 L" n11 5 x0 x: q9 T& |1 W9 V12 . C3 p; ]( t: o) U- Y2 ~13+ `" S3 ]+ r% F/ P, k4 v
14 " R) v, @1 \0 y0 Y' j15 $ ~" _, n0 _7 q: `161 ~8 N* m; |0 F% D* p. b/ m& X
17: ?! {% k4 T: k& ^. z! E
18 3 e* B# [# j% ?$ Q" |19) [* i; u9 o! _( W: `
20 5 U6 [! O$ B% z9 k5 C21 8 I _+ ]9 L! `22 3 C N$ o7 y$ u2 M) G( o" I8 f23 3 }% Y Q% E; z8 Y1 {24 ! D3 R7 B% p6 A' c5 `: _) J25% e5 A, z) R6 k7 ~- p+ o
26 & M% j$ \ ?2 \8 g ?278 z$ A3 |& @; R4 ]* p
28 5 `) G# |$ g) I5 j2 _7 w( H29 8 z' ~7 s3 Q* ^, W( l1 G9 i # g- l, }" \1 s, l b. }8 N+ i; b$ W# F& c
3.4 解析解与数值解的比较* H) R% M7 t- y P4 g8 n
3 R8 Y6 _5 w4 X* t+ L
7 B y5 d3 s' o3 _2 b, C v" `本图为例程 2.3 的运行结果,图中对解析解(蓝色)与使用 odeint() 得到的数值解(红色)进行比较。在该例中,无法观察到解析解与数值解的差异,表明数值解的误差很小。- C0 x/ W9 |1 M7 h
$ Z$ H8 A+ M2 s1 Q) i
( W; m" o" `6 p3 [) W" M图中 d i / d t di/dtdi/dt 具有最大值,最大值表示疫情增长的高潮,达到最大值后 d i / d t di/dtdi/dt 逐渐减小,但患病者比例很快增长到 100%,表明所有人都被感染成为患者。+ d0 i. \7 B( G! X
, X0 V% S" o# [/ F* K: `
) P. R( U+ ?) m! f% _, G$ X
这是特定参数的结果,还是模型的必然趋势,需要对参数的影响进行更详细的研究。+ l m' U: c$ W) i7 o2 u4 G
3 M! Z# ?3 |! l# M9 C1 r" h; {2 |: c F3 _! M- w9 o1 c* @! S$ ?
0 y& B8 a3 b' r- b9 `! [9 u2 Q
: O) W& V; e9 N
4. SI 模型参数的影响 1 U4 w2 e6 p$ H9 e( t对于 SI 模型,只有日接触率 λ \lambdaλ 和患病者比例的初值 i 0 i_0i ) u$ l- u) B! i. f( K; c
0+ q: y- f6 Z" |- G% t* F
$ }9 ]& ^, o! r& P0 D: c 会影响模型的结果,其它参数如总人数 N 并没有影响。 $ X+ @! E9 R! K! L7 D " c8 p) y, v4 I6 ~. b, z7 G5 H $ M4 D H8 [' p' }; P( T4.1 日接触率对 SI 模型的影响7 _" x" F/ J2 e6 L% G
9 e# |5 i# ]3 e6 J- ?* s3 O8 k' a! M
对不同日接触率的比较表明:" }* M6 G2 P. p: I a ?