Contents
線形計画法の基礎と応用分野
線形計画法(Linear Programming: LP)は、制約条件下で目的関数を最適化する数学的技法です。製造業では原材料配分や生産スケジュールの最適化に、金融分野ではポートフォリオ最適化やリスク管理に応用されています。この記事では、Pythonで線形計画法ソルバを実装し、実際の業務に即したコード例を通じて理解を深めます。
適用分野の再整理
以下は、線形計画法が活かされる主要な応用分野です(他のセクションと重複しないように再編成):
- 製造業: 在庫管理・生産計画最適化(原料配分、機械割当など)
- 物流業界: 輸送経路の最短化(コスト削減、納期遵守)
- 金融: 投資ポートフォリオ最適化(リスク分散、リターン最大化)
Python環境構築とライブラリ導入
Pythonでの線形計画法実装には、SciPy, PuLP, OR-Toolsなどのライブラリが利用可能です。インストール方法とバージョン管理について確認しましょう。
pipによるインストール手順
最新版ライブラリを導入するには、以下のようにpip installします:
|
1 2 |
pip install scipy pulp python-or-tools |
注意点: バージョンによってAPIが変更されるため、公式ドキュメントで現在のバージョンを確認してください。
バージョン管理の注意点
- 仮想環境(
venvやconda)を使用し、依存関係を分離することを推奨します requirements.txtに明記し、プロジェクトごとのライブラリバージョンを統一しましょう
SciPy.optimize.linprogによる実装
SciPyのlinprogはシンプルなLP問題に適しています。製品生産計画の例を用いてコードを解説します。
シンプルな最大化問題のコード例
以下は、利益最大化工場の最適化問題です:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from scipy.optimize import linprog # 目的関数(利益係数) c = [-3, -4] # 最大化 → 負号を付けて最小化に変換(SciPyでは最小化のみサポート) # 制約条件(材料AとBの使用量制限) A_eq = [[2, 5], [4, 2]] # 等式制約 A*x = b b_eq = [30, 20] # 材料A: 30kg、材料B: 20kg # 変数は非負(生産量が0以上) bounds = [(0, None), (0, None)] result = linprog(c, A_eq=A_eq, b_eq=b_eq, bounds=bounds, method='highs') print("最適解:", result.x) print("最大利益:", -result.fun) # 負号を戻して最大化値を得る |
パラメータの詳細解説
c: 目的関数係数(最大化問題では符号反転が必要)A_eq,b_eq: 等式制約 $ Ax = b $bounds: 変数範囲(Noneで無限大を表す)method='highs': 高速なソルバを指定(最新版SciPyでの推奨オプション)
注意: SciPyの
linprogは最小化問題専用なので、最大化は目的関数に負号を付けて実装する必要があります。
PuLPによるモデル構築フロー
PuLPはモデリングに直感的なインターフェースを提供します。ステップバイステップでモデルを構築しましょう。
変数定義ステップ
以下の手順で変数と制約条件を定義できます:
- 問題インスタンスの作成:
LpProblem("名前", LpMaximize) - 変数の定義:
LpVariable("x", lowBound=0, upBound=None) - 目的関数と制約条件の追加:
prob += 3*x + 4*y
目的関数設定方法
以下は製品生産計画の例です:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from pulp import LpProblem, LpVariable, lpSum # 問題定義(最大化問題) prob = LpProblem("Production_Planning", LpMaximize) # 変数定義(製品A、Bの生産量) x = LpVariable("Product_A", 0) y = LpVariable("Product_B", 0) # 目的関数: 利益最大化 prob += 3*x + 4*y, "Total_Profit" # 実行と結果出力 prob.solve() print("最適解:", x.value(), y.value()) |
OR-Toolsでの線形計画ソルバ活用
OR-Toolsは大規模な問題にも対応可能です。輸送コスト最小化を例にコードを紹介します。
大規模問題への対応方法
以下の手順で変数と制約条件を設定します:
- ソルバの初期化:
solver = pywraplp.Solver.CreateSolver("GLOP") - 変数配列の作成:
x[i][j] = solver.NumVar(0, solver.infinity(), "") - 目的関数と制約条件の追加
複数ソルバの切り替え
OR-ToolsではGLOPやCBCなど複数のソルバが利用可能です:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
from ortools.linear_solver import pywraplp def solve_transport_problem(): solver = pywraplp.Solver.CreateSolver("GLOP") if not solver: return # 変数配列(2つの供給地、3つの需要地) x = [[solver.NumVar(0, solver.infinity(), "") for j in range(3)] for i in range(2)] # 供給量制約(供給地の生産量合計) for i in range(2): solver.Constraint(10, 10).Add( sum(x[i][j] for j in range(3)) == 10 ) # 需要量制約(需要地への納品量合計) for j in range(3): solver.Constraint(5, 5).Add( sum(x[i][j] for i in range(2)) == 5 ) # 目的関数: 輸送コスト最小化(例: 各ルートの単位コストが1) objective = solver.Objective() for i in range(2): for j in range(3): objective.SetCoefficient(x[i][j], 1) objective.SetMinimization() result_status = solver.Solve() if result_status == pywraplp.Solver.OPTIMAL: print("最適解:", [x[i][j].solution_value() for i in range(2) for j in range(3)]) |
ライブラリ比較と選定基準
各ライブラリの特徴を比較し、使い分け方を紹介します。
| 項目 | SciPy | PuLP | OR-Tools |
|---|---|---|---|
| 利点 | 速度が速い(HiGHS対応) | モデリングに直感的 | 大規模問題への強み |
| 欠点 | インターフェースがシンプル | 小規模な問題向け | 学習曲線が急峻 |
| 用途例 | 最適化問題の原型実装 | 教育・小規模モデル構築 | 輸送問題・スケジュール最適化 |
ビジネス実装向けの補足
技術的な側面に加え、企業での実装において重要な点を以下に整理しました:
業務実装における考慮事項
- ソルバの選定: 問題サイズに応じてSciPy(小規模)、OR-Tools(大規模)を選びましょう
- プロジェクト管理: モデル構築後、変数・制約の検証とテストを実施
- データ連携: 業務システムとAPIで連携し、リアルタイム最適化を可能に
まとめ
本記事では、Pythonで線形計画法を扱う主要なライブラリとその使い方について解説しました。以下の要点をおさらいしてください:
- SciPyは高速処理が可能で、シンプルな問題に向く
- PuLPはモデリングの柔軟性に優れ、教育や小規模実装に適している
- OR-Toolsは大規模最適化に強みがあり、企業での活用が広がっている
記事内のサンプルコードを実際に動かしてみよう。実装にあたっては最新版ライブラリを確認してください。