問題の分類¶
| 種類 | 変数 | 例 |
|---|---|---|
| 整数計画問題 (IP) | すべて整数 | 人員配置 |
| 0-1整数計画問題 (BIP) | 0 or 1 | ナップサック問題 |
| 混合整数計画問題 (MIP) | 整数+連続 | 施設配置 |
| 組合せ最適化 | 有限集合上の選択 | TSP、グラフ彩色 |
連続変数の問題をLP緩和(LP relaxation)と呼ぶ。LP緩和の最適値は元の整数計画の最適値の上界(最小化問題では下界)を与える。
代表的な問題¶
ナップサック問題:重量制約のもとで価値最大化 → knapsack_problem
最短路問題:グラフ上の最短経路 → shortest
_path _problem 巡回セールスマン問題(TSP):すべての都市を一度ずつ訪問する最短ルート
施設配置問題(facility location):コスト最小の施設配置と割り当て
グラフ彩色問題:隣接する頂点が異なる色になるよう最少色数で彩色
解法¶
厳密解法¶
分岐限定法(branch and bound)が最も広く使われる。LP緩和で上界(下界)を計算しながら、変数を整数に固定して探索木を枝刈りしていく。
LP緩和を解いて最適値の限界(bound)を得る
非整数の変数に対してとに分岐(branch)
子ノードのLP緩和の最適値が現在の最良解より悪ければ枝刈り
すべての変数が整数になったら実行可能解として更新
カット平面法(cutting plane method)は、LP緩和の実行可能領域を切る不等式(カット)を追加して整数解に収束させる方法。分岐限定法と組み合わせた分岐カット法(branch and cut)が現代ソルバーの基本手法。
動的計画法は部分問題への再帰で解く。ナップサック問題はで解ける(擬多項式時間)。
近似解法・ヒューリスティクス¶
厳密解が計算困難(NP困難)な場合に用いる。
| 手法 | 概要 |
|---|---|
| 貪欲法 | 局所的に最良な選択を繰り返す。高速だが最適保証なし |
| 局所探索法 | 現在の解の近傍を探索して改善。山登り法など |
| シミュレーテッドアニーリング | 確率的に悪化も受け入れて局所最適を脱出 |
| 遺伝的アルゴリズム | 解の集団を進化操作(交叉・突然変異)で改善 |
| 近似アルゴリズム | 最悪ケースで最適値の倍以内を保証(-近似) |
ソルバー¶
整数計画問題は PuLP や OR-Tools などで定式化し、バックエンドのソルバーに渡す。
PuLPによる定式化例¶
import pulp
# 問題の定義(最大化)
prob = pulp.LpProblem("example", pulp.LpMaximize)
# 変数(0-1整数)
x = [pulp.LpVariable(f"x{i}", cat="Binary") for i in range(3)]
# 目的関数
prob += 5 * x[0] + 4 * x[1] + 3 * x[2]
# 制約
prob += 2 * x[0] + 3 * x[1] + x[2] <= 5
# 求解
prob.solve(pulp.PULP_CBC_CMD(msg=0))
for v in prob.variables():
print(f"{v.name} = {v.varValue}")
# => x0=1, x1=1, x2=0 (value=9)