Skip to main content

Multi-tier supply chain bullwhip effect simulator

Project description

DeepBullwhip

CI codecov Docs Python License: MIT Version

Multi-tier supply chain bullwhip effect simulator with modular demand models, ordering policies, and cost functions.

Maintained by the AI Verification & Validation (AI V&V) Lab at King Fahd University of Petroleum & Minerals (KFUPM).

DeepBullwhip Summary Dashboard


Overview

DeepBullwhip provides a configurable simulation framework for studying the bullwhip effect in serial supply chains. It is designed for researchers and practitioners who need to:

  • Simulate multi-echelon supply chains under different demand patterns
  • Compare ordering policies (Order-Up-To, custom policies) and cost structures
  • Quantify bullwhip amplification, fill rates, and total supply chain costs
  • Generate publication-grade diagnostic visualizations
  • Run Monte Carlo experiments to study forecast-accuracy vs. robustness tradeoffs

The package is extracted from a computational study on the accuracy–robustness tradeoff in ML-driven semiconductor supply chains (see simulation.ipynb).

Features

Component Description
Demand generators Pluggable via DemandGenerator ABC. Default: AR(1) + seasonal + structural shock, calibrated to WSTS semiconductor data
Ordering policies Pluggable via OrderingPolicy ABC. Default: Order-Up-To (OUT / base-stock) with configurable service level
Cost functions Pluggable via CostFunction ABC. Default: Newsvendor (holding + backorder) with per-echelon h and b
Supply chain SerialSupplyChain supporting arbitrary K-echelon serial topologies via EchelonConfig
Diagnostics 10 publication-grade plot functions + network diagram + geographic map visualization
Metrics Bullwhip ratio, fill rate, cumulative bullwhip, theoretical lower bounds
Vectorized engine VectorizedSupplyChain — matrix-based (N, K, T) simulation for Monte Carlo batching. ~100x speedup over serial for N=1000 paths

Installation

# Clone the repository
git clone https://github.com/ai-vnv/deepbullwhip.git
cd deepbullwhip

# Create virtual environment and install
python -m venv venv
source venv/bin/activate
pip install -e ".[dev]"

Dependencies

  • Core: numpy, scipy, pandas, matplotlib
  • Dev: pytest, pytest-cov
  • Optional (ML): scikit-learn, torch

Quick Start

import numpy as np
from deepbullwhip import (
    SemiconductorDemandGenerator,
    SerialSupplyChain,
)

# 1. Generate demand (156 weeks, with shock at week 104)
gen = SemiconductorDemandGenerator()
demand = gen.generate(T=156, seed=42)

# 2. Simulate the default 4-echelon semiconductor supply chain
chain = SerialSupplyChain()
forecasts_mean = np.full_like(demand, demand.mean())
forecasts_std = np.full_like(demand, demand.std())
result = chain.simulate(demand, forecasts_mean, forecasts_std)

# 3. Inspect results
for k, er in enumerate(result.echelon_results):
    print(f"E{k+1}: {er.name:12s}  BW={er.bullwhip_ratio:.2f}  "
          f"FR={er.fill_rate:.0%}  Cost={er.total_cost:,.0f}")

Default Supply Chain Configuration

Echelon Role Lead Time h (holding) b (backorder)
E1 Distributor / OEM 2 weeks 0.15 0.60
E2 Assembly & Test (OSAT) 4 weeks 0.12 0.50
E3 Foundry / Fab 12 weeks 0.08 0.40
E4 Wafer / Material Supplier 8 weeks 0.05 0.30

Vectorized Monte Carlo Simulation

For large-scale experiments, use the matrix-based engine that processes N demand paths simultaneously via NumPy broadcasting:

from deepbullwhip import SemiconductorDemandGenerator, VectorizedSupplyChain

gen = SemiconductorDemandGenerator()
demand = gen.generate_batch(T=156, n_paths=1000, seed=42)  # (1000, 156)

vchain = VectorizedSupplyChain()
fm = np.full_like(demand, demand.mean())
fs = np.full_like(demand, demand.std())
result = vchain.simulate(demand, fm, fs)

# Average metrics across all 1000 paths
print(result.mean_metrics())

# Extract a single path as standard SimulationResult
sr = result.to_simulation_result(path_index=0)

Benchmark (N=1000, T=156, K=4):

Engine Time Speedup
Serial (SerialSupplyChain) 3.9s 1x
Vectorized (VectorizedSupplyChain) 0.04s ~100x

The vectorized engine uses:

  • Pre-allocated (N, K, T) order/inventory/cost matrices
  • Circular buffer pipeline with O(1) indexing (vs O(L) list.pop)
  • Fully vectorized OUT policy and newsvendor cost across N paths and K echelons per time step
  • Batch demand generation via generate_batch() with (N, T) noise matrix

Customization

Custom echelon configuration

from deepbullwhip import EchelonConfig, SerialSupplyChain

configs = [
    EchelonConfig("Retailer", lead_time=1, holding_cost=0.20, backorder_cost=0.80),
    EchelonConfig("Manufacturer", lead_time=6, holding_cost=0.10, backorder_cost=0.40),
]
chain = SerialSupplyChain.from_config(configs)

Custom ordering policy

from deepbullwhip.policy.base import OrderingPolicy

class MyPolicy(OrderingPolicy):
    def compute_order(self, inventory_position, forecast_mean, forecast_std):
        # Your logic here
        return max(0.0, forecast_mean - inventory_position)

