Short note. A compact reference, correct as far as it goes. It will be expanded into a full guide with a worked example and an interactive demonstration.
Problem
You want a constraint to hold “most of the time” rather than always — e.g. “inventory should cover demand at least 95% of the time,” not “inventory must always cover demand no matter what,” which would force absurdly high stock levels to guard against the tail.
When to use it
Anywhere a business already thinks in service levels: inventory service level, network reliability targets, staffing to cover demand with a target probability. It’s a direct way to encode “how much risk are we willing to accept” into the model rather than picking safety stock by rule of thumb.
Formulation
A chance constraint requires:
P(a^T x >= b) >= 1 - epsilon
where epsilon is the acceptable failure probability (e.g. 0.05 for a 95%
service level). In general this is nonconvex and hard to solve directly,
but for the common case where the uncertain quantity is normally
distributed, it has a clean closed-form linear reformulation:
demand ~ Normal(mu, sigma^2)
P(inventory >= demand) >= 1 - epsilon
=> inventory >= mu + z_(1-epsilon) * sigma
where z_(1-epsilon) is the standard normal quantile (e.g. 1.645 for 95%).
This is the same idea as
newsvendor’s critical ratio, generalized
into a constraint you can drop into a larger model.
Code sketch
from scipy.stats import norm
service_level = 0.95
mu, sigma = 500, 60
z = norm.ppf(service_level)
safety_stock = z * sigma
required_inventory = mu + safety_stock # plug this into the larger MILP as a bound
Pitfalls
- The clean linear reformulation only holds for specific distributions (normal being the common one) and specific constraint structures. For general nonlinear or non-Gaussian cases, chance constraints become genuinely hard (nonconvex), and you typically approximate via sampling (scenario-based chance constraints) instead.
- Correlated uncertainty across multiple constraints (e.g. shared demand risk across several products) breaks the simple per-constraint reformulation — you need a joint chance constraint, which is meaningfully harder than the individual (marginal) version shown here.
- A 95% service level sounds safe until you have many such constraints simultaneously — the probability that all of them hold is lower than 95% unless you explicitly account for that (a joint, not marginal, guarantee).