Search code examples
pythonsimulationsimpy

use simpy.resource simulate logistics scheduling


I want to use simpy.Resource to create 4 vehicles to carry goods. The main process sends a car every 10 minutes. So it works like 1,2,3,4, 1,2,3,4. And each car takes 70 minutes to deliver. After the first vehicle is dispatched, it must wait for 70 minutes before being dispatched again.

I use this code, but it doesn't works.

def main(self):
    while True:
        print(f"{self.env.now}")
        car = Car(self.env,capacity=4) 
        yield from slef.send(car)
def send(self, car):
    while True:
        yield env.timeout(10)
        with car.request() as req:
            yield req
            print(f"{self.env.now} - car {car.count} -start")
            print(car.users)

class Car(simpy.Resource):
    def __init__(self, env, capacity=float('inf')) -> None:
        super(Car, self).__init__(env, capacity)

    def _do_get(self, event) -> None:
        try:
            self.users.remove(event.request)  # type: ignore
            yield env.time(70)
        except ValueError:
            pass
        event.succeed()
    def _do_put(self, event) -> None:
        if len(self.users) < self.capacity:
            self.users.append(event)
            event.usage_since = self._env.now
            event.succeed()

Solution

  • You do not need to customize the resource pool

    You just need a process per car to get car, send car, return car

    """"
    Quick car resouce example
    
    Programmer: Michael R. Gibbs
    
    """
    
    import simpy
    
    def main(env, car_pool):
    
        for i in range(car_pool.capacity):
            # create one process per car in pool
            env.process(send_car(env,car_pool))
    
    
    def send_car(env, car_pool):
        """
        get car from resouece pool
        send car
        return car to resouce pool
        """
        while True:
            with car_pool.request() as req:
                yield req
                print(f'{env.now} car dispatched')
                yield env.timeout(70)
            print(f'{env.now} car returned')
    
    env = simpy.Environment()
    
    car_pool = simpy.Resource(env, 4)
    main(env, car_pool)
    
    env.run(500)
    

    or, if your goal is to request sending a car every 10 minutes, then try this

    """"
    Quick car resouce example
    
    Programmer: Michael R. Gibbs
    
    """
    
    import simpy
    
    def main(env, car_pool):
    
        for i in range(car_pool.capacity):
            # create one process per car in pool
            env.process(send_car(env,car_pool))
    
    
    def send_car(env, car_pool):
        """
        get car from resouece pool
        send car
        return car to resouce pool
        """
        while True:
            with car_pool.request() as req:
                yield req
                print(f'{env.now} car dispatched')
                yield env.timeout(70)
            print(f'{env.now} car returned')
    
    env = simpy.Environment()
    
    car_pool = simpy.Resource(env, 4)
    main(env, car_pool)
    
    env.run(500)