スーパーのレジに並んでいると、「なぜかいつも自分の列だけ長い」と感じたことはないでしょうか。あるいは、Webサーバーへのアクセスが集中したときに、なぜ応答時間が「じわじわ」ではなく「ある瞬間から急に」悪化するのか、不思議に思ったことはないかもしれません。実はこれらの現象は、たった2つの数字 —— お客さんが来る速さ $\lambda$ と、さばける速さ $\mu$ —— の比だけで、驚くほど正確に説明できます。
この「待つ現象」を数学のまな板に載せるのが待ち行列理論(queueing theory)です。その中でも最も基本的で、なおかつ美しい閉じた式が全部手で導けるのが、これから扱う M/M/1 待ち行列です。M/M/1 が理解できると、次のような場面で「行列の長さ」や「待ち時間」を紙とペンで見積もれるようになります。
- コールセンター・窓口設計: オペレーターを何人置けば待ち時間が許容範囲に収まるか
- 通信・計算機システム: パケットルーターのバッファ長、CPUのジョブスケジューリング、サーバーの応答時間
この記事では、まず到着とサービスを確率モデルで表し、それを生誕死滅過程として定式化します。そこから定常分布 $p_n = (1-\rho)\rho^n$ を釣り合い式から一行ずつ導き、平均系内人数 $L = \rho/(1-\rho)$、さらにリトルの法則 $L = \lambda W$ を使って平均待ち時間 $W$ までを、途中式を省略せずに導出します。最後に Python の離散事象シミュレーションを組み、理論式が本当に成り立つことを seed 固定で確かめます。

