Simpy包的简单使用
Simpy包
基本概念
Simpy-制造仿真:SimPy 是离散事件驱动的仿真库
仿真技术是再现系统动态行为、分析系统配置与参数是否合理、预测瓶颈工序、判断系统性能是否满足规定要求、为制造系统的设计和运行提供决策支持。所有活动部件,例如车辆、顾客,、即便是信息,都可以用 process (进程) 来模拟。这些 process 存放在 environment (环境) 。所有 process 之间,以及与environment 之间的互动,通过 event (事件) 来进行.
process <–>event<–>environment
process 表达为 generators (生成器), 构建event(事件)并通过 yield 语句抛出事件。
当一个进程抛出事件,进程会被暂停,直到事件被激活(triggered)。多个进程可以等待同一个事件。 SimPy 会按照这些进程抛出的事件激活的先后, 来恢复进程。其实中最重要的一类事件是 Timeout, 这类事件允许一段时间后再被激活, 用来表达一个进程休眠或者保持当前的状态持续指定的一段时间。这类事件通过 Environment.timeout来调用。
Environment
模拟环境管理模拟时间以及事件的调度和处理。它还提供了单步执行或执行模拟的方法。正常模拟使用Environment.
Environment常用的方法
simpy.Environment.process - 添加仿真进程
simpy.Environment.event - 创建事件
simpy.Environment.timeout - 提供延时(timeout)事件
simpy.Environment.until - 仿真结束的条件(时间或事件)
simpy.Environment.run - 仿真启动
例子1-汽车启停模拟
import simpy
def car(env):
while True:
print('Start parking at %d' % env.now)
parking_duration=5
yield env.timeout(parking_duration) # 进程延时 5s,停五秒
print('Start driving at %d' % env.now)
trip_duration = 2
yield env.timeout(trip_duration) # yield抛出事件,2s,开两秒
# 仿真启动
env = simpy.Environment() # 实例化环境
env.process(car(env)) # 添加汽车进程
env.run(until=15) # 设定仿真结束条件, 这里是 15s 后停止
例子2-汽车充电模拟
from random import seed, randint
seed(23)
import simpy
class EV:
def __init__(self,env):
self.env=env
#两个主进程
self.drive_proc=env.process(self.drive(env))
self.bat_ctrl_proc = env.process(self.bat_ctrl(env))
# 需要抛出的事件
self.bat_ctrl_reactivate = env.event()
#需要抛出的事件
self.bat_ctrl_sleep = env.event()
def drive(self, env):
"""驾驶进程"""
while True:
# 驾驶 20-40 分钟
print("开始驾驶 时间: ", env.now)
yield env.timeout(randint(20, 40))
print("停止驾驶 时间: ", env.now)
# 停车 1-6 小时
print("开始停车 时间: ", env.now)
self.bat_ctrl_reactivate.succeed() # 激活充电事件
self.bat_ctrl_reactivate = env.event()
yield env.timeout(randint(60, 360)) & self.bat_ctrl_sleep # 停车时间和充电程序同时都满足
print("结束停车 时间:", env.now)
def bat_ctrl(self, env):
"""电池充电进程"""
while True:
print("充电程序休眠 时间:", env.now)
yield self.bat_ctrl_reactivate # 休眠直到充电事件被激活
print("充电程序激活 时间:", env.now)
yield env.timeout(randint(30, 90))
print("充电程序结束 时间:", env.now)
self.bat_ctrl_sleep.succeed() # 将充电事件 冷却,激活开车进程
self.bat_ctrl_sleep = env.event()
def main():
env=simpy.Environment()
ev=EV(env)
env.run(until=300)
if __name__=='__main__':
main()
共享资源
共享资源是另一种建模流程交互的方式。它们形成了一个拥塞点,进程在此排队以便使用它们。
SimPy 定义了三类资源:
Resources :一次可以由有限数量的流程使用的资源(例如,具有有限数量燃料泵的加油站)
import simpy
def car(env, name, bcs, driving_time, charge_duration):
yield env.timeout(driving_time)
print('%s arriving at %d' % (name, env.now))
with bcs.request() as req: #申请资源
yield req #判断是否可以申请到资源
#申请到资源就进行后续的操作
print('%s starting to charge at %s' % (name, env.now))
yield env.timeout(charge_duration)
print('%s leaving the bcs at %s' % (name, env.now))
env =simpy.Environment()
bcs=simpy.Resource(env,capacity=2)#定义资源只有两份
for i in range(4):
#添加进程,定义行驶时间(即定义到达充电桩时间
env.process(car(env, 'Car %d' % i, bcs, i*2, 5))
env.run(until=25)
Containers :模拟同质、无差别散装的生产和消费的资源。它可能是连续的(如水)或离散的(如苹果)。可以用来模拟一种物品的消耗和补充,但是对于同一种事物Containers是一个标准(例如,同一款汽车的油箱大小,和一筐苹果的数量等)
class GasStation:
def __init__(self, env):
#初始化环境中的资源数
self.fuel_dispensers = simpy.Resource(env, capacity=2)
#初始化 Container容量和存量
self.gas_tank = simpy.Container(env, init=100, capacity=1000)
#在环境中添加进行油量监视的进程
self.mon_proc = env.process(self.monitor_tank(env))
def monitor_tank(self, env):
"""
对油箱的存量进行监控,如果油箱的存量小于最低线,则开启加油线程
"""
while True:
if self.gas_tank.level < 100:
print(f'Calling tanker at {env.now}')
#开启加油线程
env.process(tanker(env, self))
yield env.timeout(15)
def tanker(env, gas_station):
yield env.timeout(10) # 模拟加油的船到达加油地点
print(f'Tanker arriving at {env.now}')
amount = gas_station.gas_tank.capacity - gas_station.gas_tank.level
yield gas_station.gas_tank.put(amount)#进行补充油量,作为事件抛出,一直到加油结束,加油线程完成
def car(name, env, gas_station):
print(f'Car {name} arriving at {env.now}')
with gas_station.fuel_dispensers.request() as req:
#car 到达,请求加油站的加油坑位
yield req
print(f'Car {name} starts refueling at {env.now}')
#进行加油,改变加油站油箱存量
yield gas_station.gas_tank.get(40)
#模拟给车加油
yield env.timeout(5)
#离开加油站
print(f'Car {name} done refueling at {env.now}')
def car_generator(env, gas_station):
for i in range(4):
#模拟car进行加油的进程
env.process(car(i, env, gas_station))
yield env.timeout(5)
import simpy
env = simpy.Environment()
gas_station = GasStation(env)
car_gen = env.process(car_generator(env, gas_station))
env.run(35)