Mímisbrunnr知恵の泉

← シミュレーション 一覧

🎓 レベル:基礎 | 重要度:A(必須)

📎 前提:シミュレーションとは(決定的 vs 確率的) | 関連:離散事象シミュレーションとは

要点(BLUF)

1. モデル化の4要素

現象を計算機の中で動かすには、まず対象を次の4つに切り分けます。

flowchart LR
    I["入力(確率分布)"] --> S["状態(時間発展)"]
    S --> O["出力(性能指標を集計)"]
    S -->|"次の状態を決める"| S

2. モデル化の流れ

  1. 目的の明確化:何を知りたいか(平均待ち時間?破綻確率?)。これが出力と必要精度を決める。
  2. 系の境界設定:どこまでをモデルに含めるか。
  3. 状態変数の選定:系を過不足なく記述する最小の変数群。
  4. 入力分布の決定:データやドメイン知識から確率分布を割り当てる。
  5. 時間発展ルールの記述:状態がどう更新されるか(次節の例なら「客はひとつ前の客が終わってからサービス開始」)。
  6. 出力の集計と検証:多数回(または長時間)走らせて統計量を取り、V&V で正しさを確かめる。

3. 具体例:単一窓口の待ち行列をモデル化する

役所の1窓口を考えます。客は平均到着率 λ=0.8\lambda = 0.8 人/分(到着間隔は指数分布)で来て、サービス時間は平均 1/μ=11/\mu = 1 分(μ=1.0\mu = 1.0 人/分の指数分布)。状態は「窓口がいつ空くか」、出力は「平均待ち時間」です。

ii 番目の客のサービス開始時刻は「自分の到着時刻」と「前の客の退出時刻」の遅い方:

starti=max(arrivali, departi1),waiti=startiarrivali\text{start}_i = \max(\text{arrival}_i,\ \text{depart}_{i-1}),\qquad \text{wait}_i = \text{start}_i - \text{arrival}_i
import numpy as np

# 乱数シードを固定
rng = np.random.default_rng(7)

n_cust = 100_000                      # 客の人数
inter = rng.exponential(1/0.8, n_cust)  # 到着間隔 ~ 指数(平均1/0.8分)
serv  = rng.exponential(1/1.0, n_cust)  # サービス時間 ~ 指数(平均1分)

arrival = np.cumsum(inter)            # 各客の到着時刻
start = np.zeros(n_cust)
depart = np.zeros(n_cust)
start[0] = arrival[0]
depart[0] = start[0] + serv[0]
for i in range(1, n_cust):            # 状態(窓口が空く時刻)を時間発展
    start[i] = max(arrival[i], depart[i-1])
    depart[i] = start[i] + serv[i]

wait = start - arrival               # 各客の待ち時間
rho = 0.8 / 1.0
wq_theory = rho / (1.0 * (1.0 - rho))  # M/M/1 の平均待ち時間 Wq

print(f"平均待ち時間(シミュ)= {wait.mean():.3f} 分")
print(f"M/M/1 理論値 Wq      = {wq_theory:.3f} 分")

出力:

平均待ち時間(シミュ)= 4.050 分
M/M/1 理論値 Wq      = 4.000 分

出力の意味:10万人の客をシミュレートした平均待ち時間 4.05 分が、待ち行列理論(M/M/1)の理論値 4.00 分とほぼ一致。モデル化(入力=指数分布、状態=窓口が空く時刻、出力=待ち時間の平均)が正しく組めていることの確認になります。理論値との照合は次のV&Vの典型例です。

4. 時間の進め方:固定刻み vs イベント駆動

状態を時間発展させる方法は2通りあります。

数式の直観的意味

starti=max(arrivali,departi1)\text{start}_i = \max(\text{arrival}_i, \text{depart}_{i-1}) は「窓口が空いている(前の客が帰った)か、自分が着いたか、遅い方からサービスが始まる」という当たり前の論理を式にしただけです。状態(窓口が空く時刻 depart\text{depart})が次の客の挙動を決める——この状態の引き継ぎこそが、静的な確率計算とシミュレーションを分けるポイントです。理論値と一致するのは、入力分布が M/M/1 の仮定(ポアソン到着・指数サービス)を満たすからです。

⚠️ よくある誤解・落とし穴

対応シミュレーション参照

本文の単一窓口待ち行列コード(np.random.default_rng(7))。離散事象としての一般化は離散事象シミュレーションとはへ。

関連ノート