Simpy 地铁模拟:如何解决 class 列车在排队等待资源时中断失败?

Simpy subway simulation: how to fix interrupt failure of class train while queueing for a resource?

我正在使用 simpy 进行火车模拟,到目前为止,我已经按照以下代码在单个火车实体上取得了成功。

火车流程是部分,后面是站台。每个区段和站台的资源为1,以确保一次只能使用一列火车。

但是我找不到解决以下错误的方法:

当我将第二列火车添加到模拟中时,有时会出现这样的情况:一列火车等待不可用的资源,然后该列火车在等待时发生故障。

我最终遇到了 Interrupt: Interrupt() 错误。

是否有解决这些失败的资源队列的方法?

非常感谢任何帮助。

import random
import simpy
import numpy

# Configure parameters for the model
RANDOM_SEED = random.seed() # makes results repeatable

T_MEAN_SECTION = 200.0 # journey time (seconds)

DWELL_TIME = 30.0 # dwell time mean (seconds)
DWELL_TIME_EXPO = 1/DWELL_TIME # for exponential distribution

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

REPAIR_TIME = 120.0 # mean repair time for when failure occurs (seconds)
REPAIR_TIME_EXPO = 1/REPAIR_TIME # for exponential distribution

NUM_TRAINS = 2 # number of trains to simulate

SIM_TIME_HOURS = 1 # sim time in hours
SIM_TIME_DAYS = SIM_TIME_HOURS/18.0 # number of days to simulate
SIM_TIME = 3600 * 18 * SIM_TIME_DAYS # sim time in seconds (this is used in the code below)


# Defining the times for processes
def Section(): # returns processing time for platform 7 Waterloo to 26 Bank
    return T_MEAN_SECTION

def Dwell(): # returns processing time for platform 25 Bank to platform 7 Waterloo
    return 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.num_saf = 0
        self.sum_saf = 0
        self.broken = False

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


    def running(self, repair):

        while True:

            # request section A
            request_SA = sectionA.request()

########## SIM ERROR IF FAILURE OCCURS HERE ###########
            yield request_SA

            done_in_SA = Section()          
            while done_in_SA:

                try:
                    # going on the trip
                    start = self.env.now


                    print('%s leaving platform at time %d') % (self.name, env.now)

                    # processing time
                    yield self.env.timeout(done_in_SA)

                    # releasing the section resource
                    sectionA.release(request_SA)
                    done_in_SA = 0 # Set to 0 to exit while loop

                except simpy.Interrupt:
                    self.broken = True
                    delay = random.expovariate(REPAIR_TIME_EXPO)
                    print('Oh no! Something has caused a delay of %d seconds to %s at time %d') % (delay, self.name, env.now)
                    done_in_SA -= self.env.now - start # How much time left?
                    with repair.request(priority = 1) as request_D_SA:
                        yield request_D_SA
                        yield self.env.timeout(delay)
                    self.broken = False
                    print('Okay all good now, failure fixed on %s at time %d') % (self.name, env.now)
                    self.num_saf += 1
                    self.sum_saf += delay



            # request platform A
            request_PA = platformA.request()

########## SIM ERROR IF FAILURE OCCURS HERE ###########
            yield request_PA

            done_in_PA = Dwell()
            while done_in_PA:

                try:

                    # platform process
                    start = self.env.now


                    print('%s arriving to platform A and opening doors at time %d') % (self.name, env.now)
                    yield self.env.timeout(done_in_PA)
                    print('%s closing doors, ready to depart platform A at %d\n') % (self.name, env.now)
                    # releasing the platform resource
                    platformA.release(request_PA)
                    done_in_PA = 0 # Set to 0 to exit while loop

                except simpy.Interrupt:
                    self.broken = True
                    delay = random.expovariate(REPAIR_TIME_EXPO)
                    print('Oh no! Something has caused a delay of %d seconds to %s at time %d') % (delay, self.name, env.now)
                    done_in_PA -= self.env.now - start # How much time left?
                    with repair.request(priority = 1) as request_D_PA:
                        yield request_D_PA
                        yield self.env.timeout(delay)
                    self.broken = False
                    print('Okay all good now, failure fixed on %s at time %d') % (self.name, env.now)
                    self.num_saf += 1
                    self.sum_saf += delay


        # Round trip is finished

            self.trips_complete += 1


# Defining the failure event        
    def downtime_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()

# Defining resources 
platformA = simpy.Resource(env, capacity = 1)
sectionA = simpy.Resource(env, capacity = 1)

repair = simpy.PreemptiveResource(env, capacity = 10)

trains = [Train(env, 'Train %d' % i, repair)
    for i in range(NUM_TRAINS)]


# Execute
env.run(until = SIM_TIME)

您的进程请求资源并且从不释放它。这就是第二列火车永远等待其请求成功的原因。在等待的过程中,失败的进程似乎打断了进程。这就是你得到错误的原因。请阅读 guide to resources 以了解 SimPy 的资源如何工作,尤其是完成后如何释放资源。