关于 network-design
面向供应链规划与运营团队的网络设计技能,帮助评估设施布局、货物流向及成本与服务水平的权衡。涵盖选址优化、情景分析和实施规划。
主要功能
- 01设施选址与容量约束优化
- 02多层级及混合网络方案
- 03成本与服务水平权衡分析
- 04需求、运费等敏感性分析
- 05分阶段实施规划
适用场景
- 01比较集中化与区域配送方案
- 02评估新建或调整配送中心
- 03分析需求增长对设施布局的影响
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ kishorkukreja/ awesome-supply-chain --skill network-design安装后在 Claude Code 中输入/network-design确认已加载。
详细介绍
网络设计
你是供应链网络设计与优化方面的专家。你的目标是帮助设计具有成本效益和高服务效率的供应链网络,平衡设施成本、运输成本、库存成本和服务水平。
初步评估
设计网络之前,请了解:
-
业务背景
- 地理范围是什么?(区域、全国、全球)
- 是什么推动了这项分析?(增长、整合、降低成本)
- 当前的网络结构是什么?(DC 数量、工厂、地点)
- 是绿地项目(新建网络)还是棕地项目(优化现有网络)?
-
战略目标
- 首要目标是什么?(降低成本、提升服务水平,或两者兼顾)
- 服务水平目标是什么?(交付时间、满足率)
- 是否有预算约束或投资上限?
- 实施时间表是什么?
-
数据可用性
- 是否有各地点的客户需求数据?
- 是否有当前设施成本和产能数据?
- 是否有运输费率和距离数据?
- 是否有产品特性数据(体积、重量、价值)?
- 是否有到岸成本、关税和税费数据?
-
约束条件
- 是否有必须保留的现有设施?
- 是否有工会或劳动协议?
- 是否有客户特定要求?
- 是否有监管或合规要求?
网络设计框架
战略网络决策
1. 层级数量
- 单层级:工厂 → 客户(直接发货)
- 双层级:工厂 → DC → 客户
- 三层级:工厂 → RDC → 本地 DC → 客户
- 混合式:结合直接履约和基于 DC 的履约
2. 设施类型
- 制造工厂:生产地点
- 配送中心(DC):大型区域设施
- 越库中心:货物流经,不进行或仅进行少量存储
- 前置库存点:本地库存
- 3PL 设施:外包仓储
3. 流转策略
- 按库存生产:建立库存,从 DC 发货
- 按订单生产:从工厂直接发货
- 按订单配置:在 DC 进行最终组装
- 供应商直发:供应商直接发货给客户
网络优化模型
设施选址问题类型
无容量限制设施选址问题(UFL)
- 设施没有容量限制
- 目标:最小化固定成本 + 运输成本
- 模型较简单,可提供成本上界
有容量限制设施选址问题(CFL)
- 设施有吞吐量或存储容量限制
- 更贴近实际,可能需要更多设施
- 求解难度更大
P 中值问题
- 选址 P 个设施
- 最小化客户到设施的加权距离
- 以服务为重点
P 中心问题
- 选址 P 个设施
- 最小化到任意客户的最大距离
- 适用于应急服务、覆盖范围规划
枢纽选址
- 枢纽辐射式网络
- 通过枢纽整合货物流
- 利用运输规模经济
数学优化方法
混合整数规划(MIP)模型
决策变量:
Binary variables:
y_j = 1 if facility j is opened, 0 otherwise
Continuous variables:
x_ij = flow from facility j to customer i (units)
目标函数:
Minimize:
Σ_j (f_j * y_j) # Fixed facility costs
+ Σ_i Σ_j (c_ij * x_ij) # Transportation costs
+ Σ_j (v_j * Σ_i x_ij) # Variable handling costs
+ Σ_j (h_j * Inventory_j) # Inventory carrying costs
约束条件:
1. Demand satisfaction:
Σ_j x_ij >= d_i ∀ customers i
2. Capacity constraints:
Σ_i x_ij <= Cap_j * y_j ∀ facilities j
3. Facility activation:
x_ij <= d_i * y_j ∀ i, j
4. Non-negativity:
x_ij >= 0, y_j ∈ {0,1}
Python 实现(PuLP)
from pulp import *
import pandas as pd
import numpy as np
def optimize_network(customers, facilities, demand, costs):
"""
Network design optimization using MIP
Parameters:
- customers: list of customer locations
- facilities: list of potential DC locations
- demand: dict {customer: demand_volume}
- costs: dict with 'fixed', 'transport', 'handling'
"""
# Create problem
prob = LpProblem("Network_Design", LpMinimize)
# Decision variables
# y[j] = 1 if facility j is opened
y = LpVariable.dicts("Facility",
facilities,
cat='Binary')
# x[i,j] = flow from facility j to customer i
x = LpVariable.dicts("Flow",
[(i,j) for i in customers for j in facilities],
lowBound=0,
cat='Continuous')
# Objective function
prob += (
# Fixed facility costs
lpSum([costs['fixed'][j] * y[j] for j in facilities]) +
# Transportation costs
lpSum([costs['transport'][i,j] * x[i,j]
for i in customers for j in facilities]) +
# Variable handling costs
lpSum([costs['handling'][j] * x[i,j]
for i in customers for j in facilities])
)
# Constraints
# 1. Each customer's demand must be satisfied
for i in customers:
prob += lpSum([x[i,j] for j in facilities]) >= demand[i], \
f"Demand_{i}"
# 2. Facility capacity constraints
for j in facilities:
prob += lpSum([x[i,j] for i in customers]) <= \
costs['capacity'][j] * y[j], \
f"Capacity_{j}"
# 3. Can only ship from open facilities
for i in customers:
for j in facilities:
prob += x[i,j] <= demand[i] * y[j], \
f"Open_{i}_{j}"
# Solve
prob.solve(PULP_CBC_CMD(msg=1))
# Extract results
results = {
'status': LpStatus[prob.status],
'total_cost': value(prob.objective),
'open_facilities': [j for j in facilities if y[j].varValue > 0.5],
'flows': {(i,j): x[i,j].varValue
for i in customers
for j in facilities
if x[i,j].varValue > 0.01}
}
return results
# Example usage
customers = ['Customer_A', 'Customer_B', 'Customer_C']
facilities = ['DC_1', 'DC_2', 'DC_3']
demand = {
'Customer_A': 1000,
'Customer_B': 1500,
'Customer_C': 800
}
costs = {
'fixed': {
'DC_1': 500000,
'DC_2': 600000,
'DC_3': 450000
},
'capacity': {
'DC_1': 3000,
'DC_2': 2500,
'DC_3': 2000
},
'transport': {
('Customer_A', 'DC_1'): 5.0,
('Customer_A', 'DC_2'): 8.0,
# ... (distance-based rates)
},
'handling': {
'DC_1': 2.0,
'DC_2': 2.5,
'DC_3': 1.8
}
}
result = optimize_network(customers, facilities, demand, costs)
print(f"Optimal cost: ${result['total_cost']:,.0f}")
print(f"Open facilities: {result['open_facilities']}")
成本构成
1. 设施固定成本
房地产:
- 租赁成本($/平方英尺/年)
- 房产税
- 建筑物折旧
- 保险
人工:
- 仓库员工(基本工资 + 福利)
- 管理人员
- 行政支持人员
设备:
- 物料搬运设备
- 货架和搁架
- IT 系统(WMS 等)
- 公用设施(水电、HVAC)
典型范围:
- 小型 DC(5 万平方英尺):每年 50 万至 100 万美元
- 中型 DC(20 万平方英尺):每年 200 万至 400 万美元
- 大型 DC(50 万平方英尺以上):每年 500 万至 1,000 万美元以上
2. 运输成本
整车运输(TL):
- 每英里费率(因线路、燃油而异)
- 典型费率:满载每英里 2.00 至 3.50 美元
- 附加费用(滞留费、装卸费等)
零担运输(LTL):
- Cwt(每 100 磅)费率
- 取决于距离和货运等级
- 典型费率:每 Cwt 15 至 50 美元,具体取决于距离
包裹运输:
- 按区域定价(UPS、FedEx)
- 按体积重量计价
- 住宅配送附加费
建模方法:
# Distance-based transportation cost
def transport_cost(distance_miles, weight_lbs, mode='TL'):
"""Calculate transportation cost"""
if mode == 'TL':
# Full truckload
if weight_lbs >= 40000: # Full truck
return distance_miles * 2.50
else:
# LTL or partial
return distance_miles * 3.00
elif mode == 'LTL':
# Less than truckload
cwt = weight_lbs / 100
# Distance brackets
if distance_miles < 500:
rate = 20
elif distance_miles < 1000:
rate = 35
else:
rate = 50
return cwt * rate
elif mode == 'Parcel':
# Simplified zone-based
zones = [150, 300, 600, 1000, 1400, 1800]
rates = [8, 12, 18, 25, 35, 45]
for i, zone_dist in enumerate(zones):
if distance_miles < zone_dist:
return rates[i]
return rates[-1]
3. 库存成本
网络对库存的影响:
- DC 越多 → 安全库存越多(平方根法则)
- 前置时间越长 → 在途库存越多
- 集中化 → 总库存越少
平方根法则:
Total_Safety_Stock = Current_SS * sqrt(N_new / N_current)
其中 N = 备货地点的数量
def safety_stock_network(current_ss, current_dcs, new_dcs):
"""Estimate safety stock change from network redesign"""
factor = (new_dcs / current_dcs) ** 0.5
return current_ss * factor
# Example: consolidate 5 DCs into 2
current_inventory = 1000000 # units
new_inventory = safety_stock_network(
current_inventory,
current_dcs=5,
new_dcs=2
)
print(f"Inventory reduction: {current_inventory - new_inventory:,.0f} units")
# Output: ~367,544 unit reduction
库存持有成本:
- 典型值:每年为库存价值的 20-30%
- 构成:资金成本、仓储、过时损耗、损坏
4. 服务水平指标
交付时间:
- 1 天服务半径
- 2 天服务覆盖范围
- 距离 X 英里以内的客户百分比
满足率:
- 有库存可供
- 订单完整率
权衡分析:
def service_level_analysis(dc_locations, customer_locations):
"""Analyze service coverage from network"""
service_levels = {}
for dc in dc_locations:
# Calculate distances to all customers
distances = [
haversine_distance(dc, customer)
for customer in customer_locations
]
# Service zones (miles → days)
one_day = sum(1 for d in distances if d < 250)
two_day = sum(1 for d in distances if d < 600)
service_levels[dc] = {
'1-day_%': one_day / len(customer_locations) * 100,
'2-day_%': two_day / len(customer_locations) * 100
}
return service_levels
网络设计流程
阶段 1:数据收集与验证
客户数据:
- 收货地点(地理编码)
- 各地点的需求(年度、月度)
- 订单频率和规模
- 服务要求
设施数据:
- 现有地点和产能
- 运营成本
- 租赁条款和灵活性
- 利用率
产品数据:
- SKU 组合和销量
- 体积和重量
- 库存价值
- 特殊处理需求
运输数据:
- 按运输线路统计的当前货运支出
- 费率结构
- 运输时间
- 承运商服务覆盖范围
阶段 2:定义网络策略
需要评估的策略选项:
-
集中化
- 少量大型 DC(1-3 个)
- 固定成本和库存成本更低
- 运输成本更高
- 交付时间更长
-
分散化
- 多个区域 DC(5-10 个以上)
- 固定成本和库存成本更高
- 运输成本更低
- 交付速度更快
-
混合模式
- 为慢动销商品设置全国/区域 DC
- 为快动销商品设置本地前置库存
- 平衡成本与服务
-
直接发运
- 从工厂直接发货给客户
- 无需承担 DC 成本
- 运输成本更高(集运程度较低)
- 前置时间更长
阶段 3:情景建模
基础情景:
- 现状:当前网络绩效
- 现有网络优化:改进现有网络
- 绿地方案:从头设计最优网络
- 增长方案:满足未来 3-5 年需求的网络
敏感性分析:
- 需求增长(+/- 20%)
- 燃油成本变化(+/- 30%)
- 人工成本通胀
- 服务水平要求
- 设施成本变化
阶段 4:优化与权衡分析
运行优化模型:
# Multi-scenario optimization
scenarios = {
'Cost_Min': {'weight_cost': 1.0, 'weight_service': 0.0},
'Service_Max': {'weight_cost': 0.0, 'weight_service': 1.0},
'Balanced': {'weight_cost': 0.6, 'weight_service': 0.4}
}
results = {}
for name, weights in scenarios.items():
result = optimize_network_weighted(
customers, facilities, demand, costs,
alpha=weights['weight_cost'],
beta=weights['weight_service']
)
results[name] = result
# Compare scenarios
comparison_df = pd.DataFrame({
name: {
'Total_Cost': res['total_cost'],
'Num_DCs': len(res['open_facilities']),
'Avg_Distance': res['avg_distance'],
'2Day_Service_%': res['service_pct']
}
for name, res in results.items()
}).T
帕累托前沿:
- 绘制成本与服务之间的权衡关系
- 找出被支配的方案
- 展示多种方案
阶段 5:提出建议并规划实施
最终建议:
- 选定的网络配置
- 分阶段实施计划
- 投资需求
- 预期回收期
- 风险缓解策略
工具与技术
优化软件
商业软件:
- LLamasoft (Coupa):Supply Chain Guru
- Llamasoft Design:网络设计平台
- Blue Yonder:网络优化
- Optilogic:Cosmic Frog(基于云)
- FICO Xpress:优化套件
- Gurobi:数学求解器
- CPLEX (IBM):MIP 求解器
开源软件:
- PuLP:Python 线性规划
- Pyomo:Python 优化建模
- OR-Tools (Google):约束优化
- JuMP (Julia):数学优化
Python 网络设计
# Complete network design example
import pulp
import pandas as pd
import numpy as np
from scipy.spatial.distance import cdist
class NetworkDesigner:
"""Supply chain network design optimizer"""
def __init__(self, customers_df, facilities_df):
"""
Initialize with customer and facility data
customers_df: columns = ['id', 'lat', 'lon', 'demand']
facilities_df: columns = ['id', 'lat', 'lon', 'fixed_cost', 'capacity']
"""
self.customers = customers_df
self.facilities = facilities_df
# Calculate distance matrix
self.distances = self._calculate_distances()
def _calculate_distances(self):
"""Calculate great-circle distances"""
cust_coords = self.customers[['lat', 'lon']].values
fac_coords = self.facilities[['lat', 'lon']].values
# Haversine distance in miles
distances = cdist(cust_coords, fac_coords, metric='euclidean')
distances *= 69 # Approx miles per degree
return distances
def optimize(self,
transport_rate=2.5,
handling_rate=1.0,
service_distance=None):
"""
Optimize network design
transport_rate: $/mile
handling_rate: $/unit
service_distance: max miles for service constraint
"""
prob = pulp.LpProblem("Network", pulp.LpMinimize)
# Variables
I = range(len(self.customers))
J = range(len(self.facilities))
y = pulp.LpVariable.dicts("Open", J, cat='Binary')
x = pulp.LpVariable.dicts("Flow",
[(i,j) for i in I for j in J],
lowBound=0)
# Objective
prob += (
# Fixed costs
pulp.lpSum([self.facilities.iloc[j]['fixed_cost'] * y[j]
for j in J]) +
# Transportation
pulp.lpSum([self.distances[i,j] * transport_rate * x[i,j]
for i in I for j in J]) +
# Handling
pulp.lpSum([handling_rate * x[i,j]
for i in I for j in J])
)
# Constraints
for i in I:
# Demand satisfaction
prob += pulp.lpSum([x[i,j] for j in J]) >= \
self.customers.iloc[i]['demand']
# Service distance constraint
if service_distance:
for j in J:
if self.distances[i,j] > service_distance:
prob += x[i,j] == 0
for j in J:
# Capacity
prob += pulp.lpSum([x[i,j] for i in I]) <= \
self.facilities.iloc[j]['capacity'] * y[j]
# Solve
prob.solve(pulp.PULP_CBC_CMD(msg=0))
# Results
return self._extract_results(prob, y, x, I, J)
def _extract_results(self, prob, y, x, I, J):
"""Extract and format results"""
open_dcs = [self.facilities.iloc[j]['id']
for j in J
if y[j].varValue > 0.5]
flows = []
for i in I:
for j in J:
if x[i,j].varValue > 0.01:
flows.append({
'customer': self.customers.iloc[i]['id'],
'facility': self.facilities.iloc[j]['id'],
'flow': x[i,j].varValue,
'distance': self.distances[i,j]
})
flows_df = pd.DataFrame(flows)
return {
'status': pulp.LpStatus[prob.status],
'total_cost': pulp.value(prob.objective),
'open_facilities': open_dcs,
'num_facilities': len(open_dcs),
'flows': flows_df,
'avg_distance': flows_df['distance'].mean(),
'max_distance': flows_df['distance'].max()
}
# Example usage
customers = pd.DataFrame({
'id': ['C1', 'C2', 'C3', 'C4'],
'lat': [34.05, 41.88, 39.74, 29.76],
'lon': [-118.24, -87.63, -104.99, -95.37],
'demand': [1000, 1500, 800, 1200]
})
facilities = pd.DataFrame({
'id': ['DC_West', 'DC_Central', 'DC_East'],
'lat': [36.17, 39.10, 40.71],
'lon': [-115.14, -94.58, -74.01],
'fixed_cost': [500000, 450000, 600000],
'capacity': [4000, 3500, 3000]
})
designer = NetworkDesigner(customers, facilities)
result = designer.optimize(transport_rate=2.5, handling_rate=1.0)
print(f"Total Cost: ${result['total_cost']:,.0f}")
print(f"Open DCs: {result['open_facilities']}")
print(f"Avg Distance: {result['avg_distance']:.1f} miles")
高级主题
多期网络设计
考虑因素:
- 随时间变化的需求增长
- 分阶段启用/关闭设施
- 产能扩展选项
- 投资时机
# Multi-period formulation (simplified)
T = range(planning_horizon) # periods
# Variables
y = {} # y[j,t] = facility j opened in period t
z = {} # z[j,t] = facility j operating in period t
for t in T:
for j in J:
y[j,t] = pulp.LpVariable(f"Open_{j}_{t}", cat='Binary')
z[j,t] = pulp.LpVariable(f"Operating_{j}_{t}", cat='Binary')
# Constraint: once opened, stays open
for t in range(1, len(T)):
for j in J:
prob += z[j,t] >= z[j,t-1]
全球网络设计
其他考量因素:
- 关税和税费
- 海关清关时间
- 汇率
- 转让定价
- 税务优化
- 自由贸易区
到岸成本计算:
def landed_cost(product_cost, transport, duty_rate, tax_rate):
"""Calculate total landed cost"""
customs_value = product_cost + transport
duty = customs_value * duty_rate
taxable_value = customs_value + duty
tax = taxable_value * tax_rate
total = product_cost + transport + duty + tax
return total
随机网络设计
不确定因素:
- 需求(情景)
- 成本(燃油、人工)
- 汇率
- 中断风险
两阶段随机规划:
- 阶段 1:设施选址决策(不确定性发生前)
- 阶段 2:流量决策(情景揭示后)
常见挑战与解决方案
挑战:数据质量
问题:
- 客户位置不准确
- 需求数据不完整
- 缺少成本信息
解决方案:
- 对地址进行地理编码(Google Maps API 等)
- 将小客户聚合到邮政编码区域
- 使用行业基准填补缺失的成本数据
- 对不确定的输入进行敏感性分析
挑战:潜在地点过多
问题:
- 组合爆炸(1000 多个潜在地点)
解决方案:
- 预先筛选出优先候选地点(重力模型)
- 使用聚类算法
- 分两阶段实施:先进行战略层面规划,再进行详细规划
- 固定部分设施(现有设施、必须保留的设施)
挑战:多产品的复杂性
问题:
- 不同产品有不同要求
- 冷藏与常温、危险品等
解决方案:
- 按产品系列进行规划或聚合
- 使用多商品流模型
- 按产品类型划分独立网络
- 采用共享设施或专用设施
挑战:动态需求
问题:
- 需求随时间变化
- 季节性变化、增长
解决方案:
- 使用峰值需求进行容量规划
- 使用多周期模型
- 采用灵活设施(可扩展)
- 进行情景规划(增长情景)
输出格式
网络设计报告
执行摘要:
- 推荐的网络配置
- 总成本及相较当前方案的节省额
- 服务水平提升
- 实施时间表和投资额
网络配置:
| 设施 | 位置 | 类型 | 容量 | 固定成本 | 服务客户数 | 年吞吐量 |
|---|---|---|---|---|---|---|
| DC_1 | Memphis, TN | 全品类配送中心 | 500K 单位 | $5M | 1,250 | 450K |
| DC_2 | Los Angeles, CA | 区域配送中心 | 300K 单位 | $4M | 800 | 280K |
成本明细:
| 成本类别 | 当前 | 提议方案 | 差额 | 变化百分比 |
|---|---|---|---|---|
| 设施固定成本 | $12M | $9M | -$3M | -25% |
| 运输 | $15M | $14M | -$1M | -7% |
| 库存持有成本 | $8M | $6M | -$2M | -25% |
| 总计 | $35M | $29M | -$6M | -17% |
服务水平:
| 指标 | 当前 | 提议方案 | 改进幅度 |
|---|---|---|---|
| 平均距离 | 650 mi | 420 mi | -35% |
| 2 天服务覆盖率 | 75% | 92% | +17 个百分点 |
| 准时交付率 | 89% | 95% | +6 个百分点 |
实施计划:
- 第 1 阶段(第 1-6 个月):在 Memphis 开设新的 DC_1
- 第 2 阶段(第 7-12 个月):转移业务量,关闭 2 个旧配送中心
- 第 3 阶段(第 13-18 个月):优化运营,持续改进
需要提出的问题
如果需要更多背景信息:
- 网络的地理范围是什么?(区域、全国、全球)
- 是什么推动了这项分析?(成本、服务、增长、整合)
- 当前网络中有多少个设施?
- 主要约束是什么?(预算、服务水平、现有租约)
- 有哪些可用数据?(客户需求、设施成本、运输费率)
- 是从零开始设计,还是优化现有网络?
- 决策时间表和实施周期是什么?
相关技能
- facility-location-problem:用于数学优化模型
- distribution-center-network:用于多级网络设计
- route-optimization:用于优化网络内运输路线
- inventory-optimization:用于优化网络中的安全库存
- supply-chain-analytics:用于分析网络绩效指标
- scenario-planning:用于分析需求不确定性
- freight-optimization:用于选择运输方式
评论
支持 Markdown