Simpy 4,同时启动多个进程

2024-09-30 05:14:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用的是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循环的方法

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

有什么帮助吗?谢谢:)

致意

编辑

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

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)

Tags: nameselfenvtimeisdefpositionlocation
2条回答

你的第一个密码就快到了

真正的问题是调度器的run方法中的这一行

yield env.process(car.move())

你需要降低收益率

这种屈服会导致代码等待car.move()完成,然后循环并启动下一辆车

将代码更改为

env.process(car.move())

这将异步运行car_move()进程

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

请参见下面的代码

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)

您可以使用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

相关问题 更多 >

    热门问题