pythonsimpyevent-simulation

Can you do you a closed loop system using SimPy on Python?


I am trying to model a garage which has cars available to drive. Then as times goes by cars need some repairs and they become unavailable. Once the car is repaired it goes back to the garage.

I was wondering if you can model such a system where you can keep looping the same cars back into the garage? Also, interested in tracking the unavailability of the cars...


Solution

  • Yes you can. Here is a example of a garage where cars get pulled from service for maintenance. Note when a car needs maintenance it may not be in the garage.

    """
    Simple simulation of resources that get pulled from service for maintenance
    
    Programmer: Michael R. Gibbs
    """
    
    import simpy
    import random
    
    class Car():
        """
        The resouces
        Cars require maintenance at random intervals
    
        If maintenace is required while the car is in use, maintenace is done 
        when it is returned to the garage.
        """
    
        def __init__(self,env , id, garage):
    
            self.env = env
            self.id = id
            self.garage = garage
            self.needs_repair = False
            self.down_time = 0
            self.env.process(self.repair_events())
    
        def repair_events(self):
            """
            Flags when the car needs maintenace
            """
    
            while(True):
                yield self.env.timeout(random.randint(15,20))
                self.needs_repair = True
    
                # checks if car is in the garge and can have maintence
                self.env.process(self.garage.need_repairs(self))
    
    class Garage():
        """
        Manages the car resources
    
        does repairs on the cars when needed
        """
    
        def __init__(self, env, numOfCars):
    
            self.env = env
            self.store = simpy.Store(env,numOfCars)
            self.store.items = [Car(env, id + 1, self) for id in range(numOfCars) ]
    
        def need_repairs(self, car):
            """
            Notifies the garage that the car needs maintenace
            If the car is in the garage then it is pulled from service,
            has it maintenace done, and then put back in service
    
            If the car is not in the garage, maintence is done when the 
            car returns to the garage
            """
    
            if car in self.store.items:
                print(self.env.now, f"car {car.id} needs maintenance and is in the garage")
                self.store.items.remove(car)
                yield env.process(self.make_repairs(car))
                self.store.put(car)
    
    
        def make_repairs(self, car):
            """
            Do maintenace on a car
            """
    
            print(self.env.now, f'making repairs to car {car.id}')
            repair_time = random.randint(2,5)
            yield self.env.timeout(repair_time)
    
            car.needs_repair = False
            car.down_time += repair_time
    
            print(self.env.now,f'finished repairs to car {car.id}')
    
        def put(self, car):
            """
            Return a car back to the garage
            Checks if car needs maintenace
            """
    
            print (self.env.now, f'car {car.id} has return to the garage')
    
            if car.needs_repair:
                yield env.process(self.make_repairs(car))
            
            self.store.put(car)
    
    
        def get(self):
            """
            Pulls a car from the garage
            """
            
            car = yield self.store.get()
            print(self.env.now, f"car {car.id} is leaving the garage")
    
            return car
    
    def use_car(env, garage):
        """
        Process for getting a car, use it for a random time, and return it to the garage
        """
    
        print(env.now,f"starting use car process with {len(garage.store.items)} cars in the garage")
        car = yield env.process(garage.get())
        print(env.now, f'using car {car.id}')
        yield env.timeout(random.randint(1,4))
        yield env.process(garage.put(car))
        print(env.now,f'returned car {car.id}')
    
    def sched_cars(env,garage):
        """
        Generates requests for cars
        """
    
        while True:
            yield env.timeout(random.randint(1,5))
            env.process(use_car(env,garage))
    
    # boot up the simulation
    env = simpy.Environment()
    garage = Garage(env,10)    
    
    env.process(sched_cars(env, garage))
    
    env.run(200)
    for car in garage.store.items:
        print(f'car {car.id} down time is {car.down_time}')