Chance Constraints
As a placeholder, mpi-sppy supports a PySP-style, sample-average-approximation (SAA) chance constraint of the form
As in PySP, you define a binary indicator variable in each scenario model together with your own big-M constraints linking it to satisfaction; mpi-sppy adds the single aggregating constraint that turns the per-scenario indicators into a probabilistic guarantee.
Warning
Scope: chance constraints are supported only for the extensive-form (EF) solve. A chance constraint \(\sum_s p_s z_s \ge 1 - \alpha\) is a single constraint that couples a (binary) indicator variable from every scenario, so – unlike CVaR – it does not separate across scenarios and is not inherited by the PH / APH / Lagrangian / xhat decomposition cylinders. This matches PySP, which only solves the EF. Decomposing a chance constraint (e.g. Lagrangian dualization of the coupling constraint with a scalar price) is possible but is a substantially harder effort with an integrality duality gap. If you need chance constraints under decomposition, please contact the mpi-sppy developers.
The indicator convention
For each scenario s define a binary variable z_s with
and add your own big-M constraint(s) enforcing the link (so that z_s = 1
forces satisfaction). mpi-sppy then adds
i.e. E[z] >= 1 - alpha: the probability mass of satisfying scenarios is at
least \(1 - \alpha\), so the violation probability is at most
\(\alpha\). Setting alpha = 0 forces satisfaction in every scenario (a
robust constraint); a larger alpha buys a cheaper objective by letting the
worst (most expensive to satisfy) scenarios fail. The indicator must be
binary for the constraint to be exact; a continuous “indicator” yields a
relaxation and triggers a warning.
If the indicator variable is indexed, mpi-sppy adds one chance constraint per index of the variable.
Command line (generic_cylinders)
Use the --EF flag together with:
--cc-indicator-var NAME– the name of your per-scenario binary indicator (its presence enables the chance constraint);--cc-alpha ALPHA– the allowed violation probability,0 <= alpha < 1(default0.0).
For example, the bundled capacity example builds enough capacity to meet demand with probability at least \(1 - \alpha\):
python -m mpisppy.generic_cylinders \
--module-name examples/chance_constraint/cc_capacity \
--num-scens 10 --EF --EF-solver-name gurobi \
--cc-indicator-var served --cc-alpha 0.2
With the deterministic ramp demands in that example, the cost-minimizing
capacity is the \((1-\alpha)\)-quantile of demand (here, 80). Requesting
a chance constraint without --EF is rejected at parse time.
Programmatic use
When you build the EF yourself (via ExtensiveForm or
sputils.create_EF), call mpisppy.utils.chance_constraint.add_chance_constraint()
on the assembled model after construction and before solving:
import mpisppy.utils.sputils as sputils
from mpisppy.utils import chance_constraint
ef = sputils.create_EF(scenario_names, scenario_creator)
chance_constraint.add_chance_constraint(
ef, cc_indicator_var_name="served", cc_alpha=0.2)
# ... now solve ef ...
- mpisppy.utils.chance_constraint.add_chance_constraint(ef_model, *, cc_indicator_var_name, cc_alpha)[source]
Add a PySP-style SAA chance constraint to an already-built EF model.
For a scalar indicator variable, adds to
ef_modelthe single constraintSum_s p_s * z_s >= (1 - cc_alpha) * Sum_s p_s
where
z_s = getattr(scenario_s, cc_indicator_var_name). TheSum_s p_sfactor on the right is the total probability of the scenarios in this model (1.0 for a full EF); carrying it makes the constraint correct even for normalized / bundled EFs and reduces to PySP’s plain>= 1 - alphawhen the probabilities sum to one.For an indexed indicator variable, adds one such constraint per index of the variable (one chance constraint per index, joint over scenarios).
The user is responsible for defining
z_s(binary) and the big-M constraints linking it to satisfaction, exactly as in PySP. This function adds only the aggregator.- Parameters:
ef_model (Pyomo ConcreteModel) – an assembled extensive form, i.e.
ExtensiveForm.efor the result ofsputils.create_EF. It must carry_ef_scenario_namesand expose each scenario as a sub-block with a_mpisppy_probabilityattribute.cc_indicator_var_name (str) – the name of the per-scenario indicator variable (scalar or indexed).
cc_alpha (float) – the allowed violation probability, 0 <= alpha < 1. alpha = 0 forces satisfaction in every scenario (a robust constraint).
- Returns:
the constraint component added to
ef_model(scalar or indexed), also reachable asef_model._mpisppy_chance_constraint.- Return type:
pyo.Constraint