2021年第十届数学建模国际赛小美赛B题疾病传播的风险解题全过程文档及程序

2021年第十届数学建模国际赛小美赛

B题 疾病传播的风险

原题再现:

  空气传播疾病可以通过咳嗽或打喷嚏、喷洒液体或灰尘传播。另一方面,一些常见的传染病只能通过飞沫传播。请建立一个模型,以评估密闭空间内空气传播和液滴传播疾病的可能性。要考虑的因素至少包括空间大小、空间通风和合用时间。这里希望更准确地考虑人员分布和气流条件。请给出一般结果并详细说明一些具体示例,如飞机舱室和室内体育场。结果需要包括公式或算法、每个参数的含义以及每个参数的测量方法。

整体求解过程概述(摘要)

  空气传播和液滴传播的疾病更容易在密闭空间传播。对于感染风险的概率估计,在经典的Wells-Riley模型的基础上,考虑了更多的因素,建立了一个模型。
  在影响感染风险发生概率的诸多因素中,空间的大小决定了传染病的气传病原体浓度。此外,空间的通风主要包括两个方面:通风量和气流模式。气流模式通过影响病原体的空间分布来影响受限空间中人群暴露的风险。根据这些因素的影响特点,通过对初始Wells-Riley方程参数的修正,建立了一个更具针对性的受限空间空气传播和液滴传播概率评估模型。
  考虑到人口分布和气流条件对传染病传播风险的影响,采用元胞自动机模拟传染病在这两个附加因素影响下的传播。从人口流动和人口区域分布两个方面考虑人口分布。通过引入共定位时间内人员的总距离和最大位移等参数,构造了一个测量人员迁移量的方程。在元胞自动机中模拟人的均匀分布和随机分布等几种常见分布规律,寻找分布规律的相关系数。
  对于特定场景的仿真,我们将先前改进的模型与借助python代码实现的元胞自动机相结合,具体分析飞机座舱和室内体育馆的传播概率。通过调整改进的Wells-Riley方程中的参数和元胞自动机中的元胞状态,实现了以下设置。在飞机座舱场景中,人和通风模式被分为三个座舱;在室内体育场内,设置人员分布为规则正态分布,设置两种不同的通风方式,比较上述情况下的传播概率。
  最后,我们得出结论:对于受限环境中的现实人群,建议采取适度的人口控制和社会距离限制措施,以降低不同地区人群流动造成的传播风险;对于受限建筑的通风方式,建议采用分区通风和由内而外的通风方式,以降低病原体的传播率和传染病的传播风险。

模型假设:

  为了简化这个问题,我们做了以下基本假设,每个假设都是正确的。

  ➢假设1:当研究某一时刻的感染风险概率时,室内空气混合良好且处于稳定状态。
  理由:传统Wells-Riley模型的一些参数(如量子产率)依赖于反向计算,忽略了场地几何结构、传染源位置和气流模式对传染源空间分布的影响,这可能导致低估靠近传染源的易感人群的感染风险。在处理不同环境和案例的特殊性时,使用混合假设通常比在建模中假设特定环境和场景更合理。

  ➢假设2:不同病原体在传播过程中的空气动力学特性和暴露水平相同,在模拟传播概率时,不同病原体的致病性、存活率和大小等生理特性相同。
  理由:空气紊流使感染性病原体颗粒在空气中的分布和运动具有随机性,并影响病原体在人体呼吸道的沉积速率,直接影响人体对病原体的摄入剂量和对传染病的易感性。

  ➢假设3:空气中离散传染性颗粒物的随机分布符合泊松概率分布,而忽略通过泄漏、过滤等从受限空间移除的颗粒物数量。
  理由:根据泊松分布的统计特性,在建立模型时,可以在指数方程的指数项中加入一个与传染有关的参数,使其无量纲化,便于研究者设置参数。

