【问题标题】:Simpy 4, starting multiple processes at the same timeSimpy 4,同时启动多个进程
【发布时间】:2021-02-09 10:58:15
【问题描述】:

我正在使用 Simpy 4,但不知道如何同时安排多个事件。

例如,假设一条起跑线上有 3 辆汽车,我希望它们都同时开始。例如,下面的代码不能按我的意愿工作,因为每个“移动”一个接一个地发生,而不是同时发生。

import simpy
from itertools import cycle

class Dispatch():
    def __init__(self, env, cars):
        self.cars = cars
        self.action = env.process(self.run())
    
    def run(self):
        while True:
            for car in self.cars:
                yield env.process(car.move())
            
class Car():
    def __init__(self, env, name, initial_location):
        self.env = env
        self.name = name
        self.location = initial_location
        self.path = iter(cycle(["A", "B", "C", "B"]))
    
    def move(self):
        yield env.timeout(1)
        self.location = next(self.path)
        print("{} is now at position {}, at time: {}".format(self.name, self.location, env.now))
        
env = simpy.Environment()
carA = Car(env, "carA", "A")
carB = Car(env, "carB", "A")
carC = Car(env, "carC", "A")
dispatcher = Dispatch(env, [carA,carB,carC])
env.run(until=20)

现在因为每辆车都是按顺序启动的,所以结果如下:

carA is now at position A, at time: 1
carB is now at position A, at time: 2
carC is now at position A, at time: 3
carA is now at position B, at time: 4
carB is now at position B, at time: 5
carC is now at position B, at time: 6
carA is now at position C, at time: 7
carB is now at position C, at time: 8
carC is now at position C, at time: 9

但我想要的是:

carA is now at position A, at time: 1
carB is now at position A, at time: 1
carC is now at position A, at time: 1
carA is now at position B, at time: 2
carB is now at position B, at time: 2
carC is now at position B, at time: 2
carA is now at position C, at time: 3
carB is now at position C, at time: 3
carC is now at position C, at time: 3

所以我想我正在寻找一种方法来重写 for 循环。

最终会有多辆汽车(如上例所示),我想分别控制每辆汽车。但我想作为一个起点,最好知道如何将每个汽车事件添加到事件列表中,以便它们同时开始。

有什么帮助吗?谢谢:)

最好的问候

编辑

好的,我不会把它作为答案写下来,因为我并不完全理解它。但我有我想要的结果。我创建了多个 Dispatch 对象,并分别运行每个对象。除非其他人能清楚地解释这一点,否则我会等我弄清楚后再发布答案。

class Dispatch():
    def __init__(self, env, car):
        self.car = car
        self.action = env.process(self.run())
    
    def run(self):
        while True:
            yield env.process(self.car.moveto())
            
class Car():
    def __init__(self, env, name, initial_location):
        self.env = env
        self.name = name
        self.location = initial_location
        self.path = cycle(["A", "B", "C", "B"])
    
    def moveto(self):
        if self.name == "carA":
            yield env.timeout(1)
        elif self.name == "carB":
            yield env.timeout(4)
        self.location = next(self.path)
        print("{} is now at node: {}, at time: {}".format(self.name, self.location, env.now))
        
env = simpy.Environment()
carA = Car(env, "carA", "A")
carB = Car(env, "carB", "A")
cars = [carA, carB]

for car in cars:
    Dispatch(env, car)

env.run(until=20)

【问题讨论】:

    标签: python simpy


    【解决方案1】:

    你可以同时使用threading来跑车:

    import time
    import threading
    from itertools import cycle
    
    CARS = ['carA', 'carB', 'carC']
    POS = ['A', 'B', 'C', 'D']
    
    class Car:
        def __init__(self, name):
            self.name = name
            self.pos = iter(cycle(POS))
            self.time = 1
    
        def run(self):
            while self.time < 5:
                pos = next(self.pos)
                print(f'{self.name} is now at position {pos}, at time: {self.time}')
                self.time += 1
                time.sleep(1)
    
    [threading.Thread(target=Car(car).run).start() for car in CARS]
    

    输出:

    carA is now at position A, at time: 1
    carB is now at position A, at time: 1
    carC is now at position A, at time: 1
    carB is now at position B, at time: 2
    carC is now at position B, at time: 2
    carA is now at position B, at time: 2
    carB is now at position C, at time: 3
    carA is now at position C, at time: 3
    carC is now at position C, at time: 3
    

    【讨论】:

    • 谢谢!我从没想过那样做。但我想知道如何在简单的事件队列中同时安排多个事件。
    • events 是什么意思?
    • 我正在使用 Simpy 库,它是一个离散事件模拟器。基本上,您可以在事件堆栈中安排事件。我正在寻找一种方法来添加多个事件以在堆栈中同时触发。我发现了如何做到这一点(我编辑了我的第一篇文章),但我仍在思考它是如何工作的。
    【解决方案2】:

    你的第一个代码几乎就在那里

    真正的问题是调度程序的 run 方法中的这一行。

    yield env.process(car.move())
    

    你需要降低产量

    yield 会导致您的代码等到 car.move() 完成,然后再循环并启动下一辆车。

    将代码更改为

    env.process(car.move())
    

    这将异步运行 car_move() 进程

    我做的另一件事是将机芯向下移动到汽车上。让每辆车都有自己的超时时间为您提供了选择,例如因机械故障而中断一辆车。您还可以在汽车类中添加一个参数,以赋予每辆汽车不同的速度

    查看下面的代码

    import simpy
    from itertools import cycle
    
    class Dispatch():
        def __init__(self, env, cars, startTime=0):
            self.env = env
            self.cars = cars
            self.action = env.process(self.run(startTime))
        
        def run(self,startTime):
            # wait for start of race 
            yield self.env.timeout(startTime)
            for car in self.cars:
                    # no yield here
                    env.process(car.move())
                
    class Car():
        def __init__(self, env, name, initial_location):
            self.env = env
            self.name = name
            self.location = initial_location
            self.path = iter(cycle(["A", "B", "C", "B"]))
        
        def move(self):
            # let each car move itself, more like a real car
            while True:
                print("{} is now at position {}, at time: {}".format(self.name, self.location, env.now))
                yield env.timeout(1)
                self.location = next(self.path)
            
    env = simpy.Environment()
    carA = Car(env, "carA", "A")
    carB = Car(env, "carB", "A")
    carC = Car(env, "carC", "A")
    dispatcher = Dispatch(env, [carA,carB,carC])
    env.run(until=20)
    

    【讨论】:

      猜你喜欢
      • 2020-08-24
      • 2013-07-03
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 2021-10-04
      • 2014-10-02
      • 1970-01-01
      • 2015-09-14
      相关资源
      最近更新 更多