天天看点

Simpy离散事件仿真(5)——专题指南(1)——Simpy工作原理1 一个简单例子2 更好的代码进行理解

本指南描述了SimPy的基本概念:它是如何工作的?什么是过程、事件和环境?怎么使用它们?

如果剖析分解SimPy,您会发现它仅是一个异步事件分发器——生成事件并在给定的仿真时间安排它们。事件按优先级、仿真时间和递增的事件id排序。事件还具有回调列表,这些回调在事件触发和处理时执行。事件也可能有返回值。

涉及的组件是您编写的环境(Envirement)、事件(events)和进程(process)函数。

进程函数实现您的仿真模型,即,它们定义您的仿真行为。它们其实是挂起事件实例的普通的Python生成器函数。

环境将这些事件存储在其事件列表中,并跟踪当前仿真时间。

如果进程函数产生一个事件,SimPy会将该进程添加到事件的回调中,并挂起该进程,直到触发并处理该事件。当等待事件的进程恢复时,它也将接收事件的值。

1 一个简单例子

这里有一个非常简单的例子说明了这一切:

import simpy

def example(env):
    event = simpy.events.Timeout(env, delay=1, value=42)
    value = yield event
    print('now=%d, value=%d' % (env.now, value))

env = simpy.Environment()
example_gen = example(env)
p = simpy.events.Process(env, example_gen)

env.run()
           
now=1, value=42      

上面的example()进程函数首先创建一个超时(Timeout)事件。它将环境、延迟和一个值传递给它。超时在now+delay(这就是为什么需要环境)下自行调度;其他事件类型通常在当前仿真时间调度自己。

然后,进程函数生成事件并挂起。当SimPy处理超时事件时,它将恢复。进程函数还接收事件的值(42)——但是,这是可选的,因此如果您对该值不感兴趣或者事件根本没有值,那么yield事件就可以了。

最后,进程函数打印当前仿真时间(可以通过环境的now属性访问)和值。

如果定义了所有必需的进程函数,则可以实例化所有仿真对象。在大多数情况下,首先要创建一个环境实例,因为在创建其他内容时,需要经常使用传递它。

启动进程涉及两件事:

(1)必须调用Process函数才能创建生成器对象。(这不会执行该函数的任何代码。请阅读Python yield关键字以了解原因。)

(2)然后创建进程实例,并将环境和生成器对象传递给它。这将在当前仿真时间安排一个初始化事件,启动进程函数的执行。进程实例也是进程函数返回时触发的事件。事件指南解释了为什么这很方便。

最后,可以启动SimPy的事件循环。默认情况下,只要事件列表中有事件,它就会运行,但您也可以通过提供until参数让它提前停止(请参见仿真控件)。

2 更好的代码进行理解

以下代码将更详细地描述环境及其与事件和流程功能的交互。

import simpy

def example(env):
    value = yield env.timeout(1, value=42)
    print('now=%d, value=%d' % (env.now, value))

env = simpy.Environment()
p = env.process(example(env))
env.run()
           
now=1, value=42