Pregunta

Quiero crear un modelo de simulación que simula un banco con 3 números de contadores. Quiero que haya una cola para los clientes, y si alguno de los contadores está disponible, servirá el contador durante un tiempo. Cada contador es su propio recurso Simpy (no puedo hacer un recurso con una capacidad de 3), y necesito saber qué contador atiende al cliente. Estoy teniendo problemas para implementar esto.

He encontrado este artículo que parece ser sobre el mismo problema, pero aún no conoce la implementación exacta http://comments.gmane.org/gmane.comp.python.simpy.user/1754

Supongo que necesito un rendimiento simpy.Ander, (ENV, List_of_Resources) allí para solicitar el primer contador disponible, pero no puedo averiguar cómo configurar esto correctamente, y también si hay más de un recurso disponible en el mismo Tiempo, quiero una forma de verificar esto para que pueda elegir qué contador es mejor para que el cliente vaya.

Estoy ejecutando Python Version 2.7, Simpy versión 3.0.4

Editar agregar código que muestre lo que estoy tratando de hacer y cómo no funciona ahora mismo.

import simpy
import random

LENGTH_SIM = 200.0

class Customer(object):
    def __init__(self, arrive_time, num):
        self.arrive_time = arrive_time
        self.start_service_time = -1.0
        self.finish_service_time = -1.0
        self.served_by = -1.0
        self.num = num
    def print_attributes(self):
        format_string = "#%3d  Arrive: %6.1f  Start Service: %6.1f  "\
        + " End Service: %6.1f" + "   Served By: %3d"
        print format_string %(self.num, self.arrive_time,
                              self.start_service_time,
                                self.finish_service_time, self.served_by)

class Counter(object):
    def __init__(self, number):
        self.number = number
        self.name = "Counter " + str(number)
        self.start_times = []
        self.end_times = []

class Bank(object):
    def __init__(self, env, num_counters):
        self.counters = [Counter(x+1) for x in range(num_counters)]
        self.num_counters = num_counters
        self.counters_resources = [simpy.Resource(env, capacity=1)
                                   for x in range(num_counters)]


def generate_customers(env, customers):
    count = 1
    while 1:
        wait_time = random.randint(8, 12)
        yield env.timeout(wait_time)
        customers.append(Customer(env.now, count))
        print "Generated Customer: ", count
        count += 1

def select_counter(env, bank):
    '''choose a counter for the customer'''
    for x in range(len(bank.counters)):
        if bank.counters_resources[len(bank.counters) - 1 - x].count == 0:
            print "Counter Selected: ", len(bank.counters) - 1 - x
            print bank.counters[len(bank.counters) - 1 - x].number
            print bank.counters_resources[len(bank.counters) - 1 - x].users
            return len(bank.counters) - 1 - x
    return -2.0

def gen_service_time():
    return random.random() * 20.0 + 21.0

def handle_customer(env, bank, customer, customers, num_process):
    '''handles customer'''
    print "Process ", num_process, " started at:", env.now
    counter = select_counter(env, bank)
    print "Process ", num_process, " after counter select:", env.now
    if counter != -2.0:
        with bank.counters_resources[counter].request() as req:
            yield req
            print "Process ", num_process, "Time", env.now, "In if"
            bank.counters[counter].start_times.append(env.now)
            service_time = gen_service_time()
            customer.start_service_time = env.now
            customer.finish_service_time = env.now + service_time
            bank.counters[counter].end_times.append(env.now + service_time)
            customer.served_by = counter + 1
            yield env.timeout(service_time)
    else:
        reqs = []
        for x in range(len(bank.counters)):
            reqs.append(bank.counters_resources[x].request())
        counter_used = yield simpy.events.AnyOf(env, reqs)
        for x in range(len(reqs)):
            if counter_used.keys()[0] != reqs[x]:
                print "True"
                bank.counters_resources[x].release(reqs[x])
        print "Process ", num_process, "Time", env.now, "In else"
        bank.counters[0].start_times.append(env.now)
        service_time = gen_service_time()
        customer.start_service_time = env.now
        customer.finish_service_time = env.now + service_time
        bank.counters[0].end_times.append(env.now + service_time)
        customer.served_by = 1
        yield env.timeout(service_time)
        for x in range(len(reqs)):
##            if counter_used.keys()[0] == reqs[x]:
            if 1:
                bank.counters_resources[x].release(reqs[x])




def run_bank(env, bank, customers):
    while 1:
        min_time = -1.0
        min_customer = -1.0
        for x in xrange(len(customers)):
            if customers[x].arrive_time < min_time or min_time == -1.0:
                if customers[x].arrive_time > env.now:
                    min_time = customers[x].arrive_time
                    min_customer = x
                else:
                    continue
        if min_time == -1.0:
            yield env.timeout(LENGTH_SIM - env.now)
        yield env.timeout(min_time - env.now)
        print "Calling Process: ", min_customer, "At time:", env.now
        env.process(handle_customer(env,bank,customers[min_customer],customers,
                                    min_customer + 1))

def run_sim():
    env = simpy.Environment()
    customers = []
    env.process(generate_customers(env, customers))
    env.run(until=LENGTH_SIM)
    env2 = simpy.Environment()
    bank = Bank(env2, 3)
    env2.process(run_bank(env2, bank, customers))
    env2.run(until = LENGTH_SIM)
    for x in range(len(customers)):
        customers[x].print_attributes()

if __name__ == '__main__':
    run_sim()

¿Fue útil?

Solución 2

