0

如何从回调中编写一些模拟代码(包括等待事件)?

将我的过程简化为最简单的示例,我想在我的简单模拟中发生事件时启动一些可执行代码。我所做的是将该可执行代码设置为事件的回调。该可执行代码本身具有一些简单的事件处理,特别是超时。在我的真实代码中,这发生在一个进程中,但是这个简化版本,event在 main 中显示相同的问题行为:

import simpy
if __name__ == '__main__':
    env = simpy.Environment()

    def simulationRun(event):
        print("Starting a run at time [%i]" % env.now)
        yield env.timeout(5)
        print("Ending a run at time [%i]" % env.now)

    event = env.timeout(5)
    event.callbacks.append(simulationRun)

    print("Starting simulation.")
    env.run(20)
    print("End of simulation.")

我的预期输出是:

Starting simulation.
Starting a run at time [5]
Ending a run at time [10]
End of simulation.

但是,我的实际输出是:

Starting simulation.
End of simulation.

当我删除 yield 命令时,我得到:

Starting simulation.
Starting a run at time [5]
Ending a run at time [5]
End of simulation.

显然回调设置正确,但重点是模拟simulationRun. 如何在回调的代码中运行一些模拟代码(包括等待事件)?

这使用 Python 3.4.2 和 simpy。

4

2 回答 2

2

您不应该直接使用回调。最佳做法是使用另一个simulation_run()为您启动的过程:

import simpy


def simulation_run(env):
    print("Starting a run at time [%i]" % env.now)
    yield env.timeout(5)
    print("Ending a run at time [%i]" % env.now)


def starter(env):
    yield env.timeout(5)
    env.process(simulation_run(env))


if __name__ == '__main__':
    env = simpy.Environment()
    env.process(starter(env))
    print("Starting simulation.")
    env.run(20)
    print("End of simulation.")

由于这是一种相对常见的模式,我们在 SimPy 中内置了一个实用函数,它正是这样做的:

import simpy
import simpy.util


def simulation_run(env):
    print("Starting a run at time [%i]" % env.now)
    yield env.timeout(5)
    print("Ending a run at time [%i]" % env.now)


if __name__ == '__main__':
    env = simpy.Environment()
    simpy.util.start_delayed(env, simulation_run(env), delay=5)
    print("Starting simulation.")
    env.run(20)
    print("End of simulation.")

注意:您应该始终将对 Environment 的引用传递到您的进程中,而不是使用全局范围内的引用。这可能看起来很乏味,但如果您稍后重组或重构您的代码并且全局环境不再是您所期望的或不再可用,您可能会遇到任何类型的问题。

于 2015-03-11T09:04:18.603 回答
1

问题是回调不是一个进程,因此它没有在 simpy 模拟引擎中以可以被引擎停止和重新启动的方式运行。你需要的是一个过程。您可以simulationRun通过从单独的回调函数启动该代码来创建当前进程,如下所示。

import simpy  

if __name__ == '__main__':
    env = simpy.Environment()

    def simulationRun():
        print("Starting a run at time [%i]" % env.now)
        yield env.timeout(5)
        print("Ending a run at time [%i]" % env.now)

    def callback(event):
        s = simulationRun()
        env.process(s)

    event = env.timeout(5)
    event.callbacks.append(callback)

    print("Starting simulation.")
    env.run(20)
    print("End of simulation.")
于 2015-03-10T00:59:45.787 回答