|
什么是传染病动力学?numpy和matplotlib用python实现传染病模型SI模型SIS模型SIR模型SEIR模型 什么是传染病动力学?最近,在报道疫情的众多新闻中,相信大家也看到过一些来预测新型冠状病毒会导致感染肺炎的人数。你一定好奇,这个人数要怎么预测呢?预测人数又有什么用呢? 事实上,从学科方向来说,这类研究属于传染病动力学,就是用数学模型去描述传染病在人群中传播的规律,从而预测患病人数,进而指导政府制定措施和政策去控制传染病的传播。
Y4 a, m8 [& _: @+ ]( H这类研究最早可追溯到18世纪Daniel Bernoulli对天花的研究,而我们今天所要介绍的SIR模型是1927年Kermack与McKendrick在为了研究伦敦黑死病而提出的,是传染病动力学中最基础的模型。 介绍了传染病模型的背景信息,不知道现在你对传染病模型更有兴趣,还是执着地对python更有兴趣呢?不论哪种,这篇文章会满足你所有的好奇心。 numpy和matplotlib首先,安装一下这节课我们需要使用的两个python包,numpy和matplotlib。1 M$ y) g& v' V" r/ @7 a
numpy-是python进行科学和矩阵运算最常用的包。 用numpy建立一维数组,存储和计算每天传染病人数的数据。 5 X3 |5 d& |! s/ I/ _
import numpy as np import matplotlib.pyplot as plt 用matplotlib绘制传染病人数随天数变化的曲线,给出模型预测人数变化的直观认识。 好啦,下面开始用python实现传染病模型吧。 用python实现传染病模型为了让大家能够更好地理解,我们先不直接说SIR模型,我们从最简单的开始。 SI模型首先想象这样一个场景,一个城市有 个人,假设没有人出生和死亡,忽然有一天有 个人感染了病毒成为了患者,如果每天每个患者能够有效传染 个人,那么第二天患病人数是多少呢?最简单的答案是: ,也就是说每天都会新增 个患者。那这样以来,在无限远的将来会有无穷多的人被感染,显然这是不合理的,那错在哪里?仔细思考,你一定发现了,已经患病的人就不能再被传染了,所以我们有必要把人群分为两类,易感者(S-susceptiable)和感染者(I-infective)(你猜的没错,这就是SIR中S和I的含义,R的含义之后介绍再讲)。为了之后方便计算我们记易感者和感染者在人群中的比例为 ,那么 。我们重新考虑上面的问题,顺便来个示意图: Image Name这样的话,每天新增的患者数为 ,也就是总传染人数乘以易感者所占的人群比例。0 q1 b0 ~3 F) b6 F- V
那么每天的感染者比例的增加量就是 。我们假设城市有一千万(N=10的7次方)人,每个患者每天接触感染每天0.8人(lamda=0.8),初始感染人数为45人(i0 = 45/N),我们来模拟70天(T=70)的情况。 # population
4 L" o, S8 Q8 \" [( BN = 1e76 O3 G/ }# P: j0 N! g; x B$ U; e
# simuation Time / Day/ _1 z( s0 X. [7 }! B
T = 70
" J1 y& T; Z+ d0 [8 Q# susceptiable ratio1 N4 r" z- `7 n; q1 u6 w
s = np.zeros([T])
. U! ]5 ^2 \- t5 m; e# infective ratio
2 t+ b2 Y4 g- |5 x1 w' t( C: ii = np.zeros([T])$ c; o: d# W+ I1 e
# contact rate
( U& h; V6 j. g& Dlamda = 0.8
1 }; u' U& F w9 j/ d- L- g, P5 V9 C. X3 p& }) b
# initial infective people1 l: C6 u+ o- y; t
i[0] = 45.0 / N' \& X) c' C3 V( Q
3 O# k5 [8 z0 ?' E: h
for t in range(T-1):8 g5 k7 m& A, n- @( T$ v2 B& ]( z2 i
i[t + 1] = i[t] + i[t] * lamda * (1.0 - i[t])
& V9 p$ b/ L$ t$ U5 Y/ a% ~; F+ X- ^; s- ^+ ]5 C& J0 {! b4 O
7 j3 y1 P' m; W9 Q1 A) L ]1 d( W
' E% F" [) x5 c" u- ?6 i
相信其他语句大家都明白,新知识是这两行:
$ N' e( k3 i& L) G( m6 c* d) B M! ~6 _' T4 r8 x% K9 {6 `% E4 Q
; ^% r* `0 b5 I G" L! ]/ z
s = np.zeros([T])
1 W0 w! X4 t9 y" j" l7 ai = np.zeros([T])
% Z/ g) K3 E: Z1 @ J8 w" @" M) S$ m! T" @; u
这两句话的意思是一样的,就是利用numpy(已被我们重新命名为np)的函数(zeros())来建立一个所有元素都是零的数组,而给的参数决定了这个数组的维度。比如:1 \# J q1 G+ z
1 W& G @0 I) k8 Z0 ~6 ^' Ca = np.zeros([2,3])
2 s7 d$ Q0 t. w+ a& S- da
& E1 G n m1 a7 {: W+ `0 o6 J4 c9 e
array([[0., 0., 0.],# _ _5 b* f. Y" _- i! P
[0., 0., 0.]])
, Q" Q+ t- P0 i* u+ S( {
|9 E$ b, Q9 ?! \" N* S& o' _3 D' ` ]9 z! j5 E
array([0., 0., 0., 0., 0.])
* s* q& \+ ^) D% b0 O/ ?9 v+ ]* c+ H0 u% w# w$ c* a
! k- N: m! E2 ^( \* T
类似的还有产生元素全部是1的数组的函数np.ones():# p$ D, g k, V- G$ R& J1 x3 U7 q. M
( Y2 | w/ E$ u* Za = np.ones([5])& q! ]' E" `) ]- Z
a* [* ~2 D( L$ G5 F# t/ a
8 [+ }) Z* C% ?4 _0 u1 l0 P& s
array([1., 1., 1., 1., 1.]), Y, L7 f3 G I8 S% }* v, w! E( U) L
$ S& `" @1 H( ^- k& e/ o/ Z* n: ]% }4 D# V. R+ \' P
a = np.ones([2,3])
! a. X6 n4 t! l. A# Q9 Sa* T8 f/ ?- E5 @5 R( \) c$ r
( j3 o% B( Y+ Q1 _
1 W6 K+ E0 `! @# U' _! Y! B& Parray([[1., 1., 1.],: ~$ u0 l1 v9 Q2 Q- l; m" r
[1., 1., 1.]])
- Q/ Q6 m4 I0 |) e+ w- n q0 y( d4 Q( ~9 `5 A3 u# _( Y7 }7 l
9 T8 J, A4 p$ ^plt.plot(i)
9 o1 y9 q( j& b
0 P+ B' u) z+ N* n- W# j# s' P, K% P! v1 y9 f( E: s) ~
[<matplotlib.lines.Line2D at 0x7f0c2768d6d8>]7 f+ s& M' f3 {. ]9 t/ T1 [
: s! v- F1 O0 Z; z7 Q/ Q6 B1 N! v; s# W- {; k2 | k: k
% O+ G/ m2 {7 x+ G3 c; }! }6 ^
% x) N# y7 o/ n _+ H' A3 p
' x! u% d4 P; M1 z; `* F# y实现SI模型的核心代码是第三个cell的第11,12行:* |$ k6 X# p% H! I
! Z4 {4 x2 h3 w7 a: w g
for t in range(T-1):
. Q% N5 L! j* |, d B i[t + 1] = i[t] + i[t] * lamda * (1.0 - i[t]): g" E! h5 x1 m# E% Z) f, y
& r' j1 m8 Q- F; L) W就是我们建立的数学模型,利用python的for循环语句累加迭代的方式把每天的增加量叠加到感染者比例上。 运行代码完成计算,我们利用matplotlib的pyplot来画出感染者的随天数的变化曲线:
( z% U" x. Q. Y: [- Rfig, ax = plt.subplots(figsize=(8,4))
0 C4 r9 j; E) p U0 c3 R) I2 [ax.plot(i, c='r', lw=2)
( E* j; I, d! y4 j- Y; e% uax.set_xlabel('Day',fontsize=20)
: J. c6 b4 P2 x9 wax.set_ylabel('Infective Ratio', fontsize=20)$ v, B* o* S* ^8 d! u6 ^/ M
ax.grid(1)
8 m( h* Q9 Q1 Pplt.xticks(fontsize=20)
( y) K/ _; j/ Y5 Q, j) m0 aplt.yticks(fontsize=20);
- O' S! Q% a6 B* ]/ ~, I b2 y
, ]8 X! r% G2 Y4 ] Y2 Y
5 X# _1 B3 P3 k6 L. E1 |8 n! f+ g* O ; h% e' {) j' Z! K' S% O
: i/ @2 u; x& l# g- `1 b/ m
从这个结果看到,大约在25天左右,全部人群都会变成感染者,感染率 。
" a' P; D0 @* p9 T, G) ?9 J在程序中我们假设每天每个患者传染0.8个人,你可以改变lamda的值,观察全部人群感染的天数的变化。
) _% _: G: h+ J$ K; F认真思考你会知道,lamda的现实意义就是该城市的卫生水平,衡量的是消毒,隔离这些措施执行得怎么样。回到传染病模型,按照SI模型计算的结果,我们全人类都会患病,这好可怕!原因是我们忽略了一个很重要的因素,那就是我们有奋斗在一线的医护人员,我们会被治愈!所以SI模型只适合研究具有高传染风险又不能被治愈的病(比如HIV)。 但是对于其他病,我们是可以靠医疗和自身免疫系统康复的,那么紧接着的一个问题就是,被治愈后还会再被传染上嘛?根据这个问题的回答不同,我们有了两个不同的模型,SIR 和 SIS。现在可以揭晓,SIR的R的含义了,就是移出者(Removed),现实含义就是指被治愈后不会再被感染的人。而SIS表示治愈后仍然还是易感者。下面我们用python来分别实现这两个模型。 SIS模型为了实现这个模型,我们需要引入新的一个参数,治愈率 。好啦,先上我们的新示意图: Image Name和SI模型做比较,区别就是计算感染者的增加数时要减去被治愈的人数。* | `; G, P/ C. p
所以这时候每天的增加的感染者为: ,8 Z9 o; {2 S, H& ~
增加的感染率为: 。
; L* t* v: E/ p/ f; }. y& _, R模型完成啦,修改python代码:
; v' g" i2 ^5 l1 l7 g$ G% S# susceptiable ratio0 D( ?6 _ j g- _" A% D
s = np.zeros([T])( I$ t; a! t9 _, a ^- C
# infective ratio
' z1 Z7 c) z/ R/ E7 Y$ q6 }i = np.zeros([T])
& V+ N7 p1 j0 Q. t5 L- e, g
7 B; i6 y9 ?* d3 o7 h( w# contact rate
8 X! c8 ~5 L5 R# T- Llamda = 1.0
$ S5 k5 G$ \- i" B, e2 v$ Z$ }# recover rate2 ~- U0 U% J* k. [
gamma = 0.5
* w9 J$ W9 f( F* Z
- S% r! r# Q* Z6 ^/ z# initial infective people
+ {: J" \0 e1 m, s; O; hi[0] = 45.0 / N( O* F5 u2 T# q/ W& e* ?
, r! o' I7 L. C/ G) Q( F. `+ {9 Y* b: Y9 Hfor t in range(T-1):4 z) C# }) k% _
i[t + 1] = i[t] + i[t] * lamda * (1.0 - i[t]) - gamma*i[t]9 u/ v0 ^8 U# Y# {; W$ n& f, r
5 c) P9 y+ I& k( k1 W
9 p' i/ ~8 O) q9 q* n6 l0 m
" ~ v) U) F: ~运行代码,我们画出曲线(代码和SI模型的画图完全一样):0 |# k0 h# P% l
# b. |6 q6 E+ t' N4 {
fig, ax = plt.subplots(figsize=(8,4))
T) Y7 x& N8 [' cax.plot(i, c='r', lw=2)
0 g n5 N: e7 \/ E% ^ax.set_xlabel('Day',fontsize=20)
4 L: L* I3 z1 L' @: }/ {ax.set_ylabel('Infective Ratio', fontsize=20)& X9 B& j7 v7 ^2 q& o( i
ax.grid(1)
1 q7 d6 y: w K3 o+ P( N9 cplt.xticks(fontsize=20)$ z4 F3 f; c6 m8 C& V! ^( X
plt.yticks(fontsize=20);
- G4 f6 k" L0 G/ n; O
4 [( y9 P( a c0 [2 q 7 ~+ A- U# m7 w5 G8 m
6 E9 O, h* _) G2 W" t; E- i# G8 }+ K
行代码,我们画出曲线(代码和SI模型的画图完全一样)
# E s" l! [3 k0 M可以看到,达到最大感染率的时间退后10天左右,最后感染和治愈达到动态平衡,人群中有始终有一半的人感染着。所以,SIS模型适合研究具有传染性和反复性的流行病,比如常见流感。同样的,感兴趣的话,改变lamda和gamma的值,观察曲线的变化。和lamda不同的是,gamma的现实意义就是对这种疾病的治疗水平。 SIR模型加入了移出者,被治愈的病人不会再被传染,先上我们的新示意图: Image NameSIR 模型
, x) ^' T0 h" J& m: o2 r: X5 k% |0 k注意到这里,人群被分成了三类,不再只有I和S,所以相比于之前的模型,我们需要找到新的约束关系。现在我们需要分别计算三种人每天的增加量了: * T6 K& B0 M' x+ c4 }* s3 c
- 易感者:每天都在被传染,所以一直在减少,减少量为被传染的人数:
- 感染者:增加了被感染的人,减少了治愈的人:
- 移出者:增加了治愈的人:
* }) v+ w- U; Y9 `1 V- f! d1 N
建模完成,修改python代码,并且假设人群普遍易感,新型疾病,初始没有移出者。
5 f5 V$ c8 x! H' \( i# L" ^# population6 v& ^. y/ V8 ?0 V f( `
N = 1e7 + 10 + 5: c' u& {) \+ `7 g9 C6 U
# simuation Time / Day* j' |/ |- b1 ~$ R6 B" y1 H9 I2 ~
T = 1700 k# X* E% q4 b( }* k
# susceptiable ratio
; ^% [" ]6 G% C# U$ Ns = np.zeros([T])$ b) s$ P* K: G' z8 I
# infective ratio
, Q# l9 l6 B) F0 V. G0 z7 A( Ni = np.zeros([T])7 }' k) p: y; b! {" Q s% G9 ?
# remove ratio H' s4 u0 S* z/ ~, U! f
r = np.zeros([T])$ F2 n1 h+ @/ M. g2 d
2 E; x! l5 Q( W6 x$ U F; |
# contact rate) u& c2 f4 w* y' |- r
lamda = 0.25868 c- L) E0 B& i/ J
# recover rate
) ~! X [. m, K: X) @' fgamma = 0.0821
+ z% q4 b. Y0 s; \0 f9 y+ j# N3 o" r9 I! K/ X
# initial infective people" G' C. b/ c* C
i[0] = 10.0 / N: ]# u- I; F; ]5 T
s[0] = 1e7 / N
, ]4 ^2 s5 j8 `% R' nfor t in range(T-1):
( ^6 Q ]9 e& G. Y% l# b# y `9 @9 D i[t + 1] = i[t] + i[t] * lamda * s[t] - gamma*i[t]1 h* i% g$ z6 u; P
s[t + 1] = s[t] - lamda * s[t] * i[t]: O$ K( q5 u; Z
r[t + 1] = r[t] + gamma*i[t]
* p: i; |; H1 z1 P6 J+ E' [" ^; z6 B; S& L) Z9 n
fig, ax = plt.subplots(figsize=(10,6))% k+ W b' U! f% L. y
ax.plot(s, c='b', lw=2, label='S')) v$ R3 C7 h, l {
ax.plot(i, c='r', lw=2, label='I'): }% F5 b+ s7 i. B+ z2 F
ax.plot(r, c='g', lw=2, label='R')9 P V4 e5 M0 l& K& R3 u
ax.set_xlabel('Day',fontsize=20)
6 Q; s% C& U- D7 \4 vax.set_ylabel('Infective Ratio', fontsize=20)+ D5 P6 T! S( V
ax.grid(1)6 V) q; I4 ]+ f% y. i. y
plt.xticks(fontsize=20)! m. o2 C- l. W: D
plt.yticks(fontsize=20)
1 n0 Z: [+ F. z) [6 z/ I% E" Gplt.legend();7 _, k: ?5 `1 p7 m
+ u: D8 V# Y* @0 r# |- y" }
; M! I* A. f- `+ d& u - E3 T) v J+ P# p# [. G3 @
. E9 ]9 j) E; y: n# {+ O' |1 M
感染人数峰值发生在一个月左右,最大感染人数不到人群的20%, 但是最终人群的80%都会得此病(就是最终的移出者的比例)。SIR模型适合研究没有潜伏期的急性传染病,治疗后能够痊愈并具有抗病性。 到这里,虽然不准确,我们也可以先用SIR模型来分析一下此次疫情,武汉新型冠状病毒的传染病动力学! 模型有了,其实就是确定参数的问题。一开始就有人做了这个工作: Image Name于教授给的参数是参考了非典的, ,初始易感人数为一千万, 初始感染10人,初始移出者5人,那么我们的城市总人数 , 带入我们的模型得到结果:重现于教授的模型
0 v9 H- q8 B/ B9 k: C' L高峰和尾声日期的推测基本相符。
* p$ c' Q: J4 \2 b! a, T5 o6 j( q# susceptiable ratio5 Q: [( C G8 G) e1 ]
s = np.zeros([T])
- s% x) k! s N+ q* ~+ o+ l4 R& j# infective ratio. q C( y+ s: S! e
i = np.zeros([T])8 f j3 C1 @" y8 d( O# c
# removed ratio
]' U" ^; |# }! z/ v b: D$ }r = np.zeros([T])% |' ]8 W2 k" w
' U2 }/ N1 _* ~
# birth ratio
$ y8 m" m, q# W/ bb = 20.0 / N7 g# x; \2 w( A) S8 ^. w! M A
# death ratio
/ G" c6 X* m; {# H: Ed = 10.0 / N: E0 p: _" z7 ^& w, L
6 R* n1 r6 j% a- e- [. J# contact rate$ s5 E" K* C7 h2 j: z$ k3 y
y = 1.5: G# e% d: u) S0 r# H, T7 Y
# recover rate
: \- C5 i E" u, o5 Z+ _; R! Pu = 0.8 # 1 / infective_period' Q) b' g7 i- J5 \
) o7 b+ M$ s' b# sigma = y / u
& I3 M2 K# A3 Y1 r
9 l% ^3 l; i! q. |# initial infective people
( t2 P! s8 ^4 L9 |' Y2 @* q0 Ui[0] = 45.0 / N5 J. @8 A) r) a1 X
s[0] = 1 - i[0]5 G3 C% p$ Y! R* ]3 n5 g
for t in range(T-1):
, W$ E/ s. L0 B2 [) Y i[t+1] = i[t] + i[t] * y * s[t] - u*i[t] - d*i[t]
" c4 {# |# i8 h# t$ B s[t+1] = s[t] - y * s[t] * i[t] + b - d*s[t] E% {' ^+ w3 [9 ?& U! ?$ E
r[t+1] = r[t] + u*i[t] - d*r[t]
6 |) U3 G: \( g" M S$ C
" l( R4 p; g& m0 o) @plt.plot(i)
' i. c" t6 o$ G& ^6 P5 aplt.plot(s)
Y. E9 `2 L6 b& tplt.plot(r)- M! ?. D( a+ I; x3 O4 P
plt.plot(np.diff(i),ls='--')+ U* d/ D9 D' y) H& g
. `2 E+ w, o! V, N
* z: Y: \2 H, z Y, `# r# ^[<matplotlib.lines.Line2D at 0x7f77796e8518>]/ D( f" k8 V3 F1 ?- s
9 V, U @- [/ A. \ V. r5 C 7 ~# t; B4 Q; J. m6 m! ~
6 A- h2 j, w2 G6 G5 H2 FSEIR模型但是,SIR模型和实际情况的出入会比较大,因为忽略了太多因素了,比如说潜伏期,比如说政策调控,药物,出生死亡等等。下面我们可以和前面一样,把潜伏期考虑进去,新增一个人群,叫潜伏者E(exposed): Image NameSEIR模型4 J" c! ?6 _7 f A
同样的我们需要计算各人群每天的增加量: S:每天减少:
9 Y( Y- B# [0 o+ U. Y; }E:每天增加传染,减少发病:
G) e( |0 L: l6 O- ]! T0 }( ?9 fI:每天增加发病,减少治愈:
1 o. n4 b" l* S- p% A7 aR:每天增加治愈:
_7 g0 T/ f" N( X1 a建模完成,修改我们的python程序,这里的 可以理解为潜伏期的倒数。给的4天。新型冠状病毒给目前临床的潜伏期是3-14天。
$ | @* |' m' ~# population
( T6 T1 Y% b# y( n! B: E2 SN = 1e7 + 10 + 5
7 J9 b# j" W4 Q6 K# simuation Time / Day: H6 F5 {, M2 i$ a
T = 170
, i* Z6 {" U0 c. u/ n# susceptiable ratio k b% O0 E/ i
s = np.zeros([T])
\5 Z) K& _4 K# exposed ratio
5 C) }$ _* m) L& f8 u( we = np.zeros([T]): d8 W4 w6 l6 I; c x: L: `
# infective ratio. ]4 V# \1 }8 y" f
i = np.zeros([T])3 c$ P: ?" ]- }5 q) U- J; |- A( g
# remove ratio
1 J: U8 H9 f1 C( e; n( K1 `r = np.zeros([T])' j+ Z* Q8 Y; g. u6 ^
- E1 ?/ d6 q" R) o4 j: m
# contact rate: A& Y, I$ z5 |* @" t* _
lamda = 0.50 e2 t* X+ `" O ~
# recover rate
3 ^! n+ q1 z; s0 C9 L7 Qgamma = 0.08212 H1 _8 }7 r6 ]. f
# exposed period6 v1 n: z$ U7 Q8 J0 f" P
sigma = 1 / 4
- O6 U" U t2 A7 ^" D( I5 `
1 z* V9 A d7 X- y+ F# initial infective people
0 \ W; D6 n# [! |7 ]+ r( _i[0] = 10.0 / N
, G. Z7 A5 I+ `+ Ps[0] = 1e7 / N- Q; v$ O& F$ n
e[0] = 40.0 / N
# ]0 |2 P9 G: ]# d1 pfor t in range(T-1):; r% i; @% N/ o1 y+ H, ~# d* K
s[t + 1] = s[t] - lamda * s[t] * i[t]' B9 d8 i6 Y7 M$ L4 P" W) z
e[t + 1] = e[t] + lamda * s[t] * i[t] - sigma * e[t]( ~" q' E% P9 M' W7 H; A8 R6 n! f
i[t + 1] = i[t] + sigma * e[t] - gamma * i[t]
- h0 D8 H z* _+ f% Z5 ]! B1 d r[t + 1] = r[t] + gamma * i[t]
+ ^+ r0 D' n! e3 W6 ]9 r% k" f) D! @' ^) r) p f! V7 o
+ H$ b) l- C+ l3 w! F
fig, ax = plt.subplots(figsize=(10,6))
3 U1 p5 s! z( S( d) l0 s7 vax.plot(s, c='b', lw=2, label='S')
9 ^' X# }! Z5 X' J5 B$ g) a( kax.plot(e, c='orange', lw=2, label='E')
9 e; Q7 ^0 o+ @1 w4 w' n F8 Wax.plot(i, c='r', lw=2, label='I')
5 X9 c" J7 l- j' \ax.plot(r, c='g', lw=2, label='R')
3 o- ?6 e5 g/ hax.set_xlabel('Day',fontsize=20)
* p2 y7 Z3 x! l+ J6 Q6 Iax.set_ylabel('Infective Ratio', fontsize=20)# ^4 ]; M3 a9 K, V- z3 ~ Q
ax.grid(1)
/ V, F$ w$ ]: A! O2 uplt.xticks(fontsize=20)
4 ]; O/ U+ A5 C8 wplt.yticks(fontsize=20)
% m; d, d0 C5 b: g5 h" o& w qplt.legend();
) B. x- {5 h* K, u3 [1 `+ @ F% V+ k: {& u" @: C
% x+ V \9 \- S" z 6 l- ]& C/ \: S% h
8 M( c7 v4 g% z8 ]) g
按照模型的结果,此次疫情可能真的要持续到 三四月份。这个接触率 真的非常影响表现,模型给的是个常数,但是由于政府措施的原因,这应该是个变化的值。6 M/ [+ N( x2 _( \
还有治愈率 也是。没有完美的模型,但是随着考虑因素的增多,就会越来越接近实际情况,从而指导政府的疫情方针政策的制定。5 w7 u9 \; g# x
5 L# {0 k h F9 x3 ~& M1 [3 B. a8 |) m; o* {
" j, T4 K3 S3 {* k) V9 y
( C, ^/ _ R: _+ t2 Z4 A# W2 p! Y |