スポンサーリンク

【Python】線形最適化を分かりやすくまとめ 生産計画・配送ルートのモデル例

記事内に広告が含まれています。

線形最適化についてまとめ、Pythonを使って、基本的な線形最適化問題を解いてみます。

後半に参考書籍も紹介しています。

スポンサーリンク

線形最適化とは?

線形最適化(Linear Programming)とは、「ある目的を最大化または最小化するために、複数の条件(制約)のもとで最適な値を求める数学的手法」です。

「限られた資源(お金・時間・材料など)をうまく配分して、利益を最大にしたり、コストを最小にしたりする方法」です。

線形最適化は、さまざまな分野で使われています。

例を挙げます。

  • 製造業
    限られた工場ラインや原材料で、最も利益が出る製品構成を決める
  • 物流
    トラックの積載量や移動時間の制約を守りながら、最短ルートで配送する
  • マーケティング
    限られた広告予算で、最も効果の高い媒体に配分する
  • ダイエットプラン
    摂取カロリーや栄養バランスの条件を満たしつつ、食費を最小化する

これらの問題はすべて「目的関数(最大化・最小化)」と「制約条件(~しなければならない)」を数式で表せば、線形最適化で解くことができます。

なぜ「線形」なのか?
「目的関数」や「制約条件」がすべて一次式(=直線で表される式)だからです。
たとえば 3x + 4yx + 2y ≤ 8 は直線を表します。このように「変数の次数が1である」ことが、線形最適化の特徴です。

スポンサーリンク

線形最適化の数学的理解

一般的に線形最適化問題は以下の式で表されます。

\(\text{minimize }cTx\)
\(\text{subject to }Ax ≤ b, x∈ℝ\)

\(\text{minimize }\)の後に記載されているのが最適化対象の目的関数、\(\text{subject to }\)の後ろに記載されているのが制約条件です。

\(x\) は変数のベクトル、目的関数の係数が\(c\)(ベクトル)、制約式の係数が\(A\)(行列)です。\(b\) は制約式の定数です。

目的関数が線形関数、制格式が線形式で、制約式で表される制約条件のもとに、目的関数を最小化(または最大化)する変数の値を見つける問題が線形最適化問題です。

目的関数(Objective Function)

最大化 or 最小化したい式(例:利益、距離、コストなど)
例:\(\text{maximize }3x + 4y\)

制約条件(Constraints)

満たさなければならない制約(材料の量や時間など)
例:\(x + 2y ≤ 8 x ≥ 0 y ≥ 0\)

これらを満たす \(x, y\) の最適な組み合わせ を求めます。

生産計画の最適化

例題

今回は以下の問題を解いてみます。

下表の原料でサンドイッチを製造して販売します。パンは何枚でも使えるとします。

ハム1000枚
レタス5 kg
チーズ400枚

下表の3種類のサンドイッチを製造する場合、各サンドイッチを何個ずつ製造、販売すれば売上げを最大化できるかという問題を解いてみます。「レタスサンドは人気がなさすぎて作っても売れない」というようなことは考えません。

サンドイッチ売価ハムレタスチーズ
レタスサンド150円2枚15 g
ハム2倍サンド200円4枚10 g
チーズレタスハムサンド300円2枚10 g2枚
各サンドイッチの売価と原料使用量

レタスサンドを \(x_{1}\)個、ハム2倍サンドを \(x_{2}\)個、チーズレタスサンドを \(x_{3}\)個製造する場合、目的関数は売価の最大化のため、以下のとおりとなります。

\(\text{maximize}\)
\(50 × x_{1} + 200 × x_{2} + 300 × x_{3}\)

制約式は各原料の使用量に上限があるため、以下のとおりとなります。

\(\text{subject to}\)
\(2 × x_{1} + 4 × x_{2} + 2 × x_{3} ≤ 1000\)
\(15 × x_{1} + 10 × x_{2} + 10 × x_{3} ≤ 5000\)
\(2 × x_{3} ≤ 400\)

Python実装

動作確認したpython、モジュールのバージョンは以下のとおりです。

python 3.6.0
mypulp 0.0.9

Pythonで実装します。mypulpというモジュールを使用するため、インストールしておきます。

pip install mypulp

続いて最適化計算を実装します。

from mypulp import *

# モデル生成
model = Model()

# 変数生成
# vtype='C'は連続変数(デフォルトも'C')
x1 = model.addVar(vtype='C', name='x1_Lettuce')
x2 = model.addVar(vtype='C', name='x2_Double_Ham')
x3 = model.addVar(vtype='C', name='x3_Cheese_Lettuce_Ham')

# 変数宣言後updateする
model.update()

# 目的関数
model.setObjective(150 * x1 + 200 * x2 + 300 * x3, GRB.MAXIMIZE)

# 制約
model.addConstr(2 * x1 + 4 * x2 + 2 * x3 <= 1000)
model.addConstr(15 * x1 + 10 * x2 + 10 * x3 <= 5000)
model.addConstr(2 * x3 <= 400)

# 最適化計算
model.optimize()

# 計算結果を出力
print('Sales', ':', model.ObjVal)
for v in model.getVars():
    print(v.VarName, ':', v.X)

コードの実行結果は以下のとおりです。

Sales : 97500.0
x1_Lettuce : 150.0
x2_Double_Ham : 75.0
x3_Cheese_Lettuce_Ham : 200.0

レタスサンド150個、ハム2倍サンド75個、チーズレタスハムサンド200個を製造することで、売上げが97,500円に最大化されることがわかります。

物流における配送ルート最適化

線形最適化は、物流業界でも非常に重要な役割を果たしています。

特に「配送ルートの最適化」は、コスト削減・納期短縮・燃料効率向上といった観点から、多くの企業で導入されています。

課題例 複数の店舗への配送

たとえば、以下のような状況を考えてみます。

  • ある物流センターから、複数の店舗に商品を配送したい。
  • 各店舗には異なる数量の需要がある。
  • トラックの積載量には上限がある。
  • 移動距離が短いほど、燃料費や人件費が抑えられる。

このときに、「どのトラックがどの店舗に、どのルートで配送すべきか?」をうまく決めることで、全体の配送コストを最小限に抑えることができます。

線形最適化でのモデル化

この課題は以下のように線形最適化で表現できます。

変数

\(x_{ij}\)​ … トラック \(i\) が店舗 \(j\) に配送する荷物の量

目的関数(最小化)

総移動距離 × 単位コスト(または時間、CO2排出量など)

$$\text{minimize} ∑ distance_{ij} × x_{ij}$$

制約条件

各トラックの積載量を超えない

$$∑ x_{ij} ≤ 容量_{i}$$

各店舗の需要を満たす

$$∑ x_{ij} ≥ 需要_{j}$$

負の値(マイナスの荷物)にならない

$$x_{ij} ≥ 0$$

参考書籍

こちらの本を参考にしました。Pythonでの最適化計算の方法やビジネスへの応用について、詳しく書かれています。

まとめ

基本的な線形最適化問題、Pythonコードをまとめました。Pythonについては、モジュールを利用することですぐに最適化計算を行うことができます。

タイトルとURLをコピーしました