Skip to main content

Supply Chain AI

When the Ship Got Stuck

On March 23, 2021, the container ship Ever Given ran aground in the Suez Canal. It blocked the waterway for six days. The immediate cost: approximately $9.6 billion per day in delayed trade, 369 ships waiting, and ripple effects on global supply chains that took months to resolve.

Retailers who had supply chain monitoring systems with real-time visibility detected the event within hours and began rerouting orders. Those running on batch systems with weekly reporting found out when containers stopped arriving.

The Ever Given was an extreme event, but supply chain disruptions are not rare. Port congestion, supplier factory fires, extreme weather, geopolitical trade restrictions, and pandemic-level demand shocks all create disruption risk. McKinsey estimated that the average company experiences a material supply chain disruption causing at least one month of production outages every 3.7 years.

The question for retail supply chains is not "will there be disruptions?" The question is "how quickly can we detect, quantify, and respond to disruptions?" That question is answered with data and ML, not spreadsheets and phone calls.

Beyond disruption management, AI has transformed every layer of the supply chain: predicting supplier delivery delays before they happen, optimizing last-mile delivery routes in real time, forecasting returns volumes, and building digital twins that let planners simulate what-if scenarios before committing capital.


Why This Exists

Traditional supply chain management operated on a fundamental information asymmetry: by the time a problem was visible in your inventory reports, it was already too late to respond. A supplier's 3-week delay shows up in your replenishment system when the shipment is already overdue - not when the delay is forming.

The information is often available earlier. A supplier's financial distress appears in their annual reports and news articles before they miss a delivery. Port congestion in Shanghai is visible in real-time AIS (Automatic Identification System) vessel tracking before your container gets stuck. Demand spikes for your category are visible in social media and search trends before they hit your POS system.

AI systems that integrate these signals - financial news NLP, vessel tracking, social signals, demand sensing - can give supply chain planners days to weeks of advance warning instead of post-hoc damage control.

The economic case is direct. Walmart's supply chain efficiency is estimated to give them a 2-3% cost advantage over competitors, translating to billions in annual margin. Amazon's investment in supply chain automation and ML is explicitly cited as a key competitive barrier. For smaller retailers, getting supply chain AI right can close the gap with these giants meaningfully.


Historical Context

The history of supply chain technology is a history of increasing visibility and decreasing latency.

Electronic Data Interchange (EDI) in the 1970s-1980s was the first wave: standardized formats for purchase orders, invoices, and shipping notices enabled machine-readable supply chain communication. Before EDI, every PO was a phone call or a paper document.

Walmart's supplier mandate for EDI in the 1980s was a forcing function for the industry. Combined with barcode scanning at checkout (1974, but widespread by the 1980s), Walmart became the first retailer with near-real-time inventory visibility. This was a competitive advantage that helped them undercut competitors for a decade.

ERP systems (SAP, Oracle) in the 1990s integrated supply chain data across functions but were still batch-oriented and backward-looking.

RFID (Radio Frequency Identification) deployment in the 2000s - pushed by Walmart's supplier mandate in 2005 - promised real-time item-level tracking. The cost was too high for widespread adoption, but laid groundwork for the IoT era.

The modern era: IoT sensors in warehouses and shipping containers, real-time vessel tracking via AIS, satellite imagery of factory parking lots and port congestion (now used by hedge funds to predict company earnings before they report), and ML models that process all of these signals simultaneously.

Amazon's supply chain ML (patent filings from 2013-2018) includes predictive pre-positioning (shipping items closer to predicted demand before orders are placed), robotic warehouse orchestration, and delivery route optimization. These are now standard features that Amazon operates at scale.


Core Concepts

Lead Time Prediction

Lead time is the elapsed time from placing a purchase order to receiving goods in the warehouse. For a retailer ordering from a factory in Vietnam, this might average 35 days - but with a standard deviation of 10 days due to vessel scheduling, port congestion, customs delays, and supplier production variability.

The impact of lead time uncertainty on inventory was quantified in the safety stock lesson: SS=zαLσD2+D2σL2SS = z_\alpha \sqrt{L \sigma_D^2 + D^2 \sigma_L^2}. Reducing σL\sigma_L (lead time variability) directly reduces required safety stock - without changing service level.

