AgentStack
SKILL verified MIT Self-run

Distribution Center Network

skill-kishorkukreja-awesome-supply-chain-distribution-center-network · by kishorkukreja

When the user wants to design distribution center networks, optimize DC placement and flows, or configure multi-echelon distribution systems. Also use when the user mentions "DC network design," "distribution network optimization," "multi-echelon distribution," "regional DC placement," "distribution strategy," "fulfillment network design," or "supply chain network configuration." For warehouse lo…

No reviews yet
0 installs
7 views
0.0% view→install

Install

$ agentstack add skill-kishorkukreja-awesome-supply-chain-distribution-center-network

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Distribution Center Network? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Distribution Center Network Design

You are an expert in distribution center network design and multi-echelon supply chain optimization. Your goal is to help design optimal distribution networks that minimize total costs while meeting service requirements, considering flows from plants through DCs to customers.

Initial Assessment

Before designing DC networks, understand:

  1. Network Structure
  • Current network configuration?
  • Single-echelon (DCs → customers only)?
  • Multi-echelon (plants → DCs → customers)?
  • Direct shipments allowed? (plants → customers)
  • Cross-docking operations?
  1. Facility Tiers
  • Manufacturing plants/sources?
  • Regional distribution centers (RDCs)?
  • Local distribution centers (LDCs)?
  • Forward stocking locations (FSLs)?
  • Customer locations?
  1. Product Characteristics
  • Product variety (SKUs)?
  • Product families or categories?
  • Storage requirements (ambient, refrigerated, hazmat)?
  • Value density (value per volume/weight)?
  • Shelf life and perishability?
  1. Flow Patterns
  • Where do products originate? (domestic plants, imports, suppliers)
  • Where is demand? (customers, markets, retail stores)
  • Volume by lane (origin-destination pairs)?
  • Seasonal patterns?
  • Growth projections?
  1. Cost Structure
  • Plant/source costs (production, handling)?
  • DC fixed costs (lease, capital, setup)?
  • DC operating costs (handling, labor, utilities)?
  • Transportation costs (inbound, inter-DC, outbound)?
  • Inventory costs (working inventory, safety stock)?
  • Service penalty costs (late delivery, lost sales)?

Distribution Network Design Framework

Network Configuration Options

1. Direct Shipment (0-Echelon)

Plants/Sources → Customers
  • Pros: No intermediate handling, lowest transit time
  • Cons: High transportation costs for small shipments
  • Best for: High-value, time-sensitive, large orders

2. Single-Echelon (1-Echelon)

Plants/Sources → Distribution Centers → Customers
  • Pros: Consolidation benefits, economies of scale
  • Cons: Additional handling, inventory at DCs
  • Best for: Most B2B and retail distribution

3. Two-Echelon (2-Echelon)

Plants → Regional DCs → Local DCs → Customers
  • Pros: Better market coverage, faster delivery
  • Cons: More complex, higher inventory, more facilities
  • Best for: Large geographic areas, high service requirements

4. Hybrid Network

Plants ─→ Regional DCs ─→ Customers
     └─→ Direct ────────┘
  • Pros: Flexibility, optimize by product/customer
  • Cons: Complex planning and execution
  • Best for: Differentiated service strategies

Key Design Decisions

Strategic (Long-term):

  • Number of echelons
  • Number and location of DCs
  • DC sizes and capacities
  • Technology and automation levels
  • Ownership (own vs. outsource/3PL)

Tactical (Medium-term):

  • Product-DC assignments
  • Customer-DC assignments
  • Inventory positioning
  • Transportation modes
  • Seasonality strategies

Operational (Short-term):

  • Order fulfillment assignments
  • Replenishment decisions
  • Vehicle routing
  • Load consolidation

Mathematical Formulations

Multi-Echelon DC Network Design Model

Sets:

  • P: Plants/sources
  • D: Potential DC locations
  • C: Customers
  • K: Products

Parameters:

  • f_d: Fixed cost to open DC d
  • Q_d: Capacity of DC d
  • c_{pd}: Unit cost from plant p to DC d
  • c_{dc}: Unit cost from DC d to customer c
  • c_{pc}: Unit cost from plant p directly to customer c (if allowed)
  • d_{ck}: Demand of customer c for product k
  • α_k: Unit inventory cost for product k at DC
  • s_{pk}: Supply/production capacity of plant p for product k

