Skip to content Skip to sidebar Skip to footer

Resource Not Releasing In Simpy - What Am I Doing Wrong?

I have simplified the code representing the problem as suggested and attempted to debug. Here is the most simple version of the code which still contains the bug: import simpy SIM

Solution 1:

I believe the problem comes about because the release refers to a specific request, but the request has by then already be over-written by a new request. resource_req is the request, but before it can be released, it is overwritten by a new resource_req. I believe that when you try to release this new request it does not release it properly, because it's not a release that is being handled by the resource (it's the new one).

I don't know what the solution is. I came across this post trying to find it, because I'm having the same problem myself. One obvious possibility (which I haven't tried yet) is to create a list of requests, and keep track of them, but this seems like a silly solution. There must be a way to simply free up the resource (which is the behaviour that is desired). I'll try to post back if I figure it out!

Here's a minimal working example:

import simpy

classMachine:
    def__init__(self,env):
        self.machine = simpy.Resource(env,capacity=1)
        self.load_proc = env.process(self.load(env))

    defload(self,env):
        "Load machine 1 when it's empty"whileTrue:
            self.req = self.machine.request()
            print("Waiting for machine at %d" %env.now)
            yield self.req
            print("Load machine at %d" %env.now)
            self.process_proc = env.process(self.process(env))

    defprocess(self,env):
        "Machine does process and is then emptied"print("Machine starts process at %d" %env.now)
        yield env.timeout(10)
        print("Machine finished process at %d" %env.now)
        self.machine.release(self.req)
        print("Machine released at %d" %env.now)

env = simpy.Environment()
M1 = Machine(env)
env.run(until=100)

Here there is a machine that continually tries to load, but waits for it to be empty. Once it's loaded, it tries to run a 10 second process and then releases the Resource to allow it to be loaded again. In 100 time-steps it should obviously be able to make 10 batches, but only the first one is done.

>>> 
Waiting for machine at 0
Load machine at 0
Waiting for machine at 0
Machine starts process at 0
Machine finished process at 10
Machine released at 10
>>>

It seems that the release does not work, because it is referring to the second request. Diagnosing this makes it possible to find a workaround, but it would be nice to know the right way to do it!


One possible solution is to just release a current user rather than a specific request:

import simpy

classMachine:
    def__init__(self,env):
        self.machine = simpy.Resource(env,capacity=1)
        self.load_proc = env.process(self.load(env))

    defload(self,env):
        "Load machine 1 when it's empty"whileTrue:
            print("Waiting for machine at %d" %env.now)
            yield self.machine.request()
            print("Load machine at %d" %env.now)
            self.process_proc = env.process(self.process(env))

    defprocess(self,env):
        "Machine does process and is then emptied"print("Machine starts process at %d" %env.now)
        yield env.timeout(10)
        print("Machine finished process at %d" %env.now)
        iflen(self.machine.users)>=1: self.machine.release(self.machine.users[0])
        print("Machine released at %d" %env.now)

env = simpy.Environment()
M1 = Machine(env)
env.run(until=100)

This behaves as expected, and has the advantage that you don't need a variable for the request. The release of

self.machine.release(self.machine.users[0])

is probably sufficient, unless you're at risk of releasing something that hasn't been requested already.


Update based on Stefan Scherfke's comment, is to pass the req explicitly to the new process:

import simpy

classMachine:
    def__init__(self,env):
        self.machine = simpy.Resource(env,capacity=1)
        self.load_proc = env.process(self.load(env))

    defload(self,env):
        "Load machine 1 when it's empty"whileTrue:
            print("Waiting for machine at %d" %env.now)
            req = self.machine.request()
            yield req
            print("Load machine at %d" %env.now)
            self.process_proc = env.process(self.process(env,req))

    defprocess(self,env,req):
        "Machine does process and is then emptied"print("Machine starts process at %d" %env.now)
        yield env.timeout(10)
        print("Machine finished process at %d" %env.now)
        self.machine.release(req)
        print("Machine released at %d" %env.now)

env = simpy.Environment()
M1 = Machine(env)
env.run(until=100)

This does indeed work as expected.

Solution 2:

Solved - there was a typo in the resource.

Originally defined as:

resource = simpy.Resource(env, 1)

Correct definition:

resource = simpy.Resource(env, capacity = 1)

Post a Comment for "Resource Not Releasing In Simpy - What Am I Doing Wrong?"