Дискретно-событийное моделирование с переменными интервалами


Я построил дискретно событийное моделирование системы, похожие на проблемный банк, представленный на странице Википедии, но с ключевым отличием.

Допустим, что кассир может обслуживать двух клиентов одновременно, и что заказчик-выбор времени зависит от количества клиентов, а кассир обслуживает одновременно; мне нужно, чтобы управлять динамической поддержки-выезд планирование событий, когда число одновременно обслуживаемых клиентов изменения.

Рассмотрим следующий пример, где время обслуживания одного клиента составляет 4 временных интервалов и два раза, когда кассир обслуживает двух клиентов одновременно:

t=0  CUSTOMER-ARRIVAL (1)   
t=1  TELLER-BEGINS-SERVICE (1) --> schedules CUSTOMER-DEPARTURE (1) at t_a=5
...
t=3  CUSTOMER-ARRIVAL (2)
t=4  TELLER-BEGINS-SERVICE (1) --> teller is now servicing two customers:
                                   - reschedule CUSTOMER-DEPARTURE (1) to t_b=6
                                   - schedule CUSTOMER-DEPARTURE (2) at t_c=12
...
t=6  CUSTOMER-DEPARTURE (1)    --> teller is now servicing only one customer:
                                   - reschedule CUSTOMER-DEPARTURE (2) at t_d=9
...
t=9  CUSTOMER-DEPARTURE (2)

Время рассчитывается, используя следующую формулу:

t = t_current + (4 - completed) * customer_count

Что дает такие результаты для значений выше:

  1. t_a = 1 + (4 - 0) * 1 = 5
  2. t_b = 4 + (4 - 3) * 2 = 6
  3. t_c = 4 + (4 - 0) * 2 = 12
  4. t_d = 6 + (4 - 1) * 1 = 9

Я придумал следующий код в Python; что ты бы сделал по-другому?

import heapq

class Simulator(object):

    def __init__(self):
        self.queue = []
        self.time = 0


    def schedule(self, time, callback, *args, **kwargs):
        """
        Schedules an event to be executed at a later point in time.
        ``callback`` is a callable which executed the event-specific behavior;
        the optional ``args`` and ``kwargs`` arguments will be passed to the
        event callback at invocation time.

        Returns an object which can be used to reschedule the event.
        """
        assert time > self.time
        event = [time, True, callback, args, kwargs]
        heapq.heappush(self.queue, event)
        return event


    def reschedule(self, event, time):
        """
        Reschedules ``event`` to take place at a different point in time
        """
        assert time > self.time
        rescheduled = list(event)
        event[1] = False
        rescheduled[0] = time
        heapq.heappush(self.queue, rescheduled)
        return rescheduled


    def run(self):
        """
        Simple simulation function to test the behavior
        """
        while self.queue:
            time, valid, callback, args, kwargs = heapq.heappop(self.queue)
            if not valid:
                continue
            self.time = time
            callback(*args, **kwargs)


def event(id, simulator, scheduled, rescheduled=None):
    if rescheduled is None:
        print "Event #{0}: scheduled at {1} and fired at {2}".format(id,
                scheduled, simulator.time)
    else:
        print "Event #{0}: scheduled at {1}, rescheduled at {2} and fired " \
                "at {3}".format(id, scheduled, rescheduled, simulator.time)


s = Simulator()
e1 = s.schedule(5, event, 1, s, 5)
e2 = s.schedule(7, event, 2, s, 7, 12)
e3 = s.schedule(9, event, 3, s, 9)
s.reschedule(e2, 12)
s.run()



1326
5
задан 27 июля 2011 в 09:07 Источник Поделиться
Комментарии
2 ответа

Учитывая масштабы проблемы, как я понимаю (необходимо для выполнения мероприятий в определенной последовательности, с возможностью менять последовательность в любой момент) я думаю, что дизайн кажется чистым и прямым. Я оговорился, что с: я не знаю Python, и я, кажется, пропустила ту часть, где вы гарантируя последовательность очередь член время. Я понимаю события.время должен быть ключевой последовательности по очереди, либо перепланировать будет иметь неустойчивое поведение как само собой.время идет вперед и назад, если очередь не в порядке

Дизайн оптом хоть и кажется чистым, на моих глазах.

3
ответ дан 31 июля 2011 в 12:07 Источник Поделиться

Событие-это некий объект состояния моделируемого в виде списка. Часто плохая идея.

class Event( object ):
def __init__( self, time, callback, *args, **kwargs ):
self.time= time
self.live= True
self.callback= callback
self.args= args
self.kwargs= kwargs
def invalidate( self ):
self.live= False
def __call__( self ):
if self.live:
self.callback( self.*args, **self.kwargs )

Это может быть лучше, чем список. Список, где порядок аргументов имеет решающее значение-это плохо ждет.

Код как событие[1] = ложь совершенно непрозрачной. Она должна быть заменена событие.признать недействительными() так что смысл очевиден.

Также, когда у вас есть событие класса, отдельном случае функция становится ненужной. Вы можете подкласс событие , как это.

class MyEvent( Event ):
def __call__( self, id, simulator, scheduled, rescheduled=None ):
if rescheduled is None:
print "Event #{0}: scheduled at {1} and fired at {2}".format(id,
scheduled, simulator.time)
else:
print "Event #{0}: scheduled at {1}, rescheduled at {2} and fired " \
"at {3}".format(id, scheduled, rescheduled, simulator.time)

Не пытаясь построить "Мутабельный Кортеж" в список фиксированной длины.

Либо использовать неизменяемые кортежей или соответствующего класса.

0
ответ дан 30 июля 2011 в 12:07 Источник Поделиться