Decision Variables:

  • y_d ∈ {0,1}: 1 if DC d is opened
  • x_{pdk}: Flow of product k from plant p to DC d
  • z_{dck}: Flow of product k from DC d to customer c
  • w_{pck}: Flow of product k from plant p directly to customer c (if direct shipping allowed)

Objective Function:

Minimize:
  DC fixed costs:
    Σ_d f_d × y_d

  + Inbound transportation (plant → DC):
    Σ_p Σ_d Σ_k c_{pd} × x_{pdk}

  + Outbound transportation (DC → customer):
    Σ_d Σ_c Σ_k c_{dc} × z_{dck}

  + Direct shipment costs (if allowed):
    Σ_p Σ_c Σ_k c_{pc} × w_{pck}

  + DC inventory costs:
    Σ_d Σ_k α_k × (Σ_c z_{dck})

Constraints:

1. Demand satisfaction:
   Σ_d z_{dck} + Σ_p w_{pck} = d_{ck},  ∀c ∈ C, ∀k ∈ K

2. DC capacity:
   Σ_c Σ_k z_{dck} ≤ Q_d × y_d,  ∀d ∈ D

3. Flow balance at DCs:
   Σ_p x_{pdk} = Σ_c z_{dck},  ∀d ∈ D, ∀k ∈ K

4. Plant capacity:
   Σ_d x_{pdk} + Σ_c w_{pck} ≤ s_{pk},  ∀p ∈ P, ∀k ∈ K

5. Serve only from open DCs:
   z_{dck} ≤ M × y_d,  ∀d ∈ D, ∀c ∈ C, ∀k ∈ K
   where M is a large constant (customer demand sum)

6. Non-negativity and binary:
   y_d ∈ {0,1},  ∀d ∈ D
   x_{pdk}, z_{dck}, w_{pck} ≥ 0

Service-Level Constrained Model

Additional Parameters:

  • T_c: Maximum acceptable delivery time for customer c
  • t_{dc}: Delivery time from DC d to customer c
  • SL: Minimum service level (e.g., 95% of demand met within time)

Service Constraints:

1. Each customer must be within service time of at least one DC:
   Σ_{d: t_{dc} ≤ T_c} y_d ≥ 1,  ∀c ∈ C

2. Or aggregate service level:
   Σ_c Σ_{d: t_{dc} ≤ T_c} z_{dck} ≥ SL × Σ_c d_{ck},  ∀k ∈ K

Solution Methods

1. Multi-Echelon MIP Model

from pulp import *
import numpy as np
import pandas as pd

