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判断、获取一张图片主色调的2个实例
Apr 10 Python
django轻松使用富文本编辑器CKEditor的方法
Mar 30 Python
python统计多维数组的行数和列数实例
Jun 23 Python
使用Python的Dataframe取两列时间值相差一年的所有行方法
Jul 10 Python
[原创]Python入门教程4. 元组基本操作
Oct 31 Python
python对csv文件追加写入列的方法
Aug 01 Python
Python 生成器,迭代,yield关键字,send()传参给yield语句操作示例
Oct 12 Python
Python Sphinx使用实例及问题解决
Jan 17 Python
Python 炫技操作之合并字典的七种方法
Apr 10 Python
python 监控服务器是否有人远程登录(详细思路+代码)
Dec 18 Python
python excel和yaml文件的读取封装
Jan 12 Python
Python OpenCV快速入门教程
Apr 17 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中的类-什么叫类
2006/11/20 PHP
一个更简单的无限级分类菜单代码
2007/01/16 PHP
php数据库的增删改查 php与javascript之间的交互
2017/08/31 PHP
JS支持带x身份证号码验证函数
2008/08/10 Javascript
jQuery 全选效果实现代码
2009/03/23 Javascript
js编码之encodeURIComponent使用介绍(asp,php)
2012/03/01 Javascript
js改变Iframe中Src的方法
2015/05/05 Javascript
jquery中添加属性和删除属性
2015/06/03 Javascript
jQuery如何获取动态添加的元素
2016/06/24 Javascript
JavaScript实现输入框与清空按钮联动效果
2016/09/09 Javascript
WEB前端实现裁剪上传图片功能
2016/10/17 Javascript
vue.js学习笔记:如何加载本地json文件
2017/01/17 Javascript
ES6数组的扩展详解
2017/04/25 Javascript
JavaScript 程序错误Cannot use 'in' operator to search的解决方法
2017/07/10 Javascript
bootstrap时间插件daterangepicker使用详解
2017/10/19 Javascript
node文字生成图片的示例代码
2017/10/26 Javascript
微信小程序收货地址API兼容低版本解决方法
2019/05/18 Javascript
详解Python中内置的NotImplemented类型的用法
2015/03/31 Python
python使用htmllib分析网页内容的方法
2015/05/08 Python
Python分析学校四六级过关情况
2017/11/22 Python
Python图像处理之图像的读取、显示与保存操作【测试可用】
2019/01/04 Python
python+pyqt5实现24点小游戏
2019/01/24 Python
Django中如何使用sass的方法步骤
2019/07/09 Python
python开发实例之python使用Websocket库开发简单聊天工具实例详解(python+Websocket+JS)
2020/03/18 Python
PyCharm 在Windows的有用快捷键详解
2020/04/07 Python
Python-opencv实现红绿两色识别操作
2020/06/04 Python
荷兰的时尚市场:To Be Dressed
2019/05/06 全球购物
如何利用XMLHTTP检测URL及探测服务器信息
2013/11/10 面试题
开办加工厂创业计划书
2014/01/03 职场文书
学雷锋演讲稿汇总
2014/05/10 职场文书
会计学毕业生求职信
2014/06/25 职场文书
学校百日安全生产活动总结
2014/07/05 职场文书
党员领导干部民主生活会批评与自我批评发言
2014/09/28 职场文书
自我检讨书范文
2015/01/28 职场文书
Python3 如何开启自带http服务
2021/05/18 Python
elasticSearch-api的具体操作步骤讲解
2021/06/28 Java/Android