ML can predict lead time more accurately than using historical averages because lead time depends on contextual signals:

  • Origin port congestion: vessel waiting times at Shanghai, Shenzhen, and Los Angeles ports fluctuate dramatically
  • Supplier production capacity: supplier's other commitments, labor availability, input material availability
  • Seasonal logistics demand: Q4 ocean freight rates and capacity are significantly tighter than Q2
  • Route and carrier selection: some carriers are more reliable than others for specific trade lanes
  • Customs risk: certain commodity codes face higher inspection rates at certain ports

A gradient boosted model trained on historical purchase orders with these features as inputs can predict lead time at the PO level (not just the trade lane average), enabling proactive re-ordering when a specific PO is predicted to be delayed.

Supplier Risk Assessment

Every supplier represents a concentration of risk. If a single supplier provides 30% of your category's inventory and that supplier has financial problems, your business has a problem.

Supplier risk has multiple dimensions:

  • Financial risk: Can the supplier fund operations, pay workers, and invest in production capacity?
  • Operational risk: Does the supplier have quality control problems, labor issues, or facility risks?
  • Geopolitical risk: Is the supplier in a region subject to trade restrictions, tariffs, or political instability?
  • Concentration risk: Is this supplier also your competitor's primary supplier? (When everyone is sourcing from the same factory, disruption affects the whole industry.)

ML-based supplier risk scoring:

Financial signals: Cash flow trends from financial statements, credit rating changes, trade credit payment patterns (suppliers who start paying their own suppliers late are often in financial distress before it becomes public knowledge).

NLP on news: Scan news articles, regulatory filings, and social media for mentions of the supplier in the context of layoffs, strikes, quality recalls, regulatory violations, or financial distress. Train a classifier to categorize mentions by risk type and severity.

Operational signals: Track on-time delivery rate, defect rate, and order acceptance rate for each supplier over time. Deteriorating trends predict future problems.

Satellite and IoT signals: Satellite imagery of supplier facilities can detect unusual activity (empty parking lots, dark factories). This is used by hedge funds but increasingly by supply chain analytics platforms.

Demand Sensing

Traditional demand forecasting uses point-of-sale history to predict future sales - looking backward. Demand sensing looks forward at signals that predict demand before it shows up in sales.

The key insight: demand signals exist before purchases happen. A consumer searches for a product before buying it. They click on an ad before converting. They browse a category before adding to cart.

High-frequency demand signals:

  • Web search trends (Google Trends API): search volume for product names, categories, and related terms
  • Social media mentions: volume and sentiment of product mentions on TikTok, Instagram, Twitter
  • Competitor out-of-stock signals: when competitors run out of an item, demand shifts to you
  • Macro economic indicators: consumer confidence, credit card spending data
  • Weather forecasts: known future weather drives predictable demand patterns

Demand sensing ML: a model that takes the current week's signal values and forecasts the revision to the baseline demand forecast. Think of it as a "demand forecast adjustment layer" on top of the standard demand forecast.

At Amazon, demand sensing runs continuously and can update inventory positioning decisions in hours based on social signal velocity.

Route Optimization

Last-mile delivery - the final leg from a fulfillment center or store to the customer's door - represents 53% of total shipping costs. Route optimization is the problem of finding the minimum-cost delivery sequence for a set of stops given vehicle capacity, time windows, and traffic conditions.

The Vehicle Routing Problem (VRP) is NP-hard in the general case: no polynomial-time exact solution exists. In practice:

  • Small instances (under 20 stops): exact solvers (CPLEX, Gurobi) find optimal solutions in seconds
  • Medium instances (20-200 stops): metaheuristics (simulated annealing, tabu search, genetic algorithms) find near-optimal solutions
  • Large instances (200+ stops, thousands of vehicles): ML-based approaches (pointer networks, reinforcement learning) or cluster-first-route-second heuristics

RL for last-mile routing: Train an RL agent on historical delivery data. The agent learns a policy: given current route state and remaining stops, which stop to visit next? This outperforms classical heuristics on real-world data because it can incorporate complex constraints (specific time windows, driver preferences, vehicle type restrictions) that are hard to model analytically.

Dynamic routing: Routes planned the night before must be adjusted in real time as traffic conditions change, customers reschedule, and new urgent deliveries are added. Maintain a base route plan and apply real-time adjustments using a combination of live traffic data and greedy local search.


Practical Implementation

import pandas as pd
import numpy as np
from sklearn.ensemble import GradientBoostingRegressor, RandomForestClassifier
from sklearn.model_selection import TimeSeriesSplit
from sklearn.preprocessing import LabelEncoder
import lightgbm as lgb
import warnings
warnings.filterwarnings('ignore')

