天天看點

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