まずは全体像です。M/M/1 とは、上の図のように「ポアソン過程で到着したお客さんが、1つの窓口の前に無限に長く並べる列を作り、指数分布に従うサービス時間で1人ずつさばかれていく」というシンプルなモデルです。到着の速さと処理の速さのバランスだけで、列の振る舞いのすべてが決まります。この記事を通じて、その「バランス」がどう効いてくるのかを解き明かしていきましょう。
本記事の内容
- M/M/1 の意味(ケンドール記法)と、到着・サービスの確率モデルの直感
- 生誕死滅過程としての定式化と、定常分布 $p_n=(1-\rho)\rho^n$ の導出(省略なし)
- 平均系内人数 $L$、リトルの法則による平均待ち時間 $W$ の導出と、$\rho\to 1$ での発散
- Python の離散事象シミュレーションによる理論式の検証
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が一段と深まります。M/M/1 は「ポアソン過程 × 指数分布 × 連続時間マルコフ連鎖」の合わせ技だからです。
- ポアソン過程とは?定義から性質までわかりやすく解説 — 到着のモデルそのもの
- 生誕死滅過程をわかりやすく解説 — M/M/1 の骨格になる確率過程
- マルコフ連鎖とは? — 「未来は現在だけで決まる」性質
- 連続時間マルコフ連鎖 — 状態が連続時間で遷移する枠組み
これらの用語が初耳でも、本文中で必要な性質はそのつど復習しながら進めるので、読み進めて構いません。
M/M/1 とは —— 3つの文字が表すもの
待ち行列のモデルには、デイヴィッド・ケンドールが1953年に導入した便利な記法があります。ケンドール記法 $A/B/c$ です。3つの位置に、それぞれ「到着の様子」「サービスの様子」「窓口の数」を書き込みます。
- 1文字目 $A$: 到着間隔の分布。$M$ は “Markovian”(マルコフ的)、つまり指数分布を意味します。到着が指数分布間隔ということは、到着そのものはポアソン過程です。
- 2文字目 $B$: サービス時間の分布。ここも $M$ なら指数分布。
- 3文字目 $c$: 並列に動く窓口(サーバー)の数。$1$ なら窓口は1つだけ。
つまり M/M/1 とは、「到着がポアソン過程、サービス時間が指数分布、窓口が1つ、待ち行列の容量は無限」という設定です。なぜこの設定がそんなに大事なのでしょうか。理由は、$M$(指数分布)が持つ無記憶性にあります。無記憶性のおかげで「これまで何分待ったか」を一切覚えておく必要がなくなり、システムの状態を「今、系内に何人いるか」という人数だけで完全に記述できます。この単純化が、あとで見る美しい閉じた式を可能にします。
日常語に翻訳すると、M/M/1 は「1つのレジ」「客がランダムにやってくる」「レジ打ち時間もランダム」というごく当たり前の状況そのものです。にもかかわらず、そこから「平均で何人並ぶか」「平均何分待つか」が正確に計算できてしまう —— それがこのモデルの魅力です。では、その「ランダム」の中身である $M$、すなわちポアソン到着と指数サービスを、次で確率モデルとしてきちんと押さえましょう。
到着とサービスの確率モデル
到着:ポアソン過程とレート $\lambda$
お客さんの到着を「ランダムだ」と言うだけでは数式になりません。そこでポアソン過程を使います。ポアソン過程は、「短い時間 $\Delta t$ の間に1人到着する確率が $\lambda \Delta t$ に比例し、それが過去の履歴によらず一定」という、最も自然な「完全にランダムな到着」のモデルです。ここで $\lambda$ を到着率(arrival rate)と呼び、単位時間あたり平均何人来るかを表します。$\lambda = 0.8$ 人/分なら、1分間に平均0.8人が来る、という意味です。
ポアソン過程の重要な性質は、到着間隔がパラメータ $\lambda$ の指数分布に従うことです。到着間隔を $X$ とすると、その確率密度は
$$ \begin{equation} f_X(x) = \lambda e^{-\lambda x}, \quad x \ge 0 \end{equation} $$
で、平均間隔は $E[X] = 1/\lambda$ です。到着率 $\lambda$ が大きいほど間隔は詰まる、という直感通りの関係です。
サービス:指数分布とレート $\mu$
窓口が1人をさばくのにかかる時間(サービス時間)$S$ も、パラメータ $\mu$ の指数分布に従うとします。
$$ \begin{equation} f_S(s) = \mu e^{-\mu s}, \quad s \ge 0 \end{equation} $$
平均サービス時間は $E[S] = 1/\mu$ で、$\mu$ をサービス率(service rate)と呼びます。$\mu = 1.0$ 人/分なら、窓口はフル稼働時に1分あたり平均1人をさばけます。
なぜ指数分布なのか:無記憶性
指数分布を選ぶのは計算が楽だから、というだけではありません。指数分布だけが持つ決定的な性質が無記憶性(memorylessness)です。式で書くと、任意の $s, t \ge 0$ について
$$ \begin{equation} P(S > s + t \mid S > s) = P(S > t) \end{equation} $$
が成り立ちます。「すでに $s$ 分サービスを受けている人が、さらに $t$ 分かかる確率」は、「サービスを始めたばかりの人があと $t$ 分かかる確率」と等しい、という意味です。つまり「これまでどれだけ待ったか」がまったく未来に影響しません。
この性質は、次のように確かめられます。指数分布の生存関数は $P(S>t)=e^{-\mu t}$ なので、条件付き確率の定義から
$$ \begin{align} P(S > s + t \mid S > s) &= \frac{P(S > s+t \ \text{かつ}\ S>s)}{P(S>s)} \\ &= \frac{P(S > s+t)}{P(S>s)} \quad (\because \{S>s+t\}\subset\{S>s\}) \\ &= \frac{e^{-\mu(s+t)}}{e^{-\mu s}} = e^{-\mu t} = P(S>t) \end{align} $$
となり、確かに $s$ に依存しません。1行目から2行目へは「$S>s+t$ ならば必ず $S>s$」という包含関係を使い、分子の同時確率を $P(S>s+t)$ に置き換えています。
この無記憶性のおかげで、「今サービス中の人があと何分かかるか」も「列の何番目の人が何分前から待っているか」も、一切気にしなくてよくなります。システムの状態は「今、系内に合計何人いるか」という整数 $n$ だけで完全に決まる —— これがマルコフ性であり、次に見る生誕死滅過程への橋渡しになります。
生誕死滅過程としての定式化
系内人数 $N(t)$(待っている人+サービス中の人の合計)を状態と考えましょう。無記憶性から、ごく短い時間 $\Delta t$ の間に起きることは次の3つに絞られます。
- 1人到着する(状態が $n \to n+1$):確率はおよそ $\lambda \Delta t$
- 1人サービスが終わって退去する(状態が $n \to n-1$、ただし $n \ge 1$):確率はおよそ $\mu \Delta t$
- 何も起きない:残りの確率
2人同時に到着したり、到着と退去が同時に起きたりする確率は $\Delta t$ の2次以上の微小量になり、無視できます。この「1つずつ増えたり減ったりする」構造こそが生誕死滅過程(birth-death process)です。「生誕」(birth)は到着、「死滅」(death)は退去に対応します。

