0

コールバックからシミュレーション コード (イベントの待機を含む) を作成するにはどうすればよいですか?

プロセスを可能な限り単純な例に縮小すると、simpy シミュレーションでイベントが発生したときに実行可能コードを開始したいと考えています。私がしたことは、その実行可能コードをイベントのコールバックとして設定することでした。その実行可能コード自体には、いくつかの単純なイベント処理、特にタイムアウトがあります。私の実際のコードでは、これはプロセス内で発生しますが、この単純化されたバージョンでeventは、主に同じ問題の動作が表示されます。

import simpy
if __name__ == '__main__':
    env = simpy.Environment()

    def simulationRun(event):
        print("Starting a run at time [%i]" % env.now)
        yield env.timeout(5)
        print("Ending a run at time [%i]" % env.now)

    event = env.timeout(5)
    event.callbacks.append(simulationRun)

    print("Starting simulation.")
    env.run(20)
    print("End of simulation.")

私の予想される出力は次のとおりです。

Starting simulation.
Starting a run at time [5]
Ending a run at time [10]
End of simulation.

ただし、私の実際の出力は次のとおりです。

Starting simulation.
End of simulation.

yield コマンドを削除すると、次のようになります。

Starting simulation.
Starting a run at time [5]
Ending a run at time [5]
End of simulation.

コールバックが正しく設定されていることは明らかですが、要点は でタイムアウトをシミュレートすることsimulationRunです。コールバックからコードでシミュレーション コード (イベントの待機を含む) を実行するにはどうすればよいですか?

これは Python 3.4.2 と simpy を使用します。

4

2 に答える 2

2

コールバックを直接操作しないでください。ベスト プラクティスは、自動的に を開始する別のプロセスを使用するsimulation_run()ことです。

import simpy


def simulation_run(env):
    print("Starting a run at time [%i]" % env.now)
    yield env.timeout(5)
    print("Ending a run at time [%i]" % env.now)


def starter(env):
    yield env.timeout(5)
    env.process(simulation_run(env))


if __name__ == '__main__':
    env = simpy.Environment()
    env.process(starter(env))
    print("Starting simulation.")
    env.run(20)
    print("End of simulation.")

これは比較的一般的なパターンであるため、SimPy にはユーティリティ関数が組み込まれています。これはまさにこれを行います。

import simpy
import simpy.util


def simulation_run(env):
    print("Starting a run at time [%i]" % env.now)
    yield env.timeout(5)
    print("Ending a run at time [%i]" % env.now)


if __name__ == '__main__':
    env = simpy.Environment()
    simpy.util.start_delayed(env, simulation_run(env), delay=5)
    print("Starting simulation.")
    env.run(20)
    print("End of simulation.")

注: グローバル スコープからのものを使用する代わりに、環境への参照を常にプロセスに渡す必要があります。面倒に思えるかもしれませんが、後でコードを再構築またはリファクタリングし、グローバル env が期待したものでなくなったり、使用できなくなったりすると、あらゆる種類の問題が発生する可能性があります。

于 2015-03-11T09:04:18.603 に答える
1

問題は、コールバックがプロセスではないことです。そのため、エンジンによって停止および再起動できるような方法で simpy シミュレーション エンジンで実行されていません。必要なのはプロセスです。simulationRun以下に示すように、別のコールバック関数からそのコードを開始することにより、現在のプロセスを作成できます。

import simpy  

if __name__ == '__main__':
    env = simpy.Environment()

    def simulationRun():
        print("Starting a run at time [%i]" % env.now)
        yield env.timeout(5)
        print("Ending a run at time [%i]" % env.now)

    def callback(event):
        s = simulationRun()
        env.process(s)

    event = env.timeout(5)
    event.callbacks.append(callback)

    print("Starting simulation.")
    env.run(20)
    print("End of simulation.")
于 2015-03-10T00:59:45.787 に答える