【问题标题】:How can I prioritize SimPy events that occur at the same time?如何确定同时发生的 SimPy 事件的优先级?
【发布时间】:2019-07-11 18:23:56
【问题描述】:

我在 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)会产生问题并不一致地检查条件,所以我的想法是我需要完全重新设计它们。

【问题讨论】:

  • 你能分享一些代码吗?答案可能很简单,只需重新排序一些代码行,或者可能需要事件逻辑。
  • 我相信它是this question.的副本
  • 我添加了一个示例,应该有助于解释我的问题。

标签: python simpy


【解决方案1】:

我建议更改您的代码以避免您描述的情况。您描述的代码设计对事件处理时间/顺序很敏感,即使您正确放置事件顺序,其他人也可能在未来的修订中出错。

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

那么这个过程就是:

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

【讨论】:

  • 我认为你是对的,我的问题是由于多个进程并行运行而出现的,如我添加的示例所示。我可能不得不重新设计代码。
【解决方案2】:

当多个进程同时调用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

...

【讨论】:

  • 您可以查看 simpy 文档中的The Machine Shop Example 以获得有关如何使用 simpy 的资源进行多台机器和维修人员的启发:)
猜你喜欢
  • 2014-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-10
  • 1970-01-01
  • 1970-01-01
  • 2020-03-30
  • 1970-01-01
相关资源
最近更新 更多