状態遷移図で描くと上のようになります。各状態 $n$(系内に $n$ 人いる状態)から、右へは到着率 $\lambda$ で、左へはサービス率 $\mu$ で遷移します。M/M/1 の特徴は、この $\lambda$ と $\mu$ が状態 $n$ によらず一定なことです(一般の生誕死滅過程では状態ごとに率が変わってもよい)。この「一定」という性質が、あとで定常分布を等比数列にまとめてくれます。
M/M/1 では状態依存の到着率・サービス率を次のように書けます。
$$ \lambda_n = \lambda \ (n=0,1,2,\dots), \qquad \mu_n = \mu \ (n=1,2,3,\dots), \quad \mu_0 = 0 $$
$\mu_0 = 0$ は「系内に誰もいなければ退去も起きない」ことを表します。準備が整いました。この遷移構造から、長時間たったあとに「系内に $n$ 人いる確率」がどんな値に落ち着くのか —— 定常分布 $p_n$ を求めにいきましょう。
定常分布の導出:釣り合い式から $p_n=(1-\rho)\rho^n$ へ
定常状態とは
システムを十分長く動かすと、「今この瞬間に系内に $n$ 人いる確率」$p_n$ が時間によらず一定の値に落ち着きます。これを定常分布と呼びます。定常状態では、各状態の確率が増えも減りもしません。これを数式にしたのが釣り合い式(balance equation)です。
直感的には、水が入った複数のタンクを想像してください。各タンクの水位が変わらない(定常)ということは、「タンクに流れ込む水量」と「タンクから流れ出る水量」が釣り合っている、ということです。確率の世界でも同じで、各状態について「入ってくる確率の流れ」と「出ていく確率の流れ」が等しくなります。
大域的釣り合い式
状態 $n$ に注目します。状態 $n$ から出ていく流量は、(状態 $n$ にいる確率 $p_n$)×(そこから出る率)です。$n \ge 1$ なら、右にも左にも出られるので出る率は $\lambda + \mu$。状態 $n$ に入ってくる流量は、下の状態 $n-1$ から到着で上がってくる分 $\lambda p_{n-1}$ と、上の状態 $n+1$ からサービス完了で下がってくる分 $\mu p_{n+1}$ の和です。両者を等号で結ぶと、$n \ge 1$ について
$$ \begin{equation} (\lambda + \mu)\, p_n = \lambda\, p_{n-1} + \mu\, p_{n+1} \end{equation} $$
境界の状態 $n=0$ については、出られるのは到着で上がる方向だけ(率 $\lambda$)、入ってくるのは状態1からサービス完了で下がる分だけ($\mu p_1$)なので、
$$ \begin{equation} \lambda\, p_0 = \mu\, p_1 \end{equation} $$
となります。この2本の式を解けば $p_n$ が求まります。
詳細釣り合い式への変形
大域的釣り合い式をそのまま解いてもよいのですが、生誕死滅過程には詳細釣り合い(detailed balance)というもっと強くて扱いやすい関係が成り立ちます。これは「隣り合う2状態 $n$ と $n+1$ の境界線を横切る流れが、両向きで釣り合う」というものです。

