资源未在 Simpy 中发布 - 我做错了什么?
Resource not releasing in Simpy - what am I doing wrong?
我已经按照建议简化了代表问题的代码并尝试调试。
这是最简单的代码版本,但仍然存在错误:
import simpy
SIM_TIME = 5
def source(env):
i = 0
while True:
i += 1
env.process(train(env, 'Train %d' % i, 'a'))
yield env.timeout(1)
i += 1
env.process(train(env, 'Train %d' % i, 'b'))
yield env.timeout(1)
def train(env, name, route):
resource_req = resource.request()
p3_req = p3.request()
if route == 'a':
print 'Route a %s generated' % name
yield resource_req
print 'Route a %s seized resource at time %d' % (name, env.now)
yield env.timeout(1)
resource.release(resource_req)
print 'Route a %s released resource at time %d' % (name, env.now)
elif route == 'b':
print 'Route b %s generated' % name
yield p3_req
print 'Route b %s seized resource at time %d' % (name, env.now)
yield env.timeout(1)
p3.release(p3_req)
print 'Route b %s released resource at time %d' % (name, env.now)
else:
print 'Could not find a route branch'
env = simpy.Environment()
resource = simpy.Resource(env, 1)
p3 = simpy.Resource(env, 1)
env.process(source(env))
env.run(until=SIM_TIME)
运行 的输出:
Route a Train 1 generated
Route a Train 1 seized resource at time 0
Route b Train 2 generated
Route a Train 1 released resource at time 1
Route a Train 3 generated
Route b Train 4 generated
Route a Train 5 generated
如您所见,资源显然已在 "route a" 上释放,但随后无法在路由 a 或路由 b 上占用其他资源。
我对此很困惑。任何帮助将不胜感激!
我认为问题的出现是因为发布引用了一个特定的请求,但是到那时这个请求已经被一个新的请求覆盖了。 resource_req 是请求,但在释放之前,它被新的 resource_req 覆盖。我相信当您尝试发布这个新请求时,它不会正确发布它,因为它不是资源正在处理的版本(它是新的)。
我不知道解决方案是什么。我遇到这个 post 试图找到它,因为我自己也有同样的问题。一个明显的可能性(我还没有尝试过)是创建一个请求列表,并跟踪它们,但这似乎是一个愚蠢的解决方案。必须有一种方法可以简单地释放资源(这是所需的行为)。如果我弄明白了,我会尝试 post 回来!
这是一个最小的工作示例:
import simpy
class Machine:
def __init__(self,env):
self.machine = simpy.Resource(env,capacity=1)
self.load_proc = env.process(self.load(env))
def load(self,env):
"Load machine 1 when it's empty"
while True:
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))
def process(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)
这里有一台机器不断尝试加载,但等待它为空。加载后,它会尝试 运行 一个 10 秒的进程,然后释放资源以允许再次加载它。在 100 个时间步中,它显然应该能够制作 10 个批次,但只完成了第一个。
>>>
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
>>>
好像release不行,因为是指第二个请求。诊断此问题可以找到解决方法,但最好知道正确的方法!
一种可能的解决方案是仅释放当前用户而不是特定请求:
import simpy
class Machine:
def __init__(self,env):
self.machine = simpy.Resource(env,capacity=1)
self.load_proc = env.process(self.load(env))
def load(self,env):
"Load machine 1 when it's empty"
while True:
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))
def process(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)
if len(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)
这符合预期,优点是您不需要请求变量。发布
self.machine.release(self.machine.users[0])
可能就足够了,除非您有发布尚未请求的内容的风险。
更新基于Stefan Scherfke's评论,是将请求显式传递给新进程:
import simpy
class Machine:
def __init__(self,env):
self.machine = simpy.Resource(env,capacity=1)
self.load_proc = env.process(self.load(env))
def load(self,env):
"Load machine 1 when it's empty"
while True:
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))
def process(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)
这确实按预期工作。
已解决 - 资源中有错字。
最初定义为:
resource = simpy.Resource(env, 1)
正确定义:
resource = simpy.Resource(env, capacity = 1)
我已经按照建议简化了代表问题的代码并尝试调试。
这是最简单的代码版本,但仍然存在错误:
import simpy
SIM_TIME = 5
def source(env):
i = 0
while True:
i += 1
env.process(train(env, 'Train %d' % i, 'a'))
yield env.timeout(1)
i += 1
env.process(train(env, 'Train %d' % i, 'b'))
yield env.timeout(1)
def train(env, name, route):
resource_req = resource.request()
p3_req = p3.request()
if route == 'a':
print 'Route a %s generated' % name
yield resource_req
print 'Route a %s seized resource at time %d' % (name, env.now)
yield env.timeout(1)
resource.release(resource_req)
print 'Route a %s released resource at time %d' % (name, env.now)
elif route == 'b':
print 'Route b %s generated' % name
yield p3_req
print 'Route b %s seized resource at time %d' % (name, env.now)
yield env.timeout(1)
p3.release(p3_req)
print 'Route b %s released resource at time %d' % (name, env.now)
else:
print 'Could not find a route branch'
env = simpy.Environment()
resource = simpy.Resource(env, 1)
p3 = simpy.Resource(env, 1)
env.process(source(env))
env.run(until=SIM_TIME)
运行 的输出:
Route a Train 1 generated
Route a Train 1 seized resource at time 0
Route b Train 2 generated
Route a Train 1 released resource at time 1
Route a Train 3 generated
Route b Train 4 generated
Route a Train 5 generated
如您所见,资源显然已在 "route a" 上释放,但随后无法在路由 a 或路由 b 上占用其他资源。
我对此很困惑。任何帮助将不胜感激!
我认为问题的出现是因为发布引用了一个特定的请求,但是到那时这个请求已经被一个新的请求覆盖了。 resource_req 是请求,但在释放之前,它被新的 resource_req 覆盖。我相信当您尝试发布这个新请求时,它不会正确发布它,因为它不是资源正在处理的版本(它是新的)。
我不知道解决方案是什么。我遇到这个 post 试图找到它,因为我自己也有同样的问题。一个明显的可能性(我还没有尝试过)是创建一个请求列表,并跟踪它们,但这似乎是一个愚蠢的解决方案。必须有一种方法可以简单地释放资源(这是所需的行为)。如果我弄明白了,我会尝试 post 回来!
这是一个最小的工作示例:
import simpy
class Machine:
def __init__(self,env):
self.machine = simpy.Resource(env,capacity=1)
self.load_proc = env.process(self.load(env))
def load(self,env):
"Load machine 1 when it's empty"
while True:
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))
def process(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)
这里有一台机器不断尝试加载,但等待它为空。加载后,它会尝试 运行 一个 10 秒的进程,然后释放资源以允许再次加载它。在 100 个时间步中,它显然应该能够制作 10 个批次,但只完成了第一个。
>>>
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
>>>
好像release不行,因为是指第二个请求。诊断此问题可以找到解决方法,但最好知道正确的方法!
一种可能的解决方案是仅释放当前用户而不是特定请求:
import simpy
class Machine:
def __init__(self,env):
self.machine = simpy.Resource(env,capacity=1)
self.load_proc = env.process(self.load(env))
def load(self,env):
"Load machine 1 when it's empty"
while True:
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))
def process(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)
if len(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)
这符合预期,优点是您不需要请求变量。发布
self.machine.release(self.machine.users[0])
可能就足够了,除非您有发布尚未请求的内容的风险。
更新基于Stefan Scherfke's评论,是将请求显式传递给新进程:
import simpy
class Machine:
def __init__(self,env):
self.machine = simpy.Resource(env,capacity=1)
self.load_proc = env.process(self.load(env))
def load(self,env):
"Load machine 1 when it's empty"
while True:
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))
def process(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)
这确实按预期工作。
已解决 - 资源中有错字。
最初定义为:
resource = simpy.Resource(env, 1)
正确定义:
resource = simpy.Resource(env, capacity = 1)