S4コーディング入門(第4回)ファシリティの仕組みと活用方法

  • HOME
  • S4コーディング入門(第4回)ファシリティの仕組みと活用方法

はじめに

本連載の第1回と第2回では、S4本体の機能を中心にコーディング上のノウハウをお伝えし、第3回からは「S4プロジェクトを思い通りにカスタマイズする」ために、具体的なプロジェクトを通じてテクニックをご紹介しています。今回はファシリティ関連のテクニックを見ていきます。

ファシリティの概要

S4のチュートリアルで最初に作成するプロジェクト「銀行の窓口」において、ファシリティを扱いました。「ファシリティ」資源は一定の処理能力を持つ窓口と捉えられます。「ファシリティ利用」部品と組み合わせることで、流れてきたアイテムを処理する様子を表現できます。ファシリティ利用では(1)アイテムが流れてきて、ファシリティの処理能力を1個取り出し、(2)一定時間が経過する処理を行い、(3)処理能力を開放する、という流れで進行します。この流れは別々の部品で分けて表現することもできます:(1)は「ファシリティ要求」部品で、(2)は「遅延」部品で、(3)は「ファシリティ開放」部品で置き換えられるためです。

今回の「S4コーディング入門」記事では、ファシリティを用いるサンプルを通じて資源としての「ファシリティ」と部品としての「ファシリティ利用」「ファシリティ要求」「ファシリティ開放」の設定に介入することで、様々な目的でファシリティを扱えることを示します。

今回扱うプロジェクトは以下になります。

  • ファシリティ利用時間を関数で指定: アイテムに応じてファシリティの利用時間を変える方法をご紹介いたします。
  • ファシリティの同期した停止・回復: ファシリティに備わっている停止・回復の挙動を、複数のファシリティで同期させる方法をご紹介いたします。
  • 利用したファシリティを記録: 複数のファシリティを利用するケースにおいて、利用したファシリティの情報を得る方法をご紹介いたします。

ファシリティ利用時間を関数で指定

工場などのシミュレーションでは、製品の種類によって工程の処理時間が変化することがよくあります。S4ではこのような挙動を、アイテムの属性に応じてファシリティ利用時間を変えることで実現できます。

まずプロジェクトを開きます。S4のメニュー「プロジェクト」→「プロジェクトのインポート」でファイルダイアログを開き、(S4のインストールフォルダ (通常は C:\Program Files\Mathematical Systems Inc\S-Quattro Simulation System V6))\samples\離散-ミニマル\ファシリティ利用時間を関数で指定.s4 を選択し、OKします。S4画面左側の「ワークスペース」には開いたプロジェクトが置かれています。「+」をクリックし「モデル」をダブルクリックすることでプロジェクトを開きます。

まずカスタムコードを開くと、冒頭にて本プロジェクトの概要説明が記載されています。そしてナンバリングのための numgen の定義と、今回ファシリティ利用時間を計算する関数 calc_duration の定義があります。

次に「アイテム」および「生成」を見ると、ここでは numgen を参照していないことがわかります。前回はここでナンバリングを行っていましたが、今回は別の方法として「設定」で流れてきたアイテムに対し numgen のナンバリングを施しています。

「ファシリティ利用」では「ファシリティの利用時間」で calc_duration(item) を参照しています。この設定は「コード編集」タブの上側にある UseFacility の初期化メソッド __init__ 内、 self.useTime の定義に反映されます。

self.useTime = (lambda item: constantValue(float(calc_duration(item))))

このように実際に実行されるコードに埋め込まれた状態を確認すると、式に含まれる item の意味がわかります(重要:ある入力欄で実際に使える変数名は、それが埋め込まれる生成コードを確認することで把握できます)。 itemlambda 関数の仮引数として現れます。さらに属性 self.useTime の参照箇所を探すと、「コード編集」タブの下側にある run メソッドの定義の中のローカル関数 using で見つけられます。

useTime = float(next(self.useTime(item)))

itemusing の仮引数であり、流れてきたフローアイテムに一致することが確認できます。ローカル変数 useTime は少し下で yield pause(useTime) に渡されており、利用時間分の時間経過の発生という形で処理が表現されていることがわかります。

大意は掴めましたため、さらに細かく式を見てみます。 lambda 関数は psim のジェネレータ constantValue(...) を返します。これは第3回でも扱いましたが引数を固定値として返すジェネレータであり、 run メソッド内で next 呼び出しされた際に今回の item に対する calc_duration(item) の値がそのまま(float も挟まりますが)返って来ます。

calc_duration 自体の処理は単純であり、引数 item のナンバリングされた番号が3の倍数であれば平均200、標準偏差1の正規分布に従う乱数を返し、そうでなければ定数10を返します。「記録2」でアイテム3個ごとに処理時間が変わることを確認できます。

最後に、重要なキューサイズの設定について説明します。モデル画面を見ると「ファシリティ利用」の入力側の○が白くなっています。これは同部品の「共通設定」において「入力」→「入力ポート」→「キューサイズ」を「無制限」にしたことによります(デフォルトでは「制限あり」で値0)。この場合、「生成」から1秒ごとに生成されたアイテムは「ファシリティ利用」の入力キューに溜まっていき、先に来たアイテムのファシリティ利用が済むのを待ちます。この設定により、「記録」部品には1秒ごとに1個、流れてきたアイテムの記録が蓄積します。

