pympcc.verify_b_stationarity¶
- pympcc.verify_b_stationarity(result, problem, *, tol=1e-06, max_biactive=10)[source]¶
Test B-stationarity of an MPCC solution by enumerating linearised-MPCC tangent-cone branches and solving an LP per branch.
For each biactive pair
i ∈ I_00 = {i : G_i(x*) ≤ tol AND H_i(x*) ≤ tol}the linearised tangent cone splits into two branches:G branch (G stays active):
∇G_iᵀ d = 0, ∇H_iᵀ d ≥ 0H branch (H stays active):
∇H_iᵀ d = 0, ∇G_iᵀ d ≥ 0
For every assignment of branches to the
|I_00|pairs (2^|I_00|LPs), solve:min ∇f(x*)ᵀ d s.t. ∇g_jᵀ d ≤ 0 j active inequality (g_j(x*) ≥ -tol) ∇hᵀ d = 0 ∇G_iᵀ d = 0 i ∈ I_0+ (G_i = 0, H_i > 0 — H>0 locally forces G_i to stay zero) ∇H_iᵀ d = 0 i ∈ I_+0 (G_i > 0, H_i = 0 — G>0 locally forces H_i to stay zero) branch-specific G/H linearisations for i ∈ I_00 d_j ≥ 0 if x*_j is at xl_j; d_j ≤ 0 if at xu_j ‖d‖_∞ ≤ 1 (normalisation; LP would be unbounded)x*is B-stationary iff every branch’s LP minimum is ≥ 0 (no feasible first-order descent direction in the linearised cone).- Parameters:
result (MPCCResult) – A solved MPCC result (
result.x,result.G,result.H,result.successare read).problem (MPCCProblem) – The problem instance used to produce the result.
tol (float, optional) – Tolerance for the active-set partition (default
1e-6). Pair i is biactive whenG_i ≤ tol AND H_i ≤ tol; a constraintg_jis active wheng_j ≥ -tol; a variable bound is active when|x_j − xl_j| ≤ tol(resp.xu).max_biactive (int, optional) – Skip when
|I_00| > max_biactive(default10→ up to 1024 LPs).
- Returns:
Result dict with keys:
status— one of"B-stationary"(every branch min ≥ -tol),"not B-stationary"(at least one branch admits descent),"intractable"(|I_00| > max_biactive; LP enumeration skipped), or"unknown"(result.success is False).n_biactive—|I_00|.n_branches_checked— LPs actually solved (0 on early exit).min_descent— minimum∇fᵀdover branches (Noneon early exit).witness_branch— tuple of'G'/'H'chars indexed by the biactive pairs in I_00 order;Noneif B-stationary.witness_d— ndarray, shape(n,)— the descent direction;Noneif B-stationary.
- Return type:
Notes
Uses dense LPs (
scipy.optimize.linprogwith method"highs"). Intended as a diagnostic for small/medium MPCCs; cost isO(2^|I_00| · LP)and the per-LP build is dense inn.The strongest stationarity level reachable from KKT multipliers alone (
classify_stationarity) is S, which under MPCC-LICQ is equivalent to B-stationarity. This routine directly certifies B-stationarity without needing MPCC-LICQ to hold.