大量人员的疏散模拟崩溃

问题描述 投票:0回答:1

我叫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()

第二部分是我从中导入一些特殊功能的部分。这称为附加功能。但是这些功能很小,在计算上不会花费很多时间。如果您还需要其他任何信息或我的帖子有什么问题,请随时告诉我。

我希望我们能到达某个地方。

python performance for-loop simulation lag
1个回答
0
投票

请问您有另一部分的代码吗?

谢谢!

© www.soinside.com 2019 - 2024. All rights reserved.