在 Simpy 中满足特定条件后继续执行

问题描述

我是 Simpy 的新手,我正在尝试实现一个简单的模拟,其中进程必须等到条件为 False 时,当条件变为 True 时,它​​必须继续执行其余的过程。 考虑简单的代码

import simpy
import random

condition_flag = 0

def car(env):
     while True:
         global condition_flag
         #wait for the condition to become true
         while(condition_flag != 1):
             pass
         #reset condition flag
         condition_flag = 0

         print('Start parking at %d' % env.Now)
         parking_duration = 5
         yield env.timeout(parking_duration)

         print('Start driving at %d' % env.Now)
         trip_duration = 2
         yield env.timeout(trip_duration)

def some_condition(env):
    while True:
        global condition_flag
        rand_num = random.randrange(0,10)
        if rand_num > 8:
            condition_flag = 1
        yield env.timeout(1)


env = simpy.Environment()
env.process(car(env))
env.process(some_condition(env))
env.run(until=15)

以上示例在 while 进程中的 car 条件下持续等待。 这是正确的做法吗?如果不是,如何处理? 提前致谢!

编辑和扩展(因为我无法评论这些大数据) 来自@Michael 的回答。

只是想澄清一下: 一旦满足条件(rand_num > 8),就会触发事件condition_flag 并设置为success()。这反过来又使暂停的 car 进程恢复。之后,我们将重置事件 condition_flag 以检测另一个触发器 & success()。我的理解正确吗?

另外,由于我想模拟更多的汽车,代码稍作修改

import simpy
import random

num_of_cars = 2
condition_flag = [None] * num_of_cars


def car(env,car_id):
    while True:
        global condition_flag
        # wait for the condition to become true
        print('wait for event')
        yield condition_flag[car_id]
        # reset condition flag
        condition_flag[car_id] = simpy.Event(env)
        print('event fired and reset')

        print('Start parking at %d' % env.Now)
        parking_duration = 5
        yield env.timeout(parking_duration)

        print('Start driving at %d' % env.Now)
        trip_duration = 2
        yield env.timeout(trip_duration)


def some_condition(env):
    while True:
        global condition_flag
        rand_num = random.randrange(0,num_of_cars)
        print(rand_num)
        condition_flag[rand_num].succeed()
        '''
        if rand_num > 8:
            print('condition meet ',env.Now)
            # need to check if event has been reset
            if condition_flag.triggered:
                print('event has not been reset yet')
            else:
                condition_flag.succeed()
        '''
        yield env.timeout(1)


if __name__ == '__main__':
    print('start')
    env = simpy.Environment()
    condition_flag = simpy.Event(env)
    #env.process(car(env))
    for i in range(num_of_cars):
        env.process(car(env,I))
    env.process(some_condition(env))
    env.run(until=50)
    print('stop')

以上代码运行后报错如下:

root@testuser-Vostro-3902:~/AtAI/Rack_Warehouse/LoRaSimulators/lorasim# python simple2.py
start
wait for event
wait for event
0
Traceback (most recent call last):
  File "simple2.py",line 13,in car
    yield condition_flag[car_id]
TypeError: 'Event' object does not support indexing

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "simple2.py",line 53,in <module>
    env.run(until=50)
  File "/usr/local/lib/python3.6/dist-packages/simpy/core.py",line 254,in run
    self.step()
  File "/usr/local/lib/python3.6/dist-packages/simpy/core.py",line 206,in step
    raise exc
TypeError: 'Event' object does not support indexing

我做错了什么吗?为什么进程无法对属于事件列表成员的事件让步?

解决方法

当您屈服于某个事件时,您的进程会等待该事件触发。您可以通过调用该事件的成功或失败方法在该事件触发时触发。

我更新了您的代码以使用事件而不是标志,见下文

import simpy
import random

condition_flag = None


def car(env):
    while True:
        global condition_flag
        # wait for the condition to become true
        print('wait for event')
        yield condition_flag
        # reset condition flag
        condition_flag = simpy.Event(env)
        print('event fired and reset')

        print('Start parking at %d' % env.now)
        parking_duration = 5
        yield env.timeout(parking_duration)

        print('Start driving at %d' % env.now)
        trip_duration = 2
        yield env.timeout(trip_duration)


def some_condition(env):
    while True:
        global condition_flag
        rand_num = random.randrange(0,10)
        print(rand_num)
        if rand_num > 8:
            print('condition meet ',env.now)
            # need to check if event has been reset
            if condition_flag.triggered:
                print('event has not been reset yet')
            else:
                condition_flag.succeed()
        yield env.timeout(1)


if __name__ == '__main__':
    print('start')
    env = simpy.Environment()
    condition_flag = simpy.Event(env)
    env.process(car(env))
    env.process(some_condition(env))
    env.run(until=50)
    print('stop')