整理 | 夕颜

代码解析部分来源于 | xuyuanwai(ID:xxuyuanwai)

近日,有一位B站up主上传了一段视频,用计算机仿真程序模拟了冠状病毒传播的场景,并提醒大众不要出门活动。这个视频一经推出就得到大家的关注,让人们感受到计算机程序在这场抗疫战争中可以做出的贡献。

不久后,这条视频的up主Ele实验室又放出了本程序的GitHub开源链接,公布了这个程序的相关代码。目前,这个名为VirusBroadcast的项目已获得1000多star,作者也在简介中强调了这个基于java的模拟仿真程序由于启动仓促,还有一些不足,如果有好的想法或者能提供相关数据支持的朋友可以请提issues。

B站地址:https://www.bilibili.com/video/av86478875

GitHub地址:https://github.com/KikiLetGo/VirusBroadcast

此后,有人解析了VirusBroadcast的程序代码,下面我们就来看看它是如何一步步实现的吧:

这个程序主要利用“高斯分布”算法,简单的模拟病毒传播的场景。

它由以下程序片段构成

1、病毒对象

public class Virus {}

2、床位【隔离对象】

public class Bed extends Point{    public Bed(int x, int y) {        super(x, y);    }    private boolean isEmpty=true;public boolean isEmpty() {        return isEmpty;    }    public void setEmpty(boolean empty) {        isEmpty = empty;    }}

3、主要参数【初始状态】,假设没有隔离,潜伏期为一天

