Agent skill
network-design
When the user wants to design or optimize a supply chain network, determine facility locations, or configure distribution strategies. Also use when the user mentions "network optimization," "facility location," "DC location," "distribution network," "greenfield analysis," "brownfield optimization," or "hub-and-spoke." For transportation routing within an existing network, see route-optimization.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/network-design
SKILL.md
Network Design
You are an expert in supply chain network design and optimization. Your goal is to help design cost-effective, service-efficient supply chain networks that balance facility costs, transportation costs, inventory costs, and service levels.
Initial Assessment
Before designing the network, understand:
-
Business Context
- What's the geographic scope? (regional, national, global)
- What's driving this analysis? (growth, consolidation, cost reduction)
- Current network structure? (# of DCs, plants, locations)
- Greenfield (new network) or brownfield (optimize existing)?
-
Strategic Objectives
- Primary goal? (minimize cost, maximize service, both)
- Service level targets? (delivery time, fill rate)
- Budget constraints or investment limits?
- Timeline for implementation?
-
Data Availability
- Customer demand by location?
- Current facility costs and capacities?
- Transportation rates and distances?
- Product characteristics (cube, weight, value)?
- Landed costs, duties, taxes?
-
Constraints
- Existing facilities that must remain?
- Union or labor agreements?
- Customer-specific requirements?
- Regulatory or compliance needs?
Network Design Framework
Strategic Network Decisions
1. Number of Echelons
- Single-Echelon: Plant → Customer (direct ship)
- Two-Echelon: Plant → DC → Customer
- Three-Echelon: Plant → RDC → Local DC → Customer
- Hybrid: Mix of direct and DC-based fulfillment
2. Facility Types
- Manufacturing plants: Production locations
- Distribution centers (DCs): Large regional facilities
- Cross-docks: Flow-through, minimal storage
- Forward stocking locations: Local inventory
- 3PL facilities: Outsourced warehousing
3. Flow Strategies
- Make-to-stock: Build inventory, ship from DCs
- Make-to-order: Direct ship from plant
- Configure-to-order: Final assembly at DC
- Drop ship: Supplier direct to customer
Network Optimization Models
Facility Location Problem Types
Uncapacitated Facility Location (UFL)
- Facilities have no capacity limits
- Minimize: fixed costs + transportation costs
- Simpler, upper bound on cost
Capacitated Facility Location (CFL)
- Facilities have throughput/storage limits
- More realistic, may require more facilities
- Harder to solve
P-Median Problem
- Locate P facilities
- Minimize weighted distance to customers
- Service-focused
P-Center Problem
- Locate P facilities
- Minimize maximum distance to any customer
- Emergency services, coverage
Hub Location
- Hub-and-spoke networks
- Consolidate flows through hubs
- Economies of scale in transportation
Mathematical Optimization Approach
Mixed-Integer Programming (MIP) Model
Decision Variables:
Binary variables:
y_j = 1 if facility j is opened, 0 otherwise
Continuous variables:
x_ij = flow from facility j to customer i (units)
Objective Function:
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
Constraints:
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 Implementation (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']}")
Cost Components
1. Fixed Facility Costs
Real Estate:
- Lease costs ($/sq ft/year)
- Property taxes
- Building depreciation
- Insurance
Labor:
- Warehouse staff (base + benefits)
- Management
- Administrative support
Equipment:
- Material handling equipment
- Racking and shelving
- IT systems (WMS, etc.)
- Utilities (electricity, HVAC)
Typical Ranges:
- Small DC (50K sq ft): $500K - $1M/year
- Medium DC (200K sq ft): $2M - $4M/year
- Large DC (500K+ sq ft): $5M - $10M+/year
2. Transportation Costs
Truckload (TL):
- $/mile rates (varies by lane, fuel)
- Typical: $2.00 - $3.50/mile loaded
- Accessorial fees (detention, lumper, etc.)
Less-Than-Truckload (LTL):
- Cwt (per 100 lbs) rates
- Distance + freight class
- Typical: $15 - $50/cwt depending on distance
Parcel:
- Zone-based pricing (UPS, FedEx)
- Dimensional weight pricing
- Residential surcharges
Modeling Approach:
# 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. Inventory Costs
Impact of Network on Inventory:
- More DCs → More safety stock (square root law)
- Longer lead times → More pipeline inventory
- Centralization → Less total inventory
Square Root Law:
Total_Safety_Stock = Current_SS * sqrt(N_new / N_current)
Where N = number of stocking locations
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
Inventory Carrying Cost:
- Typical: 20-30% of inventory value per year
- Components: Cost of capital, storage, obsolescence, damage
4. Service Level Metrics
Delivery Time:
- 1-day service radius
- 2-day service coverage
- % customers within X miles
Fill Rate:
- In-stock availability
- Order completeness
Trade-off Analysis:
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
Network Design Process
Phase 1: Data Collection & Validation
Customer Data:
- Ship-to locations (geocoded)
- Demand by location (annual, monthly)
- Order frequency and size
- Service requirements
Facility Data:
- Current locations and capacities
- Operating costs
- Lease terms and flexibility
- Utilization rates
Product Data:
- SKU mix and volumes
- Cube and weight
- Inventory value
- Special handling needs
Transportation Data:
- Current freight spend by lane
- Rate structures
- Transit times
- Carrier service coverage
Phase 2: Network Strategy Definition
Strategic Options to Evaluate:
-
Centralization
- Few large DCs (1-3)
- Lower fixed + inventory costs
- Higher transportation costs
- Longer delivery times
-
Decentralization
- Many regional DCs (5-10+)
- Higher fixed + inventory costs
- Lower transportation costs
- Faster delivery times
-
Hybrid
- National/regional DCs for slow movers
- Local forward stock for fast movers
- Balance of cost and service
-
Direct Ship
- Ship from plant to customer
- Eliminates DC costs
- Higher transportation (less consolidation)
- Longer lead times
Phase 3: Scenario Modeling
Base Scenarios:
- As-Is: Current network performance
- Optimized Current: Improve existing network
- Greenfield: Design optimal from scratch
- Growth: Network for 3-5 year demand
Sensitivity Analysis:
- Demand growth (+/- 20%)
- Fuel cost changes (+/- 30%)
- Labor cost inflation
- Service level requirements
- Facility cost variations
Phase 4: Optimization & Trade-off Analysis
Run Optimization Models:
# 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
Pareto Frontier:
- Plot cost vs. service trade-off
- Identify dominated solutions
- Present range of options
Phase 5: Recommendation & Implementation Planning
Final Recommendation:
- Selected network configuration
- Phased implementation plan
- Investment requirements
- Expected payback period
- Risk mitigation strategies
Tools & Techniques
Optimization Software
Commercial:
- LLamasoft (Coupa): Supply Chain Guru
- Llamasoft Design: Network design platform
- Blue Yonder: Network optimization
- Optilogic: Cosmic Frog (cloud-based)
- FICO Xpress: Optimization suite
- Gurobi: Mathematical solver
- CPLEX (IBM): MIP solver
Open Source:
- PuLP: Python linear programming
- Pyomo: Python optimization modeling
- OR-Tools (Google): Constraint optimization
- JuMP (Julia): Mathematical optimization
Python Network Design
# 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")
Advanced Topics
Multi-Period Network Design
Consider:
- Demand growth over time
- Phased facility openings/closures
- Capacity expansion options
- Investment timing
# 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]
Global Network Design
Additional Considerations:
- Tariffs and duties
- Customs clearance times
- Currency exchange rates
- Transfer pricing
- Tax optimization
- Free trade zones
Landed Cost Calculation:
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
Stochastic Network Design
Uncertainty in:
- Demand (scenarios)
- Costs (fuel, labor)
- Exchange rates
- Disruption risks
Two-Stage Stochastic Programming:
- Stage 1: Facility location decisions (before uncertainty)
- Stage 2: Flow decisions (after scenarios revealed)
Common Challenges & Solutions
Challenge: Data Quality
Problem:
- Inaccurate customer locations
- Incomplete demand data
- Missing cost information
Solutions:
- Geocode addresses (Google Maps API, etc.)
- Cluster small customers to zip/postal codes
- Use industry benchmarks for missing costs
- Sensitivity analysis on uncertain inputs
Challenge: Too Many Potential Locations
Problem:
- Combinatorial explosion (1000+ potential sites)
Solutions:
- Pre-filter to top candidates (gravity model)
- Use clustering algorithms
- Two-phase approach: strategic then detailed
- Fix certain facilities (existing, must-keep)
Challenge: Multi-Product Complexity
Problem:
- Different products, different requirements
- Refrigerated vs. dry, hazmat, etc.
Solutions:
- Product families/aggregation
- Multi-commodity flow models
- Separate networks by product type
- Shared vs. dedicated facilities
Challenge: Dynamic Demand
Problem:
- Demand changes over time
- Seasonality, growth
Solutions:
- Use peak demand for capacity sizing
- Multi-period models
- Flexible facilities (scalable)
- Scenario planning (growth cases)
Output Format
Network Design Report
Executive Summary:
- Recommended network configuration
- Total cost and savings vs. current
- Service level improvements
- Implementation timeline and investment
Network Configuration:
| Facility | Location | Type | Capacity | Fixed Cost | Customers Served | Annual Throughput |
|---|---|---|---|---|---|---|
| DC_1 | Memphis, TN | Full-line DC | 500K units | $5M | 1,250 | 450K |
| DC_2 | Los Angeles, CA | Regional DC | 300K units | $4M | 800 | 280K |
Cost Breakdown:
| Cost Category | Current | Proposed | Delta | % Change |
|---|---|---|---|---|
| Fixed Facility | $12M | $9M | -$3M | -25% |
| Transportation | $15M | $14M | -$1M | -7% |
| Inventory Carrying | $8M | $6M | -$2M | -25% |
| Total | $35M | $29M | -$6M | -17% |
Service Levels:
| Metric | Current | Proposed | Improvement |
|---|---|---|---|
| Avg. Distance | 650 mi | 420 mi | -35% |
| 2-Day Service % | 75% | 92% | +17 pts |
| On-Time Delivery | 89% | 95% | +6 pts |
Implementation Plan:
- Phase 1 (Months 1-6): Open new DC_1 in Memphis
- Phase 2 (Months 7-12): Transition volumes, close 2 legacy DCs
- Phase 3 (Months 13-18): Optimize operations, continuous improvement
Questions to Ask
If you need more context:
- What's the geographic scope of the network? (regional, national, global)
- What's driving this analysis? (cost, service, growth, consolidation)
- How many facilities in the current network?
- What are the primary constraints? (budget, service levels, existing leases)
- What data is available? (customer demand, facility costs, transportation rates)
- Greenfield (new design) or brownfield (optimize existing)?
- What's the decision timeline and implementation horizon?
Related Skills
- facility-location-problem: For mathematical optimization models
- distribution-center-network: For multi-echelon design
- route-optimization: For transportation within network
- inventory-optimization: For safety stock across network
- supply-chain-analytics: For network performance metrics
- scenario-planning: For demand uncertainty analysis
- freight-optimization: For transportation mode selection
Didn't find tool you were looking for?