Mímisbrunnr知恵の泉

← オペレーションズマネジメント 一覧

🎓 レベル:標準 | 重要度:A(必須)

📎 前提:安全在庫と発注点(安全在庫 zσLz\sigma\sqrt{L}σDLT\sigma_{DLT} の分散加法)・M/M/c 待ち行列と窓口設計(プーリング効果=同一原理) | 関連:サプライチェーンの構造とトレードオフブルウィップ効果 | 章末

要点(BLUF)

1. リスクプーリングとは:束ねると揺れが平均化する

ある製品を nn 個の地域倉庫で別々に在庫しているとします。各倉庫は自分の地域の需要のばらつきに備えて安全在庫を積みます。ここで、nn 倉庫を1つの中央倉庫に統合したらどうなるでしょうか。

直感的には「需要の合計を1か所で持つだけだから、必要在庫は変わらない」と思えます。ところが安全在庫は減ります。理由は、ある地域で需要が平均より多い日に、別の地域は平均より少ないことがあり、束ねると過不足が打ち消し合うから。バラバラに持つと各倉庫が「自分の最悪」に備えねばなりませんが、束ねれば「全体の最悪」は各最悪の単純合計よりずっと小さい。これがリスクプーリングです。

flowchart LR
  D1["分散在庫<br/>n 拠点 × z·σ<br/>合計 n·z·σ"]
  C1["集約在庫<br/>1 拠点 × z·σ·√n<br/>合計 z·σ·√n"]
  D1 -->|"集約すると 1/√n に"| C1

効くのは安全在庫(ばらつきの緩衝)であって、平均需要そのものをまかなう在庫ではありません。平均需要は束ねても足し算(変わらない)。ばらつきだけが、束ねると n\sqrt{n} でしか伸びない——ここがすべての出発点です。

2. なぜ √n か:分散は足し算だから

地域 ii の需要を DiD_i(平均 μ\mu、分散 σ2\sigma^2、互いに独立)とします。集約倉庫が受ける需要は合計 Dpool=i=1nDiD_\text{pool}=\sum_{i=1}^n D_i独立な確率変数の和は、分散が足し算になります(安全在庫と発注点 でリードタイム需要に使ったのと同じ性質)。

Var(Dpool)=i=1nVar(Di)=nσ2σpool=nσ2=σn\mathrm{Var}(D_\text{pool})=\sum_{i=1}^{n}\mathrm{Var}(D_i)=n\sigma^2 \qquad\Longrightarrow\qquad \sigma_\text{pool}=\sqrt{n\sigma^2}=\sigma\sqrt{n}

ここが急所です。平均は μpool=nμ\mu_\text{pool}=n\mu と**nn 倍(線形)**になるのに、標準偏差は σn\sigma\sqrt{n}n\sqrt{n}にしかなりません。安全在庫はサービス水準 zz(正規分位点)× 標準偏差なので、

分散時の総安全在庫=nzσ,集約時の安全在庫=zσpool=zσn\text{分散時の総安全在庫}=n\cdot z\sigma, \qquad \text{集約時の安全在庫}=z\,\sigma_\text{pool}=z\sigma\sqrt{n}

両者の比が節約率です。

集約分散=zσnnzσ=nn=1n\frac{\text{集約}}{\text{分散}}=\frac{z\sigma\sqrt{n}}{n\cdot z\sigma}=\frac{\sqrt{n}}{n}=\frac{1}{\sqrt{n}}

集約すると安全在庫は 1/n1/\sqrt{n} に縮むn=4n=4 で半分、n=9n=9 で1/3、n=16n=16 で1/4。逆に言えば、削減幅は 11/n1-1/\sqrt{n} で、拠点が多いほど集約の利得が大きいn\sqrt{n} は「拠点数」ではなく、分散が足し算という1点から出ていることに注意してください。

相関があると効果は薄れる

現実の地域需要は完全には独立でなく、景気や天候で**一緒に動く(正の相関)**ことがあります。等相関 ρ\rho(どの2拠点も相関 ρ\rho)を入れると、和の分散は共分散項が加わって

Var(Dpool)=nσ2分散の和+n(n1)ρσ2共分散の和=σ2[n+n(n1)ρ]\mathrm{Var}(D_\text{pool})=\underbrace{n\sigma^2}_{\text{分散の和}}+\underbrace{n(n-1)\rho\sigma^2}_{\text{共分散の和}} =\sigma^2\bigl[n+n(n-1)\rho\bigr] σpool=σn+n(n1)ρ,集約分散=n+n(n1)ρn=1+(n1)ρn\sigma_\text{pool}=\sigma\sqrt{n+n(n-1)\rho}, \qquad \frac{\text{集約}}{\text{分散}}=\frac{\sqrt{n+n(n-1)\rho}}{n}=\frac{\sqrt{1+(n-1)\rho}}{\sqrt{n}}