Me las arreglé para resolverlo, lo único que no entiendo es lo que hace los diferentes argumentos para el método de cancelación (simplemente los pongo a todos como ninguno y funciona, no estoy seguro de dónde se encuentra la documentación.Lo que están además de su nombre).El código fijo es el siguiente (la parte relevante que es la cláusula MOSS en la función Handle_Customer:

import simpy
import random

LENGTH_SIM = 100.0

class Customer(object):
    def __init__(self, arrive_time, num):
        self.arrive_time = arrive_time
        self.start_service_time = -1.0
        self.finish_service_time = -1.0
        self.served_by = -1.0
        self.num = num
    def print_attributes(self):
        format_string = "#%3d  Arrive: %6.1f  Start Service: %6.1f  "\
        + " End Service: %6.1f" + "   Served By: %3d"
        print format_string %(self.num, self.arrive_time,
                              self.start_service_time,
                                self.finish_service_time, self.served_by)

class Counter(object):
    def __init__(self, number):
        self.number = number
        self.name = "Counter " + str(number)
        self.start_times = []
        self.end_times = []

class Bank(object):
    def __init__(self, env, num_counters):
        self.counters = [Counter(x+1) for x in range(num_counters)]
        self.num_counters = num_counters
        self.counters_resources = [simpy.Resource(env, capacity=1)
                                   for x in range(num_counters)]


def generate_customers(env, customers):
    count = 1
    while 1:
##        wait_time = random.randint(8, 12)
        wait_time = 2
        yield env.timeout(wait_time)
        customers.append(Customer(env.now, count))
        print "Generated Customer: ", count
        count += 1

def select_counter(env, bank):
    '''choose a counter for the customer'''
    for x in range(len(bank.counters)):
        if bank.counters_resources[len(bank.counters) - 1 - x].count == 0 and\
        bank.counters_resources[len(bank.counters) - 1 - x].queue == []:
            print "Counter Selected: ", len(bank.counters) - 1 - x
            return len(bank.counters) - 1 - x
    return -2.0

def gen_service_time():
##    return random.random() * 20.0 + 19.0
    return random.randint(4, 8)

def wait_til_available(env, bank, temp_list):
    while 1:
        yield env.timeout(0.0001)
        for x in range(len(bank.counters)):
            if bank.counters_resources[x].count == 0:
                req = bank.counters_resources[x].request()
                temp_list[0] = x
                temp_list[1] = req
                return 

def handle_customer(env, bank, customer, customers, num_process):
    '''handles customer'''
    print "Process ", num_process, " started at:", env.now
    counter = select_counter(env, bank)
    if counter != -2.0:
        with bank.counters_resources[counter].request() as req:
            yield req
            bank.counters[counter].start_times.append(env.now)
            service_time = gen_service_time()
            customer.start_service_time = env.now
            customer.finish_service_time = env.now + service_time
            bank.counters[counter].end_times.append(env.now + service_time)
            customer.served_by = counter + 1
            yield env.timeout(service_time)
    else:
        reqs = []
        got_counter = 0
        for x in range(len(bank.counters)):
            reqs.append(bank.counters_resources[x].request())
        good_req = yield simpy.events.AnyOf(env, reqs)
        req = good_req.keys()[0]
        for x in range(len(bank.counters)):
            if req != reqs[x]:
                bank.counters_resources[x].release(reqs[x])
                reqs[x].cancel(None, None, None)
            else:
                got_counter = x
        bank.counters[got_counter].start_times.append(env.now)
        service_time = gen_service_time()
        customer.start_service_time = env.now
        customer.finish_service_time = env.now + service_time
        bank.counters[got_counter].end_times.append(env.now + service_time)
        customer.served_by = got_counter + 1
        yield env.timeout(service_time)
        print "Process ", num_process, " finished at:", env.now
        bank.counters_resources[got_counter].release(req)




def run_bank(env, bank, customers):
    while 1:
        min_time = -1.0
        min_customer = -1.0
        for x in xrange(len(customers)):
            if customers[x].arrive_time < min_time or min_time == -1.0:
                if customers[x].arrive_time > env.now:
                    min_time = customers[x].arrive_time
                    min_customer = x
                else:
                    continue
        if min_time == -1.0:
            yield env.timeout(LENGTH_SIM - env.now)
        yield env.timeout(min_time - env.now)
        print "Calling Process: ", min_customer+1, "At time:", env.now
        env.process(handle_customer(env,bank,customers[min_customer],customers,
                                    min_customer + 1))

def run_sim():
    env = simpy.Environment()
    customers = []
    env.process(generate_customers(env, customers))
    env.run(until=LENGTH_SIM)
    env2 = simpy.Environment()
    bank = Bank(env2, 3)
    env2.process(run_bank(env2, bank, customers))
    env2.run(until = LENGTH_SIM)
    for x in range(len(customers)):
        customers[x].print_attributes()

if __name__ == '__main__':
    run_sim()

Otros consejos

Si realmente no puede usar un recurso normal con una capacidad de 3, tal vez la tienda lo ayude.La tienda almacena objetos de contadores que puede solicitar.Cada contador tiene su propia identidad y puede, por ejemplo, hacer un seguimiento de su número de usos.Después de que se realiza un cliente, tiene que poner el contador de nuevo en la tienda:

import simpy


class Counter:
    usages = 0


def customer(env, counters):
    counter = yield counters.get()
    yield env.timeout(1)
    counter.usages += 1
    yield counters.put(counter)


env = simpy.Environment()
counters = simpy.Store(env, capacity=3)
counters.items = [Counter() for i in range(counters.capacity)]
for i in range(10):
    env.process(customer(env, counters))
env.run()
for counter in counters.items:
    print(counter.usages)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top