2015-02-03 6 views
1

Новый пользователь python здесь и первый пост на этом замечательном сайте. Я не смог найти ответ на свой вопрос, поэтому, надеюсь, он уникален.Симп: Как я могу представить неудачи в симуляции метропоезда?

Использование simpy Я пытаюсь создать симуляцию метро/метро в поезде с ошибками и ремонтами, периодически встроенными в систему. Эти сбои случаются с поездом, а также сигналы на участках дорожки и на форматах. Я прочитал и применил официальный пример Machine Shop (который вы можете увидеть сходство в прилагаемом коде), и таким образом удалось моделировать случайные сбои и ремонт в поезде, прерывая его «время в пути».

Однако я не понял, как моделировать сбои сигналов на маршрутах, по которым следуют поезда. В настоящее время я просто указываю время для поездки от A до B, которое прерывается, но только из-за сбоя поезда.

Можно ли определить каждую поездку как свой собственный процесс, то есть отдельный процесс для разделов A_to_B и B_to_C, а отдельные платформы - pA, pB и pC. Каждый из них имеет единственный ресурс (который позволяет одновременно включать только один поезд) и включать случайные сбои и ремонт для этих секционных и платформенных процессов? Мне также нужно было бы иметь несколько разделов между двумя платформами, любой из которых может иметь провал.

Любая помощь была бы принята с благодарностью.

Вот мой код до сих пор:

import random 
import simpy 
import numpy 

RANDOM_SEED = 1234 

T_MEAN_A = 240.0 # mean journey time 
T_MEAN_EXPO_A = 1/T_MEAN_A # for exponential distribution 

T_MEAN_B = 240.0 # mean journey time 
T_MEAN_EXPO_B = 1/T_MEAN_B # for exponential distribution 

DWELL_TIME = 30.0 # amount of time train sits at platform for passengers 
DWELL_TIME_EXPO = 1/DWELL_TIME 

MTTF = 3600.0 # mean time to failure (seconds) 
TTF_MEAN = 1/MTTF # for exponential distribution 

REPAIR_TIME = 240.0 
REPAIR_TIME_EXPO = 1/REPAIR_TIME 

NUM_TRAINS = 1 
SIM_TIME_DAYS = 100 
SIM_TIME = 3600 * 18 * SIM_TIME_DAYS 
SIM_TIME_HOURS = SIM_TIME/3600 


# Defining the times for processes 
def A_B(): # returns processing time for journey A to B 
    return random.expovariate(T_MEAN_EXPO_A) + random.expovariate(DWELL_TIME_EXPO) 

def B_C(): # returns processing time for journey B to C 
    return random.expovariate(T_MEAN_EXPO_B) + random.expovariate(DWELL_TIME_EXPO) 

def time_to_failure(): # returns time until next failure 
    return random.expovariate(TTF_MEAN) 


# Defining the train 
class Train(object): 

    def __init__(self, env, name, repair): 
     self.env = env 
     self.name = name 
     self.trips_complete = 0 
     self.broken = False 

    # Start "travelling" and "break_train" processes for the train 
     self.process = env.process(self.running(repair)) 
     env.process(self.break_train()) 

    def running(self, repair): 
     while True: 
     # start trip A_B 
      done_in = A_B() 
      while done_in: 
       try: 
        # going on the trip 
        start = self.env.now 
        yield self.env.timeout(done_in) 
        done_in = 0 # Set to 0 to exit while loop 

       except simpy.Interrupt: 
        self.broken = True 
        done_in -= self.env.now - start # How much time left? 
        with repair.request(priority = 1) as req: 
         yield req 
         yield self.env.timeout(random.expovariate(REPAIR_TIME_EXPO)) 
        self.broken = False 
     # Trip is finished 
      self.trips_complete += 1 

     # start trip B_C 
      done_in = B_C() 
      while done_in: 
       try: 
        # going on the trip 
        start = self.env.now 
        yield self.env.timeout(done_in) 
        done_in = 0 # Set to 0 to exit while loop 

       except simpy.Interrupt: 
        self.broken = True 
        done_in -= self.env.now - start # How much time left? 
        with repair.request(priority = 1) as req: 
         yield req 
         yield self.env.timeout(random.expovariate(REPAIR_TIME_EXPO)) 
        self.broken = False 
     # Trip is finished 
      self.trips_complete += 1 


    # Defining the failure  
    def break_train(self): 
     while True: 
      yield self.env.timeout(time_to_failure()) 
      if not self.broken: 
      # Only break the train if it is currently working 
       self.process.interrupt() 


# Setup and start the simulation 
print('Train trip simulator') 
random.seed(RANDOM_SEED) # Helps with reproduction 

# Create an environment and start setup process 
env = simpy.Environment() 
repair = simpy.PreemptiveResource(env, capacity = 1) 
trains = [Train(env, 'Train %d' % i, repair) 
    for i in range(NUM_TRAINS)] 

# Execute 
env.run(until = SIM_TIME) 


# Analysis 
trips = [] 
print('Train trips after %s hours of simulation' % SIM_TIME_HOURS) 
for train in trains: 
    print('%s completed %d trips.' % (train.name, train.trips_complete)) 
    trips.append(train.trips_complete) 

mean_trips = numpy.mean(trips) 
std_trips = numpy.std(trips) 
print "mean trips: %d" % mean_trips 
print "standard deviation trips: %d" % std_trips 

ответ

1

это выглядит, как вы используете Python 2, что немного неудачно, потому что Python 3.3 и выше дают вам некоторую гибкость с генераторами на Python. Но ваша проблема должна быть решена в Python 2, тем не менее.

вы можете использовать вложенные процессы внутри в процессе:

def sub(env): 
    print('I am a sub process') 
    yield env.timeout(1) 
    # return 23 # Only works in py3.3 and above 
    env.exit(23) # Workaround for older python versions 

def main(env): 
    print('I am the main process') 
    retval = yield env.process(sub(env)) 
    print('Sub returned', retval) 

Как вы можете видеть, вы можете использовать Process экземпляры, возвращенные Environment.process() как обычные события. Вы даже можете использовать возвращаемые значения в своих подпроцессах.

Если вы используете Python 3.3 или более поздней версии, вы не должны явно начать новую суб-процесс, но может использовать sub() как подпрограмму, а и просто пересылают событий он дает:

def sub(env): 
    print('I am a sub routine') 
    yield env.timeout(1) 
    return 23 

def main(env): 
    print('I am the main process') 
    retval = yield from sub(env) 
    print('Sub returned', retval) 

Вы также можете моделировать сигналы в качестве ресурсов, которые могут быть использованы по причине отказа или поездом. Если процесс отказа сначала запрашивает сигнал , поезд должен ждать перед сигналом, пока отказ не освободит ресурс сигнала. Если поезд проходит мимо сигнала (и, следовательно, имеет ресурс), сигнал не может сломаться. Не думаю, , это проблема, потому что поезд все равно не может остановиться. Если это должно быть проблема, просто используйте PreemptiveResource.

Надеюсь, это поможет. Пожалуйста, присоединяйтесь к нашему mailing list для обсуждения более .

+0

Спасибо Stefan – bobo