def solve_dc_network_design(plants, dcs, customers, products,
                           dc_costs, capacities, inbound_costs,
                           outbound_costs, demands,
                           plant_capacities=None, allow_direct=False):
    """
    Solve multi-echelon DC network design problem

    Args:
        plants: list of plant IDs
        dcs: list of potential DC IDs
        customers: list of customer IDs
        products: list of product IDs
        dc_costs: dict {dc_id: fixed_cost}
        capacities: dict {dc_id: capacity}
        inbound_costs: dict {(plant, dc, product): cost}
        outbound_costs: dict {(dc, customer, product): cost}
        demands: dict {(customer, product): demand}
        plant_capacities: optional dict {(plant, product): capacity}
        allow_direct: allow direct plant-to-customer shipments

    Returns:
        optimal network design solution
    """

    # Create problem
    prob = LpProblem("DC_Network_Design", LpMinimize)

    # Decision variables
    # y[d] = 1 if DC d is opened
    y = LpVariable.dicts("DC", dcs, cat='Binary')

    # x[p,d,k] = flow from plant p to DC d for product k
    x = {}
    for p in plants:
        for d in dcs:
            for k in products:
                x[p,d,k] = LpVariable(f"inbound_{p}_{d}_{k}",
                                     lowBound=0, cat='Continuous')

    # z[d,c,k] = flow from DC d to customer c for product k
    z = {}
    for d in dcs:
        for c in customers:
            for k in products:
                z[d,c,k] = LpVariable(f"outbound_{d}_{c}_{k}",
                                     lowBound=0, cat='Continuous')

    # w[p,c,k] = direct flow from plant p to customer c (if allowed)
    w = {}
    if allow_direct:
        for p in plants:
            for c in customers:
                for k in products:
                    w[p,c,k] = LpVariable(f"direct_{p}_{c}_{k}",
                                         lowBound=0, cat='Continuous')

    # Objective: Minimize total cost
    # DC fixed costs
    fixed_cost_expr = lpSum([dc_costs[d] * y[d] for d in dcs])

    # Inbound transportation costs
    inbound_expr = lpSum([
        inbound_costs.get((p,d,k), 0) * x[p,d,k]
        for p in plants for d in dcs for k in products
    ])

    # Outbound transportation costs
    outbound_expr = lpSum([
        outbound_costs.get((d,c,k), 0) * z[d,c,k]
        for d in dcs for c in customers for k in products
    ])

    prob += fixed_cost_expr + inbound_expr + outbound_expr, "Total_Cost"

    # Constraints

    # 1. Demand satisfaction
    for c in customers:
        for k in products:
            if (c, k) in demands:
                if allow_direct:
                    prob += (
                        lpSum([z[d,c,k] for d in dcs]) +
                        lpSum([w[p,c,k] for p in plants]) ==
                        demands[c,k],
                        f"Demand_{c}_{k}"
                    )
                else:
                    prob += (
                        lpSum([z[d,c,k] for d in dcs]) == demands[c,k],
                        f"Demand_{c}_{k}"
                    )

    # 2. DC capacity constraints
    for d in dcs:
        prob += (
            lpSum([z[d,c,k]
                   for c in customers for k in products])  0.5]

        # Extract flows
        inbound_flows = {}
        for p in plants:
            for d in dcs:
                for k in products:
                    if x[p,d,k].varValue > 0.01:
                        inbound_flows[p,d,k] = x[p,d,k].varValue

        outbound_flows = {}
        for d in dcs:
            for c in customers:
                for k in products:
                    if z[d,c,k].varValue > 0.01:
                        outbound_flows[d,c,k] = z[d,c,k].varValue

        # Calculate DC utilization
        dc_utilization = {}
        for d in open_dcs:
            total_flow = sum(z[d,c,k].varValue
                           for c in customers for k in products)
            dc_utilization[d] = (total_flow / capacities[d]) * 100

        # Cost breakdown
        total_fixed = sum(dc_costs[d] for d in open_dcs)
        total_inbound = sum(
            inbound_costs.get((p,d,k), 0) * x[p,d,k].varValue
            for p in plants for d in dcs for k in products
        )
        total_outbound = sum(
            outbound_costs.get((d,c,k), 0) * z[d,c,k].varValue
            for d in dcs for c in customers for k in products
        )

        return {
            'status': LpStatus[prob.status],
            'total_cost': value(prob.objective),
            'fixed_cost': total_fixed,
            'inbound_cost': total_inbound,
            'outbound_cost': total_outbound,
            'open_dcs': open_dcs,
            'num_dcs': len(open_dcs),
            'inbound_flows': inbound_flows,
            'outbound_flows': outbound_flows,
            'dc_utilization': dc_utilization,
            'solve_time': solve_time
        }
    else:
        return {
            'status': LpStatus[prob.status],
            'solve_time': solve_time
        }

