4

我已经按照建议简化了代表问题的代码并尝试进行调试。

这是仍然包含错误的代码的最简单版本:

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

如您所见,资源显然是在“路线 a”上释放的,但是在路线 a 或路线 b 上都无法获取其他资源。

我对此感到非常困惑。任何帮助将非常感激!

4

2 回答 2

3

我相信问题的出现是因为发布是指一个特定的请求,但是到那时该请求已经被一个新请求覆盖了。resource_req 是请求,但是在它可以被释放之前,它被一个新的resource_req 覆盖。我相信当您尝试发布这个新请求时,它不会正确发布它,因为它不是资源正在处理的发布(它是新的)。

我不知道解决方案是什么。我偶然发现了这篇文章,试图找到它,因为我自己也遇到了同样的问题。一个明显的可能性(我还没有尝试过)是创建一个请求列表,并跟踪它们,但这似乎是一个愚蠢的解决方案。必须有一种方法可以简单地释放资源(这是所需的行为)。如果我弄清楚了,我会尝试回帖!

这是一个最小的工作示例:

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
>>> 

似乎发布不起作用,因为它指的是第二个请求。对此进行诊断可以找到解决方法,但如果知道正确的方法会很高兴!


一种可能的解决方案是仅释放当前用户而不是特定请求:

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 的评论的更新是将 req 显式传递给新进程:

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)

这确实按预期工作。

于 2016-10-28T17:01:56.383 回答
0

已解决 - 资源中有错字。

最初定义为:

resource = simpy.Resource(env, 1)

正确定义:

resource = simpy.Resource(env, capacity = 1)
于 2016-11-29T11:56:40.307 回答