1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 16295字,需瀏覽 33分鐘

         ·

        2021-03-17 17:18

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

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

        仿真技術(shù)是再現(xiàn)系統(tǒng)動態(tài)行為、分析系統(tǒng)配置與參數(shù)是否合理、預(yù)測瓶頸工序、判斷系統(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è)琴身,然后將其存儲在琴身倉庫中。琴頸也一樣,但是從1單位木材上得到2個(gè)琴頸。琴頸存儲在琴頸倉庫中,琴身和琴頸都在等待噴涂。

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

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

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

        6. 當(dāng)木材或電子元件的原材料庫存低到一定水平時(shí),會聯(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)境,我們后面會說明。

        現(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í)間單位,將會產(chǎn)出一個(gè)琴身或琴頸,它模擬了車間的生產(chǎn)時(shí)間。

        3. 在該時(shí)間單位(在我們的示例中為1)過去之后,車間會將產(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)過程會在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)在我們增加噴涂工序和組裝工序到我們的業(yè)務(wù)模型。為了達(dá)到目的,我們增加:

        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)容,我們增加了電子元件、噴涂前和噴涂后的倉庫,并設(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)

        正如我們在生產(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í),不會有任何的偏差。
        實(shí)際上,工序生產(chǎn)產(chǎn)品的時(shí)間都是在一個(gè)平均時(shí)間上下波動的,我們假設(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)不會少于一小時(shí)。很多情況下都需要這種設(shè)定,不然有可能生成的隨機(jī)數(shù)可能是負(fù)數(shù)(仿真過程將會出錯(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á)我們原材料倉庫。

        首先我們先定義我們的庫存預(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天。
        我們在我們的Guitar_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)


        我們在Guitar_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í)就啟動,后面的yield env.timeout(16)yield env.timeout(8)表示如果預(yù)警產(chǎn)生供貨請求后,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ú)立倉庫和商場配送

        制作完琴身和琴頸后,我們將琴身和琴頸看作同一種東西,將它們存儲在同一個(gè)倉庫中(等待噴涂),這有點(diǎn)不合理?,F(xiàn)在,我們將為琴身和琴頸分別實(shí)現(xiàn)單獨(dú)的容器(倉庫),我們可以對其進(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)在,我們將琴身存儲在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è)過程會跟蹤吉他成品的庫存水平,并通知商店過來取貨。

        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)系了商場取貨'.format(self.dispatch.level, int(env.now/8), env.now % 8))                print('----------------------------------')                yield env.timeout(4)                print('在第{0}日 第{1}小時(shí),商場取走{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,我們會通知商店過來取貨。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)然也可以不暫停,不暫停的話,這里也不會觸發(fā),因?yàn)槌善穾齑嫠绞遣蛔愕?,或者?dāng)天不會再來取貨。


        組裝工序也需要修改為分別從兩個(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í)作圖。

        我們增加一個(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模塊把它用動態(tài)圖表現(xiàn)出來。
        記得程序之前需要導(dǎo)入這個(gè)模塊,并且用plt.ion()用做動態(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作圖即可。你也可以對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è)比較完整的仿真!希望您喜歡,并且可以從中獲得有用的東西。

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

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

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            蜜桃AV网站 | 积积桶肤肤免费软件大全2025 | 韩国三级电影天堂 | 免费看国产成人A级视频 | 在线黄色国产 | 深夜艹逼逼 | 亚洲图片三区 | 91麻豆精品无码一区二区三区 | 国产亚洲AV无码成人片 | 国产白嫩护士被弄高潮91 |