我可以使用simpy进行基于代理的模拟吗?

4
我知道simpy是一个基于进程的离散事件仿真框架。我有几个代理可能会同时做不同的事情。我仍然可以使用simpy来模拟我的代理吗?例如,一辆汽车到达停车场。然后司机下车。走到购物中心的入口并进入。一些购物者可能会同时离开。也可能会有几辆汽车同时到达停车场。当事件触发时,该事件使用env.timeout(time)时间执行。然而,这会增加环境的模拟时钟。因此,所有代理都会受到影响吗?有没有办法模拟这种情况?你能否建议我一个模拟框架/库来模拟这种情况? 由于@Michael的答案进行编辑:我通过使用env.process启动代理(2种类型的代理)。这些过程中的While循环函数在代理创建时产生env.timeout,并使用env.process(foo(A,B,C))创建新的过程。在这些过程中,我有几个yield env.process。在它们内部,又有一些yield env.process。我在后面的函数上使用了yield,因为代理必须等待事件完成。所有代理都使用一些共享资源和存储器,或者等待一些代理到达。不同类型的代理之间也有一些关联。因此,我使用外部字典来存储有关代理、资源和存储器的所有信息。我得到了一些有趣的结果,让我想知道我是否正在使用正确的库或代码结构来实现我想要做的事情。在阅读@Michael的答案后,我相信我走上了正确的道路。我可以启动多个代理创建过程,并使它们同时工作。
1个回答

4

是的

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)

非常好的回答,迈克尔。谢谢你。我的情况比我上面解释的更复杂。所以,我想要确保一下。由于stackoverflow不允许我写超过几百个字符,我编辑了问题。 - Muh
升级了代理代码示例,使得代理可以互相调用。 - Michael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接