🎓 レベル:応用 | 重要度:A(必須)
📎 前提:確率的在庫モデル(新聞売り子問題)(臨界比 CR=Cu/(Cu+Co)・Q*=F^{-1}(CR)。リトルウッドもオーバーブッキングもこの親戚) | 確率の土台:正規分布(標準正規・標準化)(分位点 Φ^{-1}) | 次:離散事象シミュレーション最適化
要点(BLUF)
- 収益管理(レベニューマネジメント, RM)は、消滅する容量——航空座席・ホテル室・レンタカー・公演席のように当日を過ぎれば価値がゼロになる固定キャパシティ——を、適切な顧客に・適切な価格で配分して収益を最大化する技術です。
- 中核はリトルウッドの法則(2運賃クラス)。高運賃 の客のために席を保護し、安い予約()は残席が保護水準を上回る間だけ受ける。最適保護水準 は限界分析から 、すなわち 。
- これは新聞売り子の親戚です(確率的在庫モデル(新聞売り子問題))。保護水準を「在庫」、高運賃需要を「需要」とみなすと、過小コスト ・過剰コスト の新聞売り子で、臨界比 にぴたり対応します。
- オーバーブッキング(ノーショー対策の過剰予約)も新聞売り子型です。空席損 と搭乗拒否コスト のトレードオフで、最適予約上限は臨界比 で決まります。なお RM は容量ベースの最適化で、需要曲線の傾き(価格弾力性)から最適価格を出すマーケティング・サイエンスの価格最適化とは別物です。
1. 収益管理とは:消滅する容量を、安売りしすぎず・空席も出さず
航空便の座席は、出発した瞬間に売れ残りの価値がゼロになります。在庫として翌日に繰り越せない——この「消滅する容量(perishable capacity)」が RM の出発点です。しかも顧客には早割で安く買う観光客と、直前に高く買う出張客がいる。座席は同じでも支払い意思(WTP)が違うわけです。
このとき航空会社のジレンマは明確です。安い予約を受けすぎると、後から来る高運賃の出張客に売る席がなくなる(安売りで容量を食い潰す)。かといって高運賃を待ちすぎると、出張客が思ったより来ずに空席のまま出発してしまう(消滅損)。RM は「いくつの席を高運賃のために取っておくか(保護水準)」を、需要の確率分布とコストから決める問題です。
flowchart LR
REQ["安い予約(低運賃 pL)が来た"] --> CHK{"残席 > 保護水準 Q ?"}
CHK -->|"はい(席に余裕)"| ACC["受ける(pL を確定)"]
CHK -->|"いいえ(残り Q 席)"| REJ["断る(高運賃 pH のために保護)"]
RM が成り立つ前提は3つ。(1) 容量が固定で消滅する、(2) 需要をセグメントに分けられる(運賃クラス・購入時期・キャンセル条件などのフェンスで囲い込める)、(3) 予約が時間差で入る(安い客が先・高い客が後)。この3条件が揃う航空・ホテル・レンタカー・興行で RM は威力を発揮します。
2. リトルウッドの法則:保護水準の導出
座席 席、運賃は高 と低 ()の2クラス。低運賃の客が先に予約し、高運賃の客が後から来るとします。決めるのは高運賃のための保護水準 ——「残り 席になったら、もう低運賃は断って高運賃のために取っておく」その です。
限界分析で最適 を出します。いま目の前に低運賃客が1人いて、残席がちょうど 席だとする。この** 席目**を「いま で売る」か「保護して高運賃を待つ」か。
- いま売る:確実に を得る。
- 保護する:この席が を生むのは、高運賃需要 が 以上あってこの席まで埋まるとき、すなわち確率 。期待値は 。
保護したほうが得なのは のとき。 を増やすほど「 席目まで高運賃が来る確率」 は下がるので、保護を増やす価値があるのは
が成り立つ間だけ。境目、すなわち が最適保護水準です。
直感も明快です。運賃比 が小さい(安席が高席よりずっと安い)ほど、 を小さく= を大きくしてたくさん保護する。逆に2クラスの値段が近ければ保護は薄くてよい。「安く売る機会費用」と「高く売れる確率」の釣り合いです。
3. 新聞売り子の親戚であること
リトルウッドの法則は、保護水準 を「在庫」、高運賃需要 を「需要」とみなした新聞売り子問題(確率的在庫モデル(新聞売り子問題))に他なりません。保護水準を1つ動かしたときの2つの後悔を考えます。
- 保護しすぎ( が大きく、高運賃需要が届かず保護席が空く):その席は低運賃でも売れたのに空席になった。過剰コスト 。
- 保護不足( が小さく、安く売った後に高運賃需要があふれた): で売れた席を で手放した。過小コスト 。
新聞売り子の臨界比に入れると
で 、つまり ——リトルウッドと完全に一致します。RM は「席という消滅在庫を、どの運賃クラスにどれだけ取っておくか」の新聞売り子だ、と見抜けるのが勘所です。
4. 保護水準が期待収益を最大化することを実証(コード)
席、、高運賃需要 。リトルウッドの保護水準 を計算し、保護水準 のグリッド上で期待収益を200万サンプルでモンテカルロして、最大化点が に一致するかを確かめます(低運賃需要は豊富で 席は必ず埋まると仮定)。
import numpy as np
from scipy.stats import norm
rng = np.random.default_rng(20260627)
# 2運賃クラスの座席:容量 C、高運賃 pH、低運賃 pL(pL < pH)
C = 100 # 総座席数
pH = 400.0 # 高運賃(円)
pL = 150.0 # 低運賃(円)
# 高運賃需要 D_H ~ N(muH, sigmaH)(低運賃需要は豊富で C-Q 席は必ず埋まると仮定)
muH, sigmaH = 50.0, 18.0
# リトルウッドの法則:保護水準 Q* で P(D_H > Q*) = pL/pH
# => F_H(Q*) = 1 - pL/pH、Q* = muH + norm.ppf(1 - pL/pH)*sigmaH
ratio = pL / pH
crit = 1 - ratio # = 新聞売り子の臨界比 Cu/(Cu+Co), Cu=pH-pL, Co=pL
z = norm.ppf(crit)
Q_star = muH + z * sigmaH
print(f"運賃比 pL/pH = {ratio:.4f}")
print(f"保護の臨界比 1 - pL/pH = (pH-pL)/pH = {crit:.4f}")
print(f" 新聞売り子で言えば Cu=pH-pL={pH-pL:.0f}, Co=pL={pL:.0f}, CR={crit:.4f}")
print(f"z = norm.ppf(1-pL/pH) = {z:.4f}")
print(f"高運賃の保護水準 Q* = muH + z*sigmaH = {Q_star:.2f} 席")
print(f" => 低運賃に開放するのは C - Q* = {C - Q_star:.2f} 席まで")
print()
# --- モンテカルロ:保護水準 Q のグリッドで期待収益を評価し、最大化点を確認 ---
# 収益(Q) = pL*(C-Q)(低運賃で確実に埋まる) + pH*min(D_H, Q)(保護席を高運賃が埋める)
N = 2_000_000
DH = rng.normal(muH, sigmaH, size=N)
def expected_revenue(Q):
high = np.minimum(DH, Q) # 保護席を埋めた高運賃客
rev = pL * (C - Q) + pH * high
return rev.mean()
Q_grid = np.arange(20.0, 90.0 + 0.5, 0.5)
revs = np.array([expected_revenue(Q) for Q in Q_grid])
Q_best = Q_grid[np.argmax(revs)]
print(f"MC 期待収益を最大化する保護水準 Q (グリッド) = {Q_best:.2f}")
print(f"リトルウッドの法則による Q* = {Q_star:.2f}")
print(f"Q* での期待収益 = {expected_revenue(Q_star):.2f} 円/便")
# 「保護しすぎ(全席保護)」「保護せず(全部低運賃)」との比較
print(f" 参考: 全席低運賃(Q=0) の期待収益 = {expected_revenue(0):.2f}")
print(f" 参考: 全席保護(Q=C) の期待収益 = {expected_revenue(C):.2f}")
出力:
運賃比 pL/pH = 0.3750
保護の臨界比 1 - pL/pH = (pH-pL)/pH = 0.6250
新聞売り子で言えば Cu=pH-pL=250, Co=pL=150, CR=0.6250
z = norm.ppf(1-pL/pH) = 0.3186
高運賃の保護水準 Q* = muH + z*sigmaH = 55.74 席
=> 低運賃に開放するのは C - Q* = 44.26 席まで
MC 期待収益を最大化する保護水準 Q (グリッド) = 55.50
リトルウッドの法則による Q* = 55.74
Q* での期待収益 = 24768.51 円/便
参考: 全席低運賃(Q=0) の期待収益 = 14994.10
参考: 全席保護(Q=C) の期待収益 = 19992.97
出力の意味:運賃比 なので保護の臨界比は 。新聞売り子で言えば ・ で と一致します。、保護水準 席——100席のうち約56席を高運賃に取っておき、低運賃に開放するのは約44席まで。コードはこの を使わずに保護水準を20〜90で動かしただけですが、期待収益の最大化点 55.50 がリトルウッドの 55.74 に一致しました。そして保護戦略の価値が数字に出ています——全席を安く売ると 14,994 円(容量を食い潰す)、全席を高運賃に取っておくと 19,993 円(出張客が来ず空席)、最適保護で 24,768 円。どちらの極端より2〜6割多い収益で、「安席で容量を埋めつつ、高席のぶんだけ賢く取っておく」のリトルウッドが効いていると分かります。
5. オーバーブッキング:空席損と搭乗拒否のトレードオフ(コード)
予約客の一部は当日現れません(ノーショー)。その空席を埋めるには容量を超えて予約を取る(オーバーブッキング)しかありませんが、取りすぎると全員現れたとき搭乗拒否が出ます。これも新聞売り子です——**空席損 (過小コスト )と搭乗拒否コスト (過剰コスト )**のトレードオフで、最適予約上限の臨界比は 。容量 、ノーショー率 、純収益 、搭乗拒否補償 で、最適予約上限を求めます。
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
from scipy.stats import binom
rng = np.random.default_rng(20260627)
# オーバーブッキング:容量 C、ノーショー率 r、運賃 f、搭乗拒否コスト D
C = 100 # 座席数
r = 0.15 # ノーショー率(予約1件が現れない確率)
q = 1 - r # 搭乗率
f = 300.0 # 1席あたり純収益(空席は機会損失 f)
Dcost = 800.0 # 搭乗拒否1件あたりの補償コスト
# 新聞売り子型の臨界比:限界の1予約を足すと、現れる確率 q で
# 満席なら拒否(コスト Dcost)・空席なら収益 f。
# P(現れた客数 S >= C) <= f/(f+Dcost) の間は予約を増やすべき
CR = f / (f + Dcost)
print(f"臨界比 f/(f+Dcost) = {CR:.4f}")
print(f" (空席損 f={f:.0f} が過小コスト Cu、搭乗拒否 D={Dcost:.0f} が過剰コスト Co)")
# 限界条件から最適予約上限 b* を求める:P(S_b>=C)<=CR の間は1席増やす
b_pred = C
while binom.sf(C - 1, b_pred, q) <= CR: # sf(C-1,n,q)=P(S_b>=C)
b_pred += 1
print(f"限界条件 P(S_b>=C)<=CR から予測する最適予約上限 b* = {b_pred}(超過 {b_pred - C} 席)")
print(f" b*-1={b_pred - 1} での P(S>=C) = {binom.sf(C - 1, b_pred - 1, q):.4f} (<= {CR:.4f}:もう1席増やす価値あり)")
print(f" b* ={b_pred} での P(S>=C) = {binom.sf(C - 1, b_pred, q):.4f} (> {CR:.4f}:これ以上は搭乗拒否が勝つ)")
print()
# --- モンテカルロ:予約上限 b のグリッドで期待利益を評価し、最大化点を確認 ---
# 利益(b) = f*min(S,C) - Dcost*max(S-C,0), S=現れた客数 ~ Binomial(b, q)
N = 1_000_000
b_grid = np.arange(C, C + 36)
exp_profit = []
for b in b_grid:
S = rng.binomial(b, q, size=N)
profit = f * np.minimum(S, C) - Dcost * np.maximum(S - C, 0)
exp_profit.append(profit.mean())
exp_profit = np.array(exp_profit)
b_best = b_grid[np.argmax(exp_profit)]
print(f"MC 期待利益を最大化する予約上限 b (グリッド) = {b_best}")
print(f"限界条件による予測 b* = {b_pred}")
print(f" b*={b_pred} の期待利益 = {exp_profit[b_grid == b_pred][0]:.2f} 円/便")
print(f" 超過なし b=C={C} の期待利益 = {exp_profit[0]:.2f} 円/便(ノーショーで空席)")
print(f" オーバーブッキングの利得 = {exp_profit[b_grid == b_pred][0] - exp_profit[0]:.2f} 円/便")
# --- 図:予約上限 vs 期待利益 ---
plt.figure(figsize=(10, 5.5))
plt.plot(b_grid, exp_profit, "o-", color="#1f77b4", ms=4, label="期待利益(MC)")
plt.axvline(C, color="gray", ls="--", label=f"容量 C={C}(超過なし)")
plt.scatter([b_best], [exp_profit[b_grid == b_best][0]], color="#d62728",
zorder=5, s=80, label=f"最適 b*={b_best}({b_best - C}席超過)")
plt.xlabel("予約上限 b(受け付ける予約数)")
plt.ylabel("期待利益(円/便)")
plt.title("オーバーブッキング:空席損と搭乗拒否のトレードオフ=新聞売り子型の最適予約上限")
plt.legend(); plt.tight_layout(); plt.show()
出力:
臨界比 f/(f+Dcost) = 0.2727
(空席損 f=300 が過小コスト Cu、搭乗拒否 D=800 が過剰コスト Co)
限界条件 P(S_b>=C)<=CR から予測する最適予約上限 b* = 115(超過 15 席)
b*-1=114 での P(S>=C) = 0.2530 (<= 0.2727:もう1席増やす価値あり)
b* =115 での P(S>=C) = 0.3328 (> 0.2727:これ以上は搭乗拒否が勝つ)
MC 期待利益を最大化する予約上限 b (グリッド) = 115
限界条件による予測 b* = 115
b*=115 の期待利益 = 28634.53 円/便
超過なし b=C=100 の期待利益 = 25499.54 円/便(ノーショーで空席)
オーバーブッキングの利得 = 3134.98 円/便
出力の意味:搭乗拒否(800円)が空席損(300円)より重いので、臨界比は と0.5より小さく、「満席〜超過になる確率が27%に達するまで」予約を取り増やすのが最適です。限界条件は で (まだ なので1席増やす価値あり)、 で ( なので打ち止め)と判定し、最適予約上限 (容量より15席多く受ける)。これが MC の期待利益最大化点 115 とぴたり一致しました。利得も明確で、容量ぴったり100席しか受けないと、ノーショーで空席が出て 25,500 円。15席オーバーブッキングすると 28,635 円で、+3,135 円/便。図は期待利益が について上に凸で、(赤)で頂点になる様子を示します。左に寄れば空席損で取りこぼし、右に行きすぎれば搭乗拒否補償で削られる——典型的な新聞売り子の山型です。
⚠️ よくある誤解
- 「RM はどんな商品でも使える」ではない:RM が効くのは (1) 容量が固定で消滅する、(2) 需要をセグメント化できる、(3) 予約が時間差で入る、の3条件が揃うとき。在庫を持ち越せる物販(売れ残りを翌日も売れる)では、価格は弾力性ベースの最適化(マーケティング・サイエンス)の領分で、リトルウッドの保護水準は出てきません。RM は容量ベースだと押さえること。
- 「リトルウッドは独立した特殊公式」ではない:本質は新聞売り子(確率的在庫モデル(新聞売り子問題))です。 と置けば臨界比 がそのまま出る。3クラス以上は EMSR(期待限界座席収益)法などへ拡張しますが(要最新確認)、出発点は同じ限界分析です。
- 「オーバーブッキングは取れるだけ取る」ではない:オーバーブッキングは空席損と搭乗拒否のトレードオフで、最適予約上限は臨界比 で決まります。搭乗拒否の補償・のれん損 が大きいほど超過は控えめに。本稿はノーショーを独立な二項試行とした単純モデルで、実務はノーショー率の予測誤差・グループ予約の相関・払い戻し規定を織り込みます(要最新確認)。
- 「保護水準は固定」ではない:本稿は2クラス・一発の保護水準でしたが、実際の RM は予約の進み具合を見て保護水準を更新する動的方策(ブッキングカーブ、入れ子の保護水準、ビッドプライス)で運用します。動的価格付け(残席と残り時間で値段を動かす)も同根で、いずれも「いま売るか・取っておくか」の機会費用の評価です(要最新確認)。
- 「フェンスは無くてもよい」ではない:高運賃客が安運賃に流れるカニバリゼーションを防ぐのがフェンス(事前購入・滞在条件・変更不可・会員限定など)。フェンスが弱いと、保護水準をいくら最適化しても出張客が安席を買ってしまい、RM の前提(セグメント分離)が崩れます。
関連ノート
- 確率的在庫モデル(新聞売り子問題)(前提・臨界比 。リトルウッドもオーバーブッキングもこの親戚)
- 正規分布(標準正規・標準化)(統計・ 分位点の土台)
- 離散事象シミュレーション最適化(次のトピック・閉形式が無い動的方策はシミュレーションで探索)
- マーケティング・サイエンス(価格弾力性ベースの価格最適化。RM の容量ベースと別物)
- オペレーションズ・マネジメント 全体目次