🎓 レベル:標準 | 重要度:A(必須)
📎 前提:オペレーションズ・マネジメントとは(L=λW の導入・稼働率100%の危険)・プロセス分析とリトルの法則(I=R·T の面積論) | 確率の土台:確率過程(マルコフ連鎖・ポアソン過程)(ポアソン到着・指数サービス・無記憶性) | 次:M/M/1 待ち行列モデル
要点(BLUF)
- 待ち行列は「到着がランダム・サービスに時間がかかる・窓口が有限」だから生じます。これを分類する共通語がケンドール記法 A/S/c——到着過程 A・サービス分布 S・窓口数 c。代表が M/M/1(ポアソン到着・指数サービス・1窓口)です。
- 性能は4つの指標で測ります——系内数 (サービス中+待っている総数)、待ち行列内 (待っているだけの数)、系内時間 (並んでからサービスを終えるまで)、待ち時間 (並んでからサービス開始まで)。混み具合は稼働率 (到着率 ÷ 総サービス能力)。
- プロセス分析とリトルの法則 の は待ち行列にもそのまま効きます。系全体に使えば 、待ち行列部分だけに使えば 。系内時間は「待ち+サービス」なので 。
- 安定(行列が無限に伸びない)条件は 。そして稼働率を 100% に近づけると、待ちは比例ではなく で爆発します。これが オペレーションズ・マネジメントとは で予告した「稼働率100%は危険」の正体です。
1. ケンドール記法と性能指標
到着もサービスもばらつくのに窓口は限られている――この三すくみが待ち行列を生みます。世界中の待ち行列を共通の型で表すのがケンドール記法で、A/S/c の3要素(必要なら /K/N/D を足す)で書きます。
| 記号位置 | 意味 | 代表的な値 |
|---|---|---|
| A | 到着過程 | M(ポアソン到着=到着間隔が指数)・D(一定)・G(一般) |
| S | サービス時間分布 | M(指数)・D(一定)・G(一般) |
| c | 窓口(サーバ)数 | 1, 2, 3, … |
ここで M は Markovian(無記憶) の頭文字です。到着がポアソン過程(到着間隔が指数分布)、サービス時間が指数分布だと、過去を忘れる無記憶性のおかげで「系内数」だけで将来が決まるマルコフ過程になり、解析が一気に解けます。この「なぜ指数・なぜポアソンか」の確率的土台は 確率過程(マルコフ連鎖・ポアソン過程) に譲り(到着間隔=指数・無記憶性・到着数=ポアソンの導出はそこにあります)、本章はそれを待ち行列の性能設計に使います。本ノートは記法と指標、次の M/M/1 待ち行列モデル で M/M/1 を解き切ります。
flowchart LR ARR["到着<br/>(率 λ・ランダム)"] --> Q["待ち行列<br/>(待っている Lq 人)"] Q --> SRV["窓口(c 個・率 μ)<br/>サービス中 ρ·c 人"] SRV --> OUT["退去"]
測りたい性能は4つです。系全体(待ち+サービス中)で数えるか、待っている部分だけで数えるかで、**数(L 系)と時間(W 系)**がそれぞれ2つに分かれます。
| 指標 | 読み | 何を数える/測るか |
|---|---|---|
| 系内数 | いま系の中にいる平均人数(待ち+サービス中) | |
| 待ち行列内の数 | 待っているだけの平均人数(サービス中は除く) | |
| 系内時間 | 並んでからサービスを終えて出るまでの平均時間 | |
| 待ち時間 | 並んでからサービスが始まるまでの平均時間 | |
| 稼働率 | 窓口が塞がっている割合 |
稼働率 は「持ち込まれる仕事量 ÷ さばける能力」です。到着率 (単位時間に来る数)を、総サービス能力 (窓口 個 × 1個あたり処理率 )で割ります。
なら「窓口は平均して8割の時間ふさがっている」。直感に反しますが、この が 1 に近いほど待ちは穏やかに増えるのではなく急騰します(第4節)。
2. リトルの法則を待ち行列に適用する
プロセス分析とリトルの法則 で、定常なら分布によらず (在庫=フローレート×フロータイム)が成り立つことを面積論で導きました。待ち行列の言葉に置き換えれば、これは そのものです。重要なのは、「系」をどこに引くかを変えると、別々の指標の関係式が芋づる式に出ることです。
**系全体(窓口まで含む)**にリトルの法則を当てると、平均人数 =到着率 ×平均滞在 :
待ち行列の部分だけ(窓口の手前まで)を「系」とみなすと、そこにいる平均人数 =到着率 ×そこでの平均滞在 :
同じ法則を引く線を変えて2回使っただけです。さらに、系内時間 は「待ち行列で待つ時間 」+「サービスを受ける時間」に分かれます。サービス時間は平均 (サービス率 の逆数)なので、
この一本があれば、 と は自由に行き来できます。両辺に を掛ければ ( のとき)――系内数と待ち人数の差は、サービス中の平均人数 、という関係も出ます。
安定条件 :到着が能力を超える(、すなわち )と、行列は時間とともに無限に伸び、定常状態が存在しません。 ではじめて が有限に収まります。 ちょうどは「平均では釣り合うが、ばらつきのせいで行列が発散する」境界で、ここも不安定です。
リトルの法則は分布によらない恒等式(プロセス分析とリトルの法則 で実証済み)なので、上の ・ は M/M/1 に限らずあらゆる安定な待ち行列で成立します。各指標の絶対値( がいくつか)を分布から求めるのが次章 M/M/1 待ち行列モデル の仕事です。
3. 離散事象シミュレーションで L=λW を確かめる(コード)
理屈だけでは腑に落ちません。単一窓口(c=1)に指数到着・指数サービスを流す離散事象シミュレーションを回し、 を別々に測って、 と 、 が本当に成り立つかを確かめます。
サービス開始と退去はLindley 再帰で決まります。客 の到着を 、サービス時間を 、退去を とすると、窓口が空くのは「自分が着いた時刻」か「前の客が出た時刻」の遅いほう。だから
です( がサービス開始時刻)。系内数 は、到着で +1・退去で −1 する階段関数 の時間平均として直接測ります(プロセス分析とリトルの法則 と同じ面積法)。
import numpy as np
rng = np.random.default_rng(42)
lam = 0.8 # 平均到着率(人/分):到着間隔 ~ Exp(1/λ)
mu = 1.0 # 平均サービス率(人/分):サービス時間 ~ Exp(1/μ)
N = 2_000_000 # 客数(十分長く回す)
# 指数到着・指数サービスを生成(M/M/1)
inter = rng.exponential(1.0 / lam, N) # 到着間隔
arrivals = np.cumsum(inter) # 到着時刻 A_i
service = rng.exponential(1.0 / mu, N) # サービス時間 S_i
# Lindley 再帰 D_i = max(A_i, D_{i-1}) + S_i を厳密にベクトル化
# D_i = cumS_i + cummax(A_i - cumS_{i-1}) (cumS_0=0)
cumS = np.cumsum(service)
cumS_prev = cumS - service # = cumS_{i-1}
dep = cumS + np.maximum.accumulate(arrivals - cumS_prev) # 退去時刻 D_i
start = dep - service # サービス開始 = max(A_i, D_{i-1})
wait_q = start - arrivals # 待ち行列での待ち時間 Wq_i
sojourn = dep - arrivals # 系内時間 W_i = Wq_i + S_i
# --- 客平均(W, Wq)---
W_sim = sojourn.mean()
Wq_sim = wait_q.mean()
# --- 時間平均(L, Lq):系内数 n(t) の階段関数を積分 ---
def time_average(up, down):
"""up で +1, down で -1 する階段関数の時間平均を返す。"""
t = np.concatenate([up, down])
d = np.concatenate([np.ones(up.size), -np.ones(down.size)])
order = np.argsort(t, kind="mergesort")
t, d = t[order], d[order]
level = np.cumsum(d)
dt = np.diff(t)
horizon = t[-1] - t[0]
return float(np.sum(level[:-1] * dt) / horizon), horizon
# 系内数 L:到着で +1、退去で -1
L_sim, horizon = time_average(arrivals, dep)
# 待ち行列内 Lq:到着で +1、サービス開始で -1(サービス中の1人を除く)
Lq_sim, _ = time_average(arrivals, start)
lam_meas = N / horizon # 実測の到着率(≈ λ)
# --- 理論 M/M/1 ---
rho = lam / mu
L_th = rho / (1 - rho)
Lq_th = rho**2 / (1 - rho)
W_th = 1 / (mu - lam)
Wq_th = rho / (mu - lam)
print(f"lambda={lam}, mu={mu}, rho=lambda/mu={rho:.3f}, N={N}")
print(f"実測到着率 lambda_meas = N/horizon = {lam_meas:.4f}")
print()
print("指標 シミュレーション 理論M/M/1")
print(f"L (系内数) {L_sim:8.4f} {L_th:8.4f}")
print(f"Lq (待ち人数) {Lq_sim:8.4f} {Lq_th:8.4f}")
print(f"W (系内時間) {W_sim:8.4f} {W_th:8.4f}")
print(f"Wq (待ち時間) {Wq_sim:8.4f} {Wq_th:8.4f}")
print()
print("リトルの法則・関係式の検算(シミュレーション値で)")
print(f" L vs lambda*W : {L_sim:.4f} vs {lam_meas * W_sim:.4f}")
print(f" Lq vs lambda*Wq : {Lq_sim:.4f} vs {lam_meas * Wq_sim:.4f}")
print(f" W vs Wq + 1/mu : {W_sim:.4f} vs {Wq_sim + 1.0 / mu:.4f}")
出力:
lambda=0.8, mu=1.0, rho=lambda/mu=0.800, N=2000000
実測到着率 lambda_meas = N/horizon = 0.8005
指標 シミュレーション 理論M/M/1
L (系内数) 3.9807 4.0000
Lq (待ち人数) 3.1805 3.2000
W (系内時間) 4.9726 5.0000
Wq (待ち時間) 3.9731 4.0000
リトルの法則・関係式の検算(シミュレーション値で)
L vs lambda*W : 3.9807 vs 3.9807
Lq vs lambda*Wq : 3.1805 vs 3.1805
W vs Wq + 1/mu : 4.9726 vs 4.9731
出力の意味:到着もサービスもいっさい理論式を使わず、ただ指数乱数を流して測っただけの値が、理論 M/M/1( で )と小数第2位までほぼ一致しました(残差は有限長のシミュレーション誤差)。注目すべきは下段の検算で、 と が 3.9807 で完全一致、 と も 3.1805 で完全一致しています。これは偶然ではなく、観測窓を「最後の退去まで」に取ると面積 ∫n(t)dt が全客の系内時間の総和にちょうど等しくなるためで、リトルの法則は恒等式だという プロセス分析とリトルの法則 の主張が待ち行列でも厳密に効いていることの現れです。 と も 4.97 でそろい、「系内時間=待ち時間+サービス時間」の分解も確認できました。
4. 稼働率を上げると待ちが爆発する(コード)
オペレーションズ・マネジメントとは で「稼働率100%は危険」と予告しました。なぜ危険かを M/M/1 の理論値で定量化します。サービス率 に固定し、到着率 を上げて稼働率 を と動かすと、待ち時間 がどう増えるかを見ます。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
# サービス率 mu=1 に固定し、到着率 lambda を上げて稼働率 rho=lambda/mu を 0.5→0.99 に
# M/M/1 の理論値で待ちが非線形に爆発する様子を表・図にする
mu = 1.0
rhos = np.array([0.50, 0.70, 0.80, 0.90, 0.95, 0.98, 0.99])
rows = []
for rho in rhos:
lam = rho * mu
Lq = rho**2 / (1 - rho) # 待ち行列内の平均人数
Wq = rho / (mu - lam) # 平均待ち時間
L = rho / (1 - rho) # 系内の平均人数
rows.append({"稼働率rho": rho, "Lq(待ち人数)": Lq, "Wq(待ち時間)": Wq, "L(系内数)": L})
df = pd.DataFrame(rows)
print(df.to_string(index=False, float_format=lambda x: f"{x:.3f}"))
# 稼働率を 0.9→0.95→0.99 と上げると Wq がどれだけ増えるか(倍率)
base = 0.90
Wq90 = base / (mu - base)
for rho in [0.95, 0.98, 0.99]:
Wq = rho / (mu - rho)
print(f"rho 0.90 -> {rho:.2f}: Wq {Wq90:.2f} -> {Wq:.2f} ({Wq / Wq90:.1f} 倍)")
# 図:rho に対する Wq の 1/(1-rho) 爆発
rr = np.linspace(0.01, 0.985, 400)
Wq_curve = rr / (mu - rr)
plt.figure(figsize=(9, 5.5))
plt.plot(rr, Wq_curve, color="#d62728", lw=2, label=r"$W_q=\rho/(\mu-\lambda)$")
plt.scatter(rhos, rhos / (mu - rhos), color="#1f77b4", zorder=5, label="表の各点")
for rho in rhos:
plt.annotate(f"{rho:.2f}", (rho, rho / (mu - rho)),
textcoords="offset points", xytext=(4, 6), fontsize=9)
plt.axvline(1.0, color="gray", ls="--", label=r"$\rho=1$(発散)")
plt.xlabel("稼働率 ρ=λ/μ"); plt.ylabel("平均待ち時間 Wq(分)")
plt.title("稼働率を上げると待ち時間が非線形に爆発する(M/M/1, μ=1)")
plt.ylim(0, 60); plt.legend(); plt.tight_layout()
plt.show()
出力:
稼働率rho Lq(待ち人数) Wq(待ち時間) L(系内数)
0.500 0.500 1.000 1.000
0.700 1.633 2.333 2.333
0.800 3.200 4.000 4.000
0.900 8.100 9.000 9.000
0.950 18.050 19.000 19.000
0.980 48.020 49.000 49.000
0.990 98.010 99.000 99.000
rho 0.90 -> 0.95: Wq 9.00 -> 19.00 (2.1 倍)
rho 0.90 -> 0.98: Wq 9.00 -> 49.00 (5.4 倍)
rho 0.90 -> 0.99: Wq 9.00 -> 99.00 (11.0 倍)
出力の意味:稼働率を と上げる間、待ち時間 は とおとなしい増え方です。ところが を超えてからが本番で、 と稼働率をたった5ポイント上げただけで は 9 分から 19 分へ約2.1倍、 では 99 分にまで膨れ上がります。稼働率の差は「 と で9ポイント」しかないのに、待ちは11倍。原因は の分母 で、 で分母が 0 に近づくため、待ちが で発散するからです(赤い曲線が の縦線で天井知らずに跳ね上がる)。だから現場の稼働率を 95% や 99% に「効率化」すると、ばらつきがある限り待ち時間(=リードタイム・顧客満足・仕掛在庫)が崩壊します。余力(バッファ)を残すことには、待ちを抑えるという明確な数理的価値がある――これが「稼働率100%は危険」の中身です。
⚠️ よくある誤解
- 「稼働率は高いほど良い」ではない:稼働率は設備の遊休を減らす指標ですが、 で待ち時間が で発散します。ばらつきがある系では、稼働率と待ち時間(応答性)はトレードオフです。どこまで を上げるかは「遊休コスト vs 待ちコスト」で決める設計問題で、100% は常に最適ではありません。
- 「リトルの法則は指数分布が前提」ではない:・ はプロセス分析とリトルの法則の通り分布によらない恒等式で、M/G/1 でも G/G/c でも成り立ちます。指数(M)の仮定が要るのは、 や の絶対値を閉じた式で出す段(次章 M/M/1 待ち行列モデル)であって、指標どうしの関係式ではありません。
- 「待ち時間は稼働率に比例する」ではない: は に比例しません。 型で、低稼働ではゆるやか・高稼働で急騰する凸関数です。「稼働率を1割上げたら待ちも1割増」という線形の直感は、高稼働域で大きく外れます。
- 「平均だけ見ればよい」ではない:本ノートは平均指標()を扱いましたが、実務では待ち時間の分布の裾(95パーセンタイル待ち時間など)が SLA を左右します。平均が短くても、たまに非常に長く待つ客がいる――この裾は次章の定常分布 から評価します。
関連ノート
- M/M/1 待ち行列モデル(次のトピック・birth-death から を導き、 の絶対値を出す)
- M/M/c 待ち行列と窓口設計(窓口を 個に増やす・アーランC・要員設計・プーリング)
- オペレーションズ・マネジメントとは( の導入元・稼働率100%の危険を本ノートで定量化)
- プロセス分析とリトルの法則( の面積論・分布非依存の実証。本ノートの の土台)
- 確率過程(マルコフ連鎖・ポアソン過程)(統計・ポアソン到着=指数間隔・無記憶性・到着数のポアソン分布の導出)
- オペレーションズ・マネジメント 全体目次