Mímisbrunnr知恵の泉

← 数理最適化 一覧

🎓 レベル:基礎 | 重要度:A(必須)

📎 前提:最適化問題とは | 関連:定式化の技法

要点(BLUF)

概念 ── 翻訳の3ステップ

最適化を解く前に、問題を数式にしなければならない。ここで失敗すると、どんな高性能ソルバーも無意味。翻訳は必ず次の順序で行う。

  1. 決定変数:こちらが「決められる量」は何か。単位・範囲・連続/整数を明示する。
  2. 目的関数:その変数の関数として「最良の物差し」を1つ書く。
  3. 制約:守るべき条件をすべて不等式・等式で書く(資源・需要・論理・非負)。

具体例 ── 2製品の生産計画

ある工場が製品 A・B を作る。利益は A が1個 40、B が1個 30。各製品は機械時間と材料を消費する。資源は限られている。利益最大の生産量は?

ステップ1:決定変数

xA0,xB0(製品 A・B の生産量、連続とする)x_A \ge 0,\quad x_B \ge 0 \quad (\text{製品 A・B の生産量、連続とする})

ステップ2:目的関数(利益最大化)

max 40xA+30xB\max\ 40 x_A + 30 x_B

ステップ3:制約(機械時間 ≤ 120、材料 ≤ 100)

2xA+1xB120(機械時間)1xA+1xB100(材料)xA,xB0\begin{aligned} 2 x_A + 1 x_B &\le 120 \quad (\text{機械時間}) \\ 1 x_A + 1 x_B &\le 100 \quad (\text{材料}) \\ x_A,\, x_B &\ge 0 \end{aligned}

これで現実の言葉が完全に線形計画になった。実体は第2章 線形計画の標準形と幾何 で解く。

Pythonで解いて翻訳を確認

翻訳が正しいか、scipy.optimize.linprog で解いて確かめる。linprog は 最小化なので、利益最大化は符号反転して与える(最適化問題とは の変換)。

import numpy as np
from scipy.optimize import linprog

# linprog は最小化なので、利益最大化 max 40xA+30xB は -利益を最小化する
c = [-40, -30]            # 目的(符号反転)
A_ub = [[2, 1],           # 機械時間 2xA + 1xB <= 120
        [1, 1]]           # 材料     1xA + 1xB <= 100
b_ub = [120, 100]
bounds = [(0, None), (0, None)]  # xA, xB >= 0

res = linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=bounds, method="highs")
xA, xB = res.x
print(f"最適生産量: xA={xA:.1f}, xB={xB:.1f}")
print(f"最大利益: {-res.fun:.1f}")  # 符号を戻す

実行結果:

最適生産量: xA=20.0, xB=80.0
最大利益: 3200.0

A を 20、B を 80 作ると利益 3200 が最大。検算:機械時間 220+80=1202\cdot20+80=120(ぴったり使い切り)、材料 20+80=10020+80=100(使い切り)。**両資源が制約として「効いている」**から、ここが頂点最適になっている(線形計画の標準形と幾何)。

良いモデルの作法

数式の直観的意味

なぜ「変数 → 目的 → 制約」の順なのか。変数が決まらないと目的も制約も書けない(すべて変数の関数だから)。変数の 定義域(連続か整数か、範囲)が、そのまま問題クラス(最適化問題の分類)を決める。つまりモデリングの最初の一手(変数の選び方)が、解きやすさをほぼ決めてしまう。同じ現実でも、変数の取り方次第で線形にも非線形にもなる ── ここがモデラーの腕の見せ所。

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

関連ノート