# ============================================================
# 1. Lead Time Prediction Model
# ============================================================

class LeadTimePredictor:
"""
Predict expected lead time and probability of delay for purchase orders.
Uses LightGBM trained on historical PO data enriched with
contextual signals (port congestion, carrier reliability, seasonal capacity).
"""

def __init__(self):
self.model_mean = None # Mean lead time prediction
self.model_delay_prob = None # P(delay > 1 week)
self.label_encoders = {}
self.feature_cols = None

def _build_features(self, df: pd.DataFrame) -> pd.DataFrame:
"""
Build feature set from PO data.
Input df columns: origin_port, destination_port, carrier,
order_quantity, unit_weight_kg, category,
order_date, season (Q1-Q4), supplier_id,
origin_port_congestion_index,
historical_carrier_otd_rate,
is_peak_season
"""
df = df.copy()
df['order_date'] = pd.to_datetime(df['order_date'])
df['order_month'] = df['order_date'].dt.month
df['order_quarter'] = df['order_date'].dt.quarter
df['order_dow'] = df['order_date'].dt.dayofweek

# Cyclical encoding for month
df['month_sin'] = np.sin(2 * np.pi * df['order_month'] / 12)
df['month_cos'] = np.cos(2 * np.pi * df['order_month'] / 12)

# Log-transform quantity and weight
df['log_quantity'] = np.log1p(df['order_quantity'])
df['log_weight'] = np.log1p(df['unit_weight_kg'])

# Encode categorical columns
cat_cols = ['origin_port', 'destination_port', 'carrier', 'category', 'supplier_id']
for col in cat_cols:
if col not in self.label_encoders:
self.label_encoders[col] = LabelEncoder()
df[f'{col}_enc'] = self.label_encoders[col].fit_transform(df[col].astype(str))
else:
le = self.label_encoders[col]
df[f'{col}_enc'] = df[col].astype(str).apply(
lambda x: le.transform([x])[0] if x in le.classes_ else -1
)

feature_cols = [
'order_quarter', 'order_dow', 'month_sin', 'month_cos',
'log_quantity', 'log_weight',
'origin_port_congestion_index',
'historical_carrier_otd_rate',
'is_peak_season',
] + [f'{col}_enc' for col in cat_cols]

return df, feature_cols

def fit(self, train_df: pd.DataFrame, target_col: str = 'actual_lead_time_days'):
"""
Train lead time regression model.
train_df: historical PO data with actual_lead_time_days column.
"""
df, self.feature_cols = self._build_features(train_df)

X = df[self.feature_cols].fillna(-1)
y_mean = df[target_col]
y_delay = (df[target_col] > df['expected_lead_time_days'] + 7).astype(int)

# Model 1: Predict actual lead time (regression)
self.model_mean = lgb.LGBMRegressor(
n_estimators=300,
learning_rate=0.05,
num_leaves=63,
subsample=0.8,
colsample_bytree=0.8,
verbose=-1
)
self.model_mean.fit(X, y_mean)

# Model 2: Predict probability of significant delay (classification)
self.model_delay_prob = lgb.LGBMClassifier(
n_estimators=300,
learning_rate=0.05,
num_leaves=63,
subsample=0.8,
verbose=-1
)
self.model_delay_prob.fit(X, y_delay)

return self

def predict(self, po_df: pd.DataFrame) -> pd.DataFrame:
"""
Predict lead time and delay probability for new purchase orders.
Returns original df with added columns.
"""
df, _ = self._build_features(po_df)
X = df[self.feature_cols].fillna(-1)

df['predicted_lead_time_days'] = self.model_mean.predict(X)
df['delay_probability'] = self.model_delay_prob.predict_proba(X)[:, 1]

# Expected arrival date
df['expected_arrival_date'] = pd.to_datetime(df['order_date']) + pd.to_timedelta(
df['predicted_lead_time_days'].round().astype(int), unit='D'
)

# Flag high-risk POs
df['risk_flag'] = df['delay_probability'] > 0.4

return df[['order_id', 'predicted_lead_time_days', 'delay_probability',
'expected_arrival_date', 'risk_flag']]


# ============================================================
# 2. Supplier Risk Scoring
# ============================================================

class SupplierRiskScorer:
"""
Composite supplier risk score combining multiple risk dimensions.
"""

def __init__(self):
self.supplier_history = {}

