在Python中使用SimPy进行离散事件模拟的基础

Basics of Discrete Event Simulation using SimPy in Python

SimPy(带有" Blimpie"的押韵)是用于面向过程的离散事件模拟的python软件包。

安装

安装SimPy的最简单方法是通过pip:

1
pip install simpy

您可能获得的输出将是这样的,

在撰写本文时,simpy-3.0.11是SimPy的最新版本,我们将在以下所有示例中使用它。

如果已经安装了SimPy,请使用–U选项进行pip升级。

1
pip install –U simpy

注意:您需要具有python 2.7或更高版本,对于Linux / Unix / MacOS,您可能需要root特权才能安装SimPy。

要检查SimPy是否已成功安装,请打开python shell并导入simpy。

基本概念

SimPy,这是一个离散事件模拟库。 simpy的活动组件(例如消息,车辆或客户)都通过流程进行建模。在SimPy中,活动实体称为流程。进程是产生离散事件的Python生成器。请注意,我没有返回任何东西,但我是一个yield(ing),这是普通函数和生成器之间的区别。这使我们可以创建事件并产生事件,以便等待它们被触发。

当流程产生事件时,该流程将被挂起。 SimPy允许我们在事件触发时恢复已暂停的过程。万一多个进程等待同一个事件,SimPy将以产生该事件的相同顺序恢复它们。

1
2
3
def gen(x):
y = yield x+1
return y

1
2
3
4
5
6
7
8
>>> g = gen(1)
>>> next(g)
2
>>> next(g)
Traceback (most recent call last):
File"<pyshell#2>", line 1, in <module>
next(g)
StopIteration

在变量x首次屈服之后,以上迭代停止。

经过一定数量的(模拟)时间后,将触发"超时"类型的事件。超时事件允许进程在一定时间内保持或休眠。可以通过调用进程所在的环境的相应方法来创建包括超时在内的所有事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#Import important library
from random import randint
import simpy
#Config
TALKS_PER_SESSION = 3
TALK_LENGTH = 30
BREAK_LENGTH = 15
ATTENDEES = 1
def attendee(env, name, knowledge=0, hunger=0):
 talks =0
 breaks =0
 #Repeat sessions
 while True:
   # Visit talks
   for i in range(TALKS_PER_SESSION):
   print('Talk {0} begins at {1}'.format(talks+1, env.now))
   knowledge += randint(0, 3) / (1 + hunger)
   hunger += randint(1, 4)
   talks += 1
   yield env.timeout(TALK_LENGTH)
   print(f'Talk {talks} ends at {env.now}')
 print('Attendee %s finished talks with knowledge %.2f and hunger ' '%.2f' %( name, knowledge, hunger))
 #Take a break, Go to buffet
 food = randint(3, 12)
 hunger -= min(food, hunger)
 yield env.timeout(BREAK_LENGTH)
 print('Attendee %s finished eating with hunger %.2f ' %(name, hunger))
# Run Simulation
env = simpy.Environment()
for i in range(ATTENDEES):
 env.process(attendee(env, i))
env.run(until=250)

如果运行上面的程序,我们将看到类似以下的输出,

上面我们尝试复制会议厅的场景,在该场景中,随机分配的发言人每节演讲为4个,通话时长为40分钟,通话时长为30分钟。

我们的与会者流程需要参考环境(env),名称,知识和饥饿感,以便创建新事件。会话将无限循环直至变为False。 Attendee()函数是一个生成器,它不会终止,但是一旦达到yield语句,就会将控制流传递回模拟。

最后,我们运行演示模拟"会议与会者",直到未达到250的设定值(包括-3个对话,1个休息,3个对话,1个休息,1个对话)。