python语言例子_【Python】SimPy的使用示例-Go语言中文社区
使用SimPY進行離散事件仿真
SimPY是一個Python下的第三方庫,可以方便的進行離散事件的仿真。仿真速度比較快。下面記錄一下我的一點心得,不保證完全正確,供參考。
安裝
$ pip install -U simpy
pycharm可以再File | Settings | Project: Simulation | Project Interpreter中添加
主要概念
Environment
Process
Event
Resource
SimPY使用Environment,Process,Event,Resource四大概念來進行離散事件的仿真。
Environment就是整體仿真所在的時間,主要用于提取時間。
Process就是仿真過程中的實體,如:顧客, 設備, 車輛等。 Process本質上也是一個event。源代碼里面可以看到是繼承Event的一個類。
Event是仿真中觸發的事件,可以理解為一個定時器。當定時器到時時,觸發事件。
Resource是仿真中的資源,如ATM機,服務器等。
官方示例:
>>> import simpy
>>>
>>> def clock(env, name, tick):
... while True:
... print(name, env.now)
... yield env.timeout(tick)
...
>>> env = simpy.Environment()
>>> env.process(clock(env, 'fast', 0.5))
>>> env.process(clock(env, 'slow', 1))
>>> env.run(until=2)
fast 0
slow 0
fast 0.5
slow 1
fast 1.0
fast 1.5
邏輯很簡單,
1. 創建一個env
2. 以env為參數創建process, process有名字和參數,process內部使用生成器直接調用了超時事件。
3. 運行該env
深入原理
通過SimPY的源代碼可以了解到,SimPY使用了一個heapq隊列,這個隊列中的元素是事件。Environment中對這個 隊列進行調度,實際上是將事件壓入隊列中,environment中還有step方法,就是從隊列中取出時間最小的一個事件(也就是時間點上最接近當前時間的下一個事件,使用heapq的heappop方法),然后運行這個事件的callback函數,一般就是Process。 因此仿真實際上是對一系列事件進行壓入隊列,按時間序彈出隊列的過程。這樣可以避免使用時間步長進行步進,時間步長步進的缺點就是太慢了。必須一個時間步長一個時間步長的挨個遍歷過去,如果時間步長不合理的話,會有大量的計算時間上的浪費。
另外,為了語法上的優美易用,env中使用了Python的反射機制,將常用的幾種事件,包括Process, Timeout, Anyof, Allof, Event都綁定為env的一種方法。 這個語法看上去很簡單,但實現機制相對有點難以理解(我也只是了解是一種反射),只需要記住類似env.process, env.timeout, env.event, env.all_of, env.any_of的方法調用實際上都是聲明了simpy.Process, simpy.Timeout等類的就可以了。詳細實現在simpy.core.py中。
稍微復雜一點的例子:
"""
服務站示例
場景介紹:
一個有特定服務提供工作站,客戶服務時長不一,工作機器數有限。
Client接受服務步驟:Client到達工作站,若有空閑的機器就立刻接受服務,如果沒有,就等待直到其他機器空閑下來。
每個接受過服務的Client都有一個完成滿意度(或者為進度)實時統計服務客戶數和完成滿意進度。
"""
import random
import simpy
# 可接受輸入參數
RANDOM_SEED = 0 # 不設置
NUM_MACHINES = 2 # 可以同時處理的機器數(類似工作工位數)
TIME_CONSUMING = 5 # 單任務耗時 (可以設計成隨機數)
TIME_INTERVAL = 5 # 來車的間隔時間約5分鐘 (可以設計成隨機數)
SIM_TIME = 1000 # 仿真總時間
CLIENT_NUMBER = 2 # 初始時已經占用機器數
class WorkStation(object):
"""
一個工作站,擁有特定數量的機器數。 一個客戶首先申請服務。在對應服務時間完成后結束并離開工作站
"""
def __init__(self, env, num_machines, washtime):
self.env = env
self.machine = simpy.Resource(env, num_machines)
self.washtime = washtime
self.allClient = 0
self.accomplishClient = 0
def wash(self, car):
"""服務流程"""
yield self.env.timeout(random.randint(2, 10)) # 假設服務時間為隨機數(2~10)
self.allClient += 1
per = random.randint(50, 99)
print("%s's 任務完成度:%d%%." % (car, per))
if per > 80:
self.accomplishClient += 1
print("工作站服務客戶數:%d,"
"工作站服務達標率:%.2f。" % (self.allClient, float(self.accomplishClient) / float(self.allClient)))
def Client(env, name, cw):
"""
客戶到達動作站接受服務,結束后離開
"""
print('%s 到達工作站 at %.2f.' % (name, env.now))
with cw.machine.request() as request:
yield request
print('%s 接受服務 at %.2f.' % (name, env.now))
yield env.process(cw.wash(name))
print('%s 離開服務站 at %.2f.' % (name, env.now))
def setup(env, num_machines, washtime, t_inter, clientNumber):
"""創建一個工作站,幾個初始客戶,然后持續有客戶到達. 每隔t_inter - 2, t_inter + 3分鐘(可以自定義)."""
# 創建工作站
workstation = WorkStation(env, num_machines, washtime)
# 創建clientNumber個初始客戶
for i in range(clientNumber):
env.process(Client(env, 'Client_%d' % i, workstation))
# 在仿真過程中持續創建客戶
while True:
yield env.timeout(random.randint(t_inter - 2, t_inter + 3)) # 3-8分鐘
i += 1
env.process(Client(env, 'Client_%d' % i, workstation))
# 初始化并開始仿真任務
print('開始仿真')
# 初始化seed,指定數值的時候方正結果可以復現
random.seed()
# 創建一個環境并開始仿真
env = simpy.Environment()
env.process(setup(env, NUM_MACHINES, TIME_CONSUMING, TIME_INTERVAL, CLIENT_NUMBER))
# 開始執行!
env.run(until=SIM_TIME)
輸出:
開始仿真
Client_0 到達工作站 at 0.00.
Client_1 到達工作站 at 0.00.
Client_0 接受服務 at 0.00.
Client_1 接受服務 at 0.00.
Client_2 到達工作站 at 3.00.
Client_0's 任務完成度:54%.
工作站服務客戶數:1,工作站服務達標率:0.00。
Client_3 到達工作站 at 7.00.
Client_0 離開服務站 at 7.00.
Client_2 接受服務 at 7.00.
Client_1's 任務完成度:97%.
工作站服務客戶數:2,工作站服務達標率:0.50。
.
.
.
Client_179 接受服務 at 986.00.
Client_178 離開服務站 at 986.00.
Client_180 到達工作站 at 989.00.
Client_180 接受服務 at 989.00.
Client_179's 任務完成度:89%.
工作站服務客戶數:180,工作站服務達標率:0.36。
Client_179 離開服務站 at 993.00.
Client_181 到達工作站 at 995.00.
Client_181 接受服務 at 995.00.
Client_180's 任務完成度:96%.
工作站服務客戶數:181,工作站服務達標率:0.36。
Client_180 離開服務站 at 997.00.
Process finished with exit code 0
總結
以上是生活随笔為你收集整理的python语言例子_【Python】SimPy的使用示例-Go语言中文社区的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小爱音响调用php接口_PHP调用语音合
- 下一篇: python分行_基于python实现对