サプライチェーン設計
🔥 Vibe プロンプト
「4つの候補都市から倉庫位置を決定し、サービスエリアを割り当て。賃料+輸送コストを最小化。」
サプライチェーン設計とは?
**サプライチェーン設計(施設配置問題)**は、倉庫や配送センターの最適な位置を決定し、需要を満たしながら総コストを最小化する問題です。
| 決定 | タイプ | |------|------| | どの倉庫を開くか? | バイナリ(開く/開かない) | | どれだけ出荷するか? | 連続値(数量) | | どの都市がどの倉庫から? | 派生(最短路割当) |
PuLPによる実装
import pulp
# データ
warehouses = ["台北", "台中", "高雄", "花蓮"]
cities = ["台北", "台中", "高雄", "台南", "桃園"]
fixed_cost = {"台北": 50, "台中": 30, "高雄": 25, "花蓮": 15}
capacity = {"台北": 10000, "台中": 8000, "高雄": 8000, "花蓮": 4000}
demand = {"台北": 3000, "台中": 2800, "高雄": 2500, "台南": 2000, "桃園": 2000}
# 輸送コスト(出荷単位あたり)
transport_cost = {
("台北","台北"):1, ("台北","台中"):3, ("台北","高雄"):5, ("台北","台南"):6, ("台北","桃園"):2,
("台中","台北"):3, ("台中","台中"):1, ("台中","高雄"):3, ("台中","台南"):4, ("台中","桃園"):3,
("高雄","台北"):5, ("高雄","台中"):3, ("高雄","高雄"):1, ("高雄","台南"):2, ("高雄","桃園"):5,
("花蓮","台北"):4, ("花蓮","台中"):4, ("花蓮","高雄"):5, ("花蓮","台南"):6, ("花蓮","桃園"):4,
}
prob = pulp.LpProblem("サプライチェーン設計", pulp.LpMinimize)
# 決定変数
select = {w: pulp.LpVariable(f"select_{w}", cat="Binary") for w in warehouses}
ship = {(w,c): pulp.LpVariable(f"ship_{w}_{c}", lowBound=0) for w in warehouses for c in cities}
# 目的: 固定費 + 輸送費の最小化
prob += (
pulp.lpSum(fixed_cost[w] * select[w] for w in warehouses) +
pulp.lpSum(transport_cost[(w,c)] * ship[(w,c)] for w in warehouses for c in cities)
)
# 制約1: 需要充足
for c in cities:
prob += pulp.lpSum(ship[(w,c)] for w in warehouses) >= demand[c]
# 制約2: 開いていない倉庫からは出荷不可
for w in warehouses:
prob += pulp.lpSum(ship[(w,c)] for c in cities) <= capacity[w] * select[w]
# 求解
prob.solve(pulp.PULP_CBC_CMD(msg=False))
# 結果
print(f"\n{'='*55}")
print(f"サプライチェーン設計 — {pulp.LpStatus[prob.status]}")
print(f"{'='*55}")
print(f"総コスト: ${pulp.value(prob.objective):.0f}K")
print(f"\n選択倉庫:")
for w in warehouses:
if select[w].value() == 1:
shipped = sum(ship[(w,c)].value() for c in cities)
util = shipped / capacity[w] * 100
print(f" ✅ {w}: 容量{capacity[w]}, 出荷{int(shipped)}, 稼働率{util:.0f}%")
print(f"\n出荷計画:")
print(f"{'From':<8} {'To':<8} {'数量':<8}")
for (w,c), var in ship.items():
if var.value() and var.value() > 0:
print(f"{w:<8} {c:<8} {int(var.value()):<8}")
まとめ
| 項目 | 詳細 | |------|------| | 問題 | 倉庫位置を決定し総コスト最小化 | | 変数 | バイナリ(選択)+ 連続(出荷量) | | 制約 | 需要充足、容量制限、論理リンク | | 目的 | 固定費 + 輸送費の最小化 | | 応用 | EC倉庫、工場配置、小売DC、食品物流 |
よくある問題と解決策
| 問題 | 原因 | 解決方法 | |------|------|---------| | 期待通りの結果が出ない | パラメータ設定ミス | デフォルト値と境界条件を確認 | | 実行が遅い | アルゴリズムの効率 | より効率的なデータ構造を使用 | | メモリ不足 | データ量過多 | バッチ処理を検討 | | デバッグが困難 | ログ不足 | 詳細なログ出力を追加 |
さらに学ぶには
- 公式ドキュメントを読む
- GitHubのオープンソース例を参照
- コミュニティディスカッションに参加
- コードを修正して結果の変化を観察