Simpy:我如何在火车地铁模拟中表示失败?

时间:2015-02-03 18:07:40

标签: simulation reliability simpy

新的python用户在这个伟大的网站上发布了第一篇文章。我还没有能够找到我的问题的答案,所以希望它是独一无二的。

使用simpy我正在尝试创建火车地铁/地铁模拟,其中包含定期内置于系统中的故障和维修。这些故障发生在火车上,但也发生在赛道和平台上的信号上。我已经阅读并应用了官方的机加工车间示例(您可以在附带的代码中看到相似之处),因此设法通过中断其行程时间来模拟随机故障和修理火车。

然而,我还没有弄清楚如何对列车所遵循的路线上的信号故障进行建模。我目前只是指定从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 个答案:

答案 0 :(得分: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了解更多信息 讨论