问题重述:

  问题重述

  考虑到问题陈述中确定的背景信息和限制条件,我们需要解决以下问题:

  ⚫建立一个数学模型,包括空间大小、空间通风和共定位时间等因素,以评估空气传播和液滴传播疾病在受限空间中的传播概率,同时给出参数测量值。

  ⚫在问题1所建立的模型的基础上,加入人体分布和气流条件两个因素对模型进行细化,并给出了参数的测量方法。

  ⚫将改进后的模型应用于真实场景,例如飞机座舱和室内体育场。
我们的工作

  我们的工作主要包括:

  问题1

  在经典的Wells-Riley模型的基础上,以量子值和泊松分布为核心,建立了一个考虑更多因素的受限空间气载和液滴传播概率模型。
  分析了空间尺寸对传播概率的影响。在不考虑气流、人员分布和流动性的情况下,当敏感人群暴露或吸入滴核的概率降低时,受限空间的体积越大,均匀分散在整个空间中的等效滴核浓度越低。
  分析空间通风对传播概率的影响。空间的主要通风包括两个方面:通风量和气流组织。通气量是影响感染概率的一个重要因素,已在原始方程中考虑。除通风量外,室内气流模式还影响气溶胶的空间分布,进而影响受限空间内人群的暴露风险。

  问题2

  为了准确分析人口分布对传染病传播概率的影响,可以引入元细胞自动机来模拟传染病的传播。人口分布因素可以从两个方面考虑:人口流动性和人口分布形态。人员的流动性与人员在同一地点时间内的移动或静止程度有关。受限空间内人员的流动性越好,易感人员与已易感人员之间接触的机会就越大,感染的可能性也就越大。人的分布方式大致可以分为随机分布、均匀分布等几种情况。当同一人群在受限空间内呈现不同的分布模式时,感染概率差异较大。
  可以引入人的移动性在同一地点的时间、每个人的总旅行距离、最大位移的乘积、受限空间的面积等参数,利用它们构建关系来度量人的移动性的大小。
  人的分布模式对传播概率的影响可以通过引入一个参数来表示。为了找到这个参数,使用元胞自动机进行仿真。通过调整初始状态下不同单元的分布状态来模拟该参数的值,从而模拟随机分布、均匀分布等情况下该参数的值。

  问题3

  要描述特定场景中的感染概率,需要考虑不同场景的空间结构以及人群在空间中进行的活动分析。除中间运动区外,室内运动场的观众服从正态分布。机舱内人员分布在多个频段。在前面的问题中修改的Wells-Riley模型可以与元胞自动机代码结合使用,通过改变相应的python代码并为两种场景中的每一种实现不同的空气交换气流条件,比较不同场景中感染概率随共存时间增加的变化。

模型的建立与求解整体论文缩略图

在这里插入图片描述
在这里插入图片描述

全部论文请见下方“ 只会建模 QQ名片” 点击QQ名片即可

部分程序代码:(代码和文档not free)

import numpy as np
import matplotlib.pyplot as plt
import random
import copy
lst=[]
class Modal:def __init__ (self):#参数表self.stay_time = 6 #共处的时间 tself.air_speed = 0.3 #空气的供应速度 Qself.length = 9 #三维空间的长self.width = 50 #三维空间的宽self.height = 100 #三维空间的高self.volume = self.length*self.width*self.height #空间的大小 Vself.direction = [(0,1),(1,0),(0,-1),(-1,0)] #行人移动的方向self.search = [(1,1),(1,0),(1,-1),(0,1),(0,-1),(-1,1),(-1,0),(-1,-1)] #元胞的邻居self.turn = 1#回合数目self.people_rate = 0.2 #该点有人的概率-正态分布/均匀分布self.people_move_rate = 0 #人们流动比例self.people_change_dir_rate = 0 #转向概率self.create_sick_rate = 0.01 #新增病人self.people_getsick = 0.7 #患病概率
# self.people_rate = 0.2 #人的分布(均匀)self.breath_speed = 0.48 #人均呼吸速率 pself.virus_possibility = 0.25 #每一轮感染者产生病毒的概率self.sickfromvirus = 0.7 #易感者遇到病毒被感染的概率self.virusdead = 0.5 #病毒死亡的概率
# self.people_rate = 0.2 #人的分布(均匀)self.rec_sick = 1self.rec_infect_cnt = 0self.miu1 = self.length/2 #正态分布参数self.miu2 = self.width/2 #正态分布参数self.sigma1 = (self.length/20)**2 #正态分布参数self.sigma2 = (self.width/20)**2 #正态分布参数self.rho = 0 #正态分布参数
# self.n = 500 #通风中的人数
# self.f = 0.3 #室内空气的呼气分数self.people_cnt = 0 #统计人数#初始化self.mapsize = (self.length, self.width) #空间的大小self.map = np.zeros(self.mapsize,int) #空间的初始化self.map_temp = copy.deepcopy(self.map) #当前的状态图self.map_temp_sp = copy.deepcopy(self.map) #记录特殊人员 self.map_virus = copy.deepcopy(self.map) #病毒元胞图self.time=0.001 self.people_direct = copy.deepcopy(self.map) #记录人行走的方向self.x_nscale=[2,6]self.y_nscale=[i for i in range(11,16)]+[j for j in range(31,36)]+[k for k in range(0,5)]self.x_scale = [0,1,3,4,5,7,8]self.y_scale = [i for i in range(5,11)]+[j for j in range(16,31)]+[k for k in range(36,51)]def fnormal(self,x1,y1):#这里使用的是二维正态分布函数来模拟人的正态分布#越往中间人出现的概率越大x = self.miu1y = self.miu2f1 = (1/(2*3.14*self.sigma1*self.sigma2*np.sqrt(1-self.rho*self.rho)))*np.exp(-1/(2*(1-self.rho*self.rho))*((x-self.miu1)**2/self.sigma1**2 -2*rho*(x-self.miu1)*(yself.miu2)/(self.sigma1*self.sigma2) + (y-self.miu2)**2/self.sigma2**2))x = x1y = y1f = (1/(2*3.14*self.sigma1*self.sigma2*np.sqrt(1-self.rho*self.rho)))*np.exp(-1/(2*(1-self.rho*self.rho))*((x-self.miu1)**2/self.sigma1**2 -2*rho*(x-self.miu1)*(yself.miu2)/(self.sigma1*self.sigma2) + (y-self.miu2)**2/self.sigma2**2))return f/f1def possibility(self,p):#蒙特卡洛模拟是否达到某个概率k = random.random()return k < pdef add_virus(self):#每个回合感染者都有概率传播病毒元胞p = np.random.rand()if p < self.virus_possibility:returnfor i in range (self.mapsize[0]):for j in range (self.mapsize[1]):if self.map_temp[i][j] == 2:self.map_virus[i][j] = 1returndef work_virus(self):#病毒的走动for x in range(self.mapsize[0]):for y in range(self.mapsize[1]):if self.map_virus[x][y] == 1:flag = 0
dir = random.sample([0,1,2,3],1)[0]
new_x = x + self.direction[dir][0]
new_y = y + self.direction[dir][1]
if new_x<0 or new_x>=self.mapsize[0] or new_y<0 or 
new_y>=self.mapsize[1]:continueelse:self.map_virus[x][y],self.map_virus[new_x][new_y] = 
self.map_virus[new_x][new_y],self.map_virus[x][y]#两个位置状态互换return def dead_virus(self):#病毒有概率死亡或沉底
for x in range (self.mapsize[0]):for y in range(self.mapsize[1]):if self.map_virus[x][y] == 1 and self.possibility(self.virusdead):self.map_virus[x][y] = 0def arrange(self):#整合地图从而可视化self.map = copy.deepcopy(self.map_temp)for i in range(self.mapsize[0]):for j in range(self.mapsize[1]):if self.map_virus[i][j] == 1:self.map[i][j] = 3returndef rand_make(self): #初始化人的分布x_nscale = self.x_nscaley_nscale = self.y_nscale for x in range(self.mapsize[0]):for y in range(self.mapsize[1]):if not(x in x_nscale or y in y_nscale):self.map_temp[x][y] = 1
self.people_direct[x][y] = random.randint(0,3)
self.people_cnt += 1else:self.people_direct[x][y] = -1self.map_temp[random.sample(self.x_scale,1)[0]][random.sample(self.y_scale[0:6],1)[0]] = 2self.map_temp[random.sample(self.x_scale,1)[0]][random.sample(self.y_scale[6:22],1)[0]] = 2self.map_temp[random.sample(self.x_scale,1)[0]][random.sample(self.y_scale[22:],1)[0]] = 2x1 = random.sample([i for i in range(0,8)],3)y1 = random.sample([j for j in range(11,15)],3) dict1 = dict(zip(x1,y1))for x,y in dict1.items():self.map_temp_sp[x][y]=3self.map_temp[x][y]=1else:self.map_temp[x][y]=2x2 = random.sample([i for i in range(0,8)],3)y2 = random.sample([j for j in range(31,35)],3)dict2 = dict(zip(x2,y2))for x,y in dict2.items():self.map_temp_sp[x][y]=3self.map_temp[x][y] = 1else:self.map_temp[x][y]=2self.map_temp_sp[3][1] = 4self.map_temp[3][1] = 1self.map_temp_sp[4][1] = 4self.map_temp[4][1] = 1self.map_temp_sp[5][1] = 4self.map_temp[5][1] = 1returndef infect(self,x,y): #感染
self.flag = 0infect_num = 1 #统计邻居一共有多少个人患病
# miu = 66.91
# sigma = np.sqrt(1.53)q = np.random.rand()*40+30for id in self.search:tmp_x = x+id[0]tmp_y = y+id[1]if tmp_x<0 or tmp_x>=self.mapsize[0] or tmp_y<0 or tmp_y>=self.mapsize[1]:continue if self.map_temp[tmp_x][tmp_y] == 2:infect_num += 1for id in self.search:new_x = x+id[0]new_y = y+id[1]if new_x<0 or new_x>=self.mapsize[0] or new_y<0 or new_y>=self.mapsize[1]:continuepeople_getsick = 100*(1-np.exp(-infect_num*q*self.breath_speed*self.stay_time*(1-self.volume*(1-np.exp(-
self.air_speed*self.stay_time/self.volume))/(self.air_speed*self.stay_time))/self.air_speed))if self.map_temp[new_x][new_y] == 1 and self.possibility(people_getsick):self.map_temp[new_x][new_y] = 2self.flag = 1self.rec_sick += 1returndef work_people(self,x,y):#人的走动if not self.possibility(self.people_move_rate):returndir = self.people_direct[x][y]if not self.possibility(self.people_change_dir_rate):dir += random.randint(0, 3)dir %= 4new_x = x + self.direction[dir][0]new_y = y + self.direction[dir][1]if new_x<0 or new_x>=self.mapsize[0] or new_y<0 or new_y>=self.mapsize[1]:returnif self.map_temp[new_x][new_y] != 0:returnself.people_direct[x][y],self.people_direct[new_x][new_y] = 
self.people_direct[new_x][new_y],self.people_direct[x][y]self.map_temp[x][y],self.map_temp[new_x][new_y] = 
self.map_temp[new_x][new_y],self.map_temp[x][y]#两个位置状态互换return# def work_staff(self,x, y):
# flag2 = 0
# if not self.possibility(self.people_move_rate):
# return
# dir = self.people_direct[x][y]
# r1 = [i for i in range(4)]
# r2 = [j for j in range(2)]
# random.shuffle(r1)
# random.shuffle(r2)
# for i in range(4):
# if x in self.x_nscale and y in self.y_nscale:
# dir = r1[i]
# elif x in self.x_nscale and y in self.y_scale:
# dir = r2[random.randint(0,1)]
# new_x = x + self.direction[dir][0]
# new_y = y + self.direction[dir][1]
# if self.map_temp[new_x][new_y] == 0 and new_x>=0 and new_x<self.mapsize[0] and 
new_y>=0 and new_y<self.mapsize[1] and ((new_x not in self.x_scale) and (new_y not in self.y_scale)):
# break;
# else:
# flag2 = 1
# if flag2 == 0:
# self.people_direct[x][y],self.people_direct[new_x][new_y] = 
self.people_direct[new_x][new_y],self.people_direct[x][y]
# self.map_temp[x][y],self.map_temp[new_x][new_y] = 
self.map_temp[new_x][new_y],self.map_temp[x][y]
# #两个位置状态互换
# returndef work_staff(self,x, y):#乘务员走动flag2 = 0if not self.possibility(self.people_move_rate):returndir = self.people_direct[x][y]r1 = self.x_nscaler2 = [i for i in range(11,16)]+[j for j in range(31,36)]self.x_nscale=[2,6]random.shuffle(r1)random.shuffle(r2)for i in range(6):new_x = r1[random.randint(0,len(r1)-1)]new_y = r2[i]if self.map_temp[new_x][new_y] == 0 and new_x>=0 and new_x<self.mapsize[0] and 
new_y>=0 and new_y<self.mapsize[1] and ((new_x not in self.x_scale) and (new_y not in self.y_scale)):break;else:flag2 = 1if flag2 == 0:self.people_direct[x][y],self.people_direct[new_x][new_y] = 
self.people_direct[new_x][new_y],self.people_direct[x][y]self.map_temp[x][y],self.map_temp[new_x][new_y] = 
self.map_temp[new_x][new_y],self.map_temp[x][y]self.map_temp_sp[x][y],self.map_temp_sp[new_x][new_y] = 
self.map_temp_sp[new_x][new_y],self.map_temp_sp[x][y]#两个位置状态互换returndef show(self,i=0):#可视化j = iself.arrange()plt.figure(j,figsize=(50,50))plt.imshow(self.map)ax = plt.gca()
y = [i-0.5 for i in range(0,9)]x = [j-0.5 for j in range(0,50)]plt.xticks(x)plt.yticks(y)plt.grid()returndef create_sick(self,x,y):#人在接触病毒的时候有概率被感染
# if self.possibility(self.create_sick_rate):
# self.map_temp[x][y] = 2
# self.rec_sick += 1 if (self.map_temp[x][y] == 1) and (self.map_virus[x][y] == 1):if self.possibility(self.sickfromvirus):self.map_temp[x][y] = 2self.rec_sick += 1def go(self):self.rand_make()try_num = 100while(1):self.work_virus()self.add_virus()self.dead_virus()self.show(100-try_num)#行人走动for i in range (self.mapsize[0]):for j in range (self.mapsize[1]):if not self.map_temp[i][j] == 0:self.work_people(i,j)for i in range(self.mapsize[0]):for j in range (self.mapsize[1]):if self.map_temp[i][j] == 2:self.infect(i,j)elif self.map_temp[i][j] == 1:self.create_sick(i,j)lst.append(self.rec_sick)try_num -= 1if(try_num == 0):break;
if __name__ == '__main__':modal = Modal()modal.go()
全部论文请见下方“ 只会建模 QQ名片” 点击QQ名片即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/256866.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hive-3.1.2环境安装实验

