Skip to main content

Module convex_sens

Module convex_sens 

Source
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 no lift_x_to_full and no gh#450 to reproduce. the_convex_arm_has_no_var_x_split asserts 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.rs for the numbers.

Structs§

SensPins
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 .sol block the NLP path writes under the same name, so a consumer cannot tell which engine produced it — which is the point.