我叫Johannes,我目前正在尝试使用知名的pygame包在python中模拟疏散。我创建了一个代码,该代码使用了许多代理,然后在pygame窗口中模拟了这些代理的撤离过程。为了使代码更实际,我添加了for循环来检查人和墙壁的粘菌。因此,我确实需要检查这两个条件。现在,当我运行该程序时,最多可以有35个代理(nr_agents是可以调整此数字的变量),一切正常。但是,当我增加人数,例如说70或100或更多时,疏散就会滞后,突然人们开始在整个屏幕上跳跃。首先,我以为这是关于我的chromebook(每秒处理不了很多帧),但是现在我有了更强大的笔记本电脑,并且代码仍然滞后。我本人认为这与程序进行的计算数量增加有关(由于人员交互循环,我的代码为O(n ^ 2))。但这将是非常可悲的,因为我真的需要在人与人之间以及墙与人之间的交互功能中使用for循环,以使我的代码更真实。
我试图增加每秒的帧数以使代码更好地运行,并且我试图将尽可能多的不必要的计算排除在for循环之外。除此之外,我还购买了一台新的笔记本电脑,该笔记本电脑具有更强大的处理器和更多的RAM,能够处理更多的FPS。另外,我尝试使用探查器来查找我的代码在哪里花费了很多时间(但是我仍然继续到达检查冲突的for循环)。
我的问题是:无论如何,我可以使这段代码更有效,以便ut能够处理更多的代理吗?
提示或解决方案将不胜感激。我真的没有选择。
该代码由2部分组成。主要部分如下图所示:
# Programming evacuation systems using Crowd Simulation
# Agent-Based Modelling
# Loading the pygame package
import pygame
# Importing locals
from pygame.locals import *
# Other packages
import sys
import numpy as np
import numpy.random as random
import math
import time
from additional_functions import *
# Initializing Pygame and font
pygame.init()
pygame.font.init()
timefont = pygame.font.SysFont('Comic Sans MS', 30)
"""
Creating a screen with a room that is smaller than then screen
"""
# Size of the screen
width = 800
height = 800
size = width, height # Do not adjust this
# Creating screen
roomscreen = pygame.display.set_mode(size)
# Making background white and creating colors
WHITE = (255,255,255)
RED = (255,0,0)
GREEN = (0,255,0)
BLACK = (0,0,0)
background_color = WHITE
roomscreen.fill(background_color)
pygame.display.update()
# Defining clock
clock = pygame.time.Clock()
# Creating evacuation object class
class Agent(object):
def __init__(self):
self.mass = 80 # random.uniform(40,90)
self.radius = 12
# random initialize a agent
self.x = random.uniform(100 + self.radius, 600 - self.radius)
self.y = random.uniform(100 + self.radius,700 - self.radius)
self.pos = np.array([self.x, self.y])
#self.pos = np.array([10.0, 10.0])
self.aVelocityX = 0 #random.uniform(0,1.6)
self.aVelocityY = 0 #random.uniform(0,1.6)
self.aVelocity = np.array([self.aVelocityX, self.aVelocityY])
#self.actualV = np.array([0.0, 0.0])
self.dest = np.array([700,400])
self.direction = normalize(self.dest - self.pos)
#self.direction = np.array([0.0, 0.0])
self.dSpeed = 12
self.dVelocity = self.dSpeed*self.direction
self.acclTime = 0.5 #random.uniform(8,16) #10.0
self.drivenAcc = (self.dVelocity - self.aVelocity)/self.acclTime
self.bodyFactor = 120000
self.F = 1
self.delta = 0.8 #random.uniform(0.8,1.6) #0.8 #0.08
self.Goal = 0
self.time = 0.0
print('X and Y Position:', self.pos)
print('self.direction:', self.direction)
def velocity_force(self): # function to adapt velocity
deltaV = self.dVelocity - self.aVelocity
if np.allclose(deltaV, np.zeros(2)):
deltaV = np.zeros(2)
return deltaV*self.mass/self.acclTime
def f_ij(self, other): # interaction with people
r_ij = self.radius + other.radius
d_ij = np.linalg.norm(self.pos - other.pos)
e_ij = (self.pos - other.pos)/d_ij
value = self.F*np.exp((r_ij-d_ij)/(self.delta))*e_ij
+ self.bodyFactor*g(r_ij-d_ij)*e_ij
return value
def f_ik_wall(self, wall): # interaction with the wall in the room
r_i = self.radius
d_iw,e_iw = distance_agent_to_wall(self.pos,wall)
value = -self.F*np.exp((r_i-d_iw)/self.delta)*e_iw # Assume wall and people give same force
+ self.bodyFactor*g(r_i-d_iw)*e_iw
return value
def update_dest(self):
self.dest = np.array([700,400])
# Now to let multiple objects move to the door we define
nr_agents = 35
agent_color = GREEN
line_color = BLACK
# Making room
room_height = 600 # height of the room
room_width = 600 # width of the room
room_left = 100 # left pixels coordinate
room_top = 100 # top pixels coordeinate
"""
Now we need to create the doors through which objects will leave in case of evacuation
This door's position can be determined using:
"""
# Door 1
door_ytop = 385
door_ybottom = 415
# This gives the following walls
walls = [[room_left, room_top, room_left + room_width, room_top],
[room_left, room_top, room_left, room_top+room_height],
[room_left, room_top+room_height, room_left + room_width, room_top+ room_height],
[room_left + room_width, room_top, room_left + room_width, door_ytop],
[room_left+room_width, room_top + room_height, room_left + room_width, door_ybottom]]
# initialize agents
agents = []
time_matrix = np.zeros((nr_agents, 1))
for n in range(nr_agents):
agent = Agent()
agents.append(agent)
run = True
count = 0
start_time = time.time()
while run:
# Updating time
if count < nr_agents:
current_time = time.time()
elapsed_time = current_time - start_time
# Finding delta t for this frame
dt = clock.tick(70)/1000
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.MOUSEBUTTONDOWN:
(x, y) = pygame.mouse.get_pos()
print(x, y)
roomscreen.fill(background_color)
# draw walls
for wall in walls:
start_posw = np.array([wall[0],wall[1]])
end_posw = np.array([wall[2],wall[3]])
start_posx = start_posw
end_posx = end_posw
pygame.draw.line(roomscreen, line_color, start_posx, end_posx, 3)
for agent_i in agents:
agent_i.update_dest()
agent_i.direction = normalize(agent_i.dest - agent_i.pos)
agent_i.dVelocity = agent_i.dSpeed*agent_i.direction
aVelocity_force = agent_i.velocity_force()
people_interaction = 0.0
wall_interaction = 0.0
for agent_j in agents:
if agent_i == agent_j: continue
people_interaction += agent_i.f_ij(agent_j)
for wall in walls:
wall_interaction += agent_i.f_ik_wall(wall)
sumForce = aVelocity_force + people_interaction + wall_interaction
dv_dt = sumForce/agent_i.mass
agent_i.aVelocity = agent_i.aVelocity + dv_dt*dt
agent_i.pos = agent_i.pos + agent_i.aVelocity*dt
for agent_i in agents:
agent_i.time += clock.get_time()/1000
start_position = [0, 0]
start_position[0] = int(agent_i.pos[0])
start_position[1] = int(agent_i.pos[1])
end_position = [0, 0]
end_position[0] = int(agent_i.pos[0] + agent_i.aVelocity[0])
end_position[1] = int(agent_i.pos[1] + agent_i.aVelocity[1])
end_positionDV = [0, 0]
end_positionDV[0] = int(agent_i.pos[0] + agent_i.dVelocity[0])
end_positionDV[1] = int(agent_i.pos[1] + agent_i.dVelocity[1])
if start_position[0] >= 700 or start_position[0] <= 100 and agent_i.Goal == 0:
agent_i.Goal = 1
time_matrix[count] = agent_i.time
# print('Time to Reach the Goal:', agent_i.time)
if start_position[0] > 700 or start_position[0] < 100:
count += 1
agents.remove(agent_i)
pygame.draw.circle(roomscreen, agent_color, start_position, 12, 3)
pygame.draw.line(roomscreen, agent_color, start_position, end_positionDV, 2)
pygame.draw.line(roomscreen, [255,60,0], start_position, end_positionDV, 2)
# Present text on screen
timestr = "Time: " + str(elapsed_time)
timesurface = timefont.render(timestr, False, (0, 0, 0))
roomscreen.blit(timesurface,(0,0))
# Update the screen
pygame.display.flip()
pygame.quit()
第二部分是我从中导入一些特殊功能的部分。这称为附加功能。但是这些功能很小,在计算上不会花费很多时间。如果您还需要其他任何信息或我的帖子有什么问题,请随时告诉我。
我希望我们能到达某个地方。
请问您有另一部分的代码吗?
谢谢!