1.修改hadoop相关参数 1-修改core-site.xml [bigdata@master hive]$ vim /opt/module/hadoop/etc/hadoop/core-site.xml <!-- 配置该bigdata(superUser)允许通过代理访问的主机节点 --><property><name>hadoop.proxyuser.bigdata.hosts</name><va…

STM32F1的TIM输出比较(PWM)

目录 1. OC&#xff08;Output Compare&#xff09;输出比较 2. PWM简介 3. 输出比较通道(高级) 4. 输出比较通道(通用) 5. PWM基本结构 6. 配置介绍 6.1 输出比较模块配置 6.2 给输出比较结构体赋一个默认值 6.3 配置强制输出模式 6.4 配置CRR寄存器的预装…

【复杂gRPC之Java调用go】

1 注意点 一般上来说如果java调用java的话&#xff0c;我们可以使用springcloud来做&#xff0c;而面对这种跨语言的情况下&#xff0c;gRPC就展现出了他的优势。 代码放在这了&#xff0c;请结合前面的go服务器端一起使用 https://gitee.com/guo-zonghao/java-client-grpc /…

【Git】error:failed to push some refs to ‘git@gitee.com:name/project.git‘

错误展示 今天在版本回退的时候&#xff0c;推送到gitee显示如下错误 先执行了git pull origin master&#xff0c;然后再执行push操作&#xff0c;也没有用 解决办法 执行git push -f origin master ,-f 表示强制推送。 结果 问题解决啦&#xff01;

