Python SimPyシミュレーションシリーズ(2)
4811 ワード
この記事では、SimPyを使用して2つのシミュレーション要件を解決する方法について説明します.リカバリをいつでも中断する方法 を動的に設定する方法
この2つの要件を満たすシーンは、次のとおりです.シミュレーション中、ある工程が中断する、中断は予め設定された時間又は不確定時間 に基づいてもよい.シミュレーションの過程で、人的資源も時間の変化に基づいて、シミュレーションの現実の労働者の勤務手配 リソースとプロセスの概念をレビュー
例えば、ある工程で1人の労働者を占有する必要があり、30 minを費やしてプロセスを完了し、現在呼び出すことができるすべての労働者数は10であり、コード形式は以下の通りである.
もっと詳しい紹介と資料は以前の文章Python SimPyシミュレーションシリーズ(1)を振り返ることができる.
次の2つのシナリオがあります.プロセスは随時中断し、 を回復する.スケジュールに従ってプロセスを開始または終了する .
一つのことを区別するには、中断するときに現在のプロセスを完了させてから中断するか、すぐに中断するかを区別します.具体的なシーンは、労働者が現在の職場から異動されたことを想像することができ、彼はまず手元の工程を完成しなければならないか、あるいは手元の仕事を止めて職場を離れる必要がある.
プロセスの随時中断を実現しなければならない場合、
プロセス中断の実装
マルチセグメントプロセスシミュレーション時間別スイッチリソース人数指定されたレイアウトに従って をプロビジョニング
このような操作により、リソースの占有プロセスの優先度が高くなり、通常のプロセスで呼び出すことができるリソースの数が次のようになります.
Process
(プロセス)Resource
(リソース)の数この2つの要件を満たすシーンは、次のとおりです.
Resource
とProcess
はSimPyが人的資源とプロセスに対して抽象的な構造である.Resource
は1つのキューのようなもので、その長さは予め設定する資源数であり、異なる工程は時間の前後と与えられた優先度に従ってキューに入る.Process
は構造的にはジェネレータであり、send法によりException
に伝達するProcess
を遮断することができる.例えば、ある工程で1人の労働者を占有する必要があり、30 minを費やしてプロセスを完了し、現在呼び出すことができるすべての労働者数は10であり、コード形式は以下の通りである.
import simpy
import random
WORKERNUM = 10 #
PROCESS_TIME = 30 * 60 # ,
MEAN_ = 4 * 60 #
def process(env, workers, store):
""" """
while True:
with workers.request() as req:
yield req
item = yield store.get()
print(f"{env.now} - {item} - start")
yield env.timeout(PROCESS_TIME)
print(f"{env.now} - {item} - done")
def put_item(env, store):
""" """
for i in range(100):
item = f"{i}_item"
store.put(item)
yield env.timeout(random.expovariate(1 / MEAN_))
env = simpy.Environment()
workers = simpy.Resource(env, 10)
store = simpy.Store(env)
env.process(process(env, workers, store))
env.process(put_item(env, store))
env.run()
もっと詳しい紹介と資料は以前の文章Python SimPyシミュレーションシリーズ(1)を振り返ることができる.
Process
プロセスの動的調整次の2つのシナリオがあります.
一つのことを区別するには、中断するときに現在のプロセスを完了させてから中断するか、すぐに中断するかを区別します.具体的なシーンは、労働者が現在の職場から異動されたことを想像することができ、彼はまず手元の工程を完成しなければならないか、あるいは手元の仕事を止めて職場を離れる必要がある.
プロセスの随時中断を実現しなければならない場合、
process.interrupt()
を通じてprocess
、すなわち第1のシーンを中断するしかない.割り込みがスケジュール通りに行うと、第2のシーンでは、複数の異なる時間に開くプロセスを構築してシミュレーションを行うことができる.プロセス中断の実装
from simpy import interrupt, Environment
env = Environment()
def interrupter(env, victim_proc):
yield env.timeout(1)
victim_proc.interrupt('Spam')
def victim(env):
try:
yield env.timeout(10)
except Interrupt as interrupt:
cause = interrupt.cause
マルチセグメントプロセスシミュレーション時間別スイッチ
import simpy
PROCESS_TIME = 3
def put_item(env, store):
for i in range(20):
yield env.timeout(0.5)
store.put(f"{i}_item")
def process(i, env, store, start, end):
yield env.timeout(start)
while True:
item = yield store.get()
# item
if env.now > end:
print(f"{env.now} - process {i} - end")
store.put(item)
env.exit()
else:
print(f"{env.now} - {item} - start")
yield env.timeout(PROCESS_TIME)
print(f"{env.now} - {item} - end")
env = simpy.Environment()
store = simpy.Store(env)
env.process(put_item(env, store))
for i, (start, end) in enumerate([(20, 30), (40, 50), (60, 90)]):
env.process(process(i, env, store, start, end))
env.run()
Resource
リソースの動的調整Resource
は実例化後、修正できないためである.シミュレーションの過程で資源を修正することを満たすために、逆方向の構想を用いた.まず、全てのリソース使用例PriorityResource
は、予め調整可能な最大リソース数を設定しておき、リソース数を調整する必要がある場合には、-1
の優先度を持つrequest
を使用してリソースを占有するが、通常のプロセスのデフォルト優先度は0
である.このような操作により、リソースの占有プロセスの優先度が高くなり、通常のプロセスで呼び出すことができるリソースの数が次のようになります.
=
-
import simpy
PROCESS_TIME = 2
def put_item(env, store):
for i in range(20):
yield env.timeout(0.5)
store.put(f"{i}_item")
def process(env, store, resource):
while True:
item = yield store.get()
with resource.request() as req:
yield req
yield env.timeout(PROCESS_TIME)
def set_resource(env, resource, start_time, end_time):
""" , ,
end_time np.inf ,
simpy , timeout 。
"""
duration = end_time - start_time
yield env.timeout(start_time)
with resource.request(priority=-1) as req:
yield req
yield env.timeout(duration)
env = simpy.Environment()
store = simpy.Store(env)
res = simpy.PriorityResource(env, 10)
res_time_table = [(10, 20, 5), (20, 30, 6)]
env.process(put_item(env, store))
env.process(process(env, store, res))
for start, end, target_num in res_time_table:
place_holder = 10 - target_num
for _ in range(place_holder):
env.process(set_resource(env, res, start, end))
env.run()