<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用Python的SimPy進(jìn)行制造仿真

          共 16295字,需瀏覽 33分鐘

           ·

          2021-03-17 17:18

          使用Python和SimPy創(chuàng)建一個(gè)吉他工廠仿真

          仿真是一種基于模型的活動(dòng)。它通過對(duì)系統(tǒng)模型的試驗(yàn)達(dá)到分析與研究系統(tǒng)的目的。

          仿真技術(shù)是再現(xiàn)系統(tǒng)動(dòng)態(tài)行為、分析系統(tǒng)配置與參數(shù)是否合理、預(yù)測(cè)瓶頸工序、判斷系統(tǒng)性能是否滿足規(guī)定要求、為制造系統(tǒng)的設(shè)計(jì)和運(yùn)行提供決策支持。

          在本文中,我們將使用SimPy來建立一個(gè)吉他工廠,介紹一些非常精彩的東西,你可以將這些用到你自己的仿真案例中。

          1.SimPy

          首先,什么是SimPy?SimPy文檔中將其定義為:“SimPy是基于過程的離散事件的標(biāo)準(zhǔn)Python模擬框架”。如果您沒有安裝SimPy,用下面的代碼進(jìn)行SimPy的安裝:

          pip install simpy

          2.吉他工廠

          首先我們將從頭開始建立一個(gè)吉他工廠,從非常簡單的東西到更完善的仿真系統(tǒng)。在此示例中我們生產(chǎn)一種吉他,吉他的木質(zhì)主體分為兩部分:琴身和琴頸,這兩部分是分別生產(chǎn)的,但使用的都是相同類型的木材,然后將這些半成品送到給噴涂工序車間進(jìn)行噴涂。最后,將噴涂好的琴身、琴頸和電子元件組合在一起,從而完成一個(gè)吉他的生產(chǎn)。
          我們先看看生產(chǎn)業(yè)務(wù)流程圖:

          先解釋一下業(yè)務(wù)流程:

          1. 有2個(gè)主要容器(庫存):木材倉庫和電子元件倉庫。這些容器中有N單位數(shù)量木材/電子元件,這些原材料將在生產(chǎn)流程中使用。

          2. 琴身部件從木材倉庫取出1單位木材,生產(chǎn)成1個(gè)琴身,然后將其存儲(chǔ)在琴身倉庫中。琴頸也一樣,但是從1單位木材上得到2個(gè)琴頸。琴頸存儲(chǔ)在琴頸倉庫中,琴身和琴頸都在等待噴涂。

          3. 噴涂車間給琴身和琴頸上漆,然后將它們存儲(chǔ)在已噴涂的琴身倉庫(待組裝琴身倉庫)和已噴涂的琴頸倉庫(待組裝琴頸倉庫)中。

          4. 1個(gè)琴身和1個(gè)琴頸和1單位電子元件在組裝車間就組裝出來1個(gè)成品吉他,組裝完成后存放在成品倉庫中。

          5. 生產(chǎn)完成一定量的吉他成品,商店安排人來取貨。

          6. 當(dāng)木材或電子元件的原材料庫存低到一定水平時(shí),會(huì)聯(lián)系供應(yīng)商進(jìn)行原材料供貨。T天后,供應(yīng)商送貨到達(dá)工廠的倉庫,原材料庫存增加。

          3.循序漸進(jìn)仿真

          1)簡單例子

          我們從易到難,先看看最簡單的業(yè)務(wù)模型,琴身和琴頸車間分別從木材倉庫取1單位木材,分別生產(chǎn)出1個(gè)琴身和2個(gè)琴頸,放在成品倉庫中(我們暫時(shí)稱之為產(chǎn)品倉庫),如下圖:

          代碼如下:

          import simpywood_capacity = 1000initial_wood = 500dispatch_capacity = 500
          class Guitar_Factory: def __init__(self, env): self.wood = simpy.Container(env, capacity = wood_capacity, init = initial_wood) self.dispatch = simpy.Container(env ,capacity = dispatch_capacity, init = 0)

          我們開始導(dǎo)入SimPy,之后創(chuàng)建Guitar_Factory類,并添加兩個(gè)容器(倉庫),一個(gè)是木材倉庫,最大庫存為上面設(shè)置的1000,初始化庫存為500,另一個(gè)是成品倉庫,最大庫存為上面設(shè)置的500,初始化庫存為0。注意env參數(shù),這個(gè)是SimPy的一個(gè)環(huán)境,我們后面會(huì)說明。

          現(xiàn)在我們創(chuàng)建琴身和琴頸的生產(chǎn)過程。

          def body_maker(env, guitar_factory):    while True:        yield guitar_factory.wood.get(1)        body_time = 1        yield env.timeout(body_time)        yield guitar_factory.dispatch.put(1)
          def neck_maker(env, guitar_factory): while True: yield guitar_factory.wood.get(1) neck_time = 1 yield env.timeout(neck_time) yield guitar_factory.dispatch.put(2)

          我們創(chuàng)建兩個(gè)生產(chǎn)過程,該函數(shù)有兩個(gè)參數(shù):SimPy環(huán)境和guitar_factory類(注意guitar_factory與是我們定義的Guitar_Factory不的實(shí)例化)。過程是這樣的:

          1. 在仿真運(yùn)行期間,車間從倉庫取出1單位木材 guitar_factory.wood.get(1)

          2. 在車間加工,一段時(shí)間后env.timeout(body_time),body_time定義為1個(gè)時(shí)間單位,將會(huì)產(chǎn)出一個(gè)琴身或琴頸,它模擬了車間的生產(chǎn)時(shí)間。

          3. 在該時(shí)間單位(在我們的示例中為1)過去之后,車間會(huì)將產(chǎn)出放入dispatch的容器(倉庫)中。琴身車間將用1單位木材制成1個(gè)吉他琴身,而琴頸車間將用1單位木材制成2個(gè)琴頸。


          hours = 8days = 5#定義仿真的時(shí)間長度total_time = hours * days
          env = simpy.Environment()guitar_factory = Guitar_Factory(env)
          body_maker_process = env.process(body_maker(env, guitar_factory))neck_maker_process = env.process(neck_maker(env, guitar_factory))print('仿真開始:')env.run(until = total_time)print(f'倉庫Dispatch中分別有%d 琴身和琴頸的庫存!' % guitar_factory.dispatch.level)print('仿真結(jié)束。')


          最后,我們創(chuàng)建一個(gè)仿真環(huán)境,在這個(gè)環(huán)境中實(shí)例化一個(gè)吉他工廠guitar_factory = Guitar_Factory(env)
          琴身和琴頸的生產(chǎn)過程會(huì)在env的環(huán)境中通過env.process來實(shí)例化,通過傳遞我們定義好的until=total_time給到env.run的運(yùn)行仿真環(huán)境函數(shù),將仿真運(yùn)行40小時(shí)(5天*8小時(shí))。
          我們通過guitar_factory.dispatch.level獲取成品的庫存水平。
          運(yùn)行結(jié)果如下:

          2)增加一些工序

          現(xiàn)在我們?cè)黾訃娡抗ば蚝徒M裝工序到我們的業(yè)務(wù)模型。為了達(dá)到目的,我們?cè)黾樱?/p>

          1. 噴涂前和噴涂后的容器(倉庫),和噴涂工序。

          2. 電子元件容器(倉庫)

          3. 組裝工序


          electronic_capacity = 100initial_electronic = 100
          pre_paint_capacity = 100post_paint_capacity = 200
          class Guitar_Factory: def __init__(self, env): self.wood = simpy.Container(env, capacity = wood_capacity, init = initial_wood) self.electronic = simpy.Container(env, capacity = electronic_capacity, init = initial_electronic) self.pre_paint = simpy.Container(env, capacity = pre_paint_capacity, init = 0) self.post_paint = simpy.Container(env, capacity = post_paint_capacity, init = 0) self.dispatch = simpy.Container(env ,capacity = dispatch_capacity, init = 0)

          以上內(nèi)容沒有什么新的內(nèi)容,我們?cè)黾恿穗娮釉娡壳昂蛧娡亢蟮膫}庫,并設(shè)定他們的最大庫存水平和初始化庫存水平。

          接下來我們定義噴涂和組裝工序。

          def painter(env, guitar_factory):    while True:        yield guitar_factory.pre_paint.get(10)        paint_time = 4        yield env.timeout(paint_time)        yield guitar_factory.post_paint.put(10)
          def assembler(env, guitar_factory): while True: yield guitar_factory.post_paint.get(2) yield guitar_factory.electronic.get(1) assembling_time = 1 yield env.timeout(assembling_time) yield guitar_factory.dispatch.put(1)

          正如我們?cè)谏a(chǎn)琴身和琴頸的一樣,我們創(chuàng)建噴涂和組裝的工序,噴涂需要4小時(shí),每次能同時(shí)噴涂10個(gè),放到一個(gè)名為

          post_paint的容器(倉庫)中 guitar_factory.post_paint.put(10)

          組裝工序是使用1個(gè)噴涂后的琴身和1個(gè)噴涂后的琴頸,這里我們不區(qū)分琴頸和琴身,直接提取兩個(gè)庫存

          guitar_factory.post_paint.get(2)(這里稍后需要優(yōu)化),再加上一份電子元件,經(jīng)過1個(gè)小時(shí)的組裝就得到一個(gè)成品。

          然后我們添加一些打印輸出,創(chuàng)建環(huán)境并運(yùn)行仿真。

          env = simpy.Environment()guitar_factory = Guitar_Factory(env)
          body_maker_process = env.process(body_maker(env, guitar_factory))neck_maker_process = env.process(neck_maker(env, guitar_factory))painter_process = env.process(painter(env, guitar_factory))assembler_process = env.process(assembler(env, guitar_factory))
          print(f'仿真開始:')
          env.run(until = total_time)
          print(f'噴涂前有%d 琴身和琴頸準(zhǔn)備噴涂' % guitar_factory.pre_paint.level)print(f'噴涂后有 %d 琴身和琴頸準(zhǔn)備組裝' % guitar_factory.post_paint.level)print(f'有 %d 吉他成品!' % guitar_factory.dispatch.level)print(f'----------------------------------')print(f'仿真完成。')


          3)庫存預(yù)警、供應(yīng)鏈供貨

          現(xiàn)在我們添加一些非常酷的東西,到目前為止,我們已經(jīng)為每一個(gè)工序設(shè)定了固定的時(shí)間,比如我們組裝車間需要一個(gè)小時(shí)來組織吉他。用這個(gè)參數(shù),我們生產(chǎn)一個(gè)吉他始終都是1個(gè)小時(shí),不會(huì)有任何的偏差。
          實(shí)際上,工序生產(chǎn)產(chǎn)品的時(shí)間都是在一個(gè)平均時(shí)間上下波動(dòng)的,我們假設(shè)時(shí)間服從正態(tài)分布(實(shí)際上你應(yīng)該通過實(shí)際的統(tǒng)計(jì)數(shù)據(jù)得到加工時(shí)間的分布特征來生成隨機(jī)數(shù)。)

          另外我們定義每種工序的數(shù)量(你可以理解為工序員工數(shù)量或者工序設(shè)備數(shù)量)。我們從導(dǎo)入隨機(jī)庫和定義參數(shù)開始。

          import random
          num_body = 2mean_body = 1std_body = 0.1
          num_neck = 1mean_neck = 1std_neck = 0.2
          num_paint = 1mean_paint = 4std_paint = 0.3
          num_ensam = 4mean_ensam = 1std_ensam = 0.2

          num_body設(shè)置了琴身的車間數(shù)量,設(shè)置為2,mean_body設(shè)置了生存一個(gè)琴身平均需要的時(shí)間,std_body設(shè)置了生存琴身的時(shí)間的標(biāo)準(zhǔn)差,我們修改我們的代碼:

          def body_maker(env, guitar_factory):    while True:        yield guitar_factory.wood.get(1)        body_time = random.gauss(mean_body, std_body)        yield env.timeout(body_time)        yield guitar_factory.pre_paint.put(1)
          def neck_maker(env, guitar_factory): while True: yield guitar_factory.wood.get(1) neck_time = random.gauss(mean_neck, std_neck) yield env.timeout(neck_time) yield guitar_factory.pre_paint.put(2)
          def painter(env, guitar_factory): while True: yield guitar_factory.pre_paint.get(10) paint_time = random.gauss(mean_paint, std_paint) yield env.timeout(paint_time) yield guitar_factory.post_paint.put(10)
          def assembler(env, guitar_factory): while True: yield guitar_factory.post_paint.get(1) yield guitar_factory.electronic.get(1) assembling_time = max(random.gauss(mean_ensam, std_ensam), 1) yield env.timeout(assembling_time) yield guitar_factory.dispatch.put(1)之前的例子timeout的參數(shù)我們總是設(shè)定為一個(gè)固定值,現(xiàn)在我們將這幾個(gè)工序的生產(chǎn)時(shí)間定義為一個(gè)隨機(jī)數(shù)。
          random.gauss(mean_body, std_body)

          之前的例子timeout的參數(shù)我們總是設(shè)定為一個(gè)固定值,現(xiàn)在我們將這幾個(gè)工序的生產(chǎn)時(shí)間定義為一個(gè)隨機(jī)數(shù)。

          random.gauss(mean_body, std_body)

          意思是生成一個(gè)平均數(shù)為mean_body,標(biāo)準(zhǔn)差為std_body的正態(tài)分布隨機(jī)數(shù)(正態(tài)分布也叫高斯分布,gauss)。
          另外注意,我們的組裝時(shí)間隨機(jī)數(shù)取為1到1之間的最大值。換句話說,我們說組裝吉他的時(shí)間永遠(yuǎn)不會(huì)少于一小時(shí)。很多情況下都需要這種設(shè)定,不然有可能生成的隨機(jī)數(shù)可能是負(fù)數(shù)(仿真過程將會(huì)出錯(cuò))。

          我們必須通過創(chuàng)建新功能來更改工序數(shù)量,該功能允許我們創(chuàng)建多個(gè)工序。

          def body_maker_gen(env, guitar_factory):    for i in range(num_body):        env.process(body_maker(env, guitar_factory))        yield env.timeout(0)
          body_gen = env.process(body_maker_gen(env, guitar_factory))

          當(dāng)然,這里另外還有

          neck_maker_gen, paint_maker_gen和assembler_maker_gen

          三個(gè)工序有類似的代碼。

          通過for循環(huán)我們創(chuàng)建2個(gè)琴身工序(我們定義了num_body=2),因此,我們有2個(gè)琴身工序、1個(gè)琴頸生產(chǎn)工序,1個(gè)噴涂工序和4個(gè)裝配工序。

          現(xiàn)在我們將創(chuàng)建庫存監(jiān)控和聯(lián)系供應(yīng)商的函數(shù)。我們不斷監(jiān)控原材料的庫存量(level),如果當(dāng)前庫存量低于我們定義的水平,它將致電供應(yīng)商進(jìn)行送貨。經(jīng)過一定的供應(yīng)周期后,一定量的原材料將到達(dá)我們?cè)牧蟼}庫。

          首先我們先定義我們的庫存預(yù)警水平。

          wood_critial_stock = (((8/mean_body) * num_body +(8/mean_neck) * num_neck) * 3electronic_critical_stock = (8/mean_ensam) * num_ensam * 2

          預(yù)警庫存的定義,取決于創(chuàng)建琴身或琴頸的平均時(shí)間,琴身和琴頸的制造工序數(shù)量。當(dāng)然這里我們也可以直接設(shè)定某一個(gè)數(shù)值。

          木材供應(yīng)周期為2天。
          我們?cè)谖覀兊腉uitar_Factory類定義里面添加一個(gè)預(yù)警操作過程。

          class Guitar_Factory:    def __init__(self, env):        self.wood = simpy.Container(env, capacity = wood_capacity, init = initial_wood)        self.wood_control = env.process(self.wood_stock_control(env))        self.electronic = simpy.Container(env, capacity = electronic_capacity, init = initial_electronic)        self.electronic_control = env.process(self.electronic_stock_control(env))        self.pre_paint = simpy.Container(env, capacity = pre_paint_capacity, init = 0)        self.post_paint = simpy.Container(env, capacity = post_paint_capacity, init = 0)        self.dispatch = simpy.Container(env ,capacity = dispatch_capacity, init = 0)

          def wood_stock_control(self, env): yield env.timeout(0) while True: if self.wood.level <= wood_critial_stock: print(f'在第{0}日 第{1}小時(shí),木材庫存 ({2})低于預(yù)警庫存水平下 '.format( int(env.now/8), env.now % 8,self.wood.level)) print('聯(lián)系供應(yīng)商') print('----------------------------------') yield env.timeout(16) print('在第{0}天 第{1}小時(shí),木材送達(dá)'.format(int(env.now/8), env.now % 8)) yield self.wood.put(300) print('當(dāng)前庫存是:{0}'.format( self.wood.level)) print('----------------------------------') yield env.timeout(8) else: yield env.timeout(1)


          我們?cè)贕uitar_Factory類中的__init__函數(shù)中增加wood_stock_control和electronic_stock_control兩個(gè)過程。我們看看wood_stock_control的過程是怎么樣工作的,上述代碼沒有electronic_stock_control過程,但原理是一樣的,你可以自己創(chuàng)建,也可以下載我的代碼。

          1. 首先yield env.timeout(0),意味著木材監(jiān)控進(jìn)程在仿真開始時(shí)就啟動(dòng),后面的yield env.timeout(16)yield env.timeout(8)表示如果預(yù)警產(chǎn)生供貨請(qǐng)求后,16小時(shí)后送貨到達(dá),然后再等待8小時(shí)后,我們恢復(fù)庫存監(jiān)控。

          2. while True表示該過程將在模擬運(yùn)行的所有時(shí)間內(nèi)執(zhí)行。

          3. 然后,它將檢查庫存水平是否等于或小于先前定義的臨界水平。如果庫存大于該水平,下一個(gè)時(shí)間單位再監(jiān)控yield env.timeout(1)

          4. 當(dāng)庫存水平等于或低于臨界水平時(shí),將執(zhí)行一些打印輸出時(shí)間和當(dāng)前庫存量,并且聯(lián)系供應(yīng)商送貨。

          5. 2天(16小時(shí))后,木材原材料到達(dá),木材原材料增加300到我們的倉庫中。yield self.wood.put(300)。

          6. 最后,將打印新庫存水平,并且警報(bào)將關(guān)閉1天(yield env.timeout(8))。

          我們將仿真運(yùn)行5天,結(jié)果如下:

          4)獨(dú)立倉庫和商場(chǎng)配送

          制作完琴身和琴頸后,我們將琴身和琴頸看作同一種東西,將它們存儲(chǔ)在同一個(gè)倉庫中(等待噴涂),這有點(diǎn)不合理。現(xiàn)在,我們將為琴身和琴頸分別實(shí)現(xiàn)單獨(dú)的容器(倉庫),我們可以對(duì)其進(jìn)行適當(dāng)處理。
          流程圖如下:


          guitars_made = 0
          body_pre_paint_capacity = 60neck_pre_paint_capacity = 60body_post_paint_capacity = 120neck_post_paint_capacity = 120
          class Guitar_Factory: def __init__(self, env): self.wood = simpy.Container(env, capacity = wood_capacity, init = initial_wood) self.wood_control = env.process(self.wood_stock_control(env)) self.electronic = simpy.Container(env, capacity = electronic_capacity, init = initial_electronic) self.electronic_control = env.process(self.electronic_stock_control(env)) self.body_pre_paint = simpy.Container(env, capacity = body_pre_paint_capacity, init = 0) self.neck_pre_paint = simpy.Container(env, capacity = neck_pre_paint_capacity, init = 0) self.body_post_paint = simpy.Container(env, capacity = body_post_paint_capacity, init = 0) self.neck_post_paint = simpy.Container(env, capacity = neck_post_paint_capacity, init = 0) self.dispatch = simpy.Container(env ,capacity = dispatch_capacity, init = 0) self.dispatch_control = env.process(self.dispatch_guitars_control(env))

          我們現(xiàn)在已經(jīng)知道如何制作一個(gè)容器(倉庫)了。注意這里新增一個(gè)guitars_made變量和dispatch_control方法。當(dāng)然,我們需要修改body_maker和neck_maker兩個(gè)函數(shù)(工序),把生產(chǎn)出來的琴身和琴頸分開獨(dú)立倉庫存放:

          def body_maker(env, guitar_factory):    while True:        yield guitar_factory.wood.get(1)        body_time = random.gauss(mean_body, std_body)        yield env.timeout(body_time)        yield guitar_factory.body_pre_paint.put(1)

          現(xiàn)在,我們將琴身存儲(chǔ)在body_pre_paint容器中(倉庫)。neck_maker函數(shù)也一樣處理。painter函數(shù)(工序)的提取半成品原料來源的倉庫(容器)也需要做相應(yīng)的修改,讓painter工序分別在琴身倉庫和琴頸倉庫提取材料:

          def painter(env, guitar_factory):    while True:        yield guitar_factory.body_pre_paint.get(5)        yield guitar_factory.neck_pre_paint.get(5)        paint_time = random.gauss(mean_paint, std_paint)        yield env.timeout(paint_time)        yield guitar_factory.body_post_paint.put(5)        yield guitar_factory.neck_post_paint.put(5)

          噴涂好的琴身和琴頸,分別存放在body_post_paint和neck_post_paint容器(倉庫)中。

          現(xiàn)在,我們像在電子元件或木材上一樣建立一個(gè)控制過程。這個(gè)過程會(huì)跟蹤吉他成品的庫存水平,并通知商店過來取貨。

          def dispatch_guitars_control(self, env):        global guitars_made        yield env.timeout(0)        while True:            if self.dispatch.level >= 50:                print('成品庫存為:{0}, 在第{1}日 第{2}小時(shí) 聯(lián)系了商場(chǎng)取貨'.format(self.dispatch.level, int(env.now/8), env.now % 8))                print('----------------------------------')                yield env.timeout(4)                print('在第{0}日 第{1}小時(shí),商場(chǎng)取走{2}吉他'.format(int(env.now/8), env.now % 8,self.dispatch.level))                guitars_made += self.dispatch.level                yield self.dispatch.get(self.dispatch.level)                print('----------------------------------')                yield env.timeout(8)            else:                yield env.timeout(1)


          我們創(chuàng)建了一個(gè)名為guitars_made全局變量,記錄我們的總產(chǎn)量。
          如果成品庫存水平等于或高于50,我們會(huì)通知商店過來取貨。4小時(shí)后yield env.timeout(4),他們到達(dá)倉庫并拿走所有可用的吉他yield self.dispatch.get(self.dispatch.level)


          當(dāng)他們?nèi)∽呒麜r(shí),我們用語句guitars_made + = self.dispatch.level將吉他的數(shù)量累加到guitars_made變量,用于記錄我們總共出貨了多少吉他。
          然后,控制過程將暫停8個(gè)單位時(shí)間yield env.timeout(8),當(dāng)然也可以不暫停,不暫停的話,這里也不會(huì)觸發(fā),因?yàn)槌善穾齑嫠绞遣蛔愕模蛘弋?dāng)天不會(huì)再來取貨。


          組裝工序也需要修改為分別從兩個(gè)待組裝的倉庫中提取半成品。

          def assembler(env, guitar_factory):    while True:        yield guitar_factory.body_post_paint.get(1)        yield guitar_factory.neck_post_paint.get(1)        yield guitar_factory.electronic.get(1)        assembling_time = max(random.gauss(mean_ensam, std_ensam), 1)        yield env.timeout(assembling_time)        yield guitar_factory.dispatch.put(1)


          最后,添加一些打印信息并運(yùn)行仿真程序:

          print('當(dāng)前等待噴涂的琴身數(shù)量:{0} 和琴頸數(shù)量:{1}'.format(    guitar_factory.body_pre_paint.level, guitar_factory.neck_pre_paint.level))print('當(dāng)前等待組裝的琴身數(shù)量:{0} 和琴頸數(shù)量:{1}'.format(    guitar_factory.body_post_paint.level, guitar_factory.neck_post_paint.level))print(f'當(dāng)前成品庫存量:%d ' % guitar_factory.dispatch.level)print(f'----------------------------------')print('此周期的吉他總生產(chǎn)數(shù)量: {0}'.format(guitars_made + guitar_factory.dispatch.level))print(f'----------------------------------')print(f'仿真完成!')



          5)監(jiān)控

          我們希望監(jiān)控每一個(gè)時(shí)間點(diǎn)上,仿真系統(tǒng)各個(gè)節(jié)點(diǎn)的狀態(tài),比如我們想記錄每個(gè)時(shí)間點(diǎn)的待組裝的琴身的庫存量并實(shí)時(shí)作圖。

          我們?cè)黾右粋€(gè)監(jiān)控過程函數(shù),用來監(jiān)控我們的等待組裝的琴身和琴頸的半成品庫存,看最后一行是我們新增的監(jiān)控過程env_status。

          class Guitar_Factory:    def __init__(self, env):        self.wood = simpy.Container(env, capacity = wood_capacity, init = initial_wood)        self.wood_control = env.process(self.wood_stock_control(env))        self.electronic = simpy.Container(env, capacity = electronic_capacity, init = initial_electronic)        self.electronic_control = env.process(self.electronic_stock_control(env))        self.body_pre_paint = simpy.Container(env, capacity = body_pre_paint_capacity, init = 0)        self.neck_pre_paint = simpy.Container(env, capacity = neck_pre_paint_capacity, init = 0)        self.body_post_paint = simpy.Container(env, capacity = body_post_paint_capacity, init = 0)        self.neck_post_paint = simpy.Container(env, capacity = neck_post_paint_capacity, init = 0)        self.dispatch = simpy.Container(env ,capacity = dispatch_capacity, init = 0)        self.dispatch_control = env.process(self.dispatch_guitars_control(env))        self.env_status_monitor = env.process(self.env_status(env))

          我們看看env_status是如何實(shí)現(xiàn)的。

          def env_status(self, env):  global status  status = pd.DataFrame(columns = ["datetime", "dispatch_level",'wood','electronic','body_pre_paint','neck_pre_paint','body_post_paint','neck_post_paint'])  status[["datetime", "dispatch_level",'wood','electronic','body_pre_paint','neck_pre_paint','body_post_paint','neck_post_paint']] = status[["datetime", "dispatch_level",'wood','electronic','body_pre_paint','neck_pre_paint','body_post_paint','neck_post_paint']].astype(int)  while True:    im = plt.plot(status['datetime'], status['neck_pre_paint'],color='#4D9221')    ims.append(im)    plt.title('neck_pre_paint')    plt.pause(0.001)    print('{0}在第{1}日 第{2}小時(shí),成品庫存量:{3}'.format(env.now,int(env.now/8), env.now % 8,self.dispatch.level))    tmp = {'datetime':env.now,         'dispatch_level':self.dispatch.level,         'wood':self.wood.level,         'electronic':self.electronic.level,         'body_pre_paint':self.body_pre_paint.level,         'neck_pre_paint':self.neck_pre_paint.level,         'body_post_paint':self.body_post_paint.level,         'neck_post_paint':self.neck_post_paint.level         }    status = status.append([tmp])
          yield env.timeout(1)

          我們先定義一個(gè)全局變量status,是一個(gè)pandas的dataframe類型,并且定義好它的結(jié)構(gòu),第一列是時(shí)間,后面各列是各個(gè)節(jié)點(diǎn)(容器))的庫存,并把庫存列定義為int整型。
          這里我們只用body_pre_paint待組裝的琴身庫存舉例。
          我們通過stock_list變量組裝好一個(gè)字典,然后把它追加到status變量中。看起來是這樣子的:

          然后我們通過matplotlib模塊把它用動(dòng)態(tài)圖表現(xiàn)出來。
          記得程序之前需要導(dǎo)入這個(gè)模塊,并且用plt.ion()用做動(dòng)態(tài)圖。

          import matplotlib.pyplot as plt

          plt.ion()

          在監(jiān)控函數(shù)中我們用下面的代碼來每一個(gè)時(shí)間間隔畫一次圖片。

          plt.plot(status['datetime'], status['neck_pre_paint'],color='#4D9221')

          得到neck_pre_paint的庫存變化圖,如下:

          要監(jiān)控其他庫存,只需要修改stock_list,并追加到status中,然后plot作圖即可。你也可以對(duì)status進(jìn)行統(tǒng)計(jì)各個(gè)節(jié)點(diǎn)的平均庫存。

          根據(jù)上文的系統(tǒng)配置,我們很簡單就發(fā)現(xiàn)了等待噴涂的琴頸庫存和等待噴涂的琴身的庫存不匹配,有點(diǎn)偏高,所以我們可以調(diào)整琴頸生產(chǎn)的一些參數(shù),來得到更好的庫存水平。

          比如修改這個(gè)

          或者修改這個(gè)

          至此,我們完成了一個(gè)比較完整的仿真!希望您喜歡,并且可以從中獲得有用的東西。

          本文完整代碼,請(qǐng)?jiān)诠娞?hào)內(nèi)回復(fù)“仿真”進(jìn)行下載。

          瀏覽 260
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  69视频免费在线 | 蜜芽成人网站 | 俺来也俺去也www色官网 | 天堂草原电视剧在线观看图片高清 | 欧美日韩免费观看一区=区三区 |