iOS(swiftui)——系统悬浮窗( 可在其他应用上显示,可实时更新内容)

因为ios系统对权限的限制是比较严格的,ios系统本身是不支持全局悬浮窗(可在其他app上显示)。在iphone14及之后的iPhone机型中提供了一个叫 灵动岛的功能,可以在手机上方可以添加一个悬浮窗显示内容并实时更新,但这个功能有很多局限性 如:需要iPhone14及之后的机型且系统…

Linux下c开发

编程环境 Linux 下的 C 语言程序设计与在其他环境中的 C 程序设计一样&#xff0c; 主要涉及到编辑器、编译链接器、调试器及项目管理工具。编译流程 编辑器 Linux 中最常用的编辑器有 Vi。编译连接器 编译是指源代码转化生成可执行代码的过程。在 Linux 中&#xff0c;最常用…

异常检测 | MATLAB实现基于支持向量机和孤立森林的数据异常检测(结合t-SNE降维和DBSCAN聚类)

异常检测 | MATLAB实现基于支持向量机和孤立森林的数据异常检测(结合t-SNE降维和DBSCAN聚类) 目录 异常检测 | MATLAB实现基于支持向量机和孤立森林的数据异常检测(结合t-SNE降维和DBSCAN聚类)效果一览基本介绍模型准备模型设计参考资料 效果一览 基本介绍 提取有用的特征&…