図のように、状態 $n$ と $n+1$ の間に仕切りを入れます。定常状態では、この仕切りを右向きに横切る流量(上向き $\lambda p_n$)と、左向きに横切る流量(下向き $\mu p_{n+1}$)が等しくなければなりません。もし等しくなければ、仕切りの片側に確率がたまり続けて定常でなくなるからです。したがって、すべての $n \ge 0$ について
$$ \begin{equation} \lambda\, p_n = \mu\, p_{n+1} \end{equation} $$
が成り立ちます。これが詳細釣り合い式です。$n=0$ のときは先ほどの境界式 $\lambda p_0 = \mu p_1$ と一致しますし、一般の $n$ についても大域的釣り合い式から数学的帰納法で導けます。実際、$n=0$ の式 $\lambda p_0 = \mu p_1$ を出発点に、大域的釣り合い式 $(\lambda+\mu)p_n = \lambda p_{n-1} + \mu p_{n+1}$ に $\lambda p_{n-1} = \mu p_n$ を代入すると
$$ \begin{align} (\lambda+\mu)p_n &= \mu p_n + \mu p_{n+1} \\ \lambda p_n &= \mu p_{n+1} \end{align} $$
と、次の段の詳細釣り合いが再び出てきます。1行目では左辺の $\lambda p_{n-1}$ を詳細釣り合いにより $\mu p_n$ で置き換え、2行目で両辺から $\mu p_n$ を引いています。こうして帰納的にすべての $n$ で詳細釣り合いが成立します。
利用率 $\rho$ と定常分布
詳細釣り合い式 $\lambda p_n = \mu p_{n+1}$ を $p_{n+1}$ について解くと
$$ \begin{equation} p_{n+1} = \frac{\lambda}{\mu}\, p_n = \rho\, p_n, \qquad \rho \equiv \frac{\lambda}{\mu} \end{equation} $$
となります。ここで導入した $\rho = \lambda/\mu$ を利用率(traffic intensity, 稼働率)と呼びます。「到着の速さ」を「さばく速さ」で割った、無次元の混み具合の指標です。$\rho$ が大きいほどシステムは混んでいます。
上の漸化式は「1つ状態が上がるたびに確率が $\rho$ 倍になる」という等比関係です。$p_0$ を起点に順に掛けていくと
$$ \begin{equation} p_n = \rho\, p_{n-1} = \rho^2 p_{n-2} = \cdots = \rho^n p_0 \end{equation} $$
が得られます。あとは $p_0$ を決めるだけです。確率はすべて足すと1になる(規格化条件)ので
$$ \begin{equation} \sum_{n=0}^{\infty} p_n = p_0 \sum_{n=0}^{\infty} \rho^n = 1 \end{equation} $$
この無限和は等比級数です。$\rho < 1$ のとき、公比 $\rho$ の等比級数は収束して
$$ \begin{equation} \sum_{n=0}^{\infty} \rho^n = \frac{1}{1-\rho} \end{equation} $$
となります。したがって規格化条件から $p_0 \cdot \dfrac{1}{1-\rho} = 1$、すなわち $p_0 = 1-\rho$ が決まります。これを $p_n = \rho^n p_0$ に戻すと、ついに定常分布が得られます。
$$ \begin{equation} \boxed{\ p_n = (1-\rho)\,\rho^n, \quad n = 0, 1, 2, \dots\ } \end{equation} $$
これは幾何分布(成功確率 $1-\rho$ の幾何分布)そのものです。系内人数が幾何分布に従う、というのが M/M/1 の中心的な結論です。$p_0 = 1-\rho$ は「窓口が空いている(系内に誰もいない)確率」であり、裏を返すと $\rho$ が「窓口が稼働している確率」に等しいことも読み取れます。混み具合 $\rho$ が、そのまま「窓口の忙しさ」を表しているわけです。

利用率 $\rho$ を変えて定常分布 $p_n$ を描くと上の図のようになります。$\rho=0.3$ のように空いているときは「系内0〜1人」に確率が集中して急激に減衰しますが、$\rho=0.9$ のように混んでくると裾が長く伸び、「たくさん並んでいる」状態の確率が無視できなくなります。同じ幾何分布でも、$\rho$ が1に近づくにつれて分布がなだらかに広がっていくのがよくわかります。この「裾の伸び」こそが、次に見る平均人数の発散の正体です。
安定条件 $\rho < 1$ の意味
いま等比級数の収束に $\rho < 1$ を使いました。これは単なる数学上の都合ではなく、システムが破綻せずに定常状態を持つための安定条件そのものです。
$\rho < 1$ とは $\lambda < \mu$、つまり「到着の速さ」が「さばける速さ」より小さいことを意味します。直感的には当たり前で、来る人数よりさばける人数のほうが多くなければ、列はどんどん伸びて発散してしまいます。$\rho \ge 1$ のときは等比級数が発散し、規格化できる定常分布が存在しません。物理的には「列が無限に長くなり続ける」不安定な状態に対応します。
面白いのは境界の $\rho = 1$、つまり $\lambda = \mu$(来る速さとさばく速さがちょうど同じ)の場合です。「トントンなら大丈夫では?」と思いたくなりますが、ゆらぎ(ランダムさ)のせいで列は際限なく伸びていき、やはり安定な定常分布は存在しません。ランダム性がある限り、余裕($\rho$ を1より確実に小さく保つこと)が必須なのです。この事実は、次に平均系内人数を計算すると数式としてもはっきり現れます。
平均系内人数 $L$ の導出
定常分布がわかったので、「平均して系内に何人いるか」を計算できます。これを平均系内人数 $L$ と呼びます。定義は期待値そのもので
$$ \begin{equation} L = E[N] = \sum_{n=0}^{\infty} n\, p_n = \sum_{n=0}^{\infty} n (1-\rho)\rho^n \end{equation} $$
です。$(1-\rho)$ は $n$ によらない定数なので前に出すと
$$ \begin{equation} L = (1-\rho) \sum_{n=0}^{\infty} n \rho^n \end{equation} $$
残った $\sum_{n=0}^{\infty} n\rho^n$ を求めます。ここで、等比級数 $\sum_{n=0}^\infty \rho^n = \dfrac{1}{1-\rho}$ の両辺を $\rho$ で微分するテクニックを使います。左辺を項別微分すると
$$ \begin{equation} \frac{d}{d\rho}\sum_{n=0}^{\infty} \rho^n = \sum_{n=0}^{\infty} n\rho^{n-1} = \frac{1}{\rho}\sum_{n=0}^{\infty} n\rho^n \end{equation} $$
右辺 $\dfrac{1}{1-\rho}$ を微分すると $\dfrac{1}{(1-\rho)^2}$ なので
$$ \begin{equation} \frac{1}{\rho}\sum_{n=0}^{\infty} n\rho^n = \frac{1}{(1-\rho)^2} \end{equation} $$
両辺に $\rho$ を掛けて $\sum n\rho^n$ について解くと
$$ \begin{equation} \sum_{n=0}^{\infty} n\rho^n = \frac{\rho}{(1-\rho)^2} \end{equation} $$
が得られます。これを $L$ の式に代入します。$(1-\rho)$ を掛けると1つ分約分できて
$$ \begin{equation} L = (1-\rho)\cdot \frac{\rho}{(1-\rho)^2} = \boxed{\ \frac{\rho}{1-\rho}\ } \end{equation} $$
これが M/M/1 の平均系内人数です。とてもシンプルな式ですが、$\rho \to 1$ で分母が0に近づくため $L \to \infty$ と発散します。

