Expand description
Algorithmic NLP preprocessing exposed as a composable TNLP wrapper.
Tracks pounce issue #20.
-
Phase 0 — scaffolding, options table, no-op identity path.
-
Phase 1 — Andersen-style bound tightening against linear rows.
-
Phase 2 — redundant linear-constraint removal: rows whose activity interval is implied by the (possibly Phase-1-tightened) variable box are dropped from the problem the solver sees, then reinstated with
λ=0when forwardingeval_h/finalize_solutionto the inner TNLP.Dual-attribution caveat (issue M24). A row that was itself the reason a bound got tightened in Phase 1 — e.g.
x ≥ 2tighteningx_l = 2— then has an activity interval flush against its own bound, so Phase 2 sees it as redundant and drops it. If that bound is active at the solution the interior-point method reports the dual on the variable bound multiplier (z_l/z_u) against a bound that did not exist in the original problem, while the reinstated row keepsλ = 0. The primal point, objective, and KKT stationarity (∇f − Jᵀλ − z_l + z_u = 0) are all unaffected — only the attribution of the dual differs from a no-presolve solve (row multiplier vs. bound multiplier). A faithful fix would transfer the bound multiplier back to the row’sλ, but that needs Phase-1 provenance (which row implied which bound) that is not currently tracked, and is ambiguous for multi-variable rows; it is left as future work. The behavior is pinned bytests::dropped_row_dual_lands_on_bound_not_row(M24). -
Phase 3 — structural LICQ check on the surviving equality rows. Verdict is published via
PresolveTnlp::licq_verdict. -
Phase 4 — bound-multiplier warm-start hints for variables whose bounds were tightened by Phase 1. Hints are emitted on
init_zand exposed viaPresolveTnlp::z_warm_starts. -
Phase 5 — sensitivity-aware passthrough: projects user-supplied constraint metadata and scaling through the row reduction on the way in, and expands outer→inner on the way out in
finalize_metadata. -
Phase 6 — linear-equality variable elimination (
presolve_linear_eq_reduction, issue #487). The only phase that removes columns: singleton and two-variable linear equality rows determine variables, which are substituted away and recovered atfinalize_solution. It lives in its own wrapper (linear_eq_elim::LinearEqElimTnlp) stacked outsidePresolveTnlp, so Phases 0–5 keep working in the variable space they were written against, and it is the outer layer that re-presents the reduced one. Off by default.
Re-exports§
pub use block_solve::BlockEquations;pub use block_solve::BlockSolveError;pub use block_solve::BlockSolveOptions;pub use block_solve::BlockSolveOutcome;pub use block_solve::BlockSolver;pub use block_solve::DampedNewtonSolver;pub use bound_tighten::INF_BOUND;pub use bound_tighten::LinearRow;pub use bound_tighten::TightenReport;pub use bound_tighten::tighten_bounds;pub use btf::BlockTriangularBlock;pub use btf::BlockTriangularForm;pub use components::SquareComponent;pub use components::SquareComponents;pub use coupling::AuxiliaryCouplingClass;pub use coupling::classify_block;pub use coupling::objective_gradient_support;pub use diagnostics::AuxiliaryPreprocessingDiagnostics;pub use diagnostics::AuxiliaryRejectionReason;pub use dulmage_mendelsohn::DMPart;pub use dulmage_mendelsohn::DulmageMendelsohnPartition;pub use incidence::EqualityIncidence;pub use incidence::InequalityIncidence;pub use incidence::ProbeView;pub use licq::EqRow;pub use licq::LicqVerdict;pub use licq::licq_check;pub use linear_eq_elim::FullSolution;pub use linear_eq_elim::LinearEqElimTnlp;pub use linear_eq_elim::recover_dropped_multipliers;pub use linear_eq_plan::ElimStep;pub use linear_eq_plan::EliminationPlan;pub use linear_eq_plan::LinearEqElimReport;pub use linear_eq_plan::PlanConfig;pub use linear_eq_plan::PlanInput;pub use linear_eq_plan::VarRecovery;pub use linear_eq_plan::build_plan;pub use options::AuxiliaryCouplingPolicy;pub use options::LicqAction;pub use options::PresolveOptions;pub use options::register_options;pub use reduction_frame::ReductionFrame;pub use reduction_frame::ReductionStack;pub use redundant::find_redundant_rows;
Modules§
- auxiliary
- Phase-0 orchestrator for auxiliary-equality preprocessing.
- block_
solve - Lightweight damped-Newton solver for square ≤ 8-dim auxiliary
blocks, plus the
BlockSolvertrait for the larger-block fallback. - bound_
tighten - Phase 1 — bound tightening via constraint propagation.
- btf
- Tarjan SCC + topological order → block-triangular form on each connected component of the square-matched part.
- components
- Weakly-connected component extraction on the square-matched part of a Dulmage-Mendelsohn partition.
- coupling
- Coupling classification for candidate auxiliary blocks.
- diagnostics
- Diagnostics for the auxiliary-equality preprocessing pass (Phase 0).
- dulmage_
mendelsohn - Dulmage-Mendelsohn partition into under- / square- / overdetermined parts.
- fbbt
- Feasibility-Based Bound Tightening (FBBT).
- incidence
- Bipartite incidence graph between equality rows and variables.
- inequality_
projection - Inequality projection for
InequalityCoupledcandidate blocks. - licq
- Phase 3 — LICQ degeneracy detection.
- linear_
eq_ elim - Phase 6 — the TNLP wrapper that applies a
EliminationPlan(issue #487). - linear_
eq_ plan - Phase 6, planning half — decide which variables a model’s linear equality rows determine (issue #487).
- matching
- Hopcroft-Karp bipartite matching on an
crate::incidence::EqualityIncidence. - options
- Option-table integration for
pounce-presolve. - reduction_
frame - Postsolve frame stack for the auxiliary-equality preprocessing pass.
- redundant
- Phase 2 — redundant linear-constraint detection.
- trivial_
elim - Trivial-elimination pre-pass for the auxiliary-equality preprocessing pipeline.
Structs§
- Cached
Bounds - Presolve
Tnlp - TNLP wrapper that re-presents the inner problem after presolve.
Enums§
- Presolve
Error - Errors that can arise while building a presolved TNLP.
- Witness
Rule - Which accepting test the witness-refutation gate uses to decide that a sampled point satisfies a row.
Functions§
- register
- Re-export for callers that already imported
pounce_presolve::register_optionsdirectly. - wrap_
from_ options - Convenience: read the
presolve_*keys out of anOptionsListand callwrap_with_presolve. - wrap_
with_ presolve - Top-level entry: returns a TNLP wrapping
innerwith whatever presolve passes the option table has enabled. When the master switch is off, returnsinnerunchanged. - wrap_
with_ presolve_ provider - Same as
wrap_with_presolvebut also installs anExpressionProviderso passes like FBBT (issue #62) can see constraint expression trees. Callers who have the concrete inner TNLP type (pounce-cliwithNlTnlp) should prefer this; the plainwrap_with_presolveleavespresolve_fbbtas a silent no-op.