def compute_operational_risk(
self,
supplier_id: str,
po_history_df: pd.DataFrame,
lookback_days: int = 180
) -> dict:
"""
Compute operational risk from purchase order history.
Metrics: on-time delivery rate, defect rate, order fill rate.
"""
cutoff = pd.Timestamp.now() - pd.Timedelta(days=lookback_days)
supplier_pos = po_history_df[
(po_history_df['supplier_id'] == supplier_id) &
(po_history_df['expected_arrival_date'] >= cutoff)
]

if len(supplier_pos) == 0:
return {'operational_risk_score': 0.5, 'n_pos': 0, 'data_quality': 'insufficient'}

otd_rate = (supplier_pos['actual_lead_time_days'] <= supplier_pos['expected_lead_time_days'] + 3).mean()
defect_rate = supplier_pos['defect_rate'].mean() if 'defect_rate' in supplier_pos.columns else 0.0
fill_rate = supplier_pos['fill_rate'].mean() if 'fill_rate' in supplier_pos.columns else 1.0

# Composite operational risk (lower = better)
operational_risk = (
(1 - otd_rate) * 0.5 +
defect_rate * 0.3 +
(1 - fill_rate) * 0.2
)

return {
'supplier_id': supplier_id,
'otd_rate': otd_rate,
'defect_rate': defect_rate,
'fill_rate': fill_rate,
'operational_risk_score': operational_risk,
'n_pos': len(supplier_pos),
}

def compute_financial_risk(
self,
supplier_id: str,
financial_data: dict
) -> dict:
"""
Estimate financial risk from available financial signals.
financial_data: dict with keys like current_ratio, debt_to_equity,
days_payable_outstanding, credit_score
"""
score_components = []
weights = []

if 'current_ratio' in financial_data:
# Current ratio < 1.0 = high risk
cr = financial_data['current_ratio']
cr_risk = max(0, (1.5 - cr) / 1.5)
score_components.append(cr_risk)
weights.append(0.3)

if 'debt_to_equity' in financial_data:
de = financial_data['debt_to_equity']
de_risk = min(1.0, de / 3.0) # D/E > 3 = max risk
score_components.append(de_risk)
weights.append(0.25)

if 'days_payable_outstanding' in financial_data:
dpo = financial_data['days_payable_outstanding']
# DPO increasing = supplier paying their suppliers slower
dpo_risk = min(1.0, max(0, (dpo - 30) / 60))
score_components.append(dpo_risk)
weights.append(0.25)

if 'credit_score' in financial_data:
cs = financial_data['credit_score'] # Assume 0-100 scale
cs_risk = (100 - cs) / 100
score_components.append(cs_risk)
weights.append(0.2)

if not score_components:
return {'financial_risk_score': 0.5, 'data_quality': 'insufficient'}

total_weight = sum(weights)
financial_risk = sum(s * w for s, w in zip(score_components, weights)) / total_weight

return {
'supplier_id': supplier_id,
'financial_risk_score': financial_risk,
'components': dict(zip(
['current_ratio_risk', 'de_risk', 'dpo_risk', 'credit_risk'],
score_components
))
}

def composite_risk_score(
self,
supplier_id: str,
operational_risk: float,
financial_risk: float,
geo_risk: float = 0.3, # default moderate
concentration_risk: float = 0.0
) -> dict:
"""
Combine risk dimensions into a single 0-1 risk score.
Higher = more risky.
"""
composite = (
operational_risk * 0.35 +
financial_risk * 0.35 +
geo_risk * 0.20 +
concentration_risk * 0.10
)

risk_tier = (
'Critical' if composite > 0.7 else
'High' if composite > 0.5 else
'Medium' if composite > 0.3 else
'Low'
)

return {
'supplier_id': supplier_id,
'composite_risk_score': composite,
'risk_tier': risk_tier,
'operational_risk': operational_risk,
'financial_risk': financial_risk,
'geo_risk': geo_risk,
'concentration_risk': concentration_risk,
}


# ============================================================
# 3. Returns Prediction
# ============================================================

class ReturnsPredictionModel:
"""
Predict return probability for an order at time of purchase.
Enables proactive returns management and reverse logistics planning.
"""

def __init__(self):
self.model = None
self.feature_cols = None

def build_features(self, df: pd.DataFrame) -> tuple:
"""
Features predicting return probability.
Input: order-level data with product + customer + context features.
"""
df = df.copy()
df['order_date'] = pd.to_datetime(df['order_date'])

