Search code examples
pythonsimulationsimpy

Simpy: increase store count only if sub stores have items


I'm trying to model a manufacturing line where some machines depends on specific items produced by other machines and can't start its job until previous ones put the items into their stores.

For example:

We have 4 Machines (A, B, C, D), Machine A has a Store A* (B,C,D Stores correspondingly).
Machine A can start work only if there's an item in Store A*. Item in A* consists of three items from B*, C*, D* Stores.

Is there any way to increase count in Store A* only if Stores B*, C*, D* have at least one item?


Solution

  • You need to use the env.all_of event to wait for a set of events to finish. In this case, 3 get() events from the three ouput queues from 3 machines. see the example

    """
    Simple model how one machine does not start until it has multiple inputs
    
    Programmer: Michael R. Gibbs
    """
    
    import simpy
    import random
    
    class Entity(object):
        pass
    
    def imput_process(env, id_pre, time_func, out_q):
        """
        simple loop to generate output entities
        to be consumed by the out process
        """
        
        cnt = 0
    
        while True:
            yield env.timeout(time_func())
    
            cnt += 1
            ent = Entity()
            ent.id = id_pre + ' ' + str(cnt)
    
            out_q.put(ent)
            print(f'{env.now} made entity {ent.id}')
    
    def out_process(env, a_q, b_q, c_q, time_func):
        """
        waits until has a entity from each of the queues
        then do some processing
        """
    
        while True:
    
            # make the requests in parrelle
            # note no yields here
            req_a = a_q.get()
            req_b = b_q.get()
            req_c = c_q.get()
    
            # now us a all_of to wait for all 
            # the requests to finish
            response = yield env.all_of([req_a, req_b, req_c])
    
            # response is a dict where key is the reqest and value is 
            # what is what would be returned by a yield to the request
    
            ent_a = response[req_a]
            ent_b = response[req_b]
            ent_c = response[req_c]
    
            print(f'{env.now} out has entites {ent_a.id}, {ent_b.id}, {ent_c.id}')
    
            yield env.timeout(time_func())
    
            print(f'{env.now} out process completed')
    
    # bootup
    
    env = simpy.Environment()
    
    store_a = simpy.Store(env)
    store_b = simpy.Store(env)
    store_c = simpy.Store(env)
    
    env.process(imput_process(env, 'A', lambda : random.triangular(1,1,5), store_a))
    env.process(imput_process(env, 'B', lambda : random.triangular(1,3,5), store_b))
    env.process(imput_process(env, 'C', lambda : random.triangular(1,5,5), store_c))
    
    env.process(out_process(env, store_a, store_b, store_c, lambda : random.triangular(1,2,4)))
    
    env.run(100)