日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

python语言例子_【Python】SimPy的使用示例-Go语言中文社区

發(fā)布時(shí)間:2024/7/23 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python语言例子_【Python】SimPy的使用示例-Go语言中文社区 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

使用SimPY進(jìn)行離散事件仿真

SimPY是一個(gè)Python下的第三方庫(kù),可以方便的進(jìn)行離散事件的仿真。仿真速度比較快。下面記錄一下我的一點(diǎn)心得,不保證完全正確,供參考。

安裝

$ pip install -U simpy

pycharm可以再File | Settings | Project: Simulation | Project Interpreter中添加

主要概念

Environment

Process

Event

Resource

SimPY使用Environment,Process,Event,Resource四大概念來(lái)進(jìn)行離散事件的仿真。

Environment就是整體仿真所在的時(shí)間,主要用于提取時(shí)間。

Process就是仿真過(guò)程中的實(shí)體,如:顧客, 設(shè)備, 車輛等。 Process本質(zhì)上也是一個(gè)event。源代碼里面可以看到是繼承Event的一個(gè)類。

Event是仿真中觸發(fā)的事件,可以理解為一個(gè)定時(shí)器。當(dāng)定時(shí)器到時(shí)時(shí),觸發(fā)事件。

Resource是仿真中的資源,如ATM機(jī),服務(wù)器等。

官方示例:

>>> 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

邏輯很簡(jiǎn)單,

1. 創(chuàng)建一個(gè)env

2. 以env為參數(shù)創(chuàng)建process, process有名字和參數(shù),process內(nèi)部使用生成器直接調(diào)用了超時(shí)事件。

3. 運(yùn)行該env

深入原理

通過(guò)SimPY的源代碼可以了解到,SimPY使用了一個(gè)heapq隊(duì)列,這個(gè)隊(duì)列中的元素是事件。Environment中對(duì)這個(gè) 隊(duì)列進(jìn)行調(diào)度,實(shí)際上是將事件壓入隊(duì)列中,environment中還有step方法,就是從隊(duì)列中取出時(shí)間最小的一個(gè)事件(也就是時(shí)間點(diǎn)上最接近當(dāng)前時(shí)間的下一個(gè)事件,使用heapq的heappop方法),然后運(yùn)行這個(gè)事件的callback函數(shù),一般就是Process。 因此仿真實(shí)際上是對(duì)一系列事件進(jìn)行壓入隊(duì)列,按時(shí)間序彈出隊(duì)列的過(guò)程。這樣可以避免使用時(shí)間步長(zhǎng)進(jìn)行步進(jìn),時(shí)間步長(zhǎng)步進(jìn)的缺點(diǎn)就是太慢了。必須一個(gè)時(shí)間步長(zhǎng)一個(gè)時(shí)間步長(zhǎng)的挨個(gè)遍歷過(guò)去,如果時(shí)間步長(zhǎng)不合理的話,會(huì)有大量的計(jì)算時(shí)間上的浪費(fèi)。

另外,為了語(yǔ)法上的優(yōu)美易用,env中使用了Python的反射機(jī)制,將常用的幾種事件,包括Process, Timeout, Anyof, Allof, Event都綁定為env的一種方法。 這個(gè)語(yǔ)法看上去很簡(jiǎn)單,但實(shí)現(xiàn)機(jī)制相對(duì)有點(diǎn)難以理解(我也只是了解是一種反射),只需要記住類似env.process, env.timeout, env.event, env.all_of, env.any_of的方法調(diào)用實(shí)際上都是聲明了simpy.Process, simpy.Timeout等類的就可以了。詳細(xì)實(shí)現(xiàn)在simpy.core.py中。

稍微復(fù)雜一點(diǎn)的例子:

"""

服務(wù)站示例

場(chǎng)景介紹:

一個(gè)有特定服務(wù)提供工作站,客戶服務(wù)時(shí)長(zhǎng)不一,工作機(jī)器數(shù)有限。

Client接受服務(wù)步驟:Client到達(dá)工作站,若有空閑的機(jī)器就立刻接受服務(wù),如果沒(méi)有,就等待直到其他機(jī)器空閑下來(lái)。

每個(gè)接受過(guò)服務(wù)的Client都有一個(gè)完成滿意度(或者為進(jìn)度)實(shí)時(shí)統(tǒng)計(jì)服務(wù)客戶數(shù)和完成滿意進(jìn)度。

"""

import random

import simpy

# 可接受輸入?yún)?shù)

RANDOM_SEED = 0 # 不設(shè)置

NUM_MACHINES = 2 # 可以同時(shí)處理的機(jī)器數(shù)(類似工作工位數(shù))