ρ=0\rho=0(独立)なら 1/n1/\sqrt{n}最大の節約ρ=1\rho=1(完全相関)なら n/n=1\sqrt{n}/\sqrt{n}=1節約ゼロ。みんなが同時に増減するなら、束ねても打ち消し合いが起きず、集約しても安全在庫は減りません。プーリングは独立性に依存するのです。

3. √n の節約をモンテカルロで裏取り(コード)

n=9n=9 拠点の独立な需要(各 σ=25\sigma=25)を大量に生成し、合計需要の分散が nσ2n\sigma^2 になること、そして分散在庫 nzσn\cdot z\sigma と集約在庫 zσnz\sigma\sqrt{n} の比が 1/n1/\sqrt{n} になることを実測で確かめます。安全在庫の式は 安全在庫と発注点SS=zσSS=z\sigma をそのまま使います(ここでは1期需要に着目し L=1L=1)。

import numpy as np
from scipy.stats import norm

rng = np.random.default_rng(11)

n = 9               # 拠点数
mu = 100.0          # 各拠点の平均需要
sigma = 25.0        # 各拠点の需要標準偏差(独立)
z = norm.ppf(0.95)  # 95% サービス水準の安全係数

N = 500000
dem = rng.normal(mu, sigma, size=(N, n))   # 各拠点の需要を独立に生成
agg = dem.sum(axis=1)                        # 集約後(合計)需要

ss_decentral = n * z * sigma                 # 分散在庫:各拠点 z*sigma の合計
sigma_pool_theory = sigma * np.sqrt(n)       # 集約後の標準偏差 sigma*sqrt(n)
ss_central = z * sigma_pool_theory           # 集約在庫:z*sigma*sqrt(n)
sigma_pool_emp = np.std(agg)

print(f"拠点数 n={n}, 各拠点 sigma={sigma}, z(95%)={z:.4f}")
print(f"合計需要の標準偏差:理論 sigma*sqrt(n)={sigma_pool_theory:.3f}  実測={sigma_pool_emp:.3f}")
print(f"  分散の加法:n*var = {n * sigma**2:.1f}  実測 var(agg)={np.var(agg):.1f}")
print()
print(f"分散在庫(合計) n*z*sigma       = {ss_decentral:.2f}")
print(f"集約在庫         z*sigma*sqrt(n) = {ss_central:.2f}")
print(f"節約率 集約/分散 = 1/sqrt(n)     = {ss_central / ss_decentral:.4f}  (理論 {1 / np.sqrt(n):.4f})")
print(f"削減幅 1-1/sqrt(n)               = {1 - ss_central / ss_decentral:.4f}")

print("\n[拠点数 n を変えたときの節約(z*sigma を単位に)]")
print(" n   分散在庫 n*z*sigma   集約 z*sigma*sqrt(n)   節約率 1/sqrt(n)")
for nx in [1, 2, 4, 9, 16, 25]:
    dec = nx * z * sigma
    cen = z * sigma * np.sqrt(nx)
    print(f"{nx:2d}   {dec:14.2f}   {cen:16.2f}   {cen / dec:.4f}")

出力:

拠点数 n=9, 各拠点 sigma=25.0, z(95%)=1.6449
合計需要の標準偏差:理論 sigma*sqrt(n)=75.000  実測=74.928
  分散の加法:n*var = 5625.0  実測 var(agg)=5614.3

分散在庫(合計) n*z*sigma       = 370.09
集約在庫         z*sigma*sqrt(n) = 123.36
節約率 集約/分散 = 1/sqrt(n)     = 0.3333  (理論 0.3333)
削減幅 1-1/sqrt(n)               = 0.6667

[拠点数 n を変えたときの節約(z*sigma を単位に)]
 n   分散在庫 n*z*sigma   集約 z*sigma*sqrt(n)   節約率 1/sqrt(n)
 1            41.12              41.12   1.0000
 2            82.24              58.15   0.7071
 4           164.49              82.24   0.5000
 9           370.09             123.36   0.3333
16           657.94             164.49   0.2500
25          1028.03             205.61   0.2000

出力の意味:まず分散の加法が裏取りできました——各拠点 σ2=625\sigma^2=625 の9拠点ぶんの和 nσ2=5625n\sigma^2=5625 に対し、合計需要の実測分散は 5614.35614.3(標準偏差 74.93σn=7574.93\approx\sigma\sqrt{n}=75)。合計需要のばらつきは σn=225\sigma\cdot n=225 ではなく σn=75\sigma\sqrt{n}=75 です。その結果、安全在庫は分散時 370.1 → 集約時 123.4 に縮み、節約率は 0.3333——理論の 1/9=1/31/\sqrt{9}=1/3 に一致しました。集約で安全在庫を約67%削減できる勘定です。下段の表は n\sqrt{n} の効き方で、n=4n=4 で半分(0.5)、n=16n=16 で1/4(0.25)、n=25n=25 で1/5(0.2)。拠点を多く束ねるほど効くが、効きは逓減n\sqrt{n} なので nn を4倍にして初めて半分)。この n\sqrt{n} は、第4章のプーリング効果(M/M/c 待ち行列と窓口設計 で同じ稼働率でも統合で待ちが激減)と同じ顔です。