public class Constants {    public static int ORIGINAL_COUNT=50;//初始感染数量    public static float BROAD_RATE = 0.8f;//传播率    public static float SHADOW_TIME = 1;//潜伏时间    public static int HOSPITAL_RECEIVE_TIME=10;//医院收治响应时间    public static int BED_COUNT=0;//医院床位    public static float u=0.99f;//流动意向平均值}

4、医院对象,随机分布,产生床位

public class Hospital {    private int x=800;    private int y=110;private int width;    private int height=606;    public int getWidth() {        return width;    }    public int getHeight() {        return height;    }public int getX() {        return x;    }public int getY() {        return y;    }private static Hospital hospital = new Hospital();    public static Hospital getInstance(){        return hospital;    }    private Point point = new Point(800,100);    private List<Bed> beds = new ArrayList<>();private Hospital() {        if(Constants.BED_COUNT==0){            width=0;            height=0;        }        int column = Constants.BED_COUNT/100;        width = column*6;        for(int i=0;i<column;i++){            for(int j=10;j<=610;j+=6){                Bed bed = new Bed(point.getX()+i*6,point.getY()+j);                beds.add(bed);            }        }    }public Bed pickBed(){        for(Bed bed:beds){            if(bed.isEmpty()){                return bed;            }        }        return null;    }}

5、流动目的地

public class MoveTarget {    private int x;    private int y;    private boolean arrived=false;public MoveTarget(int x, int y) {        this.x = x;        this.y = y;    }public int getX() {        return x;    }public void setX(int x) {        this.x = x;    }public int getY() {        return y;    }public void setY(int y) {        this.y = y;    }public boolean isArrived() {        return arrived;    }public void setArrived(boolean arrived) {        this.arrived = arrived;    }}

6、人员【流动及感染】

public class Person {    private City city;    private int x;    private int y;    private MoveTarget moveTarget;    int sig=1;    double targetXU;    double targetYU;    double targetSig=50;    public interface State{        int NORMAL = 0;        int SUSPECTED = NORMAL+1;        int SHADOW = SUSPECTED+1;        int CONFIRMED = SHADOW+1;        int FREEZE = CONFIRMED+1;        int CURED = FREEZE+1;    }public Person(City city, int x, int y) {        this.city = city;        this.x = x;        this.y = y;        targetXU = 100*new Random().nextGaussian()+x;        targetYU = 100*new Random().nextGaussian()+y;}    public boolean wantMove(){        double value = sig*new Random().nextGaussian()+Constants.u;        return value>0;    }private int state=State.NORMAL;public int getState() {        return state;    }public void setState(int state) {        this.state = state;    }public int getX() {        return x;    }public void setX(int x) {        this.x = x;    }public int getY() {        return y;    }public void setY(int y) {        this.y = y;    }    int infectedTime=0;    int confirmedTime=0;    public boolean isInfected(){        return state>=State.SHADOW;    }    public void beInfected(){        state = State.SHADOW;        infectedTime=MyPanel.worldTime;    }public double distance(Person person){        return Math.sqrt(Math.pow(x-person.getX(),2)+Math.pow(y-person.getY(),2));    }private void freezy(){        state = State.FREEZE;    }    private void moveTo(int x,int y){        this.x+=x;        this.y+=y;    }    private void action(){        if(state==State.FREEZE){            return;        }        if(!wantMove()){            return;        }        if(moveTarget==null||moveTarget.isArrived()){double targetX = targetSig*new Random().nextGaussian()+targetXU;            double targetY = targetSig*new Random().nextGaussian()+targetYU;            moveTarget = new MoveTarget((int)targetX,(int)targetY);}int dX = moveTarget.getX()-x;        int dY = moveTarget.getY()-y;        double length=Math.sqrt(Math.pow(dX,2)+Math.pow(dY,2));if(length<1){            moveTarget.setArrived(true);            return;        }        int udX = (int) (dX/length);        if(udX==0&&dX!=0){            if(dX>0){                udX=1;            }else{                udX=-1;            }        }        int udY = (int) (dY/length);        if(udY==0&&udY!=0){            if(dY>0){                udY=1;            }else{                udY=-1;            }        }if(x>700){            moveTarget=null;            if(udX>0){                udX=-udX;            }        }        moveTo(udX,udY);}private float SAFE_DIST = 2f;public void update(){        if(state>=State.FREEZE){            return;        }        if(state==State.CONFIRMED&&MyPanel.worldTime-confirmedTime>=Constants.HOSPITAL_RECEIVE_TIME){            Bed bed = Hospital.getInstance().pickBed();            if(bed==null){                System.out.println("隔离区没有空床位");            }else{                state=State.FREEZE;                x=bed.getX();                y=bed.getY();                bed.setEmpty(false);            }        }        if(MyPanel.worldTime-infectedTime>Constants.SHADOW_TIME&&state==State.SHADOW){            state=State.CONFIRMED;            confirmedTime = MyPanel.worldTime;        }action();List<Person> people = PersonPool.getInstance().personList;        if(state>=State.SHADOW){            return;        }       for(Person person:people){           if(person.getState()== State.NORMAL){               continue;           }           float random = new Random().nextFloat();           if(random<Constants.BROAD_RATE&&distance(person)<SAFE_DIST){               this.beInfected();           }       }    }}

7、汇总人数

public class PersonPool {    private static PersonPool personPool = new PersonPool();    public static PersonPool getInstance(){        return personPool;    }List<Person> personList = new ArrayList<Person>();public List<Person> getPersonList() {        return personList;    }private PersonPool() {        City city = new City(400,400);        for (int i = 0; i < 5000; i++) {            Random random = new Random();            int x = (int) (100 * random.nextGaussian() + city.getCenterX());            int y = (int) (100 * random.nextGaussian() + city.getCenterY());            if(x>700){                x=700;            }            Person person = new Person(city,x,y);            personList.add(person);        }    }}

8、分布点

public class Point {    private int x;    private int y;public Point(int x, int y) {        this.x = x;        this.y = y;    }public int getX() {        return x;    }public void setX(int x) {        this.x = x;    }public int getY() {        return y;    }public void setY(int y) {        this.y = y;    }}

9、显示面板,设置色块【红色:感染   黄色:潜伏  绿色:安全】

public class MyPanel extends JPanel implements Runnable {   private int pIndex=0;    public MyPanel() {        this.setBackground(new Color(0x444444));    }@Override    public void paint(Graphics arg0) {        super.paint(arg0);        //draw border        arg0.setColor(new Color(0x00ff00));        arg0.drawRect(Hospital.getInstance().getX(),Hospital.getInstance().getY(),                Hospital.getInstance().getWidth(),Hospital.getInstance().getHeight());        List<Person> people = PersonPool.getInstance().getPersonList();        if(people==null){            return;        }        people.get(pIndex).update();        for(Person person:people){switch (person.getState()){                case Person.State.NORMAL:{                    arg0.setColor(new Color(0xdddddd));}break;                case Person.State.SHADOW:{                    arg0.setColor(new Color(0xffee00));}break;                case Person.State.CONFIRMED:                case Person.State.FREEZE:{                    arg0.setColor(new Color(0xff0000));}break;            }            person.update();            arg0.fillOval(person.getX(), person.getY(), 3, 3);}        pIndex++;        if(pIndex>=people.size()){            pIndex=0;        }    }public static int worldTime=0;    @Override    public void run() {        while (true) {this.repaint();try {                Thread.sleep(100);                worldTime++;            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

10、主程序【运行】

public class Main {    public static void main(String[] args) {        MyPanel p = new MyPanel();        Thread panelThread = new Thread(p);        JFrame frame = new JFrame();        frame.add(p);        frame.setSize(1000, 800);        frame.setLocationRelativeTo(null);        frame.setVisible(true);        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        panelThread.start();List<Person> people = PersonPool.getInstance().getPersonList();        for(int i=0;i<Constants.ORIGINAL_COUNT;i++){            int index = new Random().nextInt(people.size()-1);            Person person = people.get(index);while (person.isInfected()){                index = new Random().nextInt(people.size()-1);                person = people.get(index);            }            person.beInfected();        }    }}

首先,假设某个城市初始感染人数为50,医院床位为0【人员可随意流动】,那么城市很快会被感染,感染分布如下:

此时修改流动参数,控制人员流动,则疫情传播较慢,但也会传播开来

如果此时建立隔离区,将医院的床位数设为200张,并不随意走动则疫情很快得到有效控制

如果此时建立隔离区,将医院的床位数设为200张,但随意走动则隔离床位会很快被用完,病毒又开始扩散

此时,我们隔离区变得足够大,医务人员增加床位数到1000,则病毒也会得到有效控制

这位解析者还提醒大家,不随意走动是建立隔离区是在短时间内有效控制病毒的最好方式,现在病毒防疫进入关键时期,此时此刻我们一定要听从党中央的安排,好好呆在家里,不要随意跟人接触,早日打赢病毒阻击战,让我们的生活步入正轨。

推荐阅读 

☞百度地图可查49城患者活动轨迹;谷歌申请新操作系统商标;VS Code 1.42发布 | 极客头条

☞天才?骗子?解析Deep Tech

☞AAAI 2020论文解读:商汤科技发布新视频语义分割和光流联合学习算法

☞远程办公众生相:“云”吃饭、被窝打卡、梳妆台编程......

☞2020 年,云游戏将爆发?各大科技公司云游戏布局大曝光!

☞SIM卡交换攻击盗币猖獗,比特币从业者如何自保?

你点的每一个在看,我认真当成了喜欢

火出B站的冠状病毒传播模拟仿真程序代码解析来啦!相关推荐

