C# 版本 疫情传播仿真程序
前言
前一陣子看到有人制作了《疫情傳播仿真程序》,是用?Java做的。里面根據多種實際情況,如居民移動意愿、醫護能力、病毒傳播能力,來模擬疫情的發展。看完之后,我暗暗稱奇,特別是結合一些視頻和照片,確實做得非常好。
后來過了幾天,這個視頻還上了?人民日報的微信公眾號,這時我們?.NET社區就開始騷動了起來????????,咱們?.NET能不能也做一個?
既然有需要,?2月6號那天晚上我決定說干就干,經過兩個晚上的思考與編碼,已經有了初步效果……運行效果如下:
這個效果可以這樣解讀,如果不加以任何控制,疫情會很快蔓延到整個城市,只有?8:1000床位的城市,將很快失去控制,一年后運行效果如下(非常慘烈):
參數與使用
代碼中實際有很多參數可以操作:
static double MoveWilling = 0.90f; // 移動意愿,0-1 static bool WearMask = false; // 是否戴口罩 static int HospitalBeds = 40; // 床位數 const float InffectRate = 0.8f; // 靠得夠近時,被攜帶者感染的機率 const float SecondsPerDay = 0.3f; // 模擬器的秒數,對應真實一天 const float MovingDistancePerDay = 10.0f; // 每天移動距離 const int InitialInfectorCount = 5; // 最初感染者數 const double DeathRate = 0.021; // 死亡率 // 要靠多近,才會觸發感染驗證 static float SafeDistance() => WearMask ? 1.5f : 3.5f; // 住院治愈時間,最短5天,最長12.75天,平均約7天 static float GenerateCureDays() => random.NextFloat(5, 12.75f); // 潛伏期,1-14天 static float GenerateShadowDays() => random.Next(1, 14); // 發病后,就醫時間,0-3天 static float GenerateToHospitalDays() => random.Next(0, 3);由于參數太多,很難在運行時全部都做調整,我選取了是否戴口罩、移動意愿、醫院床數作為參數,代碼如下:
protected override void OnKeyPress(KeyPressEventArgs e) {switch (e.KeyChar){case '1': MoveWilling = 0.10f; break;case '2': MoveWilling = 0.50f; break;case '3': MoveWilling = 0.90f; break;case 'M': WearMask = !WearMask; break;case 'A': HospitalBeds += 40; break;case 'D': HospitalBeds -= 40; break;case 'R':{if (MessageBox.Show("要重來嗎?", "確認", MessageBoxButtons.YesNo) == DialogResult.Yes){City = City.Create();}break;}} }其中,按數字鍵?1、?2、?3可以指定不同的移動意愿,其中?1表示居民最不愿意出門,?3表示最愿意,按?M可以控制居民是否能戴上口罩,按?A可以添加醫院可接納病人數。
一些演示
超多床位
這里我將床位調成?240個(比例為?48:?1000):
static int HospitalBeds = 240; // 床位數也可以運行時增加床位,按鍵盤?A即可(不用改代碼),運行效果如下:?
可見床位變多后,死亡率會降低,治愈人數大大提高,但仍然無法控制住疫情的發展。
“理想”情況1·沒有潛伏期
可以這樣配置:
// 0潛伏期 static float GenerateShadowDays() => 0;運行效果如下:?
可見就算潛伏期為?0,由于沒有及時就醫,疫情仍會失去控制。
“理想”情況2·沒有潛伏期、且立刻隔離就醫
像那個?Java版中,會先介紹一個“理想”情況,即感染即發病,發病即就就醫。此種模型的參數,可以這樣配置:
// 0潛伏期 static float GenerateShadowDays() => 0; // 發病后,立即就醫。 static float GenerateToHospitalDays() => 0;在這種情況下,運行效果如下:?
可見,由最初的?5人,最終只感染了?6人,理想情況下局勢很快就被控制。當然這種情況是不存在的。
戴口罩出門
假如居民都戴口罩出門,可以用如下配置(也可以運行時按下?M鍵):
static bool WearMask = true; // 一定戴口罩運行效果如下:??
堅持了?107天,疫情發展速度大大降低,但由于醫療資源的匱乏,死亡率仍然居高不下,最終仍會失去控制。
居民呆在家中不出門,且戴口罩
配置如下:
static bool WearMask = true; // 一定戴口罩 static double MoveWilling = 0.10f; // 每天只有10%的人愿意出門運行效果如下:?
病毒在最初的?5人身上,只感染了?2人。效率可謂驚人。
模擬現實模型
我想貼近現實,模擬一些現實情況,然后看看效果如何,我的腳本如下:
前?20天,不作任何控制
第?20天,全民戴口罩,移動意愿降低至?50%,床位增加?40個(模擬進入重大突發公共衛生事件Ⅰ級響應)
第?25天,移動愿意降低至?10%,床位增加?80個(模擬火神山醫院)
第?30天,床位再增加?80個,共?240個(模擬雷神山醫院)
為了盡可能短地截取?gif,我將時間縮短了,真實時間可能會和這個比例為?1:2(也就是相當于前?40天不作任何控制),腳本如下:
void StepDay() {if (day < 20){WearMask = false;MoveWilling = 0.9;HospitalBeds = 40;}if (day >= 20){WearMask = true;MoveWilling = 0.5;HospitalBeds = 80;}if (day >= 25){MoveWilling = 0.1;HospitalBeds = 160;}if (day >= 30){HospitalBeds = 240;}// 其它代碼 }運行效果如下:?
可見這真是與病毒的一部史詩級斗爭。
前?20天,沒有任何控制,病毒瘋狂肆虐,前期只花了?9天,就把醫院給擠滿了;
第?20之后,居民帶上口罩,傳播進度迅速下降,但由于潛伏期較長,發病人數仍然持續上升;
第?30天之后,由于?5天前床位(醫護資源)的跟進,發病人數增速降低;
第?35天后,發病人數開始下降;
第?68天后,除了醫院中的病人,城市中已經沒有病人;
第?78天,已經沒有被病毒感染的人了。
總結
所有這些代碼,我都上傳到了我的博客數據網站,各們可以下載代碼,通過?LINQPad6直接模擬運行,或者拷到?VisualStudio中亦可。各位也可以或者提出您的想法,?Github鏈接如下:https://github.com/sdcb/blog-data/tree/master/2020/20200207-2019-ncov-simulate
寫完這個東西,給我最大的感受就是震撼,模擬起來就是一些數據而已,但背后是千千萬萬有血有肉的病人和醫務工作者,向那些偉大的“逆行者”們致敬!
從上面的數據也可以看出,任何單項指標做好,都是不能完全阻止疫情的。我們要相互信任,做好自己。我們能做的有:盡可能呆在家,別出門,就真是對國家最好的貢獻;出門一定要戴口罩,這樣可以明顯降低感染率。
喜歡的朋友請關注我的微信公眾號:【DotNet騷操作】
最后,在新的一年里,祝大家闔家歡樂,鼠年大吉!
總結
以上是生活随笔為你收集整理的C# 版本 疫情传播仿真程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用obfuscar对.NET应用进行混
- 下一篇: 疫情之下,使用FRP实现内网穿透,远程连