Expand description
The parametric sensitivity step on the convex dispatch path.
crate::sens is the NLP arm’s producer: it reads the filter-IPM’s
converged KKT factor through PdSensBacksolver and is hard-wired to
pounce_algorithm types. This module is its convex counterpart, built on
pounce_convex::QpSensitivity — the same sIPOPT computation over the
active-set KKT the convex IPM’s solution defines.
§Why the CLI needed one at all
Before this, a .nl carrying the sIPOPT suffixes made auto decline the
convex fast path outright (issue #196) and pay the general engine’s cost for
a problem the specialized one solves, because only the general engine could
answer the question. Under an explicit solver_selection=qp-ipm the request
was warned about and dropped. Now an LP or convex QP whose pins the convex
arm can express is served where it was solved.
§The index space, which is the whole risk here
The request arrives in the .nl’s own indices:
sens_state_1— var-int, one slot per original variable;sens_state_value_1— var-real, the perturbed value;sens_init_constr— con-int, which original constraint pins each parameter.
QpSensitivity::parametric_step takes indices into the extracted QP’s
equality right-hand side b, which is a different space: the extractor
splits ranges, drops empty rows, and orders equalities and inequalities into
separate blocks. qp_extract::ConRowMap is
the single source of truth for that map, and this module reads it rather
than reconstructing the correspondence — /sens-review entry 1, in the
space that entry was written about.
Two hazards the NLP arm has and this one does not, worth naming so nobody goes looking for them:
- No var-x / full-x split. The extractor keeps variables 1:1 with the
.nl(qp.n == prob.n), including fixed ones, so there is nolift_x_to_fulland no gh#450 to reproduce.the_convex_arm_has_no_var_x_splitasserts that rather than leaving it as a reading of the extractor. - No presolve row space — but not for the reason it looks like. The
convex driver postsolves back to the extracted-QP space before anything
downstream runs, so the pins stay valid even with presolve on; that was
measured rather than assumed. Presolve is switched off anyway, because on
the one fixture that exercises it presolve fixes the parameter the pin
parametrizes and drops its row, leaving the sensitivity to read a
postsolve reconstruction instead of the converged KKT — four orders of
accuracy on the step, and an unmeasured question about whether the
reconstructed bound multipliers can move the inferred active set. See the
call site in
main.rsfor the numbers.
Structs§
- Sens
Pins - A parametric-step request resolved into the extracted QP’s own indices.
Enums§
- PinRefusal
- Why the convex arm cannot express this request. Carrying the reason (rather
than an
Option) is what lets the caller print a message a user can act on — and what keeps “the convex arm declined” distinguishable from “the convex arm answered zero”.
Functions§
- perturbed_
x - Take the step and return the perturbed primal, in the
.nl’s own variable order. - resolve_
pins - Resolve the
.nl’s sIPOPT suffixes into pins on the extracted QP. - sens_
suffix - The
.solblock the NLP path writes under the same name, so a consumer cannot tell which engine produced it — which is the point.