Skip to main content

DiffHandoff

Struct DiffHandoff 

Source
pub struct DiffHandoff {
    pub x: Vec<Number>,
    pub obj_val: Number,
    pub lambda: Vec<Number>,
    pub mult_x_lower: Vec<Number>,
    pub mult_x_upper: Vec<Number>,
    pub active_constraints: Vec<bool>,
    pub pinned_vars: Vec<bool>,
    pub active_tol: Number,
}
Expand description

Everything the implicit-function-theorem backward pass needs from a converged solve, in a solver-agnostic shape.

Producers (IPM-NLP, convex LP/QP, conic, and — for discopt — the fixed-integer leaf of a branch-and-bound) emit this; consumers (pounce.jax, pounce.torch, the C ABI, a future Rust autodiff user, discopt across the solve_nlp seam) differentiate from it.

The multiplier sign / length conventions match the existing C ABI and Python info dict (mult_g, mult_x_L, mult_x_U), so this is a re-shape of data POUNCE already returns — not a new computation — plus the precomputed active-set masks, which are the genuinely new part.

Fields§

§x: Vec<Number>

Final primal iterate x* (length n_x).

§obj_val: Number

Objective value f(x*).

§lambda: Vec<Number>

General-constraint multipliers λ (length n_g). The g/G/A duals, depending on the solver; one name across all of them.

§mult_x_lower: Vec<Number>

Variable lower-bound multipliers z_L (length n_x).

§mult_x_upper: Vec<Number>

Variable upper-bound multipliers z_U (length n_x).

§active_constraints: Vec<bool>

Constraint rows in the differentiated KKT block: equalities (always) plus inequalities whose |λ| > active_tol. Length n_g. Inactive (slack) rows drop out of the backward block.

§pinned_vars: Vec<bool>

Variables pinned in the backward (dx/dp = 0): those with an active bound (max(z_L, z_U) > active_tol) and — for a B&B leaf — integer variables fixed at the optimum (see Self::pin). Length n_x.

§active_tol: Number

The activity tolerance used to derive the masks above. Recorded so consumers and tests see the exact threshold.

Implementations§

Source§

impl DiffHandoff

Source

pub fn from_solution( x: Vec<Number>, obj_val: Number, lambda: Vec<Number>, mult_x_lower: Vec<Number>, mult_x_upper: Vec<Number>, equality_mask: &[bool], active_tol: Number, ) -> Self

Build a handoff from the raw converged solution and duals, deriving the active-set masks with active_tol.

equality_mask[i] is true when constraint i is an equality (g_l[i] == g_u[i]) — such rows are always active. Pass an empty slice when there are no general constraints.

Source

pub fn masks( mult_x_lower: &[Number], mult_x_upper: &[Number], lambda: &[Number], equality_mask: &[bool], active_tol: Number, ) -> (Vec<bool>, Vec<bool>)

Derive the active-set masks (pinned_vars, active_constraints) from borrowed duals — the single active-set derivation, shared by Self::from_solution and producers that want only the masks (e.g. the Python info dict) without surrendering the solution vectors. Keeping the rule here means “|mult| > active_tol, equalities always active” lives in exactly one place.

pinned_vars[i] is true when variable i’s lower- or upper-bound multiplier exceeds active_tol. active_constraints[i] is true for an equality row (equality_mask[i]) or one whose |lambda[i]| > active_tol. equality_mask may be empty (no equalities known) or length lambda.len().

Source

pub fn from_sens_result( res: &SensResult, equality_mask: &[bool], ) -> Option<Self>

Re-shape a SensResult from a converged solve into a DiffHandoff, using DEFAULT_ACTIVE_TOL.

Returns None when the solve did not populate the duals (mult_g / mult_x_l / mult_x_u) — i.e. it didn’t converge, or the NLP didn’t expose user-space multipliers.

equality_mask is the caller’s g_l[i] == g_u[i] test, length n_g. Pass the real mask whenever the problem has equality constraints. Equality rows are always part of the differentiated KKT block regardless of multiplier magnitude, and the mask is the only way from_sens_result learns which rows those are — a SensResult carries the constraint values (g) but not their [g_l, g_u] bounds, so equalities can’t be recovered from it.

An empty slice means “no equality information”: a row then counts as active only when |λ| > active_tol. That is correct only when the problem has no equalities. ⚠ With equalities present it silently drops any degenerate equality — one whose multiplier is ≈ 0 (redundant rows, or an equality not binding the optimum’s curvature) — from the active set, yielding a wrong backward block and wrong gradients. Dropping a row is the unsafe direction, so the empty slice is a convenience for the no-equality case, not a safe default.

Source

pub fn pin(&mut self, indices: &[Index])

Additionally pin a set of variables — the seam discopt uses for a branch-and-bound leaf: integer variables fixed at the optimum differentiate exactly like active bounds (dx/dp = 0). Indices out of range are ignored.

Source

pub fn n_x(&self) -> usize

Number of primal variables.

Source

pub fn n_g(&self) -> usize

Number of general constraints.

Source

pub fn n_pinned(&self) -> usize

Count of pinned variables (active bounds + any Self::pinned).

Source

pub fn n_active_constraints(&self) -> usize

Count of active constraint rows.

Trait Implementations§

Source§

impl Clone for DiffHandoff

Source§

fn clone(&self) -> DiffHandoff

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DiffHandoff

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. 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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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