「無制限」の設定が無い場合、アイテムが溜まる入力キューが無いため、イメージとしては各アイテムはアイコンの中に置かれます。「ファシリティ利用」では利用により時間経過が発生するため、それより手前にある「記録」や「設定」に、処理待ちのアイテムが溜まります。それも1個しか置けないため、実際には前が詰まって「生成」からアイテムを送り出せなくなり、「ファシリティ利用」の処理ペースに合わせて生成される状態になります。

アイコンの上にアイテムが置かれたり、生成が遅れたりする振る舞いはほとんどの場合想定外であるため、バグのように見えますが仕様になります。実際には適切なキュー設定が必要です。このようにアイコンやキューの仕様を理解しアイテムの流れを頭の中で追えるようになると、モデル構築の技術は格段に向上します。

ファシリティの同期した停止・回復

ファシリティの設定で、ファシリティ自体を停止させたり、停止しているファシリティを再開させたりすることができます。停止している間は、ファシリティのプロセスの進行が止まります。複数のファシリティの設定を行う場合、各々同じ設定を手動で施すことも可能ですが、設定が確率分布という形を取る場合もあり、一般に振る舞いまでは同じにはなりません。本節ではユーザ定義ジェネレータで明示的に同じ乱数の種を指定することで同じタイミングで停止と回復を行うプロジェクトについて解説いたします。

まずプロジェクトを開きます。S4のメニュー「プロジェクト」→「プロジェクトのインポート」でファイルダイアログを開き、(S4のインストールフォルダ (通常は C:\Program Files\Mathematical Systems Inc\S-Quattro Simulation System V6))\samples\離散-ミニマル\ファシリティの同期した停止・回復.s4 を選択し、OKします。S4画面左側の「ワークスペース」には開いたプロジェクトが置かれています。「+」をクリックし「モデル」をダブルクリックすることでプロジェクトを開きます。

プロジェクトの内容を見ていきます。「ファシリティ」と「ファシリティ2」の設定では、「停止確率」の箇所を除き同一の設定がなされています。「停止確率」の設定もほぼ同じで、差異は指定しているジェネレータだけです。停止の設定ではユーザ定義ジェネレータ gen_suspend1, gen_suspend2 で停止するまでの時間を与えています。回復の設定ではユーザ定義ジェネレータ gen_repair1, gen_repair2 で回復するまでの時間を与えています。これらのジェネレータはカスタムコードで定義されています。

カスタムコードを見ると、例えば gen_suspend1, gen_suspend2 は同一の関数 make_gen_suspend から作ったジェネレータであることがわかります。 make_gen_suspend は与えられたシード値から、テーブル上の値をランダムに取り出して返すジェネレータを作る関数です。 gen_suspend1, gen_suspend2 の作成時には同一のシード値を与えていますから、生成される乱数列は同一になります。 gen_repair1, gen_repair2 も同様です。これにより、「ファシリティ」と「ファシリティ2」はそれぞれ独立した設定を与えられながら、同一のタイミングで停止・回復することになります。シミュレーションを実行すると、同一の時間に停止・回復していることが print による標準出力で確認できますし、記録部品を見ると停止している間の時間間隔が変化していることが確認できます。

利用したファシリティを記録

「ファシリティ利用」部品では指定した複数のファシリティのうち1つを利用するような設定が可能です。本節ではそのようなケースにおいて利用したファシリティの情報を取り出す方法を説明いたします。

まずプロジェクトを開きます。S4のメニュー「プロジェクト」→「プロジェクトのインポート」でファイルダイアログを開き、(S4のインストールフォルダ (通常は C:\Program Files\Mathematical Systems Inc\S-Quattro Simulation System V6))\samples\離散-ミニマル\利用したファシリティを記録.s4 を選択し、OKします。S4画面左側の「ワークスペース」には開いたプロジェクトが置かれています。「+」をクリックし「モデル」をダブルクリックすることでプロジェクトを開きます。

プロジェクトの内容を見ていきます。「ファシリティ利用」部品の編集画面を開くと、「ファシリティリスト」で2つのファシリティを指定していること、および「待ち受け方法」が OR であることがわかります。これは指定したファシリティのうち最初のものが空いていればそちらを、最初のものが利用中であれば2番目のものを利用するという意味になります。

利用するファシリティを記録する設定は「コード編集」タブで行っています。 UseFacility クラスの run メソッドの中(編集可能な部分)にあるローカル関数 using の冒頭に

item.usedfac = result["use"].facility.name

という文を加えています。右辺では利用するファシリティへの参照から名前を取り出していて、左辺でフローアイテムの属性 usedfac に代入しています。 usedfac 属性は「ファシリティ利用」部品の手前にある「設定」部品で作成しています。

おわりに

第4回となる今回は3種類のサンプルプロジェクト「ファシリティ利用時間を関数で指定」「ファシリティの同期した停止・回復」「利用したファシリティを記録」についてご紹介しました。ミニマルと付いている「離散-ミニマル」に属するサンプルプロジェクトは単一の課題に注目して組み立てたプロジェクトであり、「S4プロジェクトを思い通りにカスタマイズする」ための直接的なアイデアを与える可能性が高いものになっています。今後の記事でも「離散-ミニマル」のプロジェクトを見て参ります。

監修:株式会社NTTデータ数理システム 機械学習、統計解析、数理計画、シミュレーションなどの数理科学を 背景とした技術を活用し、業種・テーマを問わず幅広く仕事をしています。
http://www.msi.co.jp NTTデータ数理システムができること
「数理科学の基礎知識」e-book無料ダウンロードはこちら

関連記事