[Pyhton] SimPy 离散事件模拟框架详解 —— 以一个简单的汽车充电排队模拟为例( 二 )


[Pyhton] SimPy 离散事件模拟框架详解 —— 以一个简单的汽车充电排队模拟为例

文章插图
2.3 一个汽车开开停停的例子下面是一个简单的汽车走走停停的例子 , 打印其走停的时间戳:
>>> def car(env):...while True:...print('Start parking at %d' % env.now)...parking_duration = 5...yield env.timeout(parking_duration)......print('Start driving at %d' % env.now)...trip_duration = 2...yield env.timeout(trip_duration)>>> import simpy>>> env = simpy.Environment()>>> env.process(car(env))<Process(car) object at 0x...>>>> env.run(until=15)Start parking at 0Start driving at 5Start parking at 7Start driving at 12Start parking at 142.4 在走走停停过程中增加充电过程(过程交互)我们在上面汽车例子基础上引入充电的过程:车走一段时间,停下来充电,电充好了,才能继续走 。这里引入了 charge_duration 过程,在该过程中简单写了一个超过的挂起事件:
>>> class Car(object):...def __init__(self, env):...self.env = env...# Start the run process everytime an instance is created....self.action = env.process(self.run())......def run(self):...while True:...print('Start parking and charging at %d' % self.env.now)...charge_duration = 5...# We yield the process that process() returns...# to wait for it to finish...yield self.env.process(self.charge(charge_duration))......# The charge process has finished and...# we can start driving again....print('Start driving at %d' % self.env.now)...trip_duration = 2...yield self.env.timeout(trip_duration)......def charge(self, duration):...yield self.env.timeout(duration)>>> import simpy>>> env = simpy.Environment()>>> car = Car(env)>>> env.run(until=15)Start parking and charging at 0Start driving at 5Start parking and charging at 7Start driving at 12Start parking and charging at 14如果我们不想等充电结束,而是想中断充电过程并开始驾驶 , 可以使用 SimPy 的 interrupt() 方法来中断正在运行的进程:
>>> def driver(env, car):...yield env.timeout(3)...car.action.interrupt()由于原来的充电过程被中断会报异常,因此我们要对异常处理下:
...try:...yield self.env.process(self.charge(charge_duration))...except simpy.Interrupt:...# When we received an interrupt, we stop charging and...# switch to the "driving" state...print('Was interrupted. Hope, the battery is full enough ...')再次运行:
>>> env = simpy.Environment()>>> car = Car(env)>>> env.process(driver(env, car))<Process(driver) object at 0x...>>>> env.run(until=15)Start parking and charging at 0Was interrupted. Hope, the battery is full enough ...Start driving at 3Start parking and charging at 5Start driving at 10Start parking and charging at 122.5 共享资源SimPy 提供三种类型的资源,用于解决建模中多个进行希望使用有限资源的问题(例如:加油站汽车场景中的燃油泵)或典型的生产者-消费者问题 。
[Pyhton] SimPy 离散事件模拟框架详解 —— 以一个简单的汽车充电排队模拟为例

文章插图
我们还用汽车充电的例子:汽车开到充电桩旁 a battery charging station (BCS) , 向两个充电桩申请使用其一进行充电,如果两个桩都在被使用,它将会等待直到可用,然后开始充电,然后开走 。
>>> def car(env, name, bcs, driving_time, charge_duration):...# Simulate driving to the BCS...yield env.timeout(driving_time)......# Request one of its charging spots...print('%s arriving at %d' % (name, env.now))...with bcs.request() as req:...yield req......# Charge the battery...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))备注: bcs.request() 将会产生一个事件,该事件会阻塞直到资源可用,一般情况下使用资源后需要调用 release 对资源进行释放,这里的 with 语句意味着自动释放 。
我们创建有两个充电桩的资源:
>>> import simpy>>> env = simpy.Environment()>>> bcs = simpy.Resource(env, capacity=2)然后我们创建 4 辆车:
>>> for i in range(4):...env.process(car(env, 'Car %d' % i, bcs, i*2, 5))最后 , 我们可以开始模拟了 。由于汽车进程在此模拟中都自行终止,因此我们无需指定直到时间——当没有更多事件时 , 模拟将自动停止:
>>> env.run()Car 0 arriving at 0Car 0 starting to charge at 0Car 1 arriving at 2Car 1 starting to charge at 2Car 2 arriving at 4Car 0 leaving the bcs at 5Car 2 starting to charge at 5Car 3 arriving at 6Car 1 leaving the bcs at 7Car 3 starting to charge at 7Car 2 leaving the bcs at 10Car 3 leaving the bcs at 12

推荐阅读