在Simpy中,如何同步两个进程以启动第三个进程?

时间:2020-05-08 20:25:48

标签: python simulation yield simpy event-simulation

我正在尝试用多台机器模拟制造过程。 Machine1的容量为1升。 Machine2的容量为2升。我们想生产2升化学药品X。因此我们在Machine1中放入了1升原料。完成后,将1L移至Machine2。同时,使用第二批1L在Machine1上运行另一轮。然后将其添加到已满一半的Machine2中。然后启动Machine2以最终产生两升。如果Machine1花费3个小时,而Machine2花费12个小时,则此过程将花费3 + 3 + 12 = 18个小时。

现在,我的方法如下。我将Machine1创建为具有容量1的资源,并将Machine2创建为具有容量2的资源。我希望在两个批次都通过Machine1之后启动Machine2。我的尝试代码如下:

import simpy
from collections import namedtuple

Chemical = namedtuple("Chemical", "name")

X_batch1 = Chemical("X_batch1")
X_batch2 = Chemical("X_batch2")


def do_process_1(env, machine1, Chemical):
    print(f"Chemical {Chemical.name} requested Machine1 at {env.now}")
    with machine1.request() as req:
        yield req
        print(f"Chemical {Chemical.name} got into Machine1 at {env.now}")
        yield env.timeout(3)
        print(f"Chemical {Chemical.name} got out of Machine1 at {env.now}")
        # yield env.timeout(2)


def do_process_2(env, machine1, machine2, Chemicals):

    # <some condition to check if process 1 is done for both Chemicals>

    # make each batch for machine2, one after the other
    print(f"{Chemicals[0]} asks for Machine2 at {env.now}.")
    print(f"{Chemicals[1]} asks for Machine2 at {env.now}.")
    with machine2.request() as req1, machine2.request() as req2:
        yield req1 & req2
        print(f"{Chemicals[0]} gets machine2 at {env.now}.")
        print(f"{Chemicals[1]} gets Machine2 at {env.now}.")
        yield env.timeout(12)
    print(f"{Chemicals[0]} got out of machine2 at {env.now}.")
    print(f"{Chemicals[1]} got out of machine2 at {env.now}.")


env = simpy.Environment()
machine1 = simpy.Resource(env, 1)
machine2 = simpy.Resource(env, 2)

env.process(do_process_1(env, machine1, X_batch1))
env.process(do_process_1(env, machine1, X_batch2))
env.process(do_process_2(env, machine2, machine1, (X_batch1, X_batch2)))
env.run(until=60)

我上面有两个障碍:

  1. 仅在两台机器都完成了机器1的处理后才应请求Machine2。我不确定如何添加此条件以及在何处添加它。
  2. Machine2必须被两次请求(按不同的批次),然后应继续进行工作。只有一个请求时,它不应开始工作。

任何帮助将不胜感激!


1 个答案:

答案 0 :(得分:0)

我用下面的代码解决了自己的问题。简而言之,我将第一台计算机的进程保存在一个变量中,并将该变量传递给第二台计算机。然后,在第二台机器的流程中对该流程使用收益。

import simpy
from collections import namedtuple

Chemical = namedtuple("Chemical", "name")

X_batch1 = Chemical("X_batch1")
X_batch2 = Chemical("X_batch2")


def do_process_1(env, machine1, Chemical):
    print(f"Chemical {Chemical.name} requested Machine1 at {env.now}")
    with machine1.request() as req:
        yield req
        print(f"Chemical {Chemical.name} got into Machine1 at {env.now}")
        yield env.timeout(3)
        print(f"Chemical {Chemical.name} got out of Machine1 at {env.now}")
        # yield env.timeout(2)


def do_process_2(env, machine2, Chemicals, procs):

    yield env.all_of(procs)

    # make each batch for machine2, one after the other
    print(f"{Chemicals[0]} asks for Machine2 at {env.now}.")
    with machine2.request() as req1, machine2.request() as req2:
        yield req1 & req2
        print(f"{Chemicals[0]} gets machine2 at {env.now}.")
        yield env.timeout(12)
    print(f"{Chemicals[0]} got out of machine2 at {env.now}.")


env = simpy.Environment()
machine1 = simpy.Resource(env, 1)
machine2 = simpy.Resource(env, 2)

proc1 = env.process(do_process_1(env, machine1, X_batch1))
proc2 = env.process(do_process_1(env, machine1, X_batch2))
env.process(do_process_2(env, machine2, (X_batch1), (proc1, proc2)))
env.process(do_process_2(env, machine2, (X_batch2), (proc1, proc2)))
env.run(until=60)