  1. 《摩尔庄园》公测突破200万,因何火出圈外?

    6月1日欢度儿童节的同时,一个陪伴无数90和00后童年的游戏,<摩尔庄园>悄悄公测了,IOS首日预下载已突破200万,达成AppStore下载总榜第一,微博话题阅读 1.2 亿,讨论 3. ...

  2. 网文广告火出圈,“歪嘴战神”能拯救网文界的颓势吗?

    短视频网文广告出现,为网文行业打开另一扇天窗. 谈到最近火出圈的广告,那非"歪嘴战神"莫属,它在抖音.微博.B站中热度一路上蹿,就连广告中的主角管云鹏,也从虎扑一路火到B站. 这个 ...

  3. 新型冠状病毒传播规律离散微观模型(结果与实际情况一致)-附源码

    新型冠状病毒传播规律离散微观模型 0 前言 1.模型 1.1 个体病毒感染概率计算模型 1.2 个体移动模型 1.3 求解过程 2 实例分析 2.1 正常活动传播模拟 2.2 隔离模拟 2.3 频繁活 ...

  4. 笑不活了!院士带领课题组硕博“整活”,科研版「苦行僧」火出圈!

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文募格学术整理.参考资料:中国科学报.澎湃新闻.王晓东课题组视频等 ...

