Help to trigger env.process() after a certain delay.

107 views
Skip to first unread message

Guangran Tang

unread,
Apr 29, 2022, 3:49:04 AM4/29/22
to python-simpy
Hi, everyone. I try to trigger a procedure after a period of time. For example, I prepare to simulate cooking dinner which has three steps: Washing vegetables,  stewing soup and grilling steak. I def three functions and want to trigger env.process(grilling steak) when 'stewing soup' has finished partly. I used 'if' but it cannot trigger correctly.
Thanks.
example.py

Sean Reed

unread,
Apr 30, 2022, 6:40:27 AM4/30/22
to python-simpy
The if statement in your steak process will just loop infinitely since it never hits a yield statement. If I understand correctly you want to start the steak process when the soup_finish container reaches a level of 3?

You could yield to a get request of 3 from that container (then immediately put 3 back if desired) before entering the main process loop like so:

def steak(env, cooking):
   yield cooking.soup_finish.get(3)
   cooking.soup_finish.put(3)  

   while True:
      yield cooking.steak_start.get(1)
      steak_time = 2
      yield env.timeout(steak_time)
      yield cooking.steak_finish.put(1)

Or use a container for soup_finish that overrides the put method to check when the level first reaches 3 to trigger the steak process:

class SoupFinishContainer(simpy.Container):

   def __init__(self, env, capacity, init):
      super().__init__(env, capacity, init)
      self.triggered = False

   def put(self, amount):

      if not self.triggered and self.level >= 3:
         self.triggered = True
         self._env.process(steak(self._env, cooking))

      return super().put(amount)

Alternatively, wrap the put method using the approach described here: https://simpy.readthedocs.io/en/4.0.1/topical_guides/monitoring.html#resource-usage.

Sean Reed

unread,
Apr 30, 2022, 6:48:03 AM4/30/22
to python-simpy
Should probably also pass in the instance of the Cooking class when instantiating the container:

class 
SoupFinishContainer(simpy.Container):

   def __init__(self, env, cooking, capacity, init):
      super().__init__(env, capacity, init)
      self.cooking = cooking
      self.triggered = False

   def put(self, amount):

      if not self.triggered and self.level >= 3:
         self.triggered = True
         self._env.process(steak(self._env, self.cooking))

      return super().put(amount)

Then in the Cooking class constructor, you would use:

self.soup_finish = SoupFinishContainer(env, self, capacity=5, init=0)

Michael Gibbs

unread,
May 2, 2022, 6:57:59 PM5/2/22
to python-simpy
you need to use a event to sync up your processes.  create a Event() lets call it start_steak_event.  pass this one event to both the soup and steak processes.  Have the stake immediately yield to the  start_steak_event  .  When the soup gets to the point the steak should start, the soup will call the  start_steak_event  succeed() method.  This will end the steak's yield and start the steak's cooking process.  

Also, you could call env.process to start your steak from inside your soup process (without a yield).  using env.process without a yield will start that process in parallel and the calling process will keep going without waiting for the called process to finish

Michael Gibbs

unread,
May 3, 2022, 11:08:02 PM5/3/22
to python-simpy
Sean is right about the if statement.  if you add a env.timeout(1) just before the if I think you will see some improvement

Guangran Tang

unread,
May 12, 2022, 9:39:40 PM5/12/22
to python-simpy
Thanks for above help.
Recently, I met some new questions. I try to use Resource(env, capicaty=2) to simulate that I have two stoves that I can cooking two soup at the same time.
def soup(env, cooking):
while True:
 with cooking.stove.request() as req:
  yield req
  yield cooking.soup_start.get(1)
  soup_time = 8
  yield env.timeout(soup_time)
  yield cooking.soup_finish.put(1)
It cannot work as my consideration. It seems to have no difference compared with 'no req'.

Michael Gibbs

unread,
May 13, 2022, 12:49:48 AM5/13/22
to python-simpy
are you making one dinner or is this a sort of assembly line of dinners?

Michael Gibbs

unread,
May 13, 2022, 3:02:52 PM5/13/22
to python-simpy
how many soup processes do you have running concurrently?  You will not see any contention until you have 3 soups running at the same time.

Michael Gibbs

unread,
May 13, 2022, 3:05:39 PM5/13/22
to python-simpy
This goes back to your earlier post.  This uses events to coordinate some cooking activities instead of while loops and stores
dinner.py
Reply all
Reply to author
Forward
0 new messages