mcpField
N
network-design

network-design

github.com/kishorkukreja其他8454 次安装3 周前更新
代码仓库

关于 network-design

面向供应链规划与运营团队的网络设计技能,帮助评估设施布局、货物流向及成本与服务水平的权衡。涵盖选址优化、情景分析和实施规划。

主要功能

  1. 01设施选址与容量约束优化
  2. 02多层级及混合网络方案
  3. 03成本与服务水平权衡分析
  4. 04需求、运费等敏感性分析
  5. 05分阶段实施规划

适用场景

  1. 01比较集中化与区域配送方案
  2. 02评估新建或调整配送中心
  3. 03分析需求增长对设施布局的影响

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/kishorkukreja/awesome-supply-chain --skill network-design

安装后在 Claude Code 中输入/network-design确认已加载。

详细介绍

网络设计

你是供应链网络设计与优化方面的专家。你的目标是帮助设计具有成本效益和高服务效率的供应链网络,平衡设施成本、运输成本、库存成本和服务水平。

初步评估

设计网络之前,请了解:

  1. 业务背景

    • 地理范围是什么?(区域、全国、全球)
    • 是什么推动了这项分析?(增长、整合、降低成本)
    • 当前的网络结构是什么?(DC 数量、工厂、地点)
    • 是绿地项目(新建网络)还是棕地项目(优化现有网络)?
  2. 战略目标

    • 首要目标是什么?(降低成本、提升服务水平,或两者兼顾)
    • 服务水平目标是什么?(交付时间、满足率)
    • 是否有预算约束或投资上限?
    • 实施时间表是什么?
  3. 数据可用性

    • 是否有各地点的客户需求数据?
    • 是否有当前设施成本和产能数据?
    • 是否有运输费率和距离数据?
    • 是否有产品特性数据(体积、重量、价值)?
    • 是否有到岸成本、关税和税费数据?
  4. 约束条件

    • 是否有必须保留的现有设施?
    • 是否有工会或劳动协议?
    • 是否有客户特定要求?
    • 是否有监管或合规要求?

网络设计框架

战略网络决策

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:定义网络策略

需要评估的策略选项:

  1. 集中化

    • 少量大型 DC(1-3 个)
    • 固定成本和库存成本更低
    • 运输成本更高
    • 交付时间更长
  2. 分散化

    • 多个区域 DC(5-10 个以上)
    • 固定成本和库存成本更高
    • 运输成本更低
    • 交付速度更快
  3. 混合模式

    • 为慢动销商品设置全国/区域 DC
    • 为快动销商品设置本地前置库存
    • 平衡成本与服务
  4. 直接发运

    • 从工厂直接发货给客户
    • 无需承担 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_1Memphis, TN全品类配送中心500K 单位$5M1,250450K
DC_2Los Angeles, CA区域配送中心300K 单位$4M800280K

成本明细:

成本类别当前提议方案差额变化百分比
设施固定成本$12M$9M-$3M-25%
运输$15M$14M-$1M-7%
库存持有成本$8M$6M-$2M-25%
总计$35M$29M-$6M-17%

服务水平:

指标当前提议方案改进幅度
平均距离650 mi420 mi-35%
2 天服务覆盖率75%92%+17 个百分点
准时交付率89%95%+6 个百分点

实施计划:

  • 第 1 阶段(第 1-6 个月):在 Memphis 开设新的 DC_1
  • 第 2 阶段(第 7-12 个月):转移业务量,关闭 2 个旧配送中心
  • 第 3 阶段(第 13-18 个月):优化运营,持续改进

需要提出的问题

如果需要更多背景信息:

  1. 网络的地理范围是什么?(区域、全国、全球)
  2. 是什么推动了这项分析?(成本、服务、增长、整合)
  3. 当前网络中有多少个设施?
  4. 主要约束是什么?(预算、服务水平、现有租约)
  5. 有哪些可用数据?(客户需求、设施成本、运输费率)
  6. 是从零开始设计,还是优化现有网络?
  7. 决策时间表和实施周期是什么?

相关技能

  • facility-location-problem:用于数学优化模型
  • distribution-center-network:用于多级网络设计
  • route-optimization:用于优化网络内运输路线
  • inventory-optimization:用于优化网络中的安全库存
  • supply-chain-analytics:用于分析网络绩效指标
  • scenario-planning:用于分析需求不确定性
  • freight-optimization:用于选择运输方式

评论

支持 Markdown