Mímisbrunnr知恵の泉

← 数理最適化 一覧

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

📎 前提:線形計画の標準形と幾何 | 関連:線形計画の双対性

要点(BLUF)

概念 ── 頂点=基底解

標準形 Ax=b, x0Ax=b,\ x\ge0AAm×nm\times n)を考える。nn 個の変数から mm 個を選んで 基底変数とし、残り nmn-m 個を 非基底変数=0 に固定する。基底の連立 BxB=bB x_B = b を解いた xB0x_B \ge 0基底実行可能解で、これが凸多面体の 頂点に対応する(線形計画の標準形と幾何)。

頂点が有限個なのは、基底の選び方が (nm)\binom{n}{m} 通りと有限だから。シンプレックス法は全部試さず、改善する方向にだけ進む。

アルゴリズム ── ピボットで隣の頂点へ

graph TD
  A["初期頂点(基底実行可能解)"] --> B["被約費用を計算"]
  B --> C{"改善する非基底変数があるか"}
  C -->|"ある"| D["入る変数を選ぶ(価格付け)"]
  D --> E["比率テストで出る変数を選ぶ"]
  E --> F["ピボット = 隣の頂点へ移動"]
  F --> B
  C -->|"ない(全て非負)"| G["最適 = 停止"]
  1. 価格付け(入る変数):非基底変数 xjx_j被約費用 cˉj=cjcBB1Aj\bar c_j = c_j - c_B^\top B^{-1} A_j を見る。cˉj<0\bar c_j < 0(最小化)なら、xjx_j を増やすと目的が下がる。
  2. 比率テスト(出る変数)xjx_j を増やすと、ある基底変数が先に0になる。最初に0になる変数が基底から出る(minibi/(B1Aj)i\min_i b_i / (B^{-1}A_j)_i、正の成分のみ)。
  3. ピボット:基底を入れ替える=隣接頂点へ移動。目的は改善(または不変)。
  4. 停止:すべての cˉj0\bar c_j \ge 0 なら、どの方向に動いても改善せず 最適

被約費用が最適性を保証する理由

被約費用 cˉj\bar c_j は「非基底変数 xjx_j を1単位増やしたときの目的の正味変化」。基底変数が連動して変わる分まで織り込んだ値だ。すべての cˉj0\bar c_j \ge 0 なら、どの非基底変数を増やしても目的は下がらない ── つまり現在の頂点が局所最適。LP は凸(局所最適と大域最適・凸性の役割)なので、局所最適は大域最適。これでシンプレックス法の停止=最適が正当化される。被約費用は双対変数 y=(B1)cBy = (B^{-1})^\top c_B を使って cˉj=cjyAj\bar c_j = c_j - y^\top A_j とも書け、ここに 双対性線形計画の双対性)が顔を出す。

Pythonで頂点最適に到達

scipy の linprog(method="highs-ds")デュアルシンプレックス。生産計画 LP を解くと、頂点 (20,80)(20,80) に到達する(線形計画の標準形と幾何 の頂点列挙と一致)。

from scipy.optimize import linprog

# max 40xA+30xB を -最小化(符号反転)
c = [-40, -30]
A_ub = [[2, 1], [1, 1]]   # 2xA+xB<=120, xA+xB<=100
b_ub = [120, 100]
bounds = [(0, None), (0, None)]

res = linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=bounds, method="highs-ds")
print(f"最適解 xA={res.x[0]:.1f}, xB={res.x[1]:.1f}, 利益={-res.fun:.0f}")

実行結果:

最適解 xA=20.0, xB=80.0, 利益=3200

頂点列挙で最大だった (20,80)(20,80) にシンプレックスが到達。原点 (0,0)(0,0) から始めて、xBx_B を入れて (0,100)(0,100)、次に xAx_A を入れて (20,80)(20,80) ── というように2回のピボットで角を渡る(具体的なピボット経路は問題と規則による)。

計算量と実務

数式の直観的意味

シンプレックス法の賢さは「内点を通らず、縁の頂点だけを目的が良くなる向きに辿る」点にある。LP の最適が頂点にある(線形計画の標準形と幾何)以上、頂点だけ調べれば十分で、しかも隣接頂点へ「下る」だけなので、凸性が後戻りしないことを保証する。被約費用が全部非負になった瞬間に「もう下る隣がない」=大域最適、と判断できる。この局所的な判定(隣だけ見る)が大域最適を保証するのは、ひとえに凸多面体+線形目的という構造のおかげ。

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

関連ノート