TIME_CONSUMING = 5 # 單任務(wù)耗時(shí) (可以設(shè)計(jì)成隨機(jī)數(shù))

TIME_INTERVAL = 5 # 來(lái)車的間隔時(shí)間約5分鐘 (可以設(shè)計(jì)成隨機(jī)數(shù))

SIM_TIME = 1000 # 仿真總時(shí)間

CLIENT_NUMBER = 2 # 初始時(shí)已經(jīng)占用機(jī)器數(shù)

class WorkStation(object):

"""

一個(gè)工作站,擁有特定數(shù)量的機(jī)器數(shù)。 一個(gè)客戶首先申請(qǐng)服務(wù)。在對(duì)應(yīng)服務(wù)時(shí)間完成后結(jié)束并離開(kāi)工作站

"""

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):

"""服務(wù)流程"""

yield self.env.timeout(random.randint(2, 10)) # 假設(shè)服務(wù)時(shí)間為隨機(jī)數(shù)(2~10)

self.allClient += 1

per = random.randint(50, 99)

print("%s's 任務(wù)完成度:%d%%." % (car, per))

if per > 80:

self.accomplishClient += 1

print("工作站服務(wù)客戶數(shù):%d,"

"工作站服務(wù)達(dá)標(biāo)率:%.2f。" % (self.allClient, float(self.accomplishClient) / float(self.allClient)))

def Client(env, name, cw):

"""

客戶到達(dá)動(dòng)作站接受服務(wù),結(jié)束后離開(kāi)

"""

print('%s 到達(dá)工作站 at %.2f.' % (name, env.now))

with cw.machine.request() as request:

yield request

print('%s 接受服務(wù) at %.2f.' % (name, env.now))

yield env.process(cw.wash(name))

print('%s 離開(kāi)服務(wù)站 at %.2f.' % (name, env.now))

def setup(env, num_machines, washtime, t_inter, clientNumber):

"""創(chuàng)建一個(gè)工作站,幾個(gè)初始客戶,然后持續(xù)有客戶到達(dá). 每隔t_inter - 2, t_inter + 3分鐘(可以自定義)."""

# 創(chuàng)建工作站

workstation = WorkStation(env, num_machines, washtime)

# 創(chuàng)建clientNumber個(gè)初始客戶

for i in range(clientNumber):

env.process(Client(env, 'Client_%d' % i, workstation))

# 在仿真過(guò)程中持續(xù)創(chuàng)建客戶

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))

# 初始化并開(kāi)始仿真任務(wù)

print('開(kāi)始仿真')

# 初始化seed,指定數(shù)值的時(shí)候方正結(jié)果可以復(fù)現(xiàn)

random.seed()

# 創(chuàng)建一個(gè)環(huán)境并開(kāi)始仿真

env = simpy.Environment()

env.process(setup(env, NUM_MACHINES, TIME_CONSUMING, TIME_INTERVAL, CLIENT_NUMBER))

# 開(kāi)始執(zhí)行!

env.run(until=SIM_TIME)

輸出:

開(kāi)始仿真

Client_0 到達(dá)工作站 at 0.00.

Client_1 到達(dá)工作站 at 0.00.

Client_0 接受服務(wù) at 0.00.

Client_1 接受服務(wù) at 0.00.

Client_2 到達(dá)工作站 at 3.00.

Client_0's 任務(wù)完成度:54%.

工作站服務(wù)客戶數(shù):1,工作站服務(wù)達(dá)標(biāo)率:0.00。

Client_3 到達(dá)工作站 at 7.00.

Client_0 離開(kāi)服務(wù)站 at 7.00.

Client_2 接受服務(wù) at 7.00.

Client_1's 任務(wù)完成度:97%.

工作站服務(wù)客戶數(shù):2,工作站服務(wù)達(dá)標(biāo)率:0.50。

.

.

.

Client_179 接受服務(wù) at 986.00.

Client_178 離開(kāi)服務(wù)站 at 986.00.

Client_180 到達(dá)工作站 at 989.00.

Client_180 接受服務(wù) at 989.00.

Client_179's 任務(wù)完成度:89%.

工作站服務(wù)客戶數(shù):180,工作站服務(wù)達(dá)標(biāo)率:0.36。

Client_179 離開(kāi)服務(wù)站 at 993.00.

Client_181 到達(dá)工作站 at 995.00.

Client_181 接受服務(wù) at 995.00.

Client_180's 任務(wù)完成度:96%.

工作站服務(wù)客戶數(shù):181,工作站服務(wù)達(dá)標(biāo)率:0.36。

Client_180 離開(kāi)服務(wù)站 at 997.00.

Process finished with exit code 0

總結(jié)

以上是生活随笔為你收集整理的python语言例子_【Python】SimPy的使用示例-Go语言中文社区的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。