疫情仿真——为何不可躺平(附python源代码)

6 篇文章 0 订阅
1 篇文章 0 订阅

一、仿真目的

自新冠疫情出现以来,国际社会对于疫情防控发出了不同的声音,如躺平、戴口罩、接种疫苗、隔离治疗等等。那么我们究竟应该采取什么样的防疫政策,戴口罩以及消耗大量财力物力的接种疫苗与隔离治疗是否有必要,躺平最终会让人类走向全民免疫还是全军覆没?我想通过本次并不是那么准确的仿真,在一定程度上反映出防疫政策的意义所在。(注:本次仿真做不到与真实世界防疫政策一直,只能在一定程度上反映问题)。

二、参数设置

2.1 场景设置

本次场景设置为一个校区,校区内有一个教室、两个宿舍。一个餐厅以及一个隔离区。各部分的分布及面积如下图所示。

2.2 参数设置

本次仿真共建立四个模型,公共参数为四个模型的共享参数,模型参数为各个模型私有参数。

2.2.1 公共参数

人数:300,教室与餐厅的距离 step1=5;教室与宿舍的距离step2=10;密切接触距离<1.5 m;运行时间:20天;初始阳性人数:1

2.2.2 模型参数

(1)模型1:躺平(密接人员感染概率为10%

(2)模型2:戴口罩(密接人员感染概率5%

(3)模型3:接种疫苗(密接人员感染概率1%

(4)模型4:隔离并治疗(密接人员感染概率为20%,阳性病人被隔离概率20%,隔离人员治愈率20%

三、代码

首先将每一天的感染状况存为图片并记录人数,最后用图片生成仿真视频,用记录的人数生成感染人数曲线图。

3.1 疫情仿真

import torch
import numpy as np
import matplotlib.pyplot as plt
import os
import time
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
import argparse
'变量定义'
parser=argparse.ArgumentParser(description='Train the individual Transformer model')
parser.add_argument('--people',type=int,default=300,help='the number of people')
parser.add_argument('--step1',type=int,default=5,help='the steps between classroom and dining room')
parser.add_argument('--step2',type=int,default=10,help='the steps between classroom and dormitory')
parser.add_argument('--prob_infected',type=int,default=20,help='the probability of being infected')
parser.add_argument('--prob_iso',type=int,default=20,help='the probability of being isolated')
parser.add_argument('--prob_recover',type=int,default=20,help='the probability of recovering')
parser.add_argument('--dis',type=int,default=1.5,help='the distance of being infected')
args=parser.parse_args()


def Background():
    plt.figure(figsize=(100,70))
    plt.xlim(0,100)
    plt.ylim(0,70)
    ##横线
    plt.hlines(y=20, xmin=30, xmax=70,colors='g',linewidth=10.0)
    plt.hlines(y=30, xmin=0, xmax=10,colors='g',linewidth=10.0)
    plt.hlines(y=30, xmin=30, xmax=70,colors='g',linewidth=10.0)
    plt.hlines(y=30, xmin=90, xmax=100,colors='g',linewidth=10.0)
    plt.hlines(y=50, xmin=0, xmax=10,colors='g',linewidth=10.0)
    plt.hlines(y=50, xmin=30, xmax=70,colors='g',linewidth=10.0)
    plt.hlines(y=50, xmin=90, xmax=100,colors='g',linewidth=10.0)
    plt.hlines(y=60, xmin=40, xmax=60,colors='r',linewidth=10.0)
    ##竖线
    plt.vlines(x=10,ymin=30,ymax=50,colors='g',linewidth=10.0)
    plt.vlines(x=30,ymin=30,ymax=50,colors='g',linewidth=10.0)
    plt.vlines(x=30,ymin=0,ymax=20,colors='g',linewidth=10.0)
    plt.vlines(x=40,ymin=60,ymax=70,colors='r',linewidth=10.0)
    plt.vlines(x=60,ymin=60,ymax=70,colors='r',linewidth=10.0)
    plt.vlines(x=70,ymin=30,ymax=50,colors='g',linewidth=10.0)
    plt.vlines(x=70,ymin=0,ymax=20,colors='g',linewidth=10.0)
    plt.vlines(x=90,ymin=30,ymax=50,colors='g',linewidth=10.0)


'绘图函数'
frame=0
def Show(Now):
    global frame
    Background()
    plt.scatter(Now[Now[:,2]==0][:,0],Now[Now[:,2]==0][:,1],s=180,c='b') # 画阴性
    plt.scatter(Now[Now[:,2]==1][:,0],Now[Now[:,2]==1][:, 1],s=180,c='r')  # 画阳性
    plt.savefig('picture/picture4/{0}.jpg'.format(frame), dpi=100)
    plt.close('all')
    frame += 1
    print(frame)

'随机位置函数'
def Generate_posi(num,x_min,x_max,y_min,y_max):
    X=[np.random.randint(x_min,x_max) for _ in range(num)]
    Y=[np.random.randint(y_min,y_max) for _ in range(num)]
    X,Y=torch.tensor(X,dtype=float).unsqueeze(1),torch.tensor(Y,dtype=float).unsqueeze(1)
    loc=torch.cat((X,Y),1)
    return loc

'移动函数:(移动步,起点X,起点Y,终点X,终点Y)'

def Move(flag,step,Now,End):
    if flag==1: #食堂与其他地方间往返
        #(1)隔离人员内部震动
        Now[Now[:,3]==1,0:2]=iso()[Now[:, 3]==1]

        # (2)非隔离人员步进
        d_x = (End[:, 0] - Now[:, 0]) / step
        d_y = (End[:, 1] - Now[:, 1]) / step
        for i in range(step):
            Show(Now) #显示当前状态
            Now[Now[:,3]==0,0]+=d_x[Now[:,3]==0] # 未隔离人员x步进
            Now[Now[:,3]==0,1]+=d_y[Now[:,3]==0] # 未隔离人员y步进
            Now=States(Now) # 更新健康状态与隔离状态


    else: #宿舍与其他地方

        # (1)隔离人员内部震动
        Now[Now[:, 3]==1,0:2] = iso()[Now[:, 3]==1]

        # (2)非隔离人员步进
        d_x1 = (End[0:int(args.people/2),0]-Now[0:int(args.people/2),0]) / step  #宿舍1的人
        d_y1 = (End[0:int(args.people/2),1]-Now[0:int(args.people/2),1]) / step
        d_x2= (End[int(args.people/2):, 0] - Now[int(args.people/2):,0]) / step #宿舍2的人
        d_y2= (End[int(args.people / 2):, 1] - Now[int(args.people / 2):, 1]) / step
        for i in range(step):
            Show(Now)  # 显示当前状态
            Dom1=Now[0:int(args.people/2),:] #宿舍1的人信息
            Dom2=Now[int(args.people/2):,:] #宿舍2的人信息
            Dom1[Dom1[:,3]==0,0]+=d_x1[Dom1[:,3]==0] #宿舍1未隔离人员x步进
            Dom1[Dom1[:,3]==0,1]+=d_y1[Dom1[:,3]==0] #宿舍1未隔离人员y步进
            Dom2[Dom2[:,3]==0,0]+=d_x2[Dom2[:,3]==0] #宿舍2未隔离人员x步进
            Dom2[Dom2[:,3]==0,1]+=d_y2[Dom2[:,3]==0] #宿舍2未隔离人员y步进

            Now[0:int(args.people / 2), :]=Dom1 #整体位置更新
            Now[int(args.people / 2):, :]=Dom2

            Now = States(Now)  # 更新感染与隔离状态

    return Now #返回最新状态

'判断病例函数'
def States(Now):

    ### 新增感染更新
    index=[]
    for i in range(len(Now)):
        self_x=Now[i,0] #i的# 自身位置
        self_y=Now[i,1]
        d=torch.le(torch.sqrt((Now[:,0]-self_x)**2+(Now[:,1]-self_y)**2),args.dis) #其他人跟自己距离小于arg.dis,则为True
        s=torch.eq(Now[:,2],1) #其他人的状态,等于1则为True
        if ((any(d&s)==True) and (int(torch.randint(low=1,high=100,size=(1,1)))<=args.prob_infected)): # 如果既小于1.5又为1,则self以50%的概率被感染
            index.append(i) # i被感染,记录
    Now[index,2]=1 #感染状态更新

    ###新增进隔离
    for i in range(len(Now)):
        ## #如果感染但还未隔离,则以以args.prob_iso的概率被勒
        if ((Now[i,2]==1) and (Now[i,3]==0) and (int(torch.randint(low=1,high=100,size=(1,1)))<args.prob_iso) ):
            Now[i,3]=1

    ###新增治愈出隔离
    for i in range(len(Now)):
        #如被隔离,则以args.prob_recover概率治愈,隔离与感染均为0
        if (Now[i,3]==1) and (int(torch.randint(low=1,high=100,size=(1,1)))<args.prob_recover):
            Now[i,2],Now[i,3]=0,0
    return Now



'初始化各地位置'
def Class():
    return Generate_posi(args.people,30,70,0,20)
def Dining():
    return Generate_posi(args.people,30,70,30,50)
def Dom():
    dom1=Generate_posi(int(args.people/2),0,10,30,50)
    dom2=Generate_posi(int(args.people/2),90,100,30,50)
    Dom=torch.cat((dom1,dom2),0)
    return Dom
def iso():
    return Generate_posi(args.people,40,60,60,70)




'主函数'
inf=[]
Now=Class() #初始位置为教室
Now=torch.cat((Now,torch.zeros((args.people,2)).double()),1) #初始状态(感染及隔离)
Now[0,2]=1 #第一个人感染
for i in range(1,21):
    Now=Move('1',args.step1,Now,Dining()) #教室去食堂
    Now=Move('1',args.step1,Now,Class()) #食堂回教室
    Now=Move('2',args.step2,Now,Dom()) # 教室回宿舍
    Now=Move('2',args.step2,Now,Class()) # 宿舍回教室
    inf.append(int(torch.sum(Now[:,2]==1)))
    print(i/20)
inf1=torch.from_numpy(np.asarray(inf))
torch.save(inf1,'inf/inf4.pt')

3.2 视频生成 

import cv2
img = cv2.imread("picture/picture4/0.jpg")  # 读取彩色图像(BGR)
height, width = img.shape[:2]  # 图片的高度和宽度
img = cv2.resize(img, (int(0.4*width), int(0.4*height)))
size=(int(0.4*width), int(0.4*height))
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
videoWrite = cv2.VideoWriter('video/Video4.mp4',fourcc,10,size)# 写入对象 1 file name
# 2 编码器 3 帧率 4 size
for i in range(0,600):
    fileName = 'picture\\picture4\\'+str(i)+'.jpg'
    img = cv2.imread(fileName)
    img = cv2.resize(img, (int(0.4*width), int(0.4*height)))
    videoWrite.write(img)# 写入方法 1 jpg data
    print((i/599)*100)
print('end!')

四、仿真结果

4.1 模型1仿真结果

4.1.1 模型1仿真视频

1

4.1.2 模型1感染人数曲线图

4.2 模型2 仿真结果

4.2.1 模型2仿真视频

模型2仿真视频

4.2.2 模型2感染人数

4.3 模型3仿真结果

4.3.1 模型3仿真视频

模型3仿真视频

4.3.2 模型3感染人数

4.4 模型4仿真结果

4.4.1 模型4仿真视频

模型4仿真视频

4.4.2 模型4感染人数

 

 五、总结

通过下图仿真结果的对比可以看出:

1)躺平的结果是所有人员被快速感染

2)戴口罩、接种疫苗等措施均能起到正面作用,因此是必要的。但上述两种举措仅能延缓人员被全部感染的过程,并不能从根本上解决问题

3)虽然隔离治疗会消耗巨大的人力财力,但这种举措可以保持病例人数稳定。并且,随着隔离率及治愈率的增加,阳性人数将会逐渐减少直至为零。因此,从仿真结果来看,隔离治疗是最有效的举措。

 

 

 

 

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值