作者 | 唐小引
出品 | CSDN(ID:CSDNnews)
這兩天,一個視頻火了起來。
視頻地址:https://www.bilibili.com/video/av86478875/
這是一個使用 Java 語言編寫的肺炎仿真程序,從統計學的角度來說,能夠從一定程度上模擬新冠肺炎病毒擴散及被控制的趨勢。
現在,作者已經將代碼開源到 GitHub 上,筆者特此 download 下來與諸君分享。
GitHub 地址:https://github.com/KikiLetGo/VirusBroadcast
在代碼中,我們假定一個城市是一個 600 x 600 的正方型。在這個城市中,每一個人爲一個 3*3 大小的圓形的點。在每一個城市中,人口所在位置在統計學上都有相應的規律。在這裏,假定城市中有 5000 個人,這 5000 個人以城市中心按照正態分佈的方式,隨機地分佈在城市的各個角落。
△城市中人口正態分佈情況
代碼如下:
Random random = new Random();
int x = (int) (100 * random.nextGaussian() + city.getCenterX());
int y = (int) (100 * random.nextGaussian() + city.getCenterY());
Person person = new Person(city, x, y);
在新型肺炎期間,根據肺炎的信息,我們可以知道,病毒存在潛伏期,醫院會對患者進行收治。本文中我們對每一個人的狀態進行簡化,分爲以下四個狀態:
- 正常
- 潛伏期
- 確診
- 在醫院治療中
其中三個狀態中,人是可以自由活動的,當然,關於人的移動,此處的處理邏輯也是簡化爲一個正態分佈的隨機移動。以下代碼爲人隨機移動到的目的地的位置:
// 根據流動意願計算當前人是否需要流動
public boolean wantMove() {
double value = sig * new Random().nextGaussian() + Constants.u;
return value > 0;
}
// 計算人流動到的目標位置
double targetX = targetSig * new Random().nextGaussian() + targetXU;
double targetY = targetSig * new Random().nextGaussian() + targetYU;
moveTarget = new MoveTarget((int) targetX, (int) targetY);
除了處理分配位置和隨機移動,還有一個被感染的函數。當我們在城市中移動的時候,當週圍的人存在攜帶病毒的人,我們就有一定的概率被感染,以下代碼描述了這個過程:
float random = new Random().nextFloat();
if (random < Constants.BROAD_RATE && distance(person) < SAFE_DIST) {
this.beInfected();
}
當然,醫院和國家的響應,會讓我們在感染數上升的同時,避免外出,所以在計算人移動的過程中,添加一個輔助變量來表示人外出移動的意願,隨着感染數的上升,人們的移動意願就會逐漸降低,爲了簡化程序,筆者在此添加了一個線性變化的流動意願修改。隨着牀位被佔據得越來越多,人們的流動意願就越來越低。
public int usedBed() {
int result = 0;
for (Bed bed : beds) {
if (!bed.isEmpty()) {
result++;
}
}
return result;
}
// 更新流動意向
public void updateU() {
int subCount = Constants.BED_COUNT / 5;
int used = usedBed();
if (used > subCount) {
Constants.u = -0.99f;
}
float mu = 1.98f * used / subCount;
Constants.u = 0.99f - mu;
}
下列圖片就是從最開始很小一部分感染羣體在不斷地流動中所帶來的大規模擴散模擬,當政府進行管控,外出人員大幅減少之後,整個疫情得到了有效的控制的演示,我們可以明確地得出一個結論,那就是「不出門、不串門」是非常行之有效的舉措。正如 UP 主在視頻最後所說的那句話 —— 「對本次疫情起到主導作用的,恰恰就是我們普普通通的每一個人」。