cristiklein / simpy

MIT License
107 stars 16 forks source link

Support one resource with one queue? #6

Open JinJinGuang opened 5 years ago

JinJinGuang commented 5 years ago

Hello~ Can simpy support that each resource has one or more queue? Specifically, I want to model many ATMs, and each ATM has one queue. I know simpy can model all ATMs with only one queue. So could you help me?

It is better that each resource has more queues and I can choose which queue to be served.

cristiklein commented 5 years ago

Hi @JinJinGuang

Could you clarify your use-case, since I really get two out of your message?

(1) One resource with multiple queues (e.g., one ATM with many queues, which would require a "queue selection" algorithm). (2) n resources each with its own queue (e.g., 10 ATMs with separate queues).

JinJinGuang commented 5 years ago

@cristiklein

Yes. Both are needed. Case (2) is what I need now. And I want to use Case (1) in other situations in the future.

Hope you can help me. Thanks a lot.

cristiklein commented 5 years ago

For case (2), I would simply create n resources.

For case (1), I would create one process per queue and a process that aggregates all queues and decides which one to submit to the resource.

If you have some existing code, I could highlight how to do the adaptation.

JinJinGuang commented 5 years ago

Thank you very much. I will try it.

JinJinGuang commented 5 years ago

Hi @cristiklein

I can deal with case (2), but have problems in case (1). Hope you can help me to highlight how to do the adaptation.

import random

import numpy as np
import simpy

class Customer(object):
    def __init__(self, env, name):
        self.name = name
        self.env = env
        self.arrive = env.now
        self.wait = None
        print('%7.4f %s: Here I am' % (self.arrive, self.name))

    def go2bank(self, bank):
        with bank.machine.request() as request:
            yield request

            self.wait = env.now - self.arrive
            print('%7.4f %s: Waited %6.3f' % (env.now, self.name, self.wait))

            yield env.process(bank.serve(self))
            print('%7.4f %s: Finished' % (env.now, self.name))

class Bank(object):
    def __init__(self, env, num_machines, servetime):
        self.env = env
        self.machine = simpy.Resource(env, capacity=num_machines)
        self.servetime = servetime

    def serve(self, customer):
        yield self.env.timeout(self.servetime)

class Source(object):
    def __init__(self, number, arrival_rate):
        self.num = number
        self.arrival_rate = arrival_rate

    def generator(self, env, bank):
        for i in range(self.num):
            c = Customer(env, 'Customer%02d' % i)
            env.process(c.go2bank(bank))

            t = random.expovariate(1.0 / self.arrival_rate)
            yield env.timeout(t)   

RANDOM_SEED = 42
NEW_CUSTOMERS = 5  # Total number of customers
INTERVAL_CUSTOMERS = 2  # Generate new customers roughly every x seconds
NUM_MACHINE = 2
SERVE_TIME = 4

# Setup and start the simulation
print('ATM')
random.seed(RANDOM_SEED)
env = simpy.Environment()

# Start processes and run
bank = Bank(env, NUM_MACHINE, SERVE_TIME)
source = Source(NEW_CUSTOMERS, INTERVAL_CUSTOMERS)
env.process(source.generator(env, bank))
env.run()

I'm confused how to deal with with bank.machine.request() as request: and how to create one process per queue and a process that aggregates all queues and decides which one to submit to the resource. Thanks a lot.

cristiklein commented 5 years ago

Hi,

I just ran your code and it looks good to me. Do I understand correctly that you want to simulated one (common) queue for two machines? If yes, then your code looks good. Customers seem to be served in first-come-first-serve order as expected.

Were you expecting a different order?

În vin., 13 sept. 2019 la 12:35, JinJinGuang notifications@github.com a scris:

Hi @cristiklein https://github.com/cristiklein

I can deal with case (2), but have problems in case (1). Hope you can help me to highlight how to do the adaptation.

import random import numpy as npimport simpy class Customer(object): def init(self, env, name): self.name = name self.env = env self.arrive = env.now self.wait = None print('%7.4f %s: Here I am' % (self.arrive, self.name))

def go2bank(self, bank):
    with bank.machine.request() as request:
        yield request

        self.wait = env.now - self.arrive
        print('%7.4f %s: Waited %6.3f' % (env.now, self.name, self.wait))

        yield env.process(bank.serve(self))
        print('%7.4f %s: Finished' % (env.now, self.name))

class Bank(object): def init(self, env, num_machines, servetime): self.env = env self.machine = simpy.Resource(env, capacity=num_machines) self.servetime = servetime

def serve(self, customer):
    yield self.env.timeout(self.servetime)

class Source(object): def init(self, number, arrival_rate): self.num = number self.arrival_rate = arrival_rate

def generator(self, env, bank):
    for i in range(self.num):
        c = Customer(env, 'Customer%02d' % i)
        env.process(c.go2bank(bank))

        t = random.expovariate(1.0 / self.arrival_rate)
        yield env.timeout(t)

RANDOM_SEED = 42NEW_CUSTOMERS = 5 # Total number of customersINTERVAL_CUSTOMERS = 2 # Generate new customers roughly every x secondsNUM_MACHINE = 2SERVE_TIME = 4

Setup and start the simulationprint('ATM')

random.seed(RANDOM_SEED) env = simpy.Environment()

Start processes and run

bank = Bank(env, NUM_MACHINE, SERVE_TIME) source = Source(NEW_CUSTOMERS, INTERVAL_CUSTOMERS) env.process(source.generator(env, bank)) env.run()

I'm confused how to deal with with bank.machine.request() as request: and how to create one process per queue and a process that aggregates all queues and decides which one to submit to the resource. Thanks a lot.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/cristiklein/simpy/issues/6?email_source=notifications&email_token=AAMVPIKD3GC3PMKEV3ITUPDQJNUG7A5CNFSM4IVOBGR2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6UUTKQ#issuecomment-531188138, or mute the thread https://github.com/notifications/unsubscribe-auth/AAMVPIOC4YJLL6LTE22SRLLQJNUG7ANCNFSM4IVOBGRQ .

-- Cristian Klein

JinJinGuang commented 5 years ago

Hi, @cristiklein

My code is to solve case(2), but I still want to solve case(1).

I want to modify the code, but don't know how to do what you said before: For case (1), I would create one process per queue and a process that aggregates all queues and decides which one to submit to the resource.