$L = \rho/(1-\rho)$ を利用率 $\rho$ に対してプロットすると上の図になります。オレンジの点はシミュレーションの実測値で、理論曲線にぴったり乗っています。注目すべきは曲線の形です。$\rho$ が0.5あたりまでは平均1人程度と穏やかですが、0.8を超えたあたりから急に立ち上がり、0.9で $L=9$、0.95で $L=19$ と爆発的に増えます。これが冒頭で触れた「ある瞬間から急に混む」現象の正体です。稼働率を上げて効率を追求すると、待ち行列が非線形に膨れ上がる —— システム設計では $\rho$ を1に近づけすぎてはいけない、という重要な教訓がこの1本の曲線に凝縮されています。では、この「人数」を「時間」に翻訳しましょう。そこで登場するのがリトルの法則です。
リトルの法則と平均待ち時間 $W$ の導出
リトルの法則
私たちが本当に知りたいのは、多くの場合「何人並んでいるか」よりも「自分が何分待たされるか」です。この2つを結ぶのが、待ち行列理論で最も有名で、しかも驚くほど一般的に成り立つリトルの法則(Little’s law)です。
$$ \begin{equation} \boxed{\ L = \lambda W\ } \end{equation} $$
ここで $L$ は平均系内人数、$\lambda$ は到着率、$W$ は1人あたりの平均系内滞在時間(待ち時間+サービス時間)です。リトルの法則の凄いところは、到着やサービスの分布の形を一切問わないことです。M/M/1 に限らず、定常状態にある「入って出ていく」あらゆるシステムで成り立ちます。
直感を掴みましょう。あなたが店を出る瞬間を想像してください。あなたは平均 $W$ 分だけ店にいました。その $W$ 分の間に、後ろのドアから平均 $\lambda W$ 人が新たに入ってきます。あなたが出るときに店内に残っている人は、まさに「あなたが滞在していた間に入ってきた人たち」なので、平均すると店内人数 $L$ は $\lambda W$ に等しくなる —— これがリトルの法則の直感的な説明です。
平均滞在時間 $W$ と平均待ち時間 $W_q$
リトルの法則を $W$ について解くだけです。$L = \rho/(1-\rho)$ と $\rho = \lambda/\mu$ を代入します。
$$ \begin{align} W &= \frac{L}{\lambda} = \frac{1}{\lambda}\cdot\frac{\rho}{1-\rho} \\ &= \frac{1}{\lambda}\cdot\frac{\lambda/\mu}{1-\lambda/\mu} \end{align} $$
分母分子に $\mu$ を掛けて整理します。$1-\lambda/\mu = (\mu-\lambda)/\mu$ なので
$$ \begin{align} W &= \frac{1}{\lambda}\cdot\frac{\lambda/\mu}{(\mu-\lambda)/\mu} = \frac{1}{\lambda}\cdot\frac{\lambda}{\mu-\lambda} \\ &= \boxed{\ \frac{1}{\mu-\lambda}\ } \end{align} $$
美しい結果です。1行目で $\rho=\lambda/\mu$ を代入し、分母の $\mu$ を約分してから、最後に $\lambda$ を約分しています。平均滞在時間は「さばく速さと来る速さの差の逆数」というシンプルな形になりました。$\mu = \lambda$($\rho=1$)で分母が0になり、待ち時間が無限大に発散する —— 安定条件がここでも顔を出します。
滞在時間 $W$ は「待ち時間」と「自分のサービス時間」の合計です。自分のサービス時間の平均は $1/\mu$ なので、純粋に列で待つ時間の平均 $W_q$ は
$$ \begin{align} W_q &= W – \frac{1}{\mu} = \frac{1}{\mu-\lambda} – \frac{1}{\mu} \\ &= \frac{\mu – (\mu-\lambda)}{\mu(\mu-\lambda)} = \frac{\lambda}{\mu(\mu-\lambda)} = \frac{\rho}{\mu-\lambda} \end{align} $$
となります。2行目で通分しています。同様に、列に並んでいる人数の平均 $L_q$(サービス中の人を除く)は、リトルの法則 $L_q = \lambda W_q$ から
$$ \begin{equation} L_q = \lambda W_q = \frac{\lambda\rho}{\mu-\lambda} = \frac{\rho^2}{1-\rho} \end{equation} $$
と求まります。$L$ と $L_q$ の差 $L – L_q = \rho$ は「サービス中の人数の平均」で、これは窓口の稼働率 $\rho$ にほかなりません。

