2020年爆發新型冠狀病毒,讓大家在見證中國的團結也讓大家感受到疫情傳播的駭人
在這里先道一聲“武漢加油、中國加油”

那么現在我們嘗試制作一個模擬疫情爆發的模型,以數字的形式展現疫情爆發點恐怖,
(1)模型設計
解釋人類模型,每個人屬性分為編號、狀態、保護措施、外出情況,
編號:作為區分每個人類模型的標識;
狀態:分為兩部分,0為健康,1為感染;
保護措施:參考狀態也份為兩部分,0為未采取保護措施,1為保護措施
外出情況:外出情況為1的將會選擇外出尋友,而為0則不會外出,
程式初期,將會生成一定數量的人類模型,然后隨機選擇百分之五(感染人數>1)的人作為感染體,
模擬開始,將會開始記錄每天的感染人數,然后隨機選擇一定數量的人外出,每個外出的人都會選擇一個人進行交流,
交流程序中,若兩個人均感染或均為感染則無問題,若一人感染則根據瘟疫感染幾率和防護措施進行隨機判定是否感染,
結束條件為全部模型的98%的人被感染,記錄天數,
效果如下圖所示:

(2)程式設計
首先,要獲取實驗資訊,所以先創建獲取資訊函式(get_info)
其次,要通過獲取的資訊來創建對應模型,所以要有創模函式(creat_mod)
然后,就是模擬實驗發生的感染函式(experiment)
最后,為方便判斷是否發生了感染,創建了感染函式(contagion)
由于實際情況需要所以還要制作選擇函式來實作概率隨機,
根據之前的需求和實際情況考慮創建了全域變數,
(3)程式實作
專案名稱:瘟疫實驗室
開發工具:sublime_text
開發模塊:random
1.前期準備
在這一部分中,將要根據情況,創建好全域變數并宣告函式,
個人推薦前期賦初值的時候設定為實驗資料,這樣可以避免前期除錯程式頻繁輸入,
代碼如下所示:
import random as r
#實驗模型
human=[]
#實驗人數
hunman_number=-1
#感染概率
infected=0
#保護措施
protect=0
#采取保護措施
human_protect=0
#每天外出人數
human_out=0
#保護者id
protect_id=[]
#外出者id
out_id=[]
#所有人id
human_id=[]
#感染者id
virus_id=[]
#函式,收集資訊
def get_info():
pass#函式,創建模型
def creat_mod():
pass
#函式,實驗
def experiment():
pass#函式,判斷是否感染
def contagion(id_1,id_2) :
pass#函式,選擇函式
def pick(contagion_p):
pass#主函式
def main():
get_info()
creat_mod()
experiment()
#程式入口
if __name__ == '__main__':
main()
2.收集資訊實作
在收集資訊函式中,將要實作收集實驗引數的作用,而實驗引數為全域變數,要想實作收集資訊就需要通過關鍵字global,
關鍵字global的作用可以在函式內對全域變數進行修改,
函式內操作就是通過input函式來實作資料的接收,難度比較低只需要需要注意兩方面即可,
一方面是資料型別,input函式所接受的資料默認為字串型別,所以要對資料進行型別轉化,可以考慮eval()函式
考慮到資料的限制,所以最后采用強轉int() 和float()
另一方面則是資料的合理性,比如感染幾率為0~1,所以超過1即為資料錯誤,又或者外出人數超過實驗總人數等等,
為避免這一情況,所以輸入一個資料就對進行判斷,
實作代碼如下:
#函式,收集資訊
def get_info():
print("*********************")
#global改變全域變數
global hunman_number,infected,protect,quarantine,human_out,human_protect
#實驗人數
hunman_number=int(input("實驗人數:"))
#感染概率
infected=float(input("疾病感染概率(0~1):"))
if infected>1 or infected<0:
print("感染概率在0到1之間")
get_info()
#保護措施有效性
protect=float(input("保護有效性(0~1):"))
if protect>1 or protect<0:
print("保護概率在0到1之間")
get_info()
#采取保護措施人數
human_protect=int(input("采取保護措施人數:"))
if human_protect>hunman_number or human_protect<0:
print("采取措施人數不可超過實驗人數")
get_info()
#外出人數
human_out=int(input("每天外出人數:"))
if human_out>hunman_number or human_protect<0:
print("外出人數不可超過實驗人數")
get_info()
3.創建模型實作
模型也需要修改一部分全域變數,所以先呼叫關鍵字global
第一步:模型的創建先通過回圈來創建實驗模型,回圈條件為實驗人數,資料(先設為0)為[id,0,0,0],
第二步:添加保護措施,原理為隨機選擇設定的人數的模型,讓模型中代表采取保護措施的數值更改為1
隨機選擇的實作考慮許久,最后選擇通過random庫中的sample()函式來實作,sample函式的作用為將指定序列進行重新隨機排列
其中有兩個引數,一個為重排序序列名,另一個代表輸出序列的前幾個,默認為全部輸出,
所以只需要將實驗人數的串列傳入進行重排序,然后輸出前指定人數個即可,
最后通過回圈,訪問選出的個體,將代表是否采取保護措施的資料更改為1(采取保護措施)
第三步:采用同樣的原理選擇5%的實驗個體作為傳染源,注意,感染人數為int型別整數,為保證感染個體不為0,采取5%人+1,
代碼實作如下所示:
#函式,創建模型
def creat_mod():
global human,human_id,protect_id,virus_id
#回圈創建指定人數的實驗個體,并將id存盤,
for id in range(0,hunman_number):
#id、state、protect、out
human.append([id,0,0,0])
human_id.append(id)
#采取保護措施人數id的集合,資料為對實驗總體進行隨機重排列,再選擇一定量輸出,
protect_id=r.sample(human_id,human_protect)
#回圈更改實驗個體
for id in protect_id:
#0為未采取保護措施,1為采取保護措施
human[id][2]=1
#原理同上
virus_id=r.sample(human_id,int(human_protect*0.05)+1)
for id in virus_id:
#0為健康,1為感染
human[id][1]=1
4.實驗實作
實驗的開始要確定結束條件,我們以百分之九十八的人感染視為結束,
確定之后,記錄天數要創建一個計數器來存代表天數的變數,
實驗采用死回圈的方式進行,跳出條件只有一個實驗感染人數超過了結束人數,所以需要加入計數器來存感染人數
代表日期的計數器與代表感染人數的計數器不同,日期計數器在程式開始運行的時候,開始計數直到程式結束,
而感染人數計數器每一次回圈都要清零重新開始計算,所以日期計數器的宣告在死回圈外,而感染人數計數器在死回圈內,
實驗分為兩部分,一部分為對之前的總結,另一部分為新的一天開始,
總結當中第一件事情便是清零計數器,
然后通過統計感染人數,原理為for回圈所有人的id,加入判斷若該id中代表狀態的資料為1則代表感染,計數器加一,
最后輸出之前一天的情況,第x天,感染人數為x人,
新的一天開始,先判斷統計人數有沒有超過失敗條件,再開始一天的操作,
隨機選擇指定人數進行外出,參考之前保護措施的原理,根據外出人數隨機選擇人進行外出,將其資料更改為1,
然后考慮到實際情況,每個人外出都是要去尋找朋友,尋找朋友則是通過random庫的choice()函式,
實作代碼如下所示:
#函式,實驗
def experiment():
global out_id
fail=int(hunman_number*0.98)
print("*****************************")
print("實驗開始,失敗條件感染人數:",fail)
day=0
while True:
#計數器清零
count=0
#統計感染人數
for i in human_id:
if human[i][1]==1:
count+=1
#外出人數
out_id=r.sample(human_id,human_out)
for id in out_id:
human[id][3]=1
#統計結果
print(day,"天感染人數",count)
#新的一天開始
day+=1
#判斷是否繼續實驗
##實驗結束
if count>=fail:
print("gameover->",day)
break
#回圈找朋友
for id in out_id:
#隨機選擇朋友
friend_id=r.choice(human_id)
#若均感染,則跳過
if human[id][1]==1 and human[friend_id][1]==1:
pass
#一方感染
else:
#判斷感染
contagion(id,friend_id)
5.感染判斷實作
若發生感染事件,則需要更改實驗體資料,所以在這一函式中可以對實驗題進行修改,需要參考關鍵字global,
然后根據情況進行分類,先尋找是哪位感染,哪位健康,然后針對健康的人是否采用保護措施進行分類討論討論,
在本模型中,計算感染方式為概率性,由疾病感染概率和保護措施有效性決定,
以0.8感染幾率0.7保護措施為例子,保護有效性為0.7所以保護失敗的幾率為0.3
所以感染疾病幾率為0.8感染幾率的情況下0.3的保護失效,結果為0.8*0.3,
根據不同的情況變動概率進行概率抽取即可,代碼實作如下
#函式,判斷是否感染 def contagion(id_1,id_2) : global human #感染概率 contagion_p=0 #第一個id為健康 if human[id_1][1]==0: #采取保護措施 if human[id_1][2]==1: contagion_p=infected*(1-protect) #未采取保護措施 else: contagion_p=infected #是否感染 human[id_1][1]=pick(contagion_p) #第二個id為健康的人 else: if human[id_2][2]==1: contagion_p=infected*(1-protect) else: contagion_p=infected human[id_2][1]=pick(contagion_p)
但是在random中沒有找到合適的方法,所以只能自制一定概率隨機抽取函式pick,
6.pick函式實作
一定概率隨機抽取函式的實作基于一點:
random.uniform(0,1)->生成0.0到1.0之間的偽亂數,之后回圈元素及其概率,計算累積概率.
如:random_pick([1,2,3,4],[0.1,0.2,0.3,0.4])
當x處于0.0到0.1之間,則輸出1
當x處于0.1到0.3之間,則輸出2
所以實作程序可以利用這一點,通過兩個串列將資料一一對應,然后通過zio改為字典,
在通過uniform函式來實作概率選擇,實作代碼如下所示:
#函式,選擇函式 def pick(contagion_p): #選擇 select=[1,0] #概率 choose=[contagion_p,1-contagion_p] x = r.uniform(0 ,1) cumprob = 0.0 for item , item_pro in zip(select , choose): cumprob += item_pro if x < cumprob: break return item
在主函式中桉順序呼叫以上函式即可,這樣就初步實作了,
(4)改進與推薦
這個程式是個人處于興趣創建的小型程式,還有許多可以改進的地方,
1.加入治愈因素,比如每天可以治愈多少人,又或者感染者過多少天可以治愈等情況,
2.加入經濟因素,比如治愈者需要成本等等,包括醫院體系等等,
3.保護措施豐富化,可以采取不同的措施來更改感染幾率,
4.可視化,比如通過更改角色顏色等方式以更加直接的方法顯示這一程序,
5.加入大量實驗資料,進行資料分析將結果制為圖表,然后根據數學方式為抗疫提出有效建議,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/180068.html
標籤:Python
下一篇:3.資料可視化入門介紹
