1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! Sensitivity analysis for POUNCE — port of upstream Ipopt's `contrib/sIPOPT/`.
//!
//! # Status
//!
//! Phases A–C complete. Wired today:
//!
//! * [`schur_data::IndexSchurData`] + [`p_calculator::IndexPCalculator`]:
//! row-selector representation of the perturbation matrix `B`.
//! * [`backsolver::DenseLuBacksolver`] + [`PdSensBacksolver`]: backsolves
//! against the converged KKT factor (test / live IPM, respectively).
//! * [`schur_driver::DenseGenSchurDriver`]: dense Schur-complement
//! factor `S = -B K⁻¹ Bᵀ` with parallel right-hand-side solves.
//! * [`step_calc::StdStepCalc`] + [`sens_app::SensApplication`]:
//! high-level `parametric_step(Δp, dx)` and
//! [`reduced_hessian::compute_reduced_hessian`] entry points.
//! * [`SensSolve`] / [`SensResult`]: one-call builder (covers the
//! `on_converged` plumbing typically required to wire the above into
//! an `IpoptApplication`).
//!
//! Verified against upstream sIPOPT 3.14.19's `parametric_cpp` golden
//! output to 1e-8 (see `tests/parametric_cpp.rs`); the standalone
//! `pounce_sens` AMPL driver in `pounce-cli` matches `sensitivity_amplsolver`'s
//! `_sens_sol` output on representative .nl problems.
//!
//! **Phase D progress** (per [pounce#7](https://github.com/jkitchin/pounce/issues/7)):
//!
//! * **Fixed-variable lifting** ✔ — `pounce_sens` handles `n_x != n_full`
//! via the `IpoptNlp::full_x_to_var_x` / `var_x_to_full_x` /
//! `full_g_to_c_block` trait methods (which delegate to
//! `BoundClassification.x_not_fixed_map` / `c_map`).
//! * **Reduced-Hessian eigendecomposition** ✔ — pure-Rust cyclic Jacobi
//! in [`eigen::symmetric_eigen`]; surfaced via
//! [`SensApplication::compute_reduced_hessian_eigen`],
//! [`SensSolve::with_reduced_hessian_eigen`], the `pounce_sens
//! --rh-eigendecomp` flag, and the Python `solve_with_sens(rh_eigendecomp=True)`
//! kwarg.
//! * **`sens_boundcheck` bound projection** ✔ (single-pass clamp) —
//! [`boundcheck::clamp_step_to_bounds`] /
//! [`boundcheck::clamp_with_nlp`] project the perturbed step onto
//! `[x_l, x_u]` after the linear solve. Surfaced via
//! [`SensSolve::with_boundcheck`], `pounce_sens --sens-boundcheck`,
//! and the Python `solve_with_sens(sens_boundcheck=True)` kwarg.
//! Upstream's iterative Schur refinement (re-factorize on each
//! violation) is **not** ported — see [`boundcheck`] module docs.
//!
//! # Algorithmic reference
//!
//! Pirnay, H., López-Negrete, R., and Biegler, L.T. (2012).
//! *Optimal sensitivity based on IPOPT.*
//! Mathematical Programming Computation, **4**(4), 307–331.
//! [DOI: 10.1007/s12532-012-0043-2](https://doi.org/10.1007/s12532-012-0043-2).
//!
//! Verified 2026-05-14 via Crossref: title, authors (Hans Pirnay; Rodrigo
//! López-Negrete; Lorenz T. Biegler), MPC volume 4 issue 4 pp 307–331.
//!
//! # Upstream source mirror
//!
//! Port targets `ref/Ipopt/contrib/sIPOPT/src/` in this repo
//! (EPL-2.0, © Hans Pirnay 2009–2011 per the file headers). Each
//! public item in this crate documents the upstream symbol it mirrors
//! with file path and (where stable) line numbers.
pub use PdSensBacksolver;
pub use ;
pub use ;
pub use symmetric_eigen;
pub use ;
pub use compute_reduced_hessian;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;