feature_cols = [
# Product features
'category_return_rate', # historical avg return rate for this category
'price',
'log_price',
'is_sale_item',
'is_new_product', # new products have higher return rates

# Customer features
'customer_historical_return_rate',
'customer_order_count',
'days_since_last_purchase',

# Order features
'order_quantity',
'payment_method_credit_card', # credit card orders return more
'is_gift_order',
'has_size_variation', # apparel size mismatch is top return reason

# Context features
'is_holiday_season',
'days_before_holiday',
]

# Derived features
df['log_price'] = np.log1p(df['price'])

available_cols = [c for c in feature_cols if c in df.columns]
return df, available_cols

def fit(self, train_df: pd.DataFrame, target_col: str = 'was_returned'):
"""Train returns prediction model."""
df, self.feature_cols = self.build_features(train_df)
X = df[self.feature_cols].fillna(0)
y = df[target_col]

self.model = lgb.LGBMClassifier(
n_estimators=300,
learning_rate=0.05,
num_leaves=63,
class_weight='balanced',
verbose=-1
)
self.model.fit(X, y)
return self

def predict_return_probability(self, orders_df: pd.DataFrame) -> pd.DataFrame:
"""Predict return probability for new orders."""
df, _ = self.build_features(orders_df)
X = df[self.feature_cols].fillna(0)
return_probs = self.model.predict_proba(X)[:, 1]

result = orders_df[['order_id']].copy()
result['return_probability'] = return_probs
result['return_risk'] = pd.cut(
return_probs,
bins=[0, 0.2, 0.4, 0.7, 1.0],
labels=['Low', 'Medium', 'High', 'Very High']
)
return result


# ============================================================
# 4. Disruption Detection
# ============================================================

class SupplyChainDisruptionDetector:
"""
Detect supply chain disruptions from multiple signals.
Implements anomaly detection on lead time, fill rate,
and external signals.
"""

def __init__(self, sensitivity: float = 2.5):
"""sensitivity: z-score threshold for anomaly flagging."""
self.sensitivity = sensitivity
self.baselines = {}

def fit_baselines(
self,
historical_df: pd.DataFrame,
group_col: str = 'trade_lane',
metric_cols: list = None
):
"""
Compute rolling baseline statistics for each trade lane / supplier.
"""
if metric_cols is None:
metric_cols = ['actual_lead_time_days', 'fill_rate', 'defect_rate']

for group in historical_df[group_col].unique():
group_data = historical_df[historical_df[group_col] == group]
self.baselines[group] = {}
for col in metric_cols:
if col in group_data.columns:
self.baselines[group][col] = {
'mean': group_data[col].mean(),
'std': group_data[col].std() + 1e-6,
'p95': group_data[col].quantile(0.95)
}

def detect_anomalies(
self,
current_df: pd.DataFrame,
group_col: str = 'trade_lane',
metric_cols: list = None
) -> pd.DataFrame:
"""
Score current observations against baselines.
Returns flagged anomalies with severity scores.
"""
if metric_cols is None:
metric_cols = ['actual_lead_time_days', 'fill_rate', 'defect_rate']

results = []
for _, row in current_df.iterrows():
group = row[group_col]
if group not in self.baselines:
continue

anomaly_scores = {}
for col in metric_cols:
if col not in row or col not in self.baselines[group]:
continue
baseline = self.baselines[group][col]
z_score = (row[col] - baseline['mean']) / baseline['std']
anomaly_scores[f'{col}_zscore'] = z_score
anomaly_scores[f'{col}_anomaly'] = abs(z_score) > self.sensitivity

max_z = max([abs(v) for k, v in anomaly_scores.items() if 'zscore' in k], default=0)
results.append({
group_col: group,
'max_anomaly_zscore': max_z,
'is_disruption': max_z > self.sensitivity,
**anomaly_scores
})

return pd.DataFrame(results)

Architecture Diagrams

Supply Chain AI System

Supplier Risk Assessment Pipeline


Production Engineering Notes

Supply Chain Digital Twins

A digital twin is a real-time simulation model of the entire supply chain. It ingests actual inventory levels, open purchase orders, demand forecasts, and transportation statuses, and can run forward simulations: "If this PO from Vietnam is delayed 2 weeks, and current demand forecast holds, which stores will be out of stock, and when?"

