The world’s leading publication for data science, AI, and ML professionals.

Simulating Brewing Operations with SimPy in Python

A tutorial for discrete event simulation in python


Photo by Roberta keiko Kitahara Santana on Unsplash
Photo by Roberta keiko Kitahara Santana on Unsplash

Industrial Engineers use discrete event simulation to evaluate alternatives on the manufacturing floor, but there are many more uses for simulation. With the SimPy package for Python– and also available in other languages- we can simulate personal projects without an expensive software license. The ReadtheDocs documentation for SimPy is good; I recommend reading that cover-to-cover more than once. But this article is for those of us that love additional examples for learning.


Introduction to SimPy with an Example

Simpy uses generator functions with a yield rather than a return, in order to store the latest step in the simulation. For an introduction to generator functions I recommend Kevin Conrad’s youtube tutorial.

This initial model utilizes the SimPy framework to start a brewing process and then clean the brewing tank afterwards. The subsequent models will be more complex.

Before importing simpy, you may need to install SimPy if you haven’t already. To install SimPy you may use pip or the alternative methods written in the SimPy documentation.

pip install simpy

Output:

Starting to brew a lager at time 0
Finished brewing the lager at time 30
Starting to brew a lager at time 35
Finished brewing the lager at time 65
Starting to brew a lager at time 70
Finished brewing the lager at time 100

In this case, the model terminated with the time unit reaching 101. The next model will terminate once the loop that processes all of the brewing processes terminates.


Using Resources and modeling processes in SimPy

Now I have 3 brewery tanks of equal size. I’m still brewing just lagers, but I want to start a new tank on days 0, 5, 11, and 20 if there are available tanks on those days. I’m on vacation on days 12–18, so I won’t want to start a brewing process during those days.

The brewing process time for lagers is still assumed to be 30 days in this model, although I realize that the brewing process time is actually variable. We’ll add a probability distribution for the processing time in the next model.

For now, the focus of this model is the type of resource, called a Resource (rather than the Container resource or the Store resource).

  • This _brewerytanks Resource will serve as the process in this model.
  • Resources are requested and then released after they are no longer in use.
  • While in use, the count of the resource will reveal how many if the resource’s capacity units are in use.

    Output:

Decide to start brewing a lager at time 0
    Number of tanks available: 3
    Started brewing at time 0
    Number of tanks now in use: 1
Decide to start brewing a lager at time 5
    Number of tanks available: 2
    Started brewing at time 5
    Number of tanks now in use: 2
Decide to start brewing a lager at time 11
    Number of tanks available: 1
    Started brewing at time 11
    Number of tanks now in use: 3
Decide to start brewing a lager at time 20
    Number of tanks available: 0
Finished brewing a lager at time 30
Finished brewing a lager at time 35
There are 1 tanks available at time 35
    Started brewing at time 35
    Number of tanks now in use: 3
There are 1 tanks available at time 40
Finished brewing a lager at time 41
There are 2 tanks available at time 46
Finished brewing a lager at time 65
There are 3 tanks available at time 70

I chose a good time to go on vacation, as there weren’t any available tanks then anyway. Actually there weren’t any available tanks until time 35.

As you can see, the outputs from the Simulation model are interesting to reflect upon. A section for deeper reading in the documentation called monitoring discusses more advanced methods of saving and monitoring outputs from the model. But for this introduction and many other scenarios, the print statements are sufficient.


Simulating with randomness

While it is possible to calculate deterministic simulation outcomes mathematically rather than to utilize a simulation model, simulations are useful for storytelling and automating data processing. Stochastic models will provide even more insights for modeling scenarios that are closer to real situations.

I read multiple resources that described brewing a lager and shared the typical brewing schedule is 4–8 weeks. The yeast will do what the yeast does, but not always on your schedule. Let’s assume a normal distribution with the mean=6 weeks and standard deviation=1 week. Once the brew has cooled (we’ll assume that is part of the process), then we’ll can or bottle the beer and store it in inventory, at the rate of 100 cases per brewery tank.

In order to track inventory, another type of resource called a Container is introduced to this model. While the Container is similar to a Resource in that they both have a capacity parameter, the Container also has an initial level parameter, and the level of the the container at a given time will reveal the amount that the container is storing.

A Container’s level can increase with a put or decrease with a get, which enables different modeling capabilities than a Resource.

Output:

Number of tanks available at time 0: 3
Started brewing at time 0 and 1 tanks now in use
Number of tanks available at time 5: 2
Started brewing at time 5 and 2 tanks now in use
Number of tanks available at time 11: 1
Started brewing at time 11 and 3 tanks now in use
Number of tanks available at time 20: 0
Finished brewing a lager at time 38.30356066389249
At time 43.30356066389249 there are now:
    1 tanks available
    100 cases of cans available for sale
Started brewing at time 43.30356066389249 and 3 tanks now in use
Finished brewing a lager at time 44.85515309121678
At time 49.85515309121678 there are now:
    1 tanks available
    200 cases of cans available for sale
Finished brewing a lager at time 53.146254345432425
At time 58.146254345432425 there are now:
    2 tanks available
    300 cases of cans available for sale
Finished brewing a lager at time 85.11565243779629
At time 90.11565243779629 there are now:
    3 tanks available
    400 cases of cans available for sale

Processing Orders

Now that you understand how to use two types of Resources, Resource and Container, the next model shares one way to process orders and sell that inventory. While this is a simple method to process orders, more complex methods might need the use of the AllOf of AnyOf SimPy events.

Output:

Before order processing, cases available: 100
After order of 1, cases available: 99
After order of 10, cases available: 89
After order of 5, cases available: 84
After order processing, cases available: 84

I hope that you found this Tutorial helpful. If you have suggestions for a Part II Brewery Simulation or would like to collaborate on the next SimPy model, I’d enjoy reading your thoughts!


Related Articles