Python實戰之製作瘟疫傳播實驗

来源:https://www.cnblogs.com/lyy135146/archive/2020/03/08/12444660.html
-Advertisement-
Play Games

通過Pyhton實戰創建一個模擬疫情爆發情況的模型,來達到提升技術的目的。 ...


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.加入大量實驗數據,進行數據分析將結果製為圖表,然後根據數學方式為抗疫提出有效建議。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 基於SSM開發餐飲業點餐系統 開發環境: Windows操作系統開發工具: MyEclipse+Jdk+Tomcat+MySql資料庫運行效果圖 @ResponseBody @RequestMapping(value = "/checkUsername") public String checkUs ...
  • 本文主要介紹Java—System類和Runtime類的概念及使用。 ...
  • 1.Java中的抽象類 用最簡單的話來說, 一個抽象類就是使用keyword聲明為abstract的 。它可能包含也可能不包含任何抽象方法。JVM將抽象類標識為 不完整類 , 該類 尚未定義其完整行為。聲明一個類 僅強制執行一件事:您不能創建此類的實例,僅此而已。那麼,為什麼還要費心創建一個根本無法 ...
  • 本文源碼: "GitHub·點這裡" || "GitEE·點這裡" 一、基本類型 1、基本類型 不使用New創建,聲明一個非引用傳遞的變數,且變數的值直接置於堆棧中,大小不隨運行環境變化,效率更高。使用new創建的引用對象存儲在堆中。 2、基本信息 基本類型包括如下幾種:byte、short、int ...
  • 有天上飛的概念,就要有落地的實現 概念十遍不如代碼一遍,朋友,希望你把文中所有的代碼案例都敲一遍 先贊後看,養成習慣 SpringBoot 圖文教程系列文章目錄 1. "SpringBoot圖文教程1「概念+案例 思維導圖」「基礎篇上」" 2. "SpringBoot圖文教程2—日誌的使用「logb ...
  • 爬蟲 什麼是爬蟲? 通過編寫代碼,模擬瀏覽器發送請求,讓其去網路上抓去數據的過程。 爬蟲分類? 通用爬蟲 抓取整張網頁的全部內容 聚焦爬蟲 抓去一張頁面的部分內容 通用爬蟲和聚焦爬蟲的關聯: 聚焦是建立在通用爬蟲的基礎上 增量式 監測網站數據的更新情況,以便將最新的數據進行爬取。 reqeusts基 ...
  • 數據可視化庫:1.matplotlib; 2.seabron(輔助的庫,更強大更豐富更好看); 3.Axes3D ...1.導包 1 import numpy as np 2 import pandas as pd 3 4 import matplotlib.pyplot as plt 5 6 im ...
  • 前段時間網路上一名程式員曬出了自己與女神之間的聊天記錄的對話截圖,通過截圖中我們可以看出,應該是這位程式員在追求這位女神,但是短短的十幾分鐘幾條聊天記錄,卻以女神不再願意搭理程式員結束,對於這樣的結局,樓主無奈道:到底是這個女人太搓還是自己太直? 通過聊天記錄我們可以看到兩個人應該是瞭解了一段時間了 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...