Visualization of SimPy parking lot simulation results

I recently shared a Python simulation modeling example using SimPy in Python. Using SimPy, a discrete-event simulation library available in Python, I modeled a parking lot with a defined amount of slots and a defined car arrival process. In this follow-up tutorial on visualization of SimPy simulation models I show how, using the same baseline example, data on parking lot slot utilization can be collected and visualized. In upcoming articles I will furthermore show how the parking lot itself can be animated using Python and SimPy.

Why SimPy is relevant to operations and logistics managers

SimPy, the open-source discrete-event simulation library for Python, offers a valuable tool for supply chain managers. It’s not about isolated features, but rather about how SimPy empowers these professionals to tackle the complexities of supply chain management.

One of SimPy’s standout advantages is its ability to create realistic models of supply chain operations. These models closely resemble the actual processes within a supply chain, making it easier for managers to analyze and understand their operations. In a field where the real-world operations can be incredibly intricate, having a simulation tool that accurately reflects these complexities is indispensable.

What makes SimPy even more appealing is its flexibility. It’s a general-purpose simulation library, which means supply chain managers can adapt it to model various aspects of their operations. Whether it’s inventory management, order processing, demand forecasting, transportation, or any other critical element of the supply chain, SimPy can be tailored to address specific challenges.

SimPy’s strength also lies in its ability to facilitate “what-if” analysis. Supply chain managers can use SimPy to test different scenarios and strategies. They can explore the impact of changes in their operations, helping them make informed decisions about optimizing supply chain processes. This ability to model different scenarios and predict outcomes is invaluable for strategic planning.

In a world where efficiency is paramount, SimPy aids in performance optimization. Supply chain managers can simulate their processes, identify bottlenecks and inefficiencies, and work on strategies to enhance overall performance. This optimization can lead to reduced costs and improved customer service.

Supply chain resilience is critical, and SimPy is a valuable tool for risk management. By modeling various risk scenarios, managers can assess the vulnerabilities in their supply chains and develop contingency plans to mitigate potential disruptions. This is essential in today’s globalized and often unpredictable supply chain landscape.

Resource allocation is another area where SimPy proves its worth. It can simulate how resources such as labor, machines, and storage space are allocated in different scenarios. This insight helps managers make informed decisions about resource planning, ensuring that resources are used efficiently and effectively.

Cost reduction is a significant benefit of using SimPy. By identifying inefficiencies and optimizing processes, managers can potentially reduce costs associated with inventory, transportation, and other operational aspects. This cost reduction directly impacts the bottom line of a company.

Model additions for visualization of SimPy parking lot model

In my previous SimPy parking lot model example I already the code of the parking lot baseline model. You can find the coding example here: SimPy parking lot simulation modeling example

In the baseline model there was no visualization. Car arrivals and departures on and from the parking lot were simply printed into the console. Now we will implement a visualization of SimPy simulation results.

In order to be able to visualize simulation results we must collect relevant simulation data, and we must monitor relevant values throughout simulation. After running the simulation the collected data is then visualized with matplotlib.pyplot.

There are several ways for how to monitor values in a SimPy simulation model, but the easiest way (for SimPy beginners) for getting started with monitoring the amount of occupied and available parking spots is to implement a custom SimPy monitoring process:

def monitor_parkingspot(self) -> None:

 
        while self.env.now <= self.simdata.duration:

            self.simdata.data_timeseries[self.env.now, 0] = self.env.now
            self.simdata.data_timeseries[self.env.now, 1] = self.spots_occupied
            self.simdata.data_timeseries[self.env.now, 2] = self.spots_available

            yield self.env.timeout(1)

I added a method to the ParkingLot class for implementing a custom monitoring process. This process checks the simulation time, the number of available spots and the number of available spots, and writes these values into a numpy ndarray. You can see from above example, that the ParkingLot class has some additional attributes and variables: .data_timeseries (: numpy.ndarray), .spots_occupied (: int), and .spots_available (: int). This is what the header and constructor of the class looks like now:

class ParkingLot:

    env             :simpy.Environment
    capacity        :int
    spots           :simpy.resources.container.Container
    spots_occupied  :int
    spots_available :int
    simdata         :Simdata

    def __init__(self, 
        env      :simpy.Environment, 
        capacity :int,
        duration :int
        ):
        
        """ constructor """
        
        self.env = env
        self.capacity = capacity
        self.spots = simpy.resources.container.Container(env, capacity, init=capacity)
        self.spots_occupied = 0
        self.spots_available = capacity
        self.simdata = Simdata(duration= duration)
        self.simdata.data_timeseries = np.zeros([duration+1, 3], dtype = int)

For the .simdata attribute, I wrote a small little class, Simdata. I will write more methods and attributes into this class in future tutorials, so I wanted to introduce it at this point.

class Simdata:

    duration         :int
    data_timeseries  :np.ndarray

    def __init__(self, 
        duration :int,
        ):
    
        """ constructor """

        self.duration = duration
        self.data_timeseries = np.zeros(duration+1, dtype = float)

The number of occupied and available spots, now variables of the ParkingLot class, are updated throughout the car arrival process:

def car_arrival(self,
        car_id          :int, 
        dwelltime_min   :float,
        dwelltime_max   :float
        )               -> None:
        """ 
    
        implement simpy process; 
        models car arrivals in the parking lot, occupying a slot for a randomly distributed duration
    
        """
    
        #print(f"Car {car_id} arrives at {self.env.now}")
    
        yield self.spots.get(1)

        self.spots_occupied += 1
        self.spots_available -= 1
        
        #print(f"Car {car_id} parks at {self.env.now}")
        
        yield self.env.timeout(random.uniform(dwelltime_min, dwelltime_max))
        
        #print(f"Car {car_id} leaves at {self.env.now}")
        
        self.spots_occupied -= 1
        self.spots_available += 1

        yield self.spots.put(1)

This facilitates results collection during simulation. I can now plot results after the simulation run is completed.

Visualizing occupied and available slots, using SimPy generated results

The last step is simple: I use matplotlib.pyplot to create a line lot showing the amount of occupied and available parking slots on the parking lot throughout simulation time.

env.process(parking_lot.monitor_parkingspot())

# run the model
env.run()

# plot simulation results
plt.plot(parking_lot.simdata.data_timeseries[:,1], linestyle = 'dotted', color = "red", label = "occupied")
plt.plot(parking_lot.simdata.data_timeseries[:,2], linestyle = 'dotted', color = "green", label = "available")
plt.legend()
plt.xlabel("sim time")
plt.ylabel("# of spots")
plt.title("parking lot utilization over time")
plt.show()

You can see that I added another SimPy process when setting up the simulation model before its execution. This is the monitoring process. It collects simulation results at every simulation increment, and stores these values in a numpy ndarray.

Here is what the results look like.

The parking lot, in this scenario, is under-utilized. 2 parking spots would have been enough for this specific car arrival scenario.

Concluding remarks and related content

In this tutorial I showed how you can monitor relevant SimPy model values throughout simulation time, and how you can implement visualization of SimPy simulation results using matplotlib.pyplot in Python.

Here are some related articles that you also might be interested in:

You May Also Like

Leave a Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.