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操作ssh实现服务器日志下载的方法
Jun 03 Python
python生成圆形图片的方法
Mar 25 Python
python爬虫超时的处理的实例
Dec 19 Python
详解Python 多线程 Timer定时器/延迟执行、Event事件
Jun 27 Python
django 2.2和mysql使用的常见问题
Jul 18 Python
Django 过滤器汇总及自定义过滤器使用详解
Jul 19 Python
django 微信网页授权认证api的步骤详解
Jul 30 Python
Pycharm连接远程服务器并实现远程调试的实现
Aug 02 Python
pycharm快捷键汇总
Feb 14 Python
Python Dataframe常见索引方式详解
May 27 Python
python中if嵌套命令实例讲解
Feb 25 Python
Python还能这么玩之只用30行代码从excel提取个人值班表
Jun 05 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性能的原理介绍
2012/09/05 PHP
php通过function_exists检测函数是否存在的方法
2015/03/18 PHP
Linux操作系统安装LAMP环境
2015/06/26 PHP
ThinkPHP和UCenter接口冲突的解决方法
2016/07/25 PHP
PHP实现生成带背景的图形验证码功能
2016/10/03 PHP
来自国外的页面JavaScript文件优化
2010/12/08 Javascript
jQuery 拖动层(在可视区域范围内)
2012/05/24 Javascript
原生js写的放大镜效果
2012/08/22 Javascript
jQuery插件开发基础简单介绍
2013/01/07 Javascript
使用js在页面中绘制表格核心代码
2013/09/16 Javascript
js和jquery设置disabled属性为true使按钮失效
2014/08/07 Javascript
JavaScript中的数组特性介绍
2014/12/30 Javascript
jquery使用slideDown实现模块缓慢拉出效果的方法
2015/03/27 Javascript
jQuery仅用3行代码实现的显示与隐藏功能完整实例
2015/10/08 Javascript
javascript数据结构之双链表插入排序实例详解
2015/11/25 Javascript
jquery实现文本框textarea自适应高度
2016/03/09 Javascript
js实现select二级联动下拉菜单
2020/04/17 Javascript
浅谈javascript中的数据类型转换
2016/12/27 Javascript
手把手搭建安装基于windows的Vue.js运行环境
2017/06/12 Javascript
详谈Object.defineProperty 及实现数据双向绑定
2020/07/18 Javascript
[04:45]上海特级锦标赛主赛事第三日TOP10
2016/03/05 DOTA
详解Django中的权限和组以及消息
2015/07/23 Python
Python聚类算法之DBSACN实例分析
2015/11/20 Python
Python装饰器用法示例小结
2018/02/11 Python
Python2.7.10以上pip更新及其他包的安装教程
2018/06/12 Python
python中多层嵌套列表的拆分方法
2018/07/02 Python
Python 中Django验证码功能的实现代码
2019/06/20 Python
Python变量作用域LEGB用法解析
2020/02/04 Python
高山背包:High Sierra
2017/11/23 全球购物
请说出你所知道的线程同步的方法
2013/04/19 面试题
ShellScript面试题一则-ShellScript编程
2014/03/05 面试题
体育教师自荐信范文
2013/12/16 职场文书
党风廉政承诺书
2014/03/27 职场文书
2014年学校德育工作总结
2014/12/05 职场文书
宾馆安全管理制度
2015/08/06 职场文书
搭建Yolov5服务器
2022/04/30 Servers