pythonsimulationsimpyevent-simulation

Simulating factory manufacture with simpy by requesting multiple resources at the same time, but running for different time


I was trying to simulate a factory manufacturing different products with different machines with simpy. For each product, we will need to allocate different machines for production. For example, the first product will ask for machines 1, 2, 5 sequentially and the second product requires machines 2, 3, and 5. For my case, I will be given a list of products we are going to manufacture and the corresponding information to make the products. One example is shown below.

Given workflow for product manufacturation

My situation was unlike most simpy simulations. I want to simulate the process of the given list of processes (with information on the machine and running time). Please note that the given list of processes comes with unfixed length, which is saying the program does not know how many events and which resources to allocate beforehand.

My problem is how to deal with the event dependencies and how to deal with requesting resources for the cases shown in the figure. A simplified example is to use ExitStack as a generalized way of context manager to request resources to run for the same duration, e.g. Requesting multiple resources simultaneously. But for my case, the dependent events (e.g. A2 and A3 in the first workflow) may run for a different duration. One may think that I can request the maximum running time out of A2 and A3. But this leads to undesired resource waste.

Any comments would be appreciated. Thank you very much!

I have tried to Google everything online and learned the most related case is Requesting multiple resources simultaneously.


Solution

  • Just an idea: it seems like each job could be split into parts which can be run independently, and which a later part depends on ?
    e.g. for the first one (colored in green):

    This way, the problem could be described as a job shop with additional precedence constraints (between last/first tasks of different jobs belonging to the same product).

    This could also make it simpler to create a simulation model, since each job (no matter whether its preceding another job or not) can just request the resource it needs for every step (and for the exact duration this step takes).
    To notify a dependent job of the completion of the jobs it depends on, a simpy AllOf event could be used:

    all_preceding_jobs_completed = AllOf(env, preceding_jobs_completion_events)
    all_preceding_jobs_completed.callbacks.append(job.mark_ready)
    

    just for illustration, a simpy/casymda-model for the described problem could look like this:
    (for the sake of a simple animation just 6 machines are modeled, instead of a flexible number) casymda-animation

    Each machine may just process one job at a time, and jobs cycle through the process until completed, waiting for machines as needed. The two depending jobs product_1 and product_2 are released when all predecessors were completed. sample code on github

    In the animated example model, each job is naively released from the buffer as soon as it becomes ready (all predecessor jobs completed, or immediately in case there are no predecessors), resulting in a makespan of 87.
    (To find better schedules (for more complex cases) it might also be interesting to look for an analytical solution e.g. as described here https://developers.google.com/optimization/scheduling/job_shop)