如何确定同时发生的 SimPy 事件的优先级?

How can I prioritize SimPy events that occur at the same time?

我 运行 在我的 SimPy 模拟中遇到了一个问题,其中多个事件以错误的顺序同时发生。具体来说,我正在为一条生产线建模,其中机器会定期发生故障并接受维护。当一台机器在t1时间修好后,应该会在那个时候恢复生产。然而,事件发生的顺序是

  1. 检查修复是否完成
  2. 完成修复
  3. 如修复,恢复生产

当我想要的时候

  1. 完成修复
  2. 检查修复是否完成
  3. 如修复,恢复生产

有什么方法可以改变事件执行的顺序吗?

这是我遇到的问题的最简单示例:

import random
import simpy

class machine:
    def __init__(self, env, process_time):
        self.env = env
        self.process_time = process_time

        self.remaining_process_time = process_time
        self.failed = False
        self.parts_made = 0

        env.process(self.production())
        env.process(self.maintenance())

    def production(self):
        while True:
            while self.remaining_process_time:
                if random.random() < 0.1:
                    # machine fails                
                    print(f'Machine failed at t={self.env.now}')
                    self.failed = True
                    while self.failed:
                        # wait for maintenance to finish
                        yield self.env.timeout(1)

                    print(f'Resuming production at t={self.env.now}\n')

                yield self.env.timeout(1)
                self.remaining_process_time -= 1
            self.parts_made += 1
            self.remaining_process_time = self.process_time

    def maintenance(self):
        while True:
            while not self.failed:
                # wait for failure to occur
                yield self.env.timeout(1)

            print(f'Starting repair at t={self.env.now}')
            ttr = random.randint(1,8)
            print(f'TTR={ttr}')
            yield self.env.timeout(ttr)
            self.failed = False
            self.remaining_process_time = self.process_time
            print(f'Finished repair at t={self.env.now}')

random.seed(1234)
env = simpy.Environment()
system = machine(env, 5)
env.run(until=50)

输出为:

Machine failed at t=2
Starting repair at t=2
TTR=1
Finished repair at t=3
Resuming production at t=4

Machine failed at t=6
Starting repair at t=6
TTR=6
Finished repair at t=12
Resuming production at t=12

Machine failed at t=14
Starting repair at t=15
TTR=1
Finished repair at t=16
Resuming production at t=16

Machine failed at t=23
Starting repair at t=24
TTR=8
Finished repair at t=32
Resuming production at t=32

Machine failed at t=37
Starting repair at t=38
TTR=2
Finished repair at t=40
Resuming production at t=40

Machine failed at t=42
Starting repair at t=43
TTR=2
Finished repair at t=45
Resuming production at t=45

对于第一次故障,修复在 t=3 正确完成,但生产直到 t=4 才恢复。再看第三次故障,故障发生在t=14,但直到t=15才开始修复。似乎这些进程 运行 并行(productionmaintenance)会产生问题并不一致地检查条件,所以我的想法是我需要完全重新设计它们。

我建议更改您的代码以避免出现您描述的情况。您描述的代码设计对事件过程敏感time/order,即使您正确设置了事件顺序,其他人也可能在以后的修订中出错。

如果你改变代码设计,让生产机器等待修复而不是定期检查,那么你应该避免这个问题。

接下来的流程是:

  1. 生产机器坏了;等待修复。
  2. 修理工完成维修;通知生产机器。
  3. 生产机器恢复生产。

问题似乎出现在多个进程同时调用 self.env.timeout(1) 时。这是我找到的解决方案:

class machine:
    def __init__(self, env, process_time):
        self.env = env
        self.process_time = process_time

        self.remaining_process_time = process_time
        self.failed = False
        self.parts_made = 0

        env.process(self.production())

    def production(self):
        while True:
            while self.remaining_process_time:
                if random.random() < 0.1:
                    # machine fails                
                    print(f'Machine failed at t={self.env.now}')
                    self.failed = True
                    yield self.env.process(self.maintenance())

                    print(f'Resuming production at t={self.env.now}\n')

                yield self.env.timeout(1)
                self.remaining_process_time -= 1
            self.parts_made += 1
            self.remaining_process_time = self.process_time

    def maintenance(self):
        print(f'Starting repair at t={self.env.now}')
        ttr = random.randint(1,8)
        print(f'TTR={ttr}')
        yield self.env.timeout(ttr)
        self.remaining_process_time = self.process_time
        print(f'Finished repair at t={self.env.now}')

random.seed(1234)

env = simpy.Environment()
system = machine(env, 5)
env.run(until=50)

这段代码产生了我期望的输出。

Machine failed at t=2
Starting repair at t=2
TTR=1
Finished repair at t=3
Resuming production at t=3

Machine failed at t=5
Starting repair at t=5
TTR=6
Finished repair at t=11
Resuming production at t=11

Machine failed at t=13
Starting repair at t=13
TTR=1
Finished repair at t=14
Resuming production at t=14

...