Custom cost function

from deepbullwhip.cost.base import CostFunction

class MyCost(CostFunction):
    def compute(self, inventory):
        # Your logic here
        return abs(inventory) * 0.1

Visualization

Diagnostic plots

All plot functions return matplotlib.figure.Figure objects and support width="single" (3.5") or width="double" (7.0") for journal formatting. Colors use the KFUPM AI V&V Lab palette.

from deepbullwhip.diagnostics.plots import (
    plot_demand_trajectory,
    plot_order_quantities,
    plot_inventory_levels,
    plot_inventory_position,
    plot_order_streams,
    plot_cost_timeseries,
    plot_cost_decomposition,
    plot_bullwhip_amplification,
    plot_summary_dashboard,
    plot_echelon_detail,
)

fig = plot_summary_dashboard(demand, result)
fig.savefig("dashboard.pdf", dpi=300)

Network and geographic visualization

from deepbullwhip.diagnostics.network import (
    kfupm_petrochemical_network,
    plot_network_diagram,
    plot_supply_chain_map,
)

network = kfupm_petrochemical_network()
fig = plot_network_diagram(network, sim_result=result)
fig = plot_supply_chain_map(network, sim_result=result)

Batch figure generation

python scripts/visualize.py --save --outdir figures --dpi 600

Project Structure

deepbullwhip/
├── __init__.py                 # Public API re-exports
├── _types.py                   # TimeSeries, EchelonResult, SimulationResult
├── sensitivity.py              # Forecast sensitivity (lambda_f)
├── demand/
│   ├── base.py                 # DemandGenerator ABC
│   └── semiconductor.py        # AR(1) + seasonal + shock
├── policy/
│   ├── base.py                 # OrderingPolicy ABC
│   └── order_up_to.py          # Order-Up-To (OUT) policy
├── cost/
│   ├── base.py                 # CostFunction ABC
│   └── newsvendor.py           # Newsvendor h/b cost
├── chain/
│   ├── config.py               # EchelonConfig + defaults
│   ├── echelon.py              # SupplyChainEchelon
│   ├── serial.py               # SerialSupplyChain
│   └── vectorized.py           # VectorizedSupplyChain (N,K,T) matrix engine
└── diagnostics/
    ├── metrics.py              # Bullwhip ratio, fill rate, etc.
    ├── plots.py                # 10 publication-grade plot functions
    └── network.py              # Network diagram + geographic map

tests/                          # 117 unit tests, 99% coverage
notebooks/
├── tutorial.ipynb              # Full API walkthrough
├── 01_supply_chain_cost.ipynb  # Cost simulation & service level tradeoffs
├── 02_bullwhip_effect.ipynb    # Bullwhip confirmation & Monte Carlo validation
└── 03_custom_policies.ipynb    # Comparing ordering policies (OUT, fixed, smoothed)
scripts/visualize.py            # CLI figure generation
simulation.ipynb                # Original research notebook

Testing

# Run all tests
python -m pytest tests/ -v

# With coverage
python -m pytest tests/ --cov=deepbullwhip --cov-report=term-missing

Current: 117 tests, 99% code coverage.

Tutorial

See notebooks/tutorial.ipynb for a step-by-step guide covering demand generation, chain configuration, simulation, visualization, and custom policy implementation.

Citation

If you use DeepBullwhip in your research, please cite:

@software{deepbullwhip,
  title  = {DeepBullwhip: Multi-Tier Supply Chain Bullwhip Effect Simulator},
  author = {Arief, Mansur M.},
  url    = {https://github.com/ai-vnv/deepbullwhip},
  year   = {2025}
}

Documentation

Full API documentation is available at ai-vnv.github.io/deepbullwhip.

License

MIT License. See LICENSE for details.

Developed and maintained by the AI V&V Lab at KFUPM.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

deepbullwhip-0.1.0.tar.gz (5.4 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

deepbullwhip-0.1.0-py3-none-any.whl (28.5 kB view details)

Uploaded Python 3

File details

Details for the file deepbullwhip-0.1.0.tar.gz.

File metadata

  • Download URL: deepbullwhip-0.1.0.tar.gz
  • Upload date:
  • Size: 5.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for deepbullwhip-0.1.0.tar.gz
Algorithm Hash digest
SHA256 cc5cf9cfafaa783063f6ea44a778f4aa8d37a642b339a60d32c3f46d6993fcf1
MD5 8f863f13081d815e8e30b9d06c7df3c4
BLAKE2b-256 088c31e19390f659f52a8f7084ab67eab5d48c70dd230ee0224baa93a46791aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for deepbullwhip-0.1.0.tar.gz:

Publisher: publish.yml on ai-vnv/deepbullwhip

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deepbullwhip-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: deepbullwhip-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 28.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for deepbullwhip-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6200dffba1afb895703bd6a2620c47ea4352b5c8120f478332fedc176cd9b27d
MD5 e075360df3fedf185bdb4b5730b27b15
BLAKE2b-256 e844048c11e86f1bc3bd2ec44e283434c3a2b242c2b3ffabe88967c2b1928f61

See more details on using hashes here.

Provenance

The following attestation bundles were made for deepbullwhip-0.1.0-py3-none-any.whl:

Publisher: publish.yml on ai-vnv/deepbullwhip

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page