Mímisbrunnr知恵の泉

← 数理最適化 一覧

🎓 レベル:基礎 | 重要度:B(標準)

📎 前提:実装:cvxpyで凸問題を解く | 関連:定式化の技法

要点(BLUF)

ツールの守備範囲

ツール得意な問題性格
scipy.optimizeLP(linprog)・無制約/制約付き非線形(minimize低レベル、行列で渡す、依存が軽い
PuLPLP・混合整数計画(MILP)モデリング言語、CBC など MILP ソルバーを呼ぶ
cvxpy凸最適化(LP/QP/SOCP/SDP)DCP で凸性を保証、錐ソルバーへ自動変換
OR-Tools組合せ・ルーティング(TSP/VRP)・制約プログラミング・MILP専用アルゴリズム、大規模ルーティングに強い
graph TD
  A["どんな問題?"] --> B{"線形か凸か離散か"}
  B -->|"LP 小規模/低レベル"| C["scipy.linprog"]
  B -->|"LP/MILP モデリング"| D["PuLP"]
  B -->|"凸 QP/SOCP/SDP"| E["cvxpy"]
  B -->|"組合せ/ルーティング"| F["OR-Tools"]

Pythonで同じLPを3ツールで解く

生産計画 LP(線形計画の標準形と幾何)を scipy・PuLP・cvxpy で解き、結果が一致することを確かめる。

import numpy as np

# scipy.optimize.linprog (低レベル: 行列で渡す。最小化なので符号反転)
from scipy.optimize import linprog
r = linprog([-40, -30], A_ub=[[2, 1], [1, 1]], b_ub=[120, 100],
            bounds=[(0, None), (0, None)], method="highs")
print(f"scipy : xA={r.x[0]:.0f}, xB={r.x[1]:.0f}, 利益={-r.fun:.0f}")

# PuLP (LP/MILPモデリング言語)
import pulp
p = pulp.LpProblem("p", pulp.LpMaximize)
xa = pulp.LpVariable("xa", lowBound=0); xb = pulp.LpVariable("xb", lowBound=0)
p += 40*xa + 30*xb
p += 2*xa + xb <= 120; p += xa + xb <= 100
p.solve(pulp.PULP_CBC_CMD(msg=0))
print(f"PuLP  : xA={xa.value():.0f}, xB={xb.value():.0f}, 利益={pulp.value(p.objective):.0f}")

# cvxpy (凸最適化モデリング言語)
import cvxpy as cp
x = cp.Variable(2, nonneg=True)
prob = cp.Problem(cp.Maximize(40*x[0] + 30*x[1]),
                  [2*x[0] + x[1] <= 120, x[0] + x[1] <= 100])
prob.solve()
print(f"cvxpy : xA={x.value[0]:.0f}, xB={x.value[1]:.0f}, 利益={prob.value:.0f}")

実行結果:

scipy : xA=20, xB=80, 利益=3200
PuLP  : xA=20, xB=80, 利益=3200
cvxpy : xA=20, xB=80, 利益=3200

3ツールとも同じ最適 (20,80)(20,80)、利益 3200。LP のような共通問題はどれでも解けるが、書き味が違う:scipy は行列を組む低レベル、PuLP/cvxpy は数式に近い。問題クラスが広がると選択が決まる ── 整数変数なら PuLP/OR-Tools、二次/錐なら cvxpy、ルーティングなら OR-Tools。

選び方の指針

数式の直観的意味

ツールの分かれ目は「問題の数理構造」そのもの。LP・凸(凸最適化 章目次)は多項式時間で大域最適が解けるので、モデリング言語(cvxpy/PuLP)が内部で適切なソルバー(シンプレックス・内点法、シンプレックス法内点法入門)へ渡せば済む。整数・組合せ(整数計画と組合せ最適化 章目次)は NP 困難なので、分枝カット(PuLP/CBC)や専用探索(OR-Tools)が要る。cvxpy が凸専用なのは、DCP(実装:cvxpyで凸問題を解く)で凸性を保証することで「解けば大域最適」を担保するため ── 非凸を弾くのは安全機構。つまりツール選択とは「自分の問題がどの問題クラスか」を見極める作業で、第1章の分類(最適化問題の分類)がそのまま実装の意思決定になる。良いモデラーは、解く前に「これは LP か、凸か、整数か、非凸か」を判定し、最も構造を活かせるツールを選ぶ。

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

関連ノート