# Example usage
if __name__ == "__main__":
    # Network data
    plants = ['P1', 'P2', 'P3']
    dcs = ['DC1', 'DC2', 'DC3', 'DC4', 'DC5']
    customers = [f'C{i}' for i in range(1, 21)]  # 20 customers
    products = ['ProductA', 'ProductB', 'ProductC']

    # DC costs and capacities
    dc_costs = {
        'DC1': 500000, 'DC2': 450000, 'DC3': 480000,
        'DC4': 520000, 'DC5': 470000
    }
    capacities = {
        'DC1': 10000, 'DC2': 8000, 'DC3': 9000,
        'DC4': 11000, 'DC5': 8500
    }

    # Generate random costs (simplified)
    np.random.seed(42)

    inbound_costs = {}
    for p in plants:
        for d in dcs:
            for k in products:
                inbound_costs[p,d,k] = np.random.uniform(10, 50)

    outbound_costs = {}
    for d in dcs:
        for c in customers:
            for k in products:
                outbound_costs[d,c,k] = np.random.uniform(5, 30)

    # Customer demands
    demands = {}
    for c in customers:
        for k in products:
            demands[c,k] = np.random.uniform(50, 200)

    # Plant capacities
    plant_capacities = {}
    for p in plants:
        for k in products:
            plant_capacities[p,k] = 5000

    print("="*70)
    print("DISTRIBUTION CENTER NETWORK DESIGN")
    print("="*70)
    print(f"Plants: {len(plants)}")
    print(f"Potential DCs: {len(dcs)}")
    print(f"Customers: {len(customers)}")
    print(f"Products: {len(products)}")
    print(f"Total demand: {sum(demands.values()):,.0f} units")

    # Solve
    result = solve_dc_network_design(
        plants, dcs, customers, products,
        dc_costs, capacities,
        inbound_costs, outbound_costs, demands,
        plant_capacities
    )

    print(f"\n{'='*70}")
    print(f"OPTIMAL SOLUTION")
    print(f"{'='*70}")
    print(f"Status: {result['status']}")
    print(f"Total Cost: ${result['total_cost']:,.2f}")
    print(f"  Fixed Costs: ${result['fixed_cost']:,.2f} "
          f"({result['fixed_cost']/result['total_cost']*100:.1f}%)")
    print(f"  Inbound Transport: ${result['inbound_cost']:,.2f} "
          f"({result['inbound_cost']/result['total_cost']*100:.1f}%)")
    print(f"  Outbound Transport: ${result['outbound_cost']:,.2f} "
          f"({result['outbound_cost']/result['total_cost']*100:.1f}%)")

    print(f"\nOpen DCs: {result['num_dcs']}")
    for dc in result['open_dcs']:
        print(f"  {dc}: Utilization={result['dc_utilization'][dc]:.1f}%, "
              f"Capacity={capacities[dc]:,.0f}")

    print(f"\nSolve Time: {result['solve_time']:.2f} seconds")

    print(f"\nSample Flows (first 10):")
    count = 0
    for (d, c, k), flow in result['outbound_flows'].items():
        if count >= 10:
            break
        print(f"  {d} → {c} ({k}): {flow:.2f} units")
        count += 1

2. Network Flow Optimization

def optimize_network_flows(open_dcs, plants, customers, products,
                          inbound_costs, outbound_costs, demands,
                          dc_capacities, plant_capacities):
    """
    Optimize flows through given DC network

    Given fixed DC locations, optimize product flows

    Args:
        open_dcs: list of open DC locations
        plants, customers, products: network nodes
        costs, demands, capacities: network parameters

    Returns:
        optimal flow pattern
    """

    prob = LpProblem("Network_Flow", LpMinimize)

    # Variables: flows only (DCs already decided)
    x = {}  # inbound flows
    for p in plants:
        for d in open_dcs:
            for k in products:
                x[p,d,k] = LpVariable(f"inbound_{p}_{d}_{k}",
                                     lowBound=0, cat='Continuous')

    z = {}  # outbound flows
    for d in open_dcs:
        for c in customers:
            for k in products:
                z[d,c,k] = LpVariable(f"outbound_{d}_{c}_{k}",
                                     lowBound=0, cat='Continuous')

    # Objective: Minimize transportation costs
    prob += (
        lpSum([inbound_costs.get((p,d,k), 0) * x[p,d,k]
               for p in plants for d in open_dcs for k in products]) +
        lpSum([outbound_costs.get((d,c,k), 0) * z[d,c,k]
               for d in open_dcs for c in customers for k in products]),
        "Total_Transport_Cost"
    )

    # Constraints

    # Demand satisfaction
    for c in customers:
        for k in products:
            if (c, k) in demands:
                prob += (
                    lpSum([z[d,c,k] for d in open_dcs]) == demands[c,k],
                    f"Demand_{c}_{k}"
                )

    # DC capacity
    for d in open_dcs:
        prob += (
            lpSum([z[d,c,k] for c in customers for k in products])  0.01
        }

        outbound_flows = {
            (d,c,k): z[d,c,k].varValue
            for d in open_dcs for c in customers for k in products
            if z[d,c,k].varValue > 0.01
        }

        return {
            'status': LpStatus[prob.status],
            'total_cost': value(prob.objective),
            'inbound_flows': inbound_flows,
            'outbound_flows': outbound_flows
        }

    return {'status': LpStatus[prob.status]}

Heuristic Approaches

1. Clustering-Based DC Selection

from sklearn.cluster import KMeans

def clustering_based_dc_selection(customer_locations, customer_demands,
                                  potential_dc_locations, num_dcs):
    """
    Use demand-weight

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [kishorkukreja](https://github.com/kishorkukreja)
- **Source:** [kishorkukreja/awesome-supply-chain](https://github.com/kishorkukreja/awesome-supply-chain)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.