Skip to main content

LowRankAugSystemSolver

Struct LowRankAugSystemSolver 

Source
pub struct LowRankAugSystemSolver { /* private fields */ }

Implementations§

Source§

impl LowRankAugSystemSolver

Source

pub fn new(inner: Box<dyn AugSystemSolver>) -> Self

Source

pub fn with_bypass_solver( inner: Box<dyn AugSystemSolver>, bypass: Box<dyn AugSystemSolver>, ) -> Self

Same as Self::new but routes the Hessian-free solves through their own inner solver.

Under limited-memory this solver drives its inner solver with two different (1,1) shapes: an empty W for the least-square multiplier initialization and the equality-multiplier estimates, and an n-diagonal B0 for the main primal-dual solves. StdAugSystemSolver keys its structure signature on W’s nonzero count, so the two alternate and every alternation re-runs the backend’s symbolic factorization — for MA57 with ma57_pivot_order = 5 a full MeTiS nested dissection of the whole KKT system, ~0.4 s per call on a 118 276-row model (gh#730).

Ipopt never pays this because its low-rank layer owns those solves, so its inner solver sees one shape for its whole life — IpTSymLinearSolver.cpp:182 asserts exactly that. Giving the bypass its own solver reproduces that invariant on both sides instead of on neither.

Deliberately not done by making the two shapes agree — e.g. substituting a zeroed n-diagonal for the empty W, which is what the shape proposed in gh#730 does. That is numerically exact, but it changes the pattern the backend orders, and a different ordering rounds differently: swept, it takes pooling_rt2stp under MA57 from obj = -4391.83 to -3273.95 (both “Optimal”, 25% apart) and cresc4 from 110 to 267 iterations. Two solvers hand each path exactly the matrix and the ordering it already had, so the win is free of trajectory movement rather than paid for with it.

The cost is one additional numeric factorization resident at once. That is the deliberate trade: memory is measurable and boundable, and a trajectory regression is what has repeatedly shipped here undetected (dev-notes/trajectory-regressions-and-\ the-fixture-sweep.md).

Source

pub fn augmented_system_requires_change( &self, coeffs: &AugSysCoeffs<'_>, ) -> bool

Pure tag/scalar comparison — port of upstream AugmentedSystemRequiresChange (IpLowRankAugSystemSolver.cpp:531-599).

Source

pub fn first_call(&self) -> bool

Source

pub fn cache(&self) -> &AugSysCache

Trait Implementations§

Source§

impl AugSystemSolver for LowRankAugSystemSolver

Source§

fn resolve( &mut self, coeffs: &AugSysCoeffs<'_>, rhs: &AugSysRhs<'_>, sol: &mut AugSysSol<'_>, ) -> ESymSolverStatus

Back-substitution against the cached factor, plus the same SMW corrections solve applies.

Without this override the trait default falls through to solve, which re-factorizes — and because PdFullSpaceSolver’s iterative refinement and its same-matrix fast path both come in through resolve, that made the majority of the augmented-system solves on the limited-memory path re-factorize a matrix that had not changed. It also left LinearSystemBackSolve reading 0.000 s for a whole run, since the only back-solve timer guard lives on the path nothing reached (gh#698).

Every condition that cannot be served falls back to solve, so this can lose an optimization but cannot change an answer — the same defensive shape as StdAugSystemSolver::resolve’s own have_factor fallback.

Source§

fn provides_inertia(&self) -> bool

Whether the underlying linear solver reports inertia.
Source§

fn number_of_neg_evals(&self) -> Index

Number of negative eigenvalues observed in the most recent factorization. Caller checks provides_inertia() first.
Source§

fn increase_quality(&mut self) -> bool

Ask the underlying solver for higher-quality pivoting.
Source§

fn last_solve_status(&self) -> ESymSolverStatus

Status of the most recent solve call.
Source§

fn set_timing_stats(&mut self, timing: Rc<TimingStatistics>)

Install the shared per-solve TimingStatistics so the linear-system factor/back-solve calls are attributed to linear_system_factorization / linear_system_back_solve. Default impl is a no-op (timing disabled); the standard solver overrides to record both fields, and composite solvers (LowRank) forward to their inner solver.
Source§

fn set_slack_scaling(&mut self, nx: Index, s_scale: &[Number])

Push the per-iterate part of linear_system_scaling=slack-based down to the linear solver’s scaling method. Default no-op; StdAugSystemSolver forwards to its TSymLinearSolver, and composite solvers forward to their inner solver. Read more
Source§

fn handles_low_rank_w(&self) -> bool

Whether this solver can consume a LowRankUpdateSymMatrix as coeffs.w directly, applying it by Sherman-Morrison-Woodbury rather than needing an assembled triplet matrix. Read more
Source§

fn solve( &mut self, coeffs: &AugSysCoeffs<'_>, rhs: &AugSysRhs<'_>, sol: &mut AugSysSol<'_>, check_neg_evals: bool, num_neg_evals: Index, ) -> ESymSolverStatus

One factor + back-substitution for the full 4×4 block system. check_neg_evals=true asks the linsol to verify that the observed inertia equals num_neg_evals; on mismatch the status is WrongInertia and the solution is left untouched.
Source§

fn system_dim(&self) -> Index

Dimension of the assembled augmented (KKT) system. Used by the interactive debugger to report inertia; default 0 for backends that don’t track it.
Source§

fn kkt_triplets(&self) -> Option<(Index, Vec<Index>, Vec<Index>, Vec<Number>)>

Triplets of the assembled KKT matrix (dim, irn, jcn, vals) (1-based lower triangle), for the debugger’s viz kkt. Default None for backends that don’t expose them.
Source§

fn l_factor(&self, _want_values: bool) -> Option<FactorPattern>

The LDLᵀ factor pattern (and optionally values) of the most recent factorization, for the debugger’s viz L. Default None.
Source§

fn set_diagnostics(&mut self, _diag: Rc<DiagnosticsState>)

Install the shared per-solve diagnostics state so KKT-dump sites can consult per-iter gating. Default impl is a no-op (diagnostics disabled); the standard solver overrides to wire in the dump path.
Source§

fn multi_solve( &mut self, coeffs: &AugSysCoeffs<'_>, rhs_list: &[&AugSysRhs<'_>], sol_list: &mut [&mut AugSysSol<'_>], check_neg_evals: bool, num_neg_evals: Index, ) -> ESymSolverStatus

Solve the same KKT system for nrhs right-hand sides. Default impl loops [solve]; concrete backends override only when they can amortize factorization across calls. Mirrors upstream’s AugSystemSolver::MultiSolve (IpAugSystemSolver.hpp:113-150). Read more
Source§

fn try_resolve_many_flat( &mut self, _coeffs: &AugSysCoeffs<'_>, _packed_rhs: &mut [Number], _nrhs: usize, ) -> Option<ESymSolverStatus>

Back-substitution only against the cached factor for nrhs right-hand sides, packed in column-major layout in packed_rhs. Each column has length dim = n_x + n_s + n_y_c + n_y_d (the aug-system dim — z/v blocks are not part of this path; callers expand them via expand_bound_multipliers after the fact). Solutions overwrite packed_rhs in place. Read more
Source§

fn try_solve_many_flat( &mut self, _coeffs: &AugSysCoeffs<'_>, _packed_rhs: &mut [Number], _nrhs: usize, _check_neg_evals: bool, _num_neg_evals: Index, ) -> Option<ESymSolverStatus>

Factorize and solve nrhs right-hand sides in a single backend call, with packed_rhs in the same column-major layout Self::try_resolve_many_flat uses. Solutions overwrite packed_rhs in place. Read more
Source§

fn multi_solve_matches_single_solve(&self, _nrhs: usize) -> bool

Whether Self::try_resolve_many_flat with nrhs columns returns bit-identical results to nrhs separate Self::resolve calls. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ByRef<T> for T

Source§

fn by_ref(&self) -> &T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Imply<T> for U
where T: ?Sized, U: ?Sized,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more