Building a supply chain digital twin requires:

  1. Synchronized data model: all entities (suppliers, DCs, stores, SKUs) with their current state in a queryable format
  2. Event-driven updates: any status change (PO received, shipment dispatched, sales recorded) propagates to the twin immediately
  3. Simulation engine: forward-simulate inventory flows given different scenarios (disruption scenarios, demand shocks, supplier failures)
  4. Scenario comparison: UI for planners to compare outcomes across scenarios and make decisions

The technology stack typically uses a graph database (Neo4j, Amazon Neptune) to represent supply chain relationships, an event streaming platform (Kafka) for state updates, and a simulation layer built in Python (using discrete event simulation libraries like SimPy).

Real-Time Visibility with IoT

Modern warehouses and transportation networks generate continuous IoT signals:

  • RFID readers at dock doors: instant PO receipt confirmation
  • Temperature sensors in refrigerated trucks: cold chain integrity monitoring
  • GPS tracking on delivery vehicles: real-time location and ETA
  • Weight sensors on warehouse shelves: real-time inventory depletion detection

Integrating these signals into the supply chain AI system requires:

  • Edge computing for data reduction (do not send every sensor ping to the cloud; aggregate at the edge)
  • Anomaly detection on sensor streams (a temperature spike in a refrigerated truck requires immediate alert)
  • Data fusion with ERP systems (associate sensor data with specific SKUs and POs)

Common Mistakes

:::danger Single-Sourcing Critical Items The single biggest supply chain vulnerability: sourcing a critical item from a single supplier. When that supplier has a problem - fire, strike, financial distress, geopolitical disruption - you have no fallback. The semiconductor shortage of 2021-2022 hit companies with single-source designs hardest. Build a dual-sourcing policy for any item that represents more than 5% of category revenue. The additional cost of maintaining a second supplier is insurance against supply chain concentration risk. :::

:::danger Treating Lead Time as Fixed in Inventory Planning Using a single average lead time number in your safety stock formula while ignoring variance is a systematic underestimate of required safety stock. If your supplier averages 30 days but the 95th percentile lead time is 50 days, your safety stock formula needs to include D2σL2D^2 \sigma_L^2. Run a sensitivity analysis: if you modeled lead time variance realistically, how much higher would your recommended safety stock be? The difference is your unmodeled risk. :::

:::warning Suppressing Alerts to Avoid Alarm Fatigue Supply chain monitoring systems that generate 100 alerts per day train planners to ignore alerts. Within weeks, the alert system is useless because nobody reads it. Design alert systems with severity tiers, automatic prioritization, and intelligent grouping (multiple POs from the same supplier delayed = one "supplier disruption" alert, not 50 individual PO alerts). Start with a high precision threshold even at the cost of recall - a system that cries wolf trains planners to ignore it, while a system that is occasionally silent about small issues is forgiven. :::


Interview Questions and Answers

Q1: How would you build a system to detect supply chain disruptions in real time?

A: A disruption detection system requires three layers. First, anomaly detection on internal signals: compute rolling baselines for on-time delivery rate, fill rate, and lead time variance per trade lane and supplier. Flag any observations more than 2-3 standard deviations from baseline. This catches operational problems already manifesting in your data. Second, early warning from external signals: monitor port congestion indices (AIS data aggregators like MarineTraffic publish congestion metrics), weather forecast APIs for hurricane/storm alerts along supply routes, geopolitical news (NLP classifier on news articles for keywords like "strike," "port closure," "sanctions," "trade restriction" associated with your supply chain geography), and supplier financial news. Third, correlation engine: link external signals to internal SKU exposure. A port congestion alert in Shanghai needs to trigger an alert for all open POs routing through Shanghai, ranked by revenue impact. The output is a prioritized list of at-risk POs with expected delay, revenue impact, and recommended actions (expedite alternative supplier, adjust safety stock, communicate to stores). The biggest engineering challenge is entity resolution: linking a news mention of "Maersk Line" to specific POs in your ERP that are on Maersk vessels.

Q2: Explain the Vehicle Routing Problem and the difference between exact solvers and heuristics.

