使用Python中的SimPy进行离散事件仿真的基础知识
SimPy(发音类似于“Blimpie”)是一个用于面向过程的离散事件仿真的Python包。
安装
安装SimPy最简单的方法是通过pip
pip install simpy
你可能会得到类似这样的输出:
在撰写本文时,simpy-3.0.11是SimPy的最新版本,我们将在以下所有示例中使用它。
如果SimPy已经安装,请使用pip的–U选项进行升级。
pip install –U simpy
注意:你需要安装python 2.7或更高版本,对于Linux/Unix/MacOS,你可能需要root权限才能安装SimPy。
要检查SimPy是否成功安装,请打开python shell并导入simpy。
基本概念
SimPy是一个离散事件仿真库。Simpy的活动组件(如消息、车辆或客户)是用进程建模的。在SimPy中,活动实体被称为进程。进程是一个产生离散事件的Python生成器。请注意,我不返回任何东西,而是一个yield(ing),这是普通函数和生成器之间的区别。这允许我们创建事件并产生它们,以便等待它们被触发。
当一个进程产生一个事件时,该进程将被挂起。SimPy允许我们在事件被触发时恢复挂起的进程。如果多个进程等待同一个事件,SimPy将按照它们产生该事件的顺序恢复它们。
def gen(x): y = yield x+1 return y
>>> g = gen(1) >>> next(g) 2 >>> next(g) Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> next(g) StopIteration
上述迭代在变量x第一次yield后停止。
超时类型的事件在经过一定量的(模拟)时间后被触发。超时事件允许进程保持或休眠一段时间。包括超时在内的所有事件都可以通过调用进程所在的Environment的相应方法来创建。
#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分钟。
我们的参与者进程需要一个Environment (env)的引用、姓名、知识和饥饿感才能创建新的事件。会议将无限循环,直到它变为False。attendee()函数是一个生成器,它不会终止,而是在到达yield语句后将控制流传递回仿真。
最后,我们运行一个演示仿真“会议参与者”,直到达到设定的250值(包括:3次演讲,1次休息,3次演讲,1次休息,1次演讲)。