  5. 清华教授穿红色短裤火“出圈”,网友:哈哈哈哈太真实了

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文来源:北京日报综合 8月11日,清华大学教授彭凯平发微博称,因与 ...

  6. 数据可视化demo_火出圈的大屏你真的会做吗?这才是老板最爱的可视化大屏

    人们一提到数据可视化这个词,很多人大脑会直接闪过两个字,那就是"火"出圈的大屏. 数据大屏,对内是企业运维透明化的看板.业务决策的驾驶舱,对外是展现运营形象的窗口.它 可是,你真的 ...

  7. 2019网络直播稳中有变:直播带货火出圈 5G带来弯道超车新机会

    TechWeb原创 作者|周小白 全文3618字,预计阅读时间9分钟 3月,熊猫直播彻底关闭:7月,斗鱼终于上市:8月,KK直播和触手直播达成合作.2019年,网络直播行业格局稳中有变. 具体来看,行 ...

  8. 塔望3W消费战略全案丨火出天际的预制菜,能否拯救开饭焦虑?

    2022年6月塔望咨询开设塔望食品大健康消费研究院(简称塔望食研院)栏目,塔望食研院以"为食品行业品牌高质量发展赋能"为理念,将不定期发布食品大健康行业研究.消费研究报告.塔望食研 ...

  9. 我用加强版RFM模型,轻松扒出B站优质up主!(含数据+实战代码)

    点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 红军不怕远征难,万水千山只等闲. ...

最新文章

  1. 网页中如何显示版权符号
  2. Vue入门教程:node安装vue命令行工具及启动项目
  3. centos7 redis5.0以前版本 集群部署示例 - 第一篇
  4. 时时流量查看工具-ifsta,nload,iftop
  5. 十一、加权线性回归案例:预测鲍鱼的年龄
  6. Windows下部署elasticsearch和kibana
  7. 一道求因子之和面试算法题
  8. 博图v14编程c语言教程_10个步骤完成PLC从编程到下载,超详细的TIA博途V13软件使用教程...
  9. 我的博客生涯开始……
  10. 基于微型计算机系统的报警器设计,防盗报警器的设计毕业设计分析.doc
  11. mysql 官网 update_UPDATE
  12. tampermonkey(油猴)——去除烦人的百度搜索广告
  13. vue + vuex 实现评论和回复
  14. 将小写金额转换成中文大写
  15. python中breakpoint什么意思_breakpoint() Python 内置函数
  16. oracle tlv,OSPF GR(Graceful Restart,平滑重启)技术
  17. 破解excel格式保护
  18. leetcode 1103分糖果II
  19. 企业选择外贸B2B平台需要考虑哪些因素
  20. 什么是ftp,什么是ftp?以及具体使用教程

热门文章

  1. java 2和java有什么区别
  2. (爱加密系列教程十二) 如何防止jd-gui查看代码
  3. verilog FAQ(zz)
  4. HDU 4079 Happy Telephones 简单题
  5. hello 博客园!
  6. 机器学习模型部署文章存档
  7. Ambari--服务管理
  8. 【金融】【论文研读】 CAPITAL ASSET PRICES: A THEORY OF MARKET EQUILIBRIUM UNDER CONDITIONS OF...
  9. [译]R语言——Shiny框架之构建(一):1.结构——1.独立应用程序——1.应用的格式和启动
  10. 中国临床数据分析市场趋势报告、技术动态创新及市场预测