基于Simulink的SIR传染病模型仿真:从微分方程到可视化实现
1. 从现实到模型为什么我们需要SIR模型来理解病毒传播最近几年大家对于“病毒传播”这个词已经不再陌生。无论是新闻里不断变动的感染曲线还是生活中讨论的防控措施背后都有一套数学模型在支撑着决策者的判断。这套模型里最经典、最基础的就是SIR模型。你可能觉得数学模型离生活很远但当你看到“基本再生数R0”、“群体免疫阈值”这些概念时其实就已经在和SIR模型打交道了。它就像一个简化但极其有力的“思维实验室”让我们能在计算机里模拟一场虚拟的疫情回答诸如“如果不加干预最终会有多少人感染”、“隔离措施需要多严格才能压平曲线”这类关键问题。SIR模型是传染病动力学研究的基石其核心思想是将人群划分为几个互斥的仓室Compartment。对于经典的SIR模型这三个仓室分别是易感者Susceptible, S、感染者Infectious, I和移除者Removed, R。这里的“移除”并非指物理消失而是指那些不再参与病毒传播的人包括康复后获得免疫力的人以及不幸病故的人。模型通过一组微分方程来描述这三类人群数量随时间变化的动态关系。虽然它做了很多理想化的假设比如人群均匀混合、不考虑年龄结构、免疫力永久有效等但正是这种简化让我们能够抓住传播动力学的核心机制并在此基础上进行各种扩展和复杂化以贴近现实。而提到仿真尤其是在工程和科研领域Simulink是一个无法绕开的强大工具。它是MATLAB的一个可视化仿真环境特别适合对动态系统进行建模、仿真和分析。对于SIR这类由微分方程描述的系统用Simulink搭建模型具有得天独厚的优势你不需要手动编写复杂的数值积分代码比如龙格-库塔法只需通过拖拽模块、连接信号线的方式就能直观地构建出模型框图。Simulink会自动处理方程的求解过程并让你能够实时调整参数如感染率、恢复率立即看到传播曲线的变化。这种“所见即所得”的建模方式极大地降低了传染病模型的学习和实验门槛无论是用于教学演示、政策评估还是学术研究都非常高效。2. SIR模型的核心机理与微分方程拆解要真正理解SIR模型不能只停留在三个字母的划分上必须深入其背后的数学机理。我们假设在一个封闭的总人口N中有S(t)个易感者I(t)个感染者R(t)个移除者且始终满足 S(t) I(t) R(t) N。2.1 核心假设与参数定义模型的运行依赖于几个关键参数它们决定了传播的速度和规模感染率β, Beta 这可能是最重要的一个参数。它表示一个感染者单位时间内能成功传染的易感者人数。更精确地说β 是“有效接触率”与“每次接触传播概率”的综合体现。在均匀混合的假设下单位时间内感染者与易感者的接触次数与易感者比例S/N成正比。因此新感染者的产生速率可以表示为β * I * (S/N)。这意味着感染者越多、易感者比例越高新感染发生得就越快。恢复率γ, Gamma 它表示感染者单位时间内恢复或移除的比例的倒数。例如如果平均感染期从染病到恢复/移除的时间为 D 天那么恢复率 γ 1/D。如果D5天则γ0.2/天。这意味着平均而言每天有20%的感染者会进入移除状态。因此感染者的移出速率即新增移除者的速率为γ * I。有了这两个参数我们就可以定义另一个至关重要的衍生参数——基本再生数Basic Reproduction Number, R0。R0的定义是在完全易感的人群中即S≈N一个感染者在其整个传染期内平均能传染的人数。计算很简单传染期长度是 1/γ在此期间他单位时间能传染 β 个人因为此时S/N≈1。所以R0 β / γ。R0是一个无量纲的数它是判断疫情是否会爆发的“阈值”。当 R0 1 时疫情会扩散当 R0 1 时疫情会逐渐消亡。例如早期新冠原始毒株的R0估计在2-3之间意味着不加控制一个病人平均会传染2-3个人。2.2 微分方程组的建立与解读基于上述定义我们可以写出经典的SIR模型微分方程组dS/dt -β * I * (S/N) dI/dt β * I * (S/N) - γ * I dR/dt γ * I我们来逐条解读dS/dt易感者变化率 永远是负值因为易感者只会因被感染而减少。减少的速率正是新感染发生的速率。dI/dt感染者变化率 这是疫情发展的核心。它等于“新感染发生速率”减去“康复移出速率”。当新感染大于康复时感染者数量增加疫情上升反之则下降。dR/dt移除者变化率 永远为正值且等于康复移出的速率。这组方程构成了一个非线性系统因为含有 I * S 项通常没有解析解必须通过数值方法求解。而这正是Simulink大显身手的地方。通过搭建这个方程组的框图我们可以直观地观察S、I、R三条曲线如何随时间演化并深刻理解参数β和γ是如何像“旋钮”一样控制着疫情曲线的陡峭与平缓。注意 这里有一个初学者常混淆的点。方程中的(S/N)项有时会被省略写成dS/dt -β * I * S。这两种形式本质上是等价的区别在于对β的定义。如果方程包含S/N则β表示“一个感染者每天有效接触并传染的人数”如果方程不包含S/N则β表示“一个感染者每天与易感者接触并传染的概率密度”此时β的量纲不同数值也会差N倍。在建模时务必统一约定本文采用包含S/N的经典形式因为它更直观地反映了易感者比例的影响。3. 手把手搭建SIR模型的Simulink仿真理论说得再多不如动手搭一遍。下面我将详细演示如何在Simulink中从零开始构建SIR模型。这个过程就像搭积木你会清晰地看到每个数学项是如何对应到一个具体模块的。3.1 模型搭建从方程到框图初始化与参数设置 首先在MATLAB命令行或新建一个脚本文件.m文件中定义模型参数和初始条件。这能让你的模型更清晰、易于修改。% SIR模型参数 N 1000; % 总人口 I0 1; % 初始感染者人数 S0 N - I0; % 初始易感者人数 R0 0; % 初始移除者人数 beta 0.3; % 感染率1/天 gamma 0.1; % 恢复率1/天对应平均感染期10天 R0_basic beta / gamma; % 计算基本再生数 fprintf(基本再生数 R0 %.2f\n, R0_basic); % 仿真时间设置 t_start 0; t_stop 150; % 仿真150天打开Simulink新建一个空白模型。构建核心计算回路 SIR模型的核心是计算dS/dt, dI/dt, dR/dt然后对它们积分得到S, I, R。我们以dI/dt β*I*(S/N) - γ*I为例展示搭建过程。从库浏览器中拖入两个Constant模块分别命名为Beta和Gamma并将它们的值分别设置为beta和gamma注意这里我们直接使用工作区变量名Simulink会自动识别。拖入三个Integrator积分器模块分别命名为Integrator_S,Integrator_I,Integrator_R。在它们的初始化Initial condition参数中分别填入S0,I0,R0。积分器的输出就是当前的S, I, R值。现在搭建β*I*(S/N)部分。用Product乘法模块将Beta、Integrator_I的输出、以及Integrator_S的输出连接起来。但注意我们需要的是S/N所以先要用一个Divide除法模块计算Integrator_S / N。这里N可以用一个Constant模块输入值为N。计算γ*I部分用Product模块连接Gamma和Integrator_I的输出。计算dI/dt用一个Sum加法模块将其图标形状设置为圆形符号设置为|-表示加第一项减第二项将β*I*(S/N)的结果接入正端γ*I的结果接入负端。这个Sum模块的输出就是dI/dt。最后将这个dI/dt信号线连接到Integrator_I的输入端口。至此感染者的反馈回路就完成了。积分器根据变化率更新II又反过来影响变化率的计算。完成整个系统 按照同样的逻辑搭建dS/dt和dR/dt的回路。dS/dt回路非常简单它就是-β*I*(S/N)。直接用之前计算好的β*I*(S/N)信号通过一个Gain增益模块增益设为-1或者一个Unary Minus一元取负模块然后连接到Integrator_S的输入。dR/dt回路就是γ*I将之前计算好的γ*I信号直接连接到Integrator_R的输入。最后用Scope示波器模块或者To Workspace模块将三个积分器的输出即S, I, R的值连接起来用于观察和记录数据。为了同时观察三条曲线可以拖入一个Mux模块将S, I, R三个信号合并再输入到一个Scope中。3.2 关键模块配置与仿真运行Solver配置至关重要 在Model Configuration Parameters快捷键CtrlE中找到Solver选项。对于这种连续系统我们需要选择变步长或定步长的ODE求解器。对于初学者推荐使用ode45 (Dormand-Prince)这是一个变步长、非刚性的常用求解器能自动调整步长平衡精度和速度。将仿真时间设置为[t_start, t_stop]。运行与观察 点击运行按钮。仿真结束后双击Scope模块你应该能看到三条曲线易感者S从初始值单调下降感染者I先上升达到一个峰值然后下降至零移除者R单调上升最终趋于总人口N。I曲线的峰值高度和出现时间直接反映了疫情的严重程度和速度。参数实验 这才是仿真的乐趣所在。不要关闭模型回到MATLAB命令行改变beta或gamma的值例如将beta从0.3改为0.2模拟戴口罩、减少接触等干预措施然后再次运行仿真。你会立刻看到疫情曲线变得平缓峰值降低、推迟。这就是“压平曲线”的数学可视化。你也可以尝试改变R0保持γ不变通过调整β来设定不同的R0如1.5 2.5 3.5对比疫情发展的巨大差异。实操心得 在搭建模型时善用Bus Creator和Bus Selector模块来管理信号线能让模型框图更整洁。尤其是当模型扩展变量增多时将所有状态变量S, I, R打包成一个总线信号在需要的地方再解包取出可以避免画面被密密麻麻的信号线淹没。另外将关键参数β, γ, N封装成Mask子系统并创建对话框这样无需进入模型内部直接在顶层双击模块就能修改参数体验会好很多。4. 模型扩展、结果分析与现实局限性探讨基础的SIR模型揭示了传播动力学的基本规律但现实世界要复杂得多。Simulink的模块化特性使得扩展模型变得相对容易。同时对仿真结果进行深入分析并理解模型的边界是更有价值的部分。4.1 常见模型扩展方向SEIR模型 在感染I之前增加一个潜伏期Exposed, E仓室。潜伏者已感染病毒但尚未具备传染力。这需要引入一个潜伏期转染率参数σσ 1/平均潜伏期。微分方程变为 dS/dt -β * I * S/N dE/dt β * I * S/N - σ * E dI/dt σ * E - γ * I dR/dt γ * I 在Simulink中这意味著增加一个积分器代表E并增加相应的流入来自S和流出流向I计算。SIRS模型 考虑免疫力并非永久康复者经过一段时间后可能再次变为易感者。这需要在R到S之间增加一个回流引入一个免疫力丧失率参数如ξ。这可以用来模拟像流感这样季节性反复的传染病。引入干预措施 这是政策模拟的关键。例如可以在模型中让感染率β随时间变化。我们可以用一个Clock模块获取仿真时间然后通过一个MATLAB Function模块或Lookup Table模块定义一条β随时间变化的曲线。比如仿真第30天开始实行严格管控β值从0.3骤降至0.1第80天放松β回升至0.2。通过这种方式可以定量评估“封城”、“社交距离”等政策的效果。考虑人口动力学 在长周期仿真中可能需要考虑出生新增易感者和自然死亡。这可以通过在dS/dt方程中加入一个常数出生率并在每个仓室都减去一个与人口成比例的自然死亡率来实现。4.2 仿真结果分析与解读运行基础SIR模型后我们得到S(t) I(t) R(t)的曲线。从中我们可以提取出几个关键流行病学指标疫情峰值Peak of Epidemic 即感染者I(t)的最大值。这代表了医疗系统需要应对的最大瞬时压力。通过Simulink的Max模块或者将数据导出到MATLAB用max()函数均可求得。达峰时间 疫情达到峰值所需的时间。这决定了防控措施的窗口期有多长。最终感染规模 当t→∞时移除者R(∞)的数值。这代表了在不加干预或干预不变的情况下总人口中最终会被感染的比例。值得注意的是即使疫情结束I0也不会是所有人都被感染总会有一部分人自始至终是易感者。这个最终的比例S(∞)可以通过求解所谓的“最终规模方程”来理论估算仿真结果则给出了直观答案。基本再生数R0与有效再生数Rt 仿真初期我们可以验证I(t)是否呈指数增长其增长率与 (β - γ) 相关。更重要的是在疫情发展中有效再生数Rt R0 * (S(t)/N)是一个动态变化的指标。当S(t)下降越来越多人感染或免疫Rt就会下降。当Rt持续小于1时疫情就会开始衰退。我们可以在Simulink中实时计算并绘制Rt曲线这对于判断疫情拐点非常有帮助。4.3 模型的局限性、校准与思考SIR模型虽然强大但我们必须清醒认识它的局限性避免陷入“数学原教旨主义”的误区。理想化假设 “人群均匀混合”是最大的理想化。现实中传播发生在复杂的社交网络、空间地理和年龄结构中。一个超级传播者事件可能用SIR模型完全无法预测。参数不确定性 β和γ尤其是早期的β和R0很难准确估计。它们会随着病毒变异、人群行为改变、季节变化而动态变化。模型结果对参数非常敏感所谓“垃圾进垃圾出”Garbage in, garbage out。忽略细节 模型忽略了疾病的严重程度分布轻症、重症、无症状、医疗资源挤兑对死亡率的影响、检测能力限制对报告数据的影响等。因此模型的价值不在于做出精确的预测而在于进行“如果-那么”的情景分析What-if Analysis和趋势判断。例如我们可以问“如果感染率降低20%疫情峰值会推迟多少天降低多少” Simulink仿真可以快速给出定量比较。这才是数学模型在公共卫生决策中扮演的核心角色——一个用于思想实验和策略评估的沙盘。踩坑实录 在早期使用Simulink仿真时我曾犯过一个错误没有正确设置积分器的初始条件或者SIR的初始和不为N。这会导致模型行为异常比如总人口数不守恒。一个良好的习惯是在模型中加入一个Display模块或者To Workspace模块实时计算和显示 SIR 的和确保它恒等于N作为模型正确性的一个基本校验。另外当疫情规模很大I/N很高时如果仿真步长设置不当可能会产生数值不稳定。这时可以尝试更换为刚性求解器如ode15s或减小最大步长。

相关新闻