4. 相関がプーリング効果を消す(コード)

「独立なら 1/n1/\sqrt{n}」を支えるのは独立性でした。拠点間の需要相関 ρ\rho010\to1 に振り、節約率がどう変わるかを見ます。理論 1+(n1)ρ/n\sqrt{1+(n-1)\rho}/\sqrt{n} と、相関を入れた多変量正規からのモンテカルロ実測を並べます。

import numpy as np
from scipy.stats import norm
import matplotlib.pyplot as plt
import japanize_matplotlib

rng = np.random.default_rng(23)
n = 9
mu, sigma = 100.0, 25.0
z = norm.ppf(0.95)
N = 300000

rhos = np.array([0.0, 0.2, 0.4, 0.6, 0.8, 1.0])
print(f"n={n} 拠点・各 sigma={sigma}・z(95%)={z:.4f}")
print("rho   理論 sigma_pool   実測 sigma_pool   集約/分散   理論 sqrt(1+(n-1)rho)/sqrt(n)")
ratios_emp, ratios_theory = [], []
for rho in rhos:
    cov = sigma**2 * ((1 - rho) * np.eye(n) + rho * np.ones((n, n)))
    dem = rng.multivariate_normal(np.full(n, mu), cov, size=N, check_valid="ignore")
    agg = dem.sum(axis=1)
    sp_emp = np.std(agg)
    sp_th = sigma * np.sqrt(n + n * (n - 1) * rho)
    ratio_emp = sp_emp / (n * sigma)              # = z*sp_emp / (n*z*sigma)
    ratio_th = np.sqrt(1 + (n - 1) * rho) / np.sqrt(n)
    ratios_emp.append(ratio_emp)
    ratios_theory.append(ratio_th)
    print(f"{rho:.1f}   {sp_th:12.2f}   {sp_emp:12.2f}   {ratio_emp:.4f}      {ratio_th:.4f}")

plt.figure(figsize=(9, 5.5))
plt.plot(rhos, ratios_theory, "-", color="#1f77b4", lw=2,
         label="理論 sqrt(1+(n-1)rho)/sqrt(n)")
plt.plot(rhos, ratios_emp, "o", color="#d62728", ms=8, label="モンテカルロ実測")
plt.axhline(1 / np.sqrt(n), color="green", ls="--",
            label=f"rho=0 の最大節約 1/sqrt(n)={1 / np.sqrt(n):.3f}")
plt.axhline(1.0, color="gray", ls=":", label="rho=1 効果ゼロ(集約=分散)")
plt.xlabel("拠点間の需要相関 rho")
plt.ylabel("集約在庫 / 分散在庫(小さいほど節約大)")
plt.title(f"リスクプーリングは独立(rho=0)で最大・完全相関(rho=1)で消える(n={n})")
plt.legend(); plt.grid(alpha=0.3); plt.tight_layout(); plt.show()

出力:

n=9 拠点・各 sigma=25.0・z(95%)=1.6449
rho   理論 sigma_pool   実測 sigma_pool   集約/分散   理論 sqrt(1+(n-1)rho)/sqrt(n)
0.0          75.00          75.01   0.3334      0.3333
0.2         120.93         120.99   0.5377      0.5375
0.4         153.70         153.62   0.6828      0.6831
0.6         180.62         180.43   0.8019      0.8028
0.8         204.02         204.12   0.9072      0.9068
1.0         225.00         225.35   1.0016      1.0000

出力の意味:相関 ρ\rho を上げるほど、集約後の標準偏差 σpool\sigma_\text{pool}7522575\to225 と膨らみ、節約率(集約/分散)は 0.3331.0000.333\to1.000 へ単調に悪化します。ρ=0\rho=0(独立)では理論どおり 1/9=0.3331/\sqrt{9}=0.333 の最大節約ρ=1\rho=1(完全相関)では 1.0001.000=効果ゼロ——9拠点が完全に同時に増減するなら、合計の標準偏差は σn+n(n1)=σn=225\sigma\sqrt{n+n(n-1)}=\sigma\cdot n=225、つまりただの nnになり、束ねる旨みが消えます。図の赤点(モンテカルロ)は青い理論曲線にぴたり乗り、緑の破線(ρ=0\rho=0 の床 0.3330.333)と灰の点線(ρ=1\rho=1 の天井 1.01.0)の間を滑らかに上がります。実務的な含意は重要で、プーリングが効くのは需要が独立に近いとき——地域差・季節差で互いに打ち消し合う製品では集約が効き、景気や流行で一斉に動く製品では効きが鈍い。集約の意思決定は、まず拠点間の相関を見ることから始まります。

⚠️ よくある誤解

関連ノート