Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 60035bb

Browse files
committed
diffusion simulator
1 parent b4b1718 commit 60035bb

File tree

2 files changed

+126
-0
lines changed

2 files changed

+126
-0
lines changed

‎taiyangxue/diffusionsimulator/app.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# 引入pygame和sys模块
2+
import pygame, sys
3+
import math
4+
from pygame.locals import *
5+
import time
6+
import people
7+
8+
WIDTH = 500
9+
HEIGHT = 500
10+
11+
RADIUS = 25
12+
POINT_RADIUS = 5
13+
14+
BLACK = (0,0,0)
15+
WHITE = (255,255,255)
16+
PINK = (255,192,203)
17+
RED = (255,0,0)
18+
19+
# 初始化pygame
20+
pygame.init()
21+
22+
# 设置窗口与窗口标题
23+
windowSurface = pygame.display.set_mode((WIDTH,HEIGHT),0,8)
24+
pygame.display.set_caption('疫情模拟')
25+
26+
# 初始化人群
27+
p = people.People(600, 1)
28+
29+
COLORS = [BLACK, PINK, RED]
30+
31+
# 事件循环
32+
while True:
33+
for event in pygame.event.get():
34+
if event.type == QUIT:
35+
pygame.quit()
36+
sys.exit()
37+
38+
windowSurface.fill(WHITE) # 设置画布背景 起到擦除的作用
39+
40+
for i in range(len(p._status)): # 健康
41+
x_point = p._people[i][0]
42+
y_point = p._people[i][1]
43+
pygame.draw.circle(windowSurface,COLORS[p._status[i]],(int(x_point), int(y_point)), POINT_RADIUS)
44+
45+
# 绘制窗口到屏幕上
46+
pygame.display.update()
47+
time.sleep(0.1)
48+
p.update()

‎taiyangxue/diffusionsimulator/people.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
4+
5+
class People(object):
6+
def __init__(self, count=1000, first_infected_count=3):
7+
self.count = count
8+
self.first_infected_count = first_infected_count
9+
self.init()
10+
11+
def init(self):
12+
self._people = np.random.normal(250, 100, (self.count, 2)) # 产生中值为1,幅度为正负100的,count组样本,每个样本有两个值 作为位置
13+
self.reset()
14+
15+
def reset(self):
16+
self._round = 0 # 表示哪一次循环
17+
self._status = np.array([0] * self.count)
18+
self._timer = np.array([0] * self.count)
19+
self.random_people_state(self.first_infected_count, 1)
20+
21+
def random_people_state(self, num, state=1):
22+
"""随机挑选人设置状态
23+
"""
24+
assert self.count > num
25+
# TODO:极端情况下会出现无限循环
26+
n = 0
27+
while n < num:
28+
i = np.random.randint(0, self.count)
29+
if self._status[i] == state:
30+
continue
31+
else:
32+
self.set_state(i, state)
33+
n += 1
34+
35+
def set_state(self, i, state):
36+
self._status[i] = state
37+
# 记录状态改变的时间
38+
self._timer[i] = self._round # 哪次循环中状态发生在哪次循环中
39+
40+
def move(self, width=1, x=.0):
41+
movement = np.random.normal(0, width, (self.count, 2))
42+
43+
normal = np.random.normal(0, 1, self.count)
44+
switch = np.where(normal < x, 1, 0)
45+
movement[switch == 0] = 0 # 随机产生不移动的情况
46+
self._people = self._people + movement # 位置发生变换
47+
48+
def change_state(self): # 设置成为确证
49+
dt = self._round - self._timer
50+
# 必须先更新时钟再更新状态
51+
d = np.random.randint(3, 7)
52+
# print("change_state:", (self._status == 1) & ((dt == d) | (dt > 14)))
53+
self._timer[(self._status == 1) & ((dt == d) | (dt > 14))] = self._round
54+
self._status[(self._status == 1) & ((dt == d) | (dt > 14))] += 1
55+
56+
def affect(self, safe_distance=5):
57+
"""感染最接近的健康人"""
58+
# np.vstack((self._people[self._status == 1],self._people[self._status == 2]))
59+
for inf in self._people[(self._status == 1) | (self._status == 2)]: # self.infected:
60+
dm = (self._people - inf) ** 2
61+
d = dm.sum(axis=1) ** 0.5 # 计算一个欧氏距离 (x1,y1) (x2,y2) ==> ((x1-x2)^2 + (y1-y2)^2)^(1/2)
62+
sorted_index = d.argsort()
63+
for i in sorted_index:
64+
if d[i] >= safe_distance:
65+
break # 超出范围,不用管了
66+
if self._status[i] > 0: # 已经感染的排除掉
67+
continue
68+
self._status[i] = 1
69+
# 记录状态改变的时间
70+
self._timer[i] = self._round
71+
break # 只传 1 个
72+
73+
def update(self):
74+
"""每一次迭代更新"""
75+
self.change_state()
76+
self.affect()
77+
self.move(3, 1.99)
78+
self._round += 1

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /