供應鏈網路設計
問題描述
你是一家中型電商的老闆,要決定在台灣設立幾個倉庫、分別在哪個城市、每個倉庫服務哪些區域,才能讓總成本(倉庫租金 + 運輸成本)最低?
設施選址問題 (Facility Location Problem)
import pulp
import math
# === 候選倉庫位置 ===
warehouses = ["台北", "台中", "高雄", "花蓮"]
# === 服務城市 ===
cities = ["台北", "新北", "桃園", "新竹", "台中", "彰化", "雲林",
"嘉義", "台南", "高雄", "屏東", "宜蘭", "花蓮", "台東"]
# === 資料 ===
# 倉庫固定成本(月租金,萬元)
fixed_cost = {"台北": 50, "台中": 30, "高雄": 25, "花蓮": 15}
# 倉庫容量(件/月)
capacity = {"台北": 10000, "台中": 8000, "高雄": 8000, "花蓮": 4000}
# 城市需求(件/月)
demand = {
"台北": 3000, "新北": 2500, "桃園": 2000, "新竹": 1500,
"台中": 2800, "彰化": 1200, "雲林": 800, "嘉義": 1000,
"台南": 2000, "高雄": 2500, "屏東": 800, "宜蘭": 600,
"花蓮": 500, "台東": 300
}
# 運輸成本(每件每公里)
cost_per_km_per_unit = 0.5
# 距離矩陣(公里)
distance = {
("台北", "台北"): 0, ("台北", "新北"): 20, ("台北", "桃園"): 40,
("台北", "新竹"): 80, ("台北", "台中"): 180, ("台北", "彰化"): 200,
("台北", "雲林"): 240, ("台北", "嘉義"): 260, ("台北", "台南"): 310,
("台北", "高雄"): 350, ("台北", "屏東"): 370, ("台北", "宜蘭"): 60,
("台北", "花蓮"): 180, ("台北", "台東"): 350,
("台中", c): abs(distance.get(("台北", c), 999) - 180) if distance.get(("台北", c)) else 999
for c in cities
}
# 建立問題
prob = pulp.LpProblem("供應鏈網路設計", pulp.LpMinimize)
# 變數:y[w] = 1 表示選擇倉庫 w
select = {w: pulp.LpVariable(f"select_{w}", cat="Binary") for w in warehouses}
# 變數:x[w][c] = 從倉庫 w 運送到城市 c 的數量
ship = {}
for w in warehouses:
for c in cities:
ship[(w, c)] = pulp.LpVariable(f"ship_{w}_{c}", lowBound=0, cat="Continuous")
# 目標:總成本 = 倉庫固定成本 + 運輸成本
prob += (
pulp.lpSum(fixed_cost[w] * select[w] for w in warehouses) +
pulp.lpSum(ship[(w, c)] * distance.get((w, c), 999) * cost_per_km_per_unit
for w in warehouses for c in cities)
)
# 限制:每個城市的需求必須滿足
for c in cities:
prob += pulp.lpSum(ship[(w, c)] for w in warehouses) >= demand[c]
# 限制:倉庫產能限制
for w in warehouses:
prob += pulp.lpSum(ship[(w, c)] for c in cities) <= capacity[w] * select[w]
# 求解
prob.solve()
print(f"\n=== 供應鏈網路設計結果 ===")
print(f"求解狀態: {pulp.LpStatus[prob.status]}")
print(f"總成本: {pulp.value(prob.objective):.2f} 萬元/月")
print(f"\n選擇的倉庫:")
for w in warehouses:
if select[w].value() == 1:
print(f" ✅ {w} (固定成本: {fixed_cost[w]} 萬元/月)")
print(f"\n配送計畫:")
for w in warehouses:
if select[w].value() == 1:
total = sum(ship[(w, c)].value() for c in cities)
print(f"\n{w} 倉庫 (總出貨: {int(total)} 件):")
for c in cities:
qty = ship[(w, c)].value()
if qty and qty > 0:
dist_val = distance.get((w, c), 999)
cost = qty * dist_val * cost_per_km_per_unit
print(f" → {c}: {int(qty)} 件 (距離 {dist_val}km, 運費 {cost:.0f} 元)")