新的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
答案 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了解更多信息 讨论