一、仿真目的
自新冠疫情出现以来,国际社会对于疫情防控发出了不同的声音,如躺平、戴口罩、接种疫苗、隔离治疗等等。那么我们究竟应该采取什么样的防疫政策,戴口罩以及消耗大量财力物力的接种疫苗与隔离治疗是否有必要,躺平最终会让人类走向全民免疫还是全军覆没?我想通过本次并不是那么准确的仿真,在一定程度上反映出防疫政策的意义所在。(注:本次仿真做不到与真实世界防疫政策一直,只能在一定程度上反映问题)。
二、参数设置
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仿真视频
4.1.2 模型1感染人数曲线图
4.2 模型2 仿真结果
4.2.1 模型2仿真视频
4.2.2 模型2感染人数
4.3 模型3仿真结果
4.3.1 模型3仿真视频
4.3.2 模型3感染人数
4.4 模型4仿真结果
4.4.1 模型4仿真视频
4.4.2 模型4感染人数
?
?五、总结
通过下图仿真结果的对比可以看出:
(1)躺平的结果是所有人员被快速感染
(2)戴口罩、接种疫苗等措施均能起到正面作用,因此是必要的。但上述两种举措仅能延缓人员被全部感染的过程,并不能从根本上解决问题
(3)虽然隔离治疗会消耗巨大的人力财力,但这种举措可以保持病例人数稳定。并且,随着隔离率及治愈率的增加,阳性人数将会逐渐减少直至为零。因此,从仿真结果来看,隔离治疗是最有效的举措。
?
?
?
?
|