Search code examples
pythonsimulationsimpytraffic-simulationevent-simulation

How to simulate a starting queue before opening times in a Simulation process with Simpy?


I am studying SimPy and I came across this interesting tutorial that allows to simulate a queue in a bank.

I wanted to know if it is possible and how to create an initial queue.

Let's assume that the bank opens at 09:00 but we have already 20 customers waiting to be served + the other that will come with the defined probabilistic arrival rate.

How to do that? Thank you for you support.

"""
Bank with multiple queues example
Covers:
- Resources: Resource
- Iterating processes
Scenario:
  A multi-counter bank with a random service time and customers arrival process. Based on the
  program bank10.py from TheBank tutorial of SimPy 2. (KGM)
By Aaron Janeiro Stone
"""
from simpy import *
import random

maxNumber = 30      # Max number of customers
maxTime = 400.0     # Rumtime limit
timeInBank = 20.0   # Mean time in bank
arrivalMean = 10.0  # Mean of arrival process
seed = 12345        # Seed for simulation


def Customer(env, name, counters):
    arrive = env.now
    Qlength = [NoInSystem(counters[i]) for i in range(len(counters))]
    print("%7.4f %s: Here I am. %s" % (env.now, name, Qlength))
    for i in range(len(Qlength)):
        if Qlength[i] == 0 or Qlength[i] == min(Qlength):
            choice = i  # the chosen queue number
            break
    with counters[choice].request() as req:
        # Wait for the counter
        yield req
        wait = env.now - arrive
        # We got to the counter
        print('%7.4f %s: Waited %6.3f' % (env.now, name, wait))
        tib = random.expovariate(1.0 / timeInBank)
        yield env.timeout(tib)
        print('%7.4f %s: Finished' % (env.now, name))


def NoInSystem(R):
    """Total number of customers in the resource R"""
    return max([0, len(R.put_queue) + len(R.users)])


def Source(env, number, interval, counters):
    for i in range(number):
        c = Customer(env, 'Customer%02d' % i, counters)
        env.process(c)
        t = random.expovariate(1.0 / interval)
        yield env.timeout(t)


# Setup and start the simulation
print('Bank with multiple queues')
random.seed(seed)
env = Environment()

counters = [Resource(env), Resource(env)]
env.process(Source(env, maxNumber, arrivalMean, counters))
env.run(until=maxTime)

Solution

  • added a function to load the queues with customers before the bank opens which is time 0.

    """
    Bank with multiple queues example
    Covers:
    - Resources: Resource
    - Iterating processes
    Scenario:
      A multi-counter bank with a random service time and customers arrival process. Based on the
      program bank10.py from TheBank tutorial of SimPy 2. (KGM)
    By Aaron Janeiro Stone
    """
    from simpy import *
    import random
    
    qStartNum = 20      # number of people in queue at start
    maxNumber = 30      # Max number of customers after start
    maxTime = 400.0     # Rumtime limit
    timeInBank = 20.0   # Mean time in bank
    arrivalMean = 10.0  # Mean of arrival process
    seed = 12345        # Seed for simulation
    
    
    def Customer(env, name, counters):
        arrive = env.now
        Qlength = [NoInSystem(counters[i]) for i in range(len(counters))]
        print("%7.4f %s: Here I am. %s" % (env.now, name, Qlength))
        for i in range(len(Qlength)):
            if Qlength[i] == 0 or Qlength[i] == min(Qlength):
                choice = i  # the chosen queue number
                break
        with counters[choice].request() as req:
            # Wait for the counter
            yield req
            wait = env.now - arrive
            # We got to the counter
            print('%7.4f %s: Waited %6.3f' % (env.now, name, wait))
            tib = random.expovariate(1.0 / timeInBank)
            yield env.timeout(tib)
            print('%7.4f %s: Finished' % (env.now, name))
    
    
    def NoInSystem(R):
        """Total number of customers in the resource R"""
        return max([0, len(R.put_queue) + len(R.users)])
    
    
    def Source(env, minNumber, maxNumber, interval, counters):
        for i in range(minNumber, maxNumber):
            c = Customer(env, 'Customer%02d' % i, counters)
            env.process(c)
            t = random.expovariate(1.0 / interval)
            yield env.timeout(t)
    
    def preSource(env, number, counters):
        """
        Queues customers before bank opens
        """
        for i in range(number):
            c = Customer(env, 'Customer%02d' % i, counters)
            env.process(c)
    
    
    # Setup and start the simulation
    print('Bank with multiple queues')
    random.seed(seed)
    env = Environment()
    
    counters = [Resource(env), Resource(env)]
    preSource(env, qStartNum, counters)
    env.process(Source(env, qStartNum, qStartNum + maxNumber, arrivalMean, counters))
    env.run(until=maxTime)