我可以使用 simpy 进行基于代理的模拟吗?
Can I use simpy to do agent-based simulation?
我知道simpy是一个基于过程的离散事件仿真框架。我有几个可能同时做不同事情的代理。我还可以使用 simpy 来模拟我的代理吗?例如,汽车到达停车场。然后驱动程序存在。走到一个商场门口,进去了。一些购物者可能会同时离开。也可以有几辆车同时到达停车场。当事件触发时,该事件使用 env.timeout(time)
时间来执行。但是,这会增加环境的模拟时钟。因此,对于所有代理?有没有办法模拟这种情况?你能建议我一个模拟 framework/library 来模拟这样的场景吗?
根据@Michael 的回答进行编辑: 我确实使用env.process
启动代理(2 种类型的代理)。这些进程内部的 While 循环函数产生 env.timeout
用于代理创建,并且还使用 env.process(foo(A,B,C))
创建新进程。在这些过程中,我有几个 yield env.process
。在它们里面还有一些 yield env.process
。我在后面的函数中使用 yield
,因为代理必须等待事件完成。所有代理都在使用一些共享资源和存储或等待某些代理到达。不同类型的代理之间也存在一些关联。因此,我使用外部词典来存储有关代理、资源和商店的所有信息。我得到了一些有趣的结果,让我思考我是否使用了正确的库或代码结构来实现我想做的事情。阅读@Michael 的回答后,我相信我是在正确的轨道上。我可以启动多个代理创建进程,它们可以同时工作。
是
env.timeout 不提前时钟。
当代理调用 env.timeout 时,该代理会一直等到时钟到达那个时间,它不会阻止其他代理做事。当第一个代理等待 env.timeout 完成时,其他代理仍然可以做事。
请注意,每个代理都需要使用 env.process 异步启动,而不是使用 yield
这是一个不太简单的例子
"""
agents calling each other in a agent base sim
Programmer Michael R. Gibbs
"""
import simpy
import random
class Agent():
"""
Agents do a background activity, and from time to time make a call to a friend agent
Agents wait to finish doing stuff, then call back the calling friend agent
"""
def __init__(self, env, agent_id):
"""
set up agent
Need to set the friend later since that agent may not have been created yet
"""
self.env = env
self.agent_id = agent_id
self.friend = None # set this before starting sim
self.friend_called = None
# kick off background activity, and activty that makes calls from time to time
env.process(self.agent_stuff())
env.process(self.make_call())
def receive_call(self, agent):
"""
agent is busy, will call back later
"""
# save caller for later callback
self.friend_called = agent
print(f"{self.env.now} agent {self.agent_id} just got a call from agent {agent.agent_id}")
def receive_callback(self, agent):
"""
getting a call from the agent this agent called ealier
"""
print(f"{self.env.now} agent {self.agent_id} just got a callback from agent {agent.agent_id}")
def make_call(self):
"""
loop making calls from time to time
"""
while True:
yield self.env.timeout(random.randint(4,9))
self.friend.receive_call(self)
print(f"{self.env.now} agent {self.agent_id} just made a call to agent {self.friend.agent_id}")
def agent_stuff(self):
"""
agent process doing agent stuff
"""
while True:
t = random.randint(1,5)
print(f"{self.env.now} agent {self.agent_id} will do his thing in {t}")
yield env.timeout(t)
print(f"{self.env.now} agent {self.agent_id} is doing his thing")
if self.friend_called is not None:
# oh look, someone called, call them back
self.friend_called.receive_callback(self)
print(f"{self.env.now} agent {self.agent_id} just made a call to agent {self.friend.agent_id}")
self.friend_called = None
env = simpy.Environment()
# create agents, which also starts their processes
agent1 = Agent(env,1)
agent2 = Agent(env,2)
# set the friend
agent1.friend = agent2
agent2.friend = agent1
env.run(100)
我知道simpy是一个基于过程的离散事件仿真框架。我有几个可能同时做不同事情的代理。我还可以使用 simpy 来模拟我的代理吗?例如,汽车到达停车场。然后驱动程序存在。走到一个商场门口,进去了。一些购物者可能会同时离开。也可以有几辆车同时到达停车场。当事件触发时,该事件使用 env.timeout(time)
时间来执行。但是,这会增加环境的模拟时钟。因此,对于所有代理?有没有办法模拟这种情况?你能建议我一个模拟 framework/library 来模拟这样的场景吗?
根据@Michael 的回答进行编辑: 我确实使用env.process
启动代理(2 种类型的代理)。这些进程内部的 While 循环函数产生 env.timeout
用于代理创建,并且还使用 env.process(foo(A,B,C))
创建新进程。在这些过程中,我有几个 yield env.process
。在它们里面还有一些 yield env.process
。我在后面的函数中使用 yield
,因为代理必须等待事件完成。所有代理都在使用一些共享资源和存储或等待某些代理到达。不同类型的代理之间也存在一些关联。因此,我使用外部词典来存储有关代理、资源和商店的所有信息。我得到了一些有趣的结果,让我思考我是否使用了正确的库或代码结构来实现我想做的事情。阅读@Michael 的回答后,我相信我是在正确的轨道上。我可以启动多个代理创建进程,它们可以同时工作。
是
env.timeout 不提前时钟。 当代理调用 env.timeout 时,该代理会一直等到时钟到达那个时间,它不会阻止其他代理做事。当第一个代理等待 env.timeout 完成时,其他代理仍然可以做事。
请注意,每个代理都需要使用 env.process 异步启动,而不是使用 yield
这是一个不太简单的例子
"""
agents calling each other in a agent base sim
Programmer Michael R. Gibbs
"""
import simpy
import random
class Agent():
"""
Agents do a background activity, and from time to time make a call to a friend agent
Agents wait to finish doing stuff, then call back the calling friend agent
"""
def __init__(self, env, agent_id):
"""
set up agent
Need to set the friend later since that agent may not have been created yet
"""
self.env = env
self.agent_id = agent_id
self.friend = None # set this before starting sim
self.friend_called = None
# kick off background activity, and activty that makes calls from time to time
env.process(self.agent_stuff())
env.process(self.make_call())
def receive_call(self, agent):
"""
agent is busy, will call back later
"""
# save caller for later callback
self.friend_called = agent
print(f"{self.env.now} agent {self.agent_id} just got a call from agent {agent.agent_id}")
def receive_callback(self, agent):
"""
getting a call from the agent this agent called ealier
"""
print(f"{self.env.now} agent {self.agent_id} just got a callback from agent {agent.agent_id}")
def make_call(self):
"""
loop making calls from time to time
"""
while True:
yield self.env.timeout(random.randint(4,9))
self.friend.receive_call(self)
print(f"{self.env.now} agent {self.agent_id} just made a call to agent {self.friend.agent_id}")
def agent_stuff(self):
"""
agent process doing agent stuff
"""
while True:
t = random.randint(1,5)
print(f"{self.env.now} agent {self.agent_id} will do his thing in {t}")
yield env.timeout(t)
print(f"{self.env.now} agent {self.agent_id} is doing his thing")
if self.friend_called is not None:
# oh look, someone called, call them back
self.friend_called.receive_callback(self)
print(f"{self.env.now} agent {self.agent_id} just made a call to agent {self.friend.agent_id}")
self.friend_called = None
env = simpy.Environment()
# create agents, which also starts their processes
agent1 = Agent(env,1)
agent2 = Agent(env,2)
# set the friend
agent1.friend = agent2
agent2.friend = agent1
env.run(100)