系内人数 $L$、待ち人数 $L_q$、そしてその差である「サービス中の平均人数」$\rho$ を並べて描いたのが上の図です。$L$(青)と $L_q$(オレンジ)はどちらも $\rho\to 1$ で発散しますが、両者の差は常に $\rho$(緑の破線)で、これは決して1を超えません。窓口は1つしかないので当然です。混雑は「サービス中の人」ではなく「並んで待っている人」が増えることで生じる、という構造が見て取れます。ここまでの理論を、次は具体的な数値で確かめてみましょう。
具体例:レジの混み具合を計算する
数式だけでは実感がわきにくいので、具体的な数字を入れてみましょう。あるコンビニのレジで、お客さんが平均して1分あたり0.8人来る($\lambda = 0.8$ 人/分)とします。レジ係は1人をさばくのに平均1分かかる(サービス率 $\mu = 1.0$ 人/分、平均サービス時間1分)とします。
まず利用率は
$$ \rho = \frac{\lambda}{\mu} = \frac{0.8}{1.0} = 0.8 $$
レジは80%の時間だけ稼働している計算です。窓口が空いている確率は $p_0 = 1-\rho = 0.2$、つまり2割の時間はお客さんがいません。系内にちょうど1人いる確率は $p_1 = (1-\rho)\rho = 0.2\times 0.8 = 0.16$、2人いる確率は $p_2 = 0.2\times 0.8^2 = 0.128$ です。
平均系内人数は
$$ L = \frac{\rho}{1-\rho} = \frac{0.8}{0.2} = 4 \ \text{人} $$
平均して4人が系内にいます。平均滞在時間は
$$ W = \frac{1}{\mu-\lambda} = \frac{1}{1.0-0.8} = 5 \ \text{分} $$
来店から退店まで平均5分。そのうち純粋に列で待つ時間は
$$ W_q = W – \frac{1}{\mu} = 5 – 1 = 4 \ \text{分} $$
平均4分待たされます。ここで、もし来客がわずかに増えて $\lambda = 0.9$ になったらどうなるでしょう。$\rho = 0.9$ となり、$L = 0.9/0.1 = 9$ 人、$W = 1/0.1 = 10$ 分。来客が0.8から0.9へ13%増えただけで、待ち時間は5分から10分へと倍増します。稼働率を上げることの怖さが、身近な数字ではっきりわかります。この非線形な効き方が本当に起きるのか、次はコンピュータの中に仮想のレジを作って確かめましょう。
Python実装:離散事象シミュレーションで検証する
理論式が正しいことを、乱数で到着とサービスを発生させる離散事象シミュレーション(discrete-event simulation)で確かめます。方針はシンプルで、$n$ 人分の到着間隔とサービス時間を指数乱数で生成し、各客の「サービス開始時刻」と「退去時刻」を順に計算していきます。$i$ 番目の客のサービス開始時刻は「自分の到着時刻」と「1つ前の客の退去時刻」の遅いほうです(窓口が空くまで待つ)。
import numpy as np
def simulate_mm1(lam, mu, n_arrivals, seed=0):
rng = np.random.default_rng(seed)
# 到着間隔 ~ Exp(lam), サービス時間 ~ Exp(mu)
inter = rng.exponential(1.0 / lam, n_arrivals)
arrival = np.cumsum(inter) # 各客の到着時刻
service = rng.exponential(1.0 / mu, n_arrivals)
start = np.zeros(n_arrivals) # サービス開始時刻
depart = np.zeros(n_arrivals) # 退去時刻
for i in range(n_arrivals):
# 窓口が空くのを待つ:到着時刻 と 直前客の退去時刻 の遅いほう
start[i] = arrival[i] if i == 0 else max(arrival[i], depart[i-1])
depart[i] = start[i] + service[i]
sojourn = depart - arrival # 系内滞在時間(待ち+サービス)
return arrival, depart, sojourn
この関数は、指数乱数で到着とサービスを作り、逐次的に退去時刻を計算します。np.cumsum で到着間隔を足し上げて到着時刻の列を作り、max(arrival[i], depart[i-1]) で「前の客が終わるまで待つ」という待ち行列の本質を1行で表現しています。滞在時間 sojourn の平均が、理論の $W$ に一致するはずです。
次に、系内人数 $N(t)$ の時間平均から $L$ を、そして各状態の滞在時間から定常分布 $p_n$ を推定します。到着を $+1$、退去を $-1$ のイベントとして時刻順に並べ、区間ごとに「その間の人数 × 経過時間」を足し上げれば、時間平均の系内人数が求まります。最初の1割は過渡期(システムが温まる前)なので捨てます。
import numpy as np
def measure(arrival, depart, warmup_frac=0.1):
# 到着(+1)・退去(-1)を時刻順に並べる
events = [(t, +1) for t in arrival] + [(t, -1) for t in depart]
events.sort()
warmup = arrival[int(len(arrival) * warmup_frac)] # 過渡期の打ち切り時刻
n, prev_t, area = 0, 0.0, 0.0
state_time = {} # 系内人数 = k だった総時間
for t, delta in events:
dt = t - prev_t
if prev_t >= warmup: # 温まった後だけ集計
area += n * dt # ∫ N(t) dt
state_time[n] = state_time.get(n, 0.0) + dt
n += delta
prev_t = t
total = depart[-1] - warmup
L_sim = area / total # 時間平均の系内人数
kmax = max(state_time)
p_sim = np.array([state_time.get(k, 0.0) for k in range(kmax+1)]) / total
return L_sim, p_sim
ここでは「系内人数の時間積分 $\int N(t)\,dt$ を総時間で割る」ことで時間平均 $L$ を求めています。同時に、各人数 $k$ だった総滞在時間を記録し、それを総時間で割って定常確率 $p_k$ を推定します。定常分布の定義(長時間のうち状態 $k$ にいる時間の割合)をそのまま数値化した形です。では、$\lambda=0.8, \mu=1.0$($\rho=0.8$)で20万人分を流し、理論値と比べます。
import numpy as np
lam, mu = 0.8, 1.0
rho = lam / mu
arrival, depart, sojourn = simulate_mm1(lam, mu, 200000, seed=42)
L_sim, p_sim = measure(arrival, depart)
# 過渡期を除いた滞在時間の平均(= W の実測)
warm = arrival[len(arrival)//10]
W_sim = sojourn[arrival >= warm].mean()
print(f"L 理論 {rho/(1-rho):.4f} 実測 {L_sim:.4f}")
print(f"W 理論 {1/(mu-lam):.4f} 実測 {W_sim:.4f}")
for k in range(3):
print(f"p{k} 理論 {(1-rho)*rho**k:.4f} 実測 {p_sim[k]:.4f}")
実行すると、次のような出力が得られます。
L 理論 4.0000 実測 3.9816
W 理論 5.0000 実測 4.9734
p0 理論 0.2000 実測 0.2013
p1 理論 0.1600 実測 0.1603
p2 理論 0.1280 実測 0.1286
理論値と実測値が小数第2位までほぼ一致しました。平均系内人数 $L=4$、平均滞在時間 $W=5$ 分、定常分布 $p_0, p_1, p_2$ のいずれも、乱数から作った仮想のレジがきちんと理論を再現しています。手で導いた式が、確かに現実(をまねたシミュレーション)を言い当てていることが確認できました。次に、この結果をグラフで見てみましょう。
定常分布の一致
まず、実測した定常分布 $p_n$ を理論式 $(1-\rho)\rho^n$ と重ねます。

水色の棒がシミュレーションの実測、オレンジの折れ線が理論の幾何分布です。すべての $n$ で棒の高さが理論曲線にぴたりと乗っており、系内人数が確かに公比 $\rho=0.8$ の幾何分布に従うことが目で見て確認できます。$n$ が1つ増えるごとに確率が0.8倍ずつ減衰していく様子も、指数的な減り方としてきれいに現れています。
系内人数の時間推移
次に、系内人数 $N(t)$ が時間とともにどう変化するかを追ってみます。

階段状の水色の線が、ある1回のシミュレーションでの系内人数の推移(サンプルパス)です。到着があると1段上がり、退去があると1段下がります。0人(空いている)から一時的に8人以上まで混む瞬間まで、大きく揺れているのがわかります。オレンジの破線は理論の平均 $L=4$ で、瞬間ごとには大きくばらつくものの、長時間で均せば確かに平均4人前後を推移しています。「平均は4人でも、運が悪いと8人待ち」という現実のばらつきが、この1枚に表れています。
滞在時間の分布
滞在時間 $W$ そのものの分布も見てみましょう。M/M/1 では、滞在時間はパラメータ $\mu-\lambda$ の指数分布に従うことが知られています。

水色のヒストグラムが実測の滞在時間分布、オレンジの曲線が理論の指数分布 $(\mu-\lambda)e^{-(\mu-\lambda)t}$ です。両者はよく一致しており、滞在時間が平均5分の指数分布になることが確認できます。指数分布なので「短時間で済む人が多いが、たまに非常に長く待たされる人がいる」という長い裾を持ちます。赤い破線が平均 $W=5$ 分の位置です。
リトルの法則の検証
最後に、リトルの法則 $L = \lambda W$ が本当に成り立つかを、さまざまな $\rho$ で確かめます。各 $\rho$ について実測した $L$ を横軸、実測した $\lambda W$ を縦軸にプロットします。

18通りの利用率 $\rho$ でシミュレーションした点が、すべて対角線 $L=\lambda W$ の上に見事に並んでいます。混んでいても空いていても、$L$ と $\lambda W$ が常に等しい —— リトルの法則が分布の形によらず普遍的に成り立つ、という主張が実測で裏付けられました。この法則があるからこそ、「人数」の計算から「時間」の計算へと自由に行き来できるのです。
まとめ
本記事では、M/M/1 待ち行列の理論・導出・実装を解説しました。
- モデル: 到着はポアソン過程(率 $\lambda$)、サービスは指数分布(率 $\mu$)、窓口1個。指数分布の無記憶性により、状態は系内人数 $n$ だけで完全に決まる
- 生誕死滅過程 → 定常分布: 詳細釣り合い式 $\lambda p_n = \mu p_{n+1}$ から漸化式 $p_{n+1}=\rho p_n$ を得て、規格化により $p_n = (1-\rho)\rho^n$(幾何分布)を導いた。$\rho = \lambda/\mu$ は利用率
- 安定条件: 等比級数が収束する $\rho < 1$($\lambda < \mu$)が、定常状態が存在する条件。$\rho=1$ でも列は発散する
- 平均量: 平均系内人数 $L = \rho/(1-\rho)$、リトルの法則 $L=\lambda W$ から平均滞在時間 $W = 1/(\mu-\lambda)$、平均待ち時間 $W_q = \rho/(\mu-\lambda)$。いずれも $\rho\to 1$ で発散する
- 検証: Python の離散事象シミュレーションで、定常分布・$L$・$W$・リトルの法則がすべて理論と一致することを seed 固定で確認した
M/M/1 の最大の教訓は、利用率を1に近づけすぎると待ち行列が非線形に爆発することです。効率(高い稼働率)と快適さ(短い待ち時間)はトレードオフの関係にあり、この曲線を知っていれば、システムにどれだけの余裕を持たせるべきかを定量的に判断できます。
次のステップとして、以下の記事も参考にしてください。
- ポアソン過程とは?定義から性質までわかりやすく解説 — 到着モデルの土台
- 生誕死滅過程をわかりやすく解説 — M/M/1 を含む、より一般の枠組み
- 連続時間マルコフ連鎖 — 待ち行列を状態遷移として捉える視点
M/M/1 を足がかりに、窓口が複数の M/M/c(待ち時間からオペレーター数を設計する)、待合室に上限がある M/M/1/K、サービス時間が一般分布の M/G/1(ポラチェック・ヒンチンの公式)へと発展させていくと、現実のシステム設計にそのまま使える待ち行列理論の全体像が見えてきます。