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 によって上書きされます。この新しいリクエストをリリースしようとしても、適切にリリースされないと思います。これは、リソースによって処理されているリリースではないためです (新しいリクエストです)。

解決策が何であるかわかりません。私自身も同じ問題を抱えているので、見つけようとしてこの投稿に出くわしました。明白な可能性の 1 つ (私はまだ試していません) は、リクエストのリストを作成してそれらを追跡することですが、これはばかげた解決策のように思えます。リソースを単純に解放する方法が必要です (これが望ましい動作です)。分かり次第追記しようと思います!

最小限の作業例を次に示します。

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 バッチを作成できるはずですが、最初の 1 つだけが実行されます。

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

2番目のリクエストを参照しているため、リリースが機能していないようです。これを診断することで回避策を見つけることができますが、それを行う正しい方法を知っておくとよいでしょう!


考えられる解決策の 1 つは、特定の要求ではなく、現在のユーザーを解放することです。

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 に答える