【Mac】brew提示arch -arm64 brew以及uname返回x86_64的问题

背景 使用MacBook 14 M1 Pro两年了&#xff0c;自从使用了第三方Shell工具WindTerm后&#xff0c;使用brew时会提示我使用arch -arm64 brew安装&#xff0c;一开始没太在意&#xff0c;直到今天朋友问我uname -a返回的是什么架构&#xff0c;我才惊讶的发现竟然返回的是x86_64…

vue3-vite前端快速入门教程 vue-element-admin

Vue3快速入门学习 初始化项目 # 创建项目 npm create vitelatest my-vue-app -- --template vue # 安装依赖 npm i # 运行 npm run dev 模板语法 文本插值​ 最基本的数据绑定形式是文本插值&#xff0c;它使用的是“Mustache”语法 (即双大括号)&#xff1a; <span&g…

AI助力智慧农业,基于YOLOv8全系列模型【n/s/m/l/x】开发构建不同参数量级的识别系统

智慧农业随着数字化信息化浪潮的演变有了新的定义&#xff0c;在前面的系列博文中&#xff0c;我们从一些现实世界里面的所见所想所感进行了很多对应的实践&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《自建数据集&#xff0c;基于YOLOv7开发构建农田场景下杂草…

玩转大数据10:深度学习与神经网络在大数据中的应用

目录 1. 引言&#xff1a;深度学习和神经网络在大数据中的重要性和应用场景 2. 深度学习的基本概念和架构 3. Java中的深度学习框架 3.1. Deeplearning4j框架介绍及Java编程模型 3.2. DL4J、Keras和TensorFlow的集成 4. 大数据与深度学习的结合 4.1. 大数据与深度学…

HarmonyOS4.0从零开始的开发教程09页签切换

HarmonyOS&#xff08;七&#xff09;页签切换 List组件和Grid组件的使用 Tabs组件的使用 概述 在我们常用的应用中&#xff0c;经常会有视图内容切换的场景&#xff0c;来展示更加丰富的内容。比如下面这个页面&#xff0c;点击底部的页签的选项&#xff0c;可以实现“首页…