火出B站的冠状病毒传播模拟仿真程序代码解析来啦!
整理 | 夕颜代码解析部分来源于 |xuyuanwai(ID:xxuyuanwai)近日,有一位B站up主上传了一段视频,用计算机仿真程序模拟了冠状病毒传播的场景,并提醒大众不要出门...
整理 | 夕颜
代码解析部分来源于 | 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发布 | 极客头条
☞AAAI 2020论文解读:商汤科技发布新视频语义分割和光流联合学习算法
☞远程办公众生相:“云”吃饭、被窝打卡、梳妆台编程......
☞2020 年,云游戏将爆发?各大科技公司云游戏布局大曝光!
你点的每一个在看,我认真当成了喜欢
更多推荐
所有评论(0)