A: The Vehicle Routing Problem (VRP) asks: given a fleet of vehicles with limited capacity, a depot, and a set of customers with known demands and time windows, find the minimum-cost set of routes that serves all customers. It is a generalization of the Traveling Salesman Problem (NP-hard). Exact solvers (CPLEX, Gurobi with branch-and-cut algorithms) find the mathematically optimal solution but scale poorly: a 50-stop VRP might take minutes, a 500-stop VRP might take hours. These are used for daily route planning in off-peak batch jobs, not real-time dynamic routing. Metaheuristics (simulated annealing, large neighborhood search, genetic algorithms) find near-optimal solutions in seconds for hundreds of stops. OR-Tools (Google's open-source library) implements high-quality metaheuristics and is the practical standard for mid-size instances. ML-based approaches (pointer networks, RL) are used for real-time re-routing where the problem changes continuously (traffic updates, new delivery requests) and you need a policy that can produce a route in milliseconds, not a solver that optimizes from scratch each time. The tradeoff: ML solutions are typically 3-8% worse than exact solutions but 100-1000x faster, acceptable for dynamic real-time adjustment.

Q3: How would you design a supplier risk scoring system for a retailer with 500 suppliers?

A: I would build a composite multi-dimensional risk model updated daily. Four risk dimensions: operational risk (OTD rate, fill rate, defect rate from PO history - weighted average over last 6 months with recency weighting), financial risk (credit score from a commercial provider like Dun & Bradstreet, current ratio and debt/equity from annual reports, days payable outstanding trends - increasing DPO often precedes financial distress), reputational and news risk (NLP pipeline monitoring news for each supplier, classifying mentions by risk type: labor disputes, regulatory violations, quality recalls, financial distress - sentiment-weighted alert score), and geopolitical risk (country risk index from providers like Control Risks, trade route risk for relevant supply corridors). Each dimension is scored 0-1 and combined with weights calibrated to historical importance: operational risk tends to dominate for day-to-day planning, financial and geopolitical risk dominate for long-term sourcing strategy. The composite score triggers different responses: scores in "High" tier automatically generate a supply chain manager review, "Critical" tier triggers escalation to category VP and evaluation of alternative suppliers. Critically, the model is validated quarterly by back-testing: do the risk scores 6 months ago predict actual disruptions in the subsequent 6 months? This prevents the model from becoming a checkbox exercise.

Q4: What is demand sensing and how does it differ from demand forecasting?

A: Demand forecasting is the process of predicting future demand from historical data - primarily backward-looking. Demand sensing is the process of detecting current or near-future demand signals before they appear in POS data - forward-looking in a 0-14 day horizon. The distinction is timing: a demand forecast made on Monday for next month uses last month's sales data. A demand sensing signal on Monday uses this morning's search volume, last night's social media mentions, and yesterday's web traffic. The value of demand sensing is in the narrow window between when demand begins forming and when it shows up in your inventory depletion. For most retail items, the first indicators of a demand spike (search volume, social buzz, competitor out-of-stocks) appear 24-72 hours before the sales spike hits POS. If your replenishment lead time is 24 hours (urban fulfillment), this window is actionable. If your lead time is 30 days (ocean freight), demand sensing for same-season response is less valuable - but it can still inform next-season purchase quantities for fast-fashion items. Production implementation: train a model on historical (external signals, demand outcome) pairs. For real-time use, pull current signal values hourly, compute predicted demand adjustment factor, and multiply your standard demand forecast by this factor for the short-horizon inventory positioning decision.

Q5: Describe how you would build a returns prediction model and how it would be used operationally.

A: Returns prediction answers: at order placement time, what is the probability this specific order will be returned? Key features: product category (apparel returns at 30-40%, electronics at 10-15%, furniture at 5%), order characteristics (quantity ordered, presence of size variation suggesting fit uncertainty, is_gift_order which has higher return rates post-holiday), customer history (customer's historical return rate - a customer who returns 50% of orders is very different from one who returns 5%), price (higher-price items return more, both because customers are more discerning and because the effort of return is more justified), and purchase channel (mobile purchases return slightly more than desktop, possibly due to image quality differences). Train a gradient boosted classifier on historical orders with actual return outcomes as the target. The model produces a probability of return for each new order. Operational uses: (1) Proactive communication - email high-return-probability customers with size guides, care instructions, and easy return labels to set expectations and reduce friction; (2) Reverse logistics capacity planning - aggregate return probabilities across tomorrow's orders to predict returns volume at each fulfillment center for staffing and restocking decisions; (3) Return prevention - for very high probability returns in apparel, consider proactively reaching out to confirm the customer ordered the right size before shipping; (4) Fraud detection - a customer with a 90% historical return rate ordering 10 units of a high-value item might warrant review.

© 2026 EngineersOfAI. All rights reserved.