Python实现病毒仿真器的方法示例(附demo)


Posted in Python onFebruary 19, 2020

最近新冠在神州大陆横行,全国上下一心抗击疫情。作为一枚程序员,我也希望可以为抗击疫情做出自己的贡献,钟院士一直劝说大家不要出门,减少人口间的流动。对此,我特意做了一个病毒仿真器,探询冠状病毒传播。

1. 仿真效果

仿真开始,一开始只有5个发病者,传播率为0.8,潜伏期为14天

Python实现病毒仿真器的方法示例(附demo)

由于人口的流动,以及医院床位的隔离,一开始病毒扩撒不是很速度

Python实现病毒仿真器的方法示例(附demo)

随着医院床位满了,隔离失败,加上人口的流动,病患数开始几何式的增加

Python实现病毒仿真器的方法示例(附demo)

2. 什么是仿真器

仿真器(emulator)以某一系统复现另一系统的功能。与计算机模拟系统(Computer Simulation)的区别在于,仿真器致力于模仿系统的外在表现、行为,而不是模拟系统的抽象模型。

3. python如何实现仿真器

现在来谈谈仿真器实现的原理。仿真器使用Python和PyQt5实现。PyQt5是封装了Qt library的跨平台GUI开发库,基于Python语言。

这里主要涉及到仿真器效果绘制,以及如何模拟多个参数。先来说一下绘制市民的状态。绘制的工作通过drawing.py文件的Drawing类来完成。该类是QWidget的子类,这也就意味着Drawing类本身是PyQt5的一个组件。与按钮、标签类似。只是并不需要往Drawing上放置任何子组件。只要在Drawing上绘制各种图形即可。

在PyQt5中,任何一个QWidget的子类,都可以实现一个paintEvent方法,当组件每次刷新时,就会调用paintEvent方法重新绘制组件的内容。Drawing类中paintEvent方法的代码如下:

# 每次Drawing刷新,都会调用该方法
  def paintEvent(self,event):
    qp = QPainter()
    qp.begin(self)
    self.drawing(qp) # 绘制城市的各种状态的市民
    qp.end()

在绘制图像前,需要创建QPainter对象,然后调用QPainter对象的begin方法,结束绘制后,需要调用QPainter对象的end方法。上面代码中的drawing方法用于完成具体的绘制工作。

仿真器设置一个人员池,来进行人员的流动性

class Persons(metaclass=Singleton):
  def __init__(self):
    self.persons = []          # 保存所有的人员
    self.latency_persons = []      # 保存处于潜伏期的人员
 
    city = City(Params.city_center_x,Params.city_center_y)
 
    for value in range(0, Params.city_person_count):
      x = Params.person_position_scale * next_gaussian() + city.center_x
      y = Params.person_position_scale * next_gaussian() + city.center_y
      if x > Params.city_width:
        x = Params.city_width
      if y > Params.city_height:
        y = Params.city_height
      self.persons.append(Person(city,x,y))
  # 获取特定人群的数量
  def get_person_size(self,state):
    if state == -1:
      return len(self.persons)
    count = 0
    for person in self.persons:
      if person.state == state:
        count += 1
    return count

仿真代码

from PyQt5.QtWidgets import *
from socket import *
 
