Skip to main content

Crate pounce_presolve

Crate pounce_presolve 

Source
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 λ=0 when forwarding eval_h / finalize_solution to 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 ≥ 2 tightening x_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 by tests::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_z and exposed via PresolveTnlp::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 at finalize_solution. It lives in its own wrapper (linear_eq_elim::LinearEqElimTnlp) stacked outside PresolveTnlp, 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 BlockSolver trait 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 InequalityCoupled candidate 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§

CachedBounds
PresolveTnlp
TNLP wrapper that re-presents the inner problem after presolve.

Enums§

PresolveError
Errors that can arise while building a presolved TNLP.
WitnessRule
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_options directly.
wrap_from_options
Convenience: read the presolve_* keys out of an OptionsList and call wrap_with_presolve.
wrap_with_presolve
Top-level entry: returns a TNLP wrapping inner with whatever presolve passes the option table has enabled. When the master switch is off, returns inner unchanged.
wrap_with_presolve_provider
Same as wrap_with_presolve but also installs an ExpressionProvider so passes like FBBT (issue #62) can see constraint expression trees. Callers who have the concrete inner TNLP type (pounce-cli with NlTnlp) should prefer this; the plain wrap_with_presolve leaves presolve_fbbt as a silent no-op.