[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

推薦閱讀