class Transmission:
  def __init__(self,ui):
    self.ui = ui
    self.host = 'localhost'
    self.port = 5678
    self.addr = (self.host,self.port)
 
  def send_command(self,command,value=None):
    tcp_client_socket = socket(AF_INET,SOCK_STREAM)
    tcp_client_socket.connect(self.addr)
 
    if value == None:
      value = 0
 
    data = command + ':' + str(value)
    tcp_client_socket.send(('%s\r\n' % data).encode(encoding='utf-8'))
    data = tcp_client_socket.recv(1024)
    result = data.decode('utf-8').strip()
    tcp_client_socket.close()
    return result
  def setup(self):
    self.ui.horizontalSliderBedCount.valueChanged.connect(self.bed_count_value_change)
    self.ui.pushButtonUpdateBedCount.clicked.connect(self.update_bed_count)
 
    self.ui.horizontalSliderFlowIntention.valueChanged.connect(self.flow_intention_value_change)
    self.ui.pushButtonFlowIntention.clicked.connect(self.update_flow_intention)
 
    self.ui.horizontalSliderBroadRate.valueChanged.connect(self.broad_rate_value_change)
    self.ui.pushButtonBroadRate.clicked.connect(self.update_broad_rate)
 
    self.ui.horizontalSliderLatency.valueChanged.connect(self.latency_value_change)
    self.ui.pushButtonLatency.clicked.connect(self.update_latency)
 
    self.ui.pushButtonClose.clicked.connect(self.close_virus_simulation)
 
  def bed_count_value_change(self):
    self.ui.labelBedIncrement.setText(
      f'<html><head/><body><p><span style=\" font-size:24pt; color:#0000ff;\">{self.ui.horizontalSliderBedCount.value()}</span></p></body></html>')
 
  def update_bed_count(self):
    print(self.ui.horizontalSliderBedCount.value())
    result = self.send_command('add_bed_count', self.ui.horizontalSliderBedCount.value())
    if result == 'ok':
      QMessageBox.information(self.ui.centralwidget, '消息', f'成功添加了{self.ui.horizontalSliderBedCount.value()}张床位',
                  QMessageBox.Ok)
 
  def flow_intention_value_change(self):
    self.ui.labelFlowIntention.setText(
      f'<html><head/><body><p><span style=\" font-size:24pt; color:#fc02ff;\">{self.ui.horizontalSliderFlowIntention.value() / 100}</span></p></body></html>')
 
  def update_flow_intention(self):
    result = self.send_command('set_flow_intention', self.ui.horizontalSliderFlowIntention.value())
    if result == 'ok':
      QMessageBox.information(self.ui.centralwidget, '消息',
                  f'成功设置流动意向为{self.ui.horizontalSliderFlowIntention.value() / 100}', QMessageBox.Ok)
 
  def broad_rate_value_change(self):
    self.ui.labelBroadRate.setText(
      f'<html><head/><body><p><span style=\" font-size:24pt; color:#fc0107;\">{self.ui.horizontalSliderBroadRate.value() / 100}</span></p></body></html>')
 
  def update_broad_rate(self):
    result = self.send_command('set_broad_rate', self.ui.horizontalSliderBroadRate.value())
    if result == 'ok':
      QMessageBox.information(self.ui.centralwidget, '消息',
                  f'成功设置传播率为{self.ui.horizontalSliderBroadRate.value() / 100}', QMessageBox.Ok)
 
  def latency_value_change(self):
    self.ui.labelLatency.setText(
      f'<html><head/><body><p><span style=\" font-size:24pt; color:#ffff0a;\">{self.ui.horizontalSliderLatency.value()}</span></p></body></html>')
 
  def update_latency(self):
    result = self.send_command('set_latency', self.ui.horizontalSliderLatency.value())
    if result == 'ok':
      QMessageBox.information(self.ui.centralwidget, '消息', f'成功设置传播率为{self.ui.horizontalSliderLatency.value()}',
                  QMessageBox.Ok)
 
  def close_virus_simulation(self):
    reply = QMessageBox.information(self.ui.centralwidget, "请问", "是否真的要关闭病毒扩散仿真器?",
                    QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
    if reply == QMessageBox.Yes:
      result = self.send_command('close')
      if result == 'ok':
        QMessageBox.information(self.ui.centralwidget, '消息', '已经成功关闭病毒扩散仿真器', QMessageBox.Ok)

设置变量

class Params:
  success = False
 
  # 初始感染人数
  original_infected_count = 50
 
  # 病毒传播率
  broad_rate = 0.8
 
  # 病毒潜伏期,14天
  virus_latency = 140
 
  # 医院收治响应时间
  hospital_receive_time = 10
 
  # 医院床位
  hospital_bed_count = 100
 
  # 安全距离
  safe_distance = 2
 
  # 平均流动意向[-3,3]  值越大,流动意向越强
  average_flow_intention = 3
 
  # 城市总人口数量
  city_person_count = 5000
 
  # 病死率
  fatality_rate = 0.02
 
  # 死亡时间
  dead_time = 30
  # 死亡时间方差
  dead_variance = 30
 
  # 城市宽度
  city_width = 1100
 
  # 城市高度
  city_height = 800
 
  # 医院宽度(需要计算获得)
  hospial_width = 0
 
  # 城市中心x坐标
  city_center_x = 550
 
  # 城市中心y坐标
  city_center_y = 400
 
  # 用于计算城市中每个人随机位置的scale(用于正态分布)
  person_position_scale = 200
 
  current_time = 1 # 当前时间

我们可以根据这些修改仿真页面

Python实现病毒仿真器的方法示例(附demo) 

以上就是Python实现病毒仿真器的方法示例的详细内容,更多关于请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python实现分割文件及合并文件的方法
Jul 10 Python
在Python的Django框架中为代码添加注释的方法
Jul 16 Python
Python随手笔记第一篇(2)之初识列表和元组
Jan 23 Python
详解python3实现的web端json通信协议
Dec 29 Python
python+matplotlib绘制3D条形图实例代码
Jan 17 Python
python中requests和https使用简单示例
Jan 18 Python
tensorflow实现加载mnist数据集
Sep 08 Python
Python使用sorted对字典的key或value排序
Nov 15 Python
利用python提取wav文件的mfcc方法
Jan 09 Python
Python函数的参数常见分类与用法实例详解
Mar 30 Python
Python3.7实现验证码登录方式代码实例
Feb 14 Python
Python3自带工具2to3.py 转换 Python2.x 代码到Python3的操作
Mar 03 Python
python内打印变量之%和f的实例
Feb 19 #Python
Python 实现日志同时输出到屏幕和文件
Feb 19 #Python
python 控制台单行刷新,多行刷新实例
Feb 19 #Python
python tqdm 实现滚动条不上下滚动代码(保持一行内滚动)
Feb 19 #Python
python 解决tqdm模块不能单行显示的问题
Feb 19 #Python
python 实现在shell窗口中编写print不向屏幕输出
Feb 19 #Python
Python换行与不换行的输出实例
Feb 19 #Python
You might like
PHP从零开始打造自己的MVC框架之入口文件实现方法详解
2019/06/03 PHP
JSON JQUERY模板实现说明
2010/07/03 Javascript
javascript取消文本选定的实现代码
2010/11/14 Javascript
js阻止默认事件与js阻止事件冒泡示例分享 js阻止冒泡事件
2014/01/27 Javascript
jquery实现倒计时代码分享
2014/06/13 Javascript
JQuery包裹DOM节点的方法
2015/06/11 Javascript
使用Node.js为其他程序编写扩展的基本方法
2015/06/23 Javascript
JS鼠标拖拽实例分析
2015/11/23 Javascript
js操作数组函数实例小结
2015/12/10 Javascript
JavaScript实现Base64编码转换
2016/04/23 Javascript
非常酷炫的Bootstrap图片轮播动画
2016/05/27 Javascript
JavaScript实现的浏览器下载文件的方法
2017/08/09 Javascript
js 开发之autocomplete=&quot;off&quot;在chrom中失效的解决办法
2017/09/28 Javascript
Vue $mount实战之实现消息弹窗组件
2019/04/22 Javascript
Angular4.0动画操作实例详解
2019/05/10 Javascript
浅谈redux, koa, express 中间件实现对比解析
2019/05/23 Javascript
怎么使用javascript深度拷贝一个数组
2019/06/06 Javascript
node 标准输入流和输出流代码实例
2019/09/19 Javascript
Angular 多级路由实现登录页面跳转(小白教程)
2019/11/19 Javascript
uni-app 支持多端第三方地图定位的方法
2020/01/03 Javascript
浅谈Vue3 Composition API如何替换Vue Mixins
2020/04/29 Javascript
python爬虫获取新浪新闻教学
2018/12/23 Python
Python使用pymongo库操作MongoDB数据库的方法实例
2019/02/22 Python
Python转换时间的图文方法
2019/07/01 Python
使用PyInstaller将Pygame库编写的小游戏程序打包为exe文件及出现问题解决方法
2019/09/06 Python
利用PyQt5+Matplotlib 绘制静态/动态图的实现代码
2020/07/13 Python
你所知道的集合类都有哪些?主要方法?
2012/12/31 面试题
销售简历自我评价
2014/01/24 职场文书
护士个人总结范文
2015/02/13 职场文书
2015年银行柜员工作总结报告
2015/04/01 职场文书
学术研讨会主持词
2015/07/04 职场文书
2016大学生求职自荐信范文
2016/01/28 职场文书
FP-growth算法发现频繁项集——发现频繁项集
2021/06/24 Python
Window server中安装Redis的超详细教程
2021/11/17 Redis
全面盘点MySQL中的那些重要日志文件
2021/11/27 MySQL
CSS3实现指纹特效代码
2022/03/17 HTML / CSS