Skip to main content

IpoptCalculatedQuantities

Struct IpoptCalculatedQuantities 

Source
pub struct IpoptCalculatedQuantities {
    pub s_max: Number,
    pub kappa_d: Number,
    pub slack_move: Number,
    /* private fields */
}
Expand description

Calculated-quantities object. Holds shared handles on data and the NLP; per-quantity caches live in RefCells here.

Fields§

§s_max: Number

Optimality scaling cap from IpOptErrorConvCheck defaults.

§kappa_d: Number

Damping coefficient for the bound-multiplier complementarity term (kappa_d in upstream’s RegisterOptions).

§slack_move: Number

Correction size for very small slacks (slack_move option, default mach_eps^{3/4}). Drives calculate_safe_slack’s upper cap on the moved bound — port of upstream’s slack_move_ (IpIpoptCalculatedQuantities.cpp:525).

Implementations§

Source§

impl IpoptCalculatedQuantities

Source

pub fn new(data: IpoptDataHandle, nlp: Rc<RefCell<dyn IpoptNlp>>) -> Self

Source

pub fn data(&self) -> &IpoptDataHandle

Source

pub fn nlp(&self) -> &Rc<RefCell<dyn IpoptNlp>>

Source

pub fn curr_slack_x_l(&self) -> Rc<dyn Vector>

Source

pub fn curr_slack_x_u(&self) -> Rc<dyn Vector>

Source

pub fn curr_slack_s_l(&self) -> Rc<dyn Vector>

Source

pub fn curr_slack_s_u(&self) -> Rc<dyn Vector>

Source

pub fn trial_slack_x_l(&self) -> Rc<dyn Vector>

Source

pub fn trial_slack_x_u(&self) -> Rc<dyn Vector>

Source

pub fn trial_slack_s_l(&self) -> Rc<dyn Vector>

Source

pub fn trial_slack_s_u(&self) -> Rc<dyn Vector>

Source

pub fn adjusted_trial_bounds(&self) -> Option<AdjustedBounds>

Compute the four trial slacks with safe-slack flooring and, if any component was corrected, the adjusted variable bounds that make the trial slacks exactly representable. Port of the bound-adjustment block in IpoptAlgorithm::AcceptTrialPoint (IpIpoptAlg.cpp:664-706): new_x_L = Px_L^T x - safe_slack_x_L, new_x_U = Px_U^T x + safe_slack_x_U, likewise for s/d. Returns None when no slack needed correcting.

Source

pub fn curr_grad_f(&self) -> Rc<dyn Vector>

Source

pub fn trial_grad_f(&self) -> Rc<dyn Vector>

Source

pub fn curr_c(&self) -> Rc<dyn Vector>

Source

pub fn trial_c(&self) -> Rc<dyn Vector>

Source

pub fn curr_d(&self) -> Rc<dyn Vector>

Source

pub fn trial_d(&self) -> Rc<dyn Vector>

Source

pub fn curr_jac_c(&self) -> Rc<dyn Matrix>

Source

pub fn curr_jac_d(&self) -> Rc<dyn Matrix>

Source

pub fn curr_exact_hessian(&self) -> Rc<dyn SymMatrix>

Source

pub fn curr_d_minus_s(&self) -> Rc<dyn Vector>

curr_d - s — port of IpIpoptCalculatedQuantities.cpp:1185-1206.

Source

pub fn trial_d_minus_s(&self) -> Rc<dyn Vector>

Source

pub fn curr_jac_c_t_times_vec(&self, vec: &dyn Vector) -> Rc<dyn Vector>

J_c^T y_c — for a generic vec argument (IpIpoptCalculatedQuantities.cpp:1373-1404).

Source

pub fn curr_jac_d_t_times_vec(&self, vec: &dyn Vector) -> Rc<dyn Vector>

J_d^T y_d for arbitrary vec.

Source

pub fn curr_jac_c_t_times_curr_y_c(&self) -> Rc<dyn Vector>

Source

pub fn curr_jac_d_t_times_curr_y_d(&self) -> Rc<dyn Vector>

Source

pub fn curr_jac_c_times_vec(&self, vec: &dyn Vector) -> Rc<dyn Vector>

J_c vIpIpoptCalculatedQuantities.cpp:1303-1321.

Source

pub fn curr_jac_d_times_vec(&self, vec: &dyn Vector) -> Rc<dyn Vector>

J_d vIpIpoptCalculatedQuantities.cpp:1323-1343.

Source

pub fn curr_grad_lag_x(&self) -> Rc<dyn Vector>

∇_x L = ∇f(x) + J_c^T y_c + J_d^T y_d - P_L z_L + P_U z_U per IpIpoptCalculatedQuantities.cpp:1993-2030.

Source

pub fn curr_grad_lag_s(&self) -> Rc<dyn Vector>

∇_s L = -y_d - P_L v_L + P_U v_U (IpIpoptCalculatedQuantities.cpp:2069-2098).

Source

pub fn curr_compl_x_l(&self) -> Rc<dyn Vector>

Source

pub fn curr_compl_x_u(&self) -> Rc<dyn Vector>

Source

pub fn curr_compl_s_l(&self) -> Rc<dyn Vector>

Source

pub fn curr_compl_s_u(&self) -> Rc<dyn Vector>

Source

pub fn curr_relaxed_compl_x_l(&self) -> Rc<dyn Vector>

s_L .* z_L - mu — relaxed complementarity used in the KKT RHS. IpIpoptCalculatedQuantities.cpp:2406-2430.

Source

pub fn curr_relaxed_compl_x_u(&self) -> Rc<dyn Vector>

Source

pub fn curr_relaxed_compl_s_l(&self) -> Rc<dyn Vector>

Source

pub fn curr_relaxed_compl_s_u(&self) -> Rc<dyn Vector>

Source

pub fn curr_sigma_x(&self) -> Rc<dyn Vector>

Source

pub fn curr_sigma_s(&self) -> Rc<dyn Vector>

Source

pub fn curr_f(&self) -> Number

Source

pub fn unscaled_curr_f(&self) -> Number

Unscaled objective at the current iterate. curr_f returns the internally scaled value (f · df_); upstream IPOPT prints the unscaled objective in its iteration log, so this divides the scaling back out. Mirrors IpoptCalculatedQuantities:: unscaled_curr_f. A zero factor (scaling never determined) is treated as the identity.

Source

pub fn curr_unscaled_dual_infeasibility_max(&self) -> Number

Max-norm dual infeasibility in the unscaled (user-original) space. Self::curr_dual_infeasibility_max is evaluated in the internally-scaled NLP space (objective × df, constraints × dc); because POUNCE applies no variable scaling, every term of the Lagrangian gradient ∇f + Jᵀy − z carries the same objective factor df, so the unscaling is a single divide by df = obj_scaling_factor. A zero or unit factor returns the scaled value unchanged — the common no-scaling path stays division-free.

Source

pub fn curr_unscaled_complementarity_max(&self) -> Number

Max-norm complementarity in the unscaled space. Each bound block s · z scales uniformly by df: the slack’s dc/dd factor and the multiplier’s df/dc (df/dd) factor cancel in the product, leaving df. So this is the scaled max-norm divided by df. See Self::curr_unscaled_dual_infeasibility_max.

Source

pub fn curr_unscaled_primal_infeasibility_max(&self) -> Number

Max-norm primal infeasibility in the unscaled space. Unlike the dual/complementarity terms the constraint scaling is per-row (c_scaled = dc ⊙ c_user, (d−s)_scaled = dd ⊙ (d−s)_user), so each block is unscaled element-by-element before the max-norm. When no row scaling is active (c_scale_vec/d_scale_vec both None — the common case) this is exactly Self::curr_primal_infeasibility_max.

Source

pub fn curr_unscaled_nlp_constraint_violation_max(&self) -> Number

Max-norm constraint violation of the original NLP, in user units: |c_i| over the equality block and max(0, d_l_i − d_i, d_i − d_u_i) over the inequality block. This is what upstream’s inf_pr_output = original — its default — prints in the inf_pr column, and what its end-of-run “Constraint violation” line reports. Mirrors IpIpoptCalculatedQuantities.cpp:unscaled_curr_nlp_constraint_violation.

Deliberately not Self::curr_primal_infeasibility_max, which is max(‖c‖_∞, ‖d − s‖_∞) — the violation of the internal slack reformulation. The two diverge whenever the slack drifts from d(x): s is confined to [d_l, d_u], so d = s + (d − s) with d − s > 0 clears a lower bound however large that gap grows. On a model that is all inequalities the gap is the whole number — on Mittelmann’s robot_a POUNCE reported 2.79e4 at an iterate where Ipopt reported 0.00e+00 and every original row was in fact satisfied (pounce#476).

Display only. The filter’s theta, the barrier-parameter strategies and the convergence test all stay on the internal measure — that split is upstream’s, not a shortcut.

Judged against the declared bounds where the NLP tracks them, so the bound_relax_factor widening cannot forgive a violation the user would still see (same reasoning as Self::relative_d_infeasibility_max).

Source

pub fn curr_relative_primal_infeasibility_max(&self) -> Number

Largest primal infeasibility of a constraint row relative to that row’s own magnitude|c_i| / |b_i| over the equality block and dist(d_i, [d_l_i, d_u_i]) / max(|d_l_i|, |d_u_i|) over the inequality block, whichever is worse.

See Self::relative_d_infeasibility_max and Self::relative_c_infeasibility_max for the two blocks; both use the row’s declared magnitude, never a live or relaxed stand-in, and both abstain (contribute nothing) on a row that has no declared magnitude to be relative to.

Source

pub fn relative_c_infeasibility_max(&self) -> Number

The equality-block half of Self::curr_relative_primal_infeasibility_max: max_i |c_i| / |b_i|, where b_i is the row’s declared right-hand side (IpoptNlp::declared_c_rhs).

POUNCE folds g_i(x) == b_i into c_i(x) = 0, so |c_i| is the violation and by itself carries no magnitude to be judged against — which is why every runtime feasibility decision on an equality row was an absolute one, and why down-scaling such a row shrank |c_i| under the absolute tolerance and flipped a true infeasibility verdict to Solve_Succeeded (gh #390, residual of #387). Dividing by the pre-fold RHS restores it: s·g(x) == s·b has residual s·(g(x) − b) and RHS s·b, so the ratio is the same at every s — the point.

Both numerator and denominator are taken in the internally-scaled space, so the solver’s own row scaling dc_i cancels too.

A homogeneous row (b_i = 0) contributes nothing. It has no declared magnitude to be relative to, and needs none: s·g(x) == 0 is the same row at every s, so the absolute test is already invariant there. Dividing by zero — or by a fabricated floor — would turn float-noise residuals into 100% “violations” on the single most common equality row there is. Non-finite entries likewise contribute nothing: an unjudgeable row must not fabricate a relative verdict. When the NLP does not track the RHS at all (declared_c_rhs is None — e.g. the restoration NLP, whose c block is not the user’s rows), the whole block abstains.

“Homogeneous” is judged numerically, not by b_i == 0 exactly: a row abstains once |b_i| sinks under its own noise floor. An exact-zero test is the right idea measured with the wrong instrument — a converter that emits 2^-53 where the model says 0 (Maros-Mészáros QSC*/QSCFXM*, and every one of the 15 problems in gh #446, carry equality rows with an RHS at 1e-171e-16) declares a magnitude that is pure rounding residue — a target no iterate could be positioned finely enough to hit. |c_i| cannot be driven below the same floor either, so the ratio was noise over noise: QSCSD1 read 81× violated at a converged KKT point whose absolute violation was 9.2e-15, which vetoed its success certificate and then armed the rapid-infeasibility pre-filter — a feasible convex QP reported Converged to a point of local infeasibility. Comparing against the row’s own noise floor keeps the scale invariance that is the whole point of the measure (both sides carry dc_i), which an absolute cutoff on |b_i| would have thrown away.

Source

pub fn curr_primal_infeasibility_above_noise(&self, kappa: Number) -> Number

Self::curr_primal_infeasibility_maxmax(‖c‖_∞, ‖d − s‖_∞) — counting each row only where its residual rises above the finest value that residual can take in floating point (gh #528).

Both residuals are differences of quantities the row’s own size: c_i = g_i(x) − b_i and d_i − s_i with s_i confined to d_i’s bounds. A difference of doubles of magnitude m is quantised in units of eps · m, so no iterate can place either residual strictly between 0 and eps · m_i — it lands on an exact 0 or on a multiple of the quantum, and which of the two is arithmetic luck. Once eps · m_i exceeds tol that luck decides whether a fully converged solve gets a certificate: on gh #528’s LPs (|b| ~ 1e8, so one ulp is 1.5e-8 against the default tol = 1e-8) the KKT error was pinned one ulp above the tolerance at the exact optimum, the solve kept iterating at a point it could not improve, and it exited Search_Direction_Becomes_Too_Small with the right answer in hand.

The floor per row is the larger of two irreducible effects, both carrying [ROW_NOISE_KAPPA] for the same reason Self::row_noise_floor does (accumulation over the row’s nonzeros and the linear solve’s conditioning):

  • Placing xSelf::row_noise_floor, eps · ‖x‖_∞ passed through the row at max_j |∂g_i/∂x_j|. A row whose Jacobian is empty gets INFINITY there, meaning “abstain”, which is the safe direction for the relative measures that floor was written for and the unsafe one here — silencing a constant row 0 = b would forgive a genuine infeasibility outright. Non-finite floors are therefore read as 0: such a row is judged on its residual alone.
  • Forming the residualeps · m_i, with m_i the magnitude of the quantities subtracted: the declared right-hand side |b_i| on the equality block (the value c_i was formed against), and max(|d_i|, |s_i|) on the inequality block. A block with no declared magnitude to hand (the restoration NLP’s c, whose rows are not the user’s) contributes nothing here and is left to the placement floor.

A row’s residual is counted in full or not at all, matching how Self::relative_c_infeasibility_max and Self::relative_d_infeasibility_max use their floors: the question is whether the row says anything, not how much of it to subtract.

Source

pub fn relative_d_infeasibility_max(&self) -> Number

The inequality-block half of Self::curr_relative_primal_infeasibility_max: max_i |d_i − s_i| / max(|d_i|, |d_l_i|, |d_u_i|).

This is the scale-free companion to Self::curr_unscaled_primal_infeasibility_max. An absolute violation measure cannot tell “satisfied” from “violated by 10% of everything the row is” once the row’s numbers are small — x >= 0.7 written as 1e-12·x >= 0.7e-12 has an absolute violation of 1e-13 at x = 0.6, under every absolute tolerance, while the row is violated by a seventh of its own right-hand side. The ratio is 0.14 at every writing of the row.

Computed entirely in the internally-scaled space: numerator and denominator both carry the row scaling dd_i, so it cancels and the ratio is invariant under it — which is the point.

The magnitude comes from the row’s declared bounds only — the current value d_i is deliberately excluded. On an active row the value converges to the bound, so for a zero-bound row (g(x) >= 0, ubiquitous) both the violation and |d_i| go to zero together and their ratio hovers near 1 at a perfectly converged point — including |d_i| made HS13’s genuine solution read as 100% violated and vetoed its certificate. A zero bound also needs no relative treatment in the first place: s·g >= 0 is the same row at every s, so the absolute test is already invariant there. Rows whose bounds are all zero or non-finite therefore contribute nothing (the relative measure abstains) — “zero” measured against the row’s own noise floor rather than exactly, for the reason spelled out on Self::relative_c_infeasibility_max: a converter that writes 2^-53 where the model says 0 otherwise hands a bound made of rounding residue to a measure that then reads the row as 100% violated. QPILOTNO carries 43 such inequality bounds at 1e-171e-15, and one of them — a row sitting at exactly d(x) = 0 against a declared bound of 1.1e-16 — pinned rel_viol at 1.0 for the whole run and drove the gh #446 local-infeasibility verdict from this block. Equality rows are judged by Self::relative_c_infeasibility_max, which plumbs the pre-fold RHS back to supply the magnitude the fold into c(x) = 0 erased.

The violation judged is the distance of d(x) outside the declared box — NOT the lifted residual |d − s| the absolute measure uses. |d − s| only bounds the true violation from above: mid-solve the slack lags d while d is comfortably inside its bounds, so a slack-lag of 1% of a small row’s magnitude read as “violated” at points that are genuinely feasible. That armed the rapid-infeasibility pre-filter at degenerate QP endgames, where the no-descent confirmation is vacuous (the violation is already ~0, so no materially less-violating point exists) — and 18 feasible CUTEr QPs were reported locally infeasible. Measured, not hypothetical.

Source

pub fn obj_scaling_factor(&self) -> Number

The objective scaling factor df currently in force (1.0 when no objective scaling is active).

Exposed because the termination logic must be able to tell an honest certificate from one an extreme scale has masked (gh #200): the scale factor itself is the discriminating signal, not the error.

Source

pub fn computed_obj_scaling_factor(&self) -> Number

The solver-computed part of the objective scale — see IpoptNlp::computed_obj_scaling_factor. The masked-certificate test keys on this, not on the product, so a user who deliberately scales a well-conditioned objective down is not second-guessed.

Source

pub fn curr_unscaled_nlp_error(&self) -> Number

Overall unscaled max-norm KKT error — max of the unscaled dual infeasibility, primal infeasibility, and complementarity. This is the honest “distance from a KKT point in the user’s own units”, as opposed to Self::curr_nlp_error, which additionally applies the s_d/s_c optimality scaling. Used by the status-fidelity gate and surfaced to callers that must independently verify a returned certificate (pounce#173).

Source

pub fn trial_f(&self) -> Number

Source

pub fn curr_barrier_obj(&self) -> Number

Source

pub fn trial_barrier_obj(&self) -> Number

Source

pub fn curr_grad_barrier_obj_x(&self) -> Rc<dyn Vector>

Gradient of the barrier objective wrt x: ∇_x φ = ∇f(x) − μ · [P_L · (1/s_L) − P_U · (1/s_U)] + damping Mirrors IpIpoptCalculatedQuantities.cpp:CalcGradBarrierObjectiveX.

Source

pub fn curr_grad_barrier_obj_s(&self) -> Rc<dyn Vector>

Gradient of the barrier objective wrt s: ∇_s φ = − μ · [P_L · (1/s_s_L) − P_U · (1/s_s_U)] + damping

Source

pub fn curr_grad_barr_t_delta( &self, delta_x: &dyn Vector, delta_s: &dyn Vector, ) -> Number

Directional derivative of the barrier objective along (δx, δs): gradBarrTDelta = ∇_x φ · δx + ∇_s φ · δs. Port of IpIpoptCalculatedQuantities.cpp:CurrGradBarrTDelta (called IpCq().curr_gradBarrTDelta() in upstream after the search dir has been computed).

Source

pub fn curr_dwd(&self, delta_x: &dyn Vector, delta_s: &dyn Vector) -> Number

δᵀ(W + Σ_x + δ_pert_x I)δ_x + δ_sᵀ(Σ_s + δ_pert_s I)δ_s — the quadratic-model term used by IpPenaltyLSAcceptor.cpp: InitThisLineSearch:101-129. Reads W and the active PD perturbations from crate::ipopt_data::IpoptData. Returns 0 if the result would be negative (matching upstream’s if dWd <= 0 then dWd = 0 guard at line 133).

Source

pub fn curr_constraint_violation(&self) -> Number

Source

pub fn constraint_violation_rows(&self) -> usize

Number of constraint rows backing the 1-norm above, i.e. dim(c) + dim(d - s). Upstream never needs this because it treats theta as a bare scalar, but any threshold expressed in theta units is a sum over this many rows — a theta of T is a mean per-row residual of T / rows. The filter acceptor uses it to floor the theta_max reference so the ceiling means the same thing on a 10-row and a 50 000-row model.

Source

pub fn trial_constraint_violation(&self) -> Number

Source

pub fn curr_primal_infeasibility_max(&self) -> Number

Max-norm primal infeasibility — max(||c||_∞, ||d − s||_∞). Used by the iteration output’s inf_pr column when inf_pr_output == INTERNAL. Mirrors IpIpoptCalculatedQuantities.cpp:CurrPrimalInfeasibility(NORM_MAX).

Source

pub fn curr_dual_infeasibility_max(&self) -> Number

Max-norm dual infeasibility — max(||∇_x L||_∞, ||∇_s L||_∞). Mirrors IpIpoptCalculatedQuantities.cpp:CurrDualInfeasibility(NORM_MAX).

Source

pub fn curr_dual_infeasibility_scale_max(&self) -> Number

Magnitude of the largest term the Lagrangian gradient is assembled from — the scale Self::curr_dual_infeasibility_max is a residual of (gh #532).

  D = max( ‖∇f‖_∞ , ‖J_cᵀ y_c‖_∞ , ‖J_dᵀ y_d‖_∞ ,
           ‖P_L z_L‖_∞ , ‖P_U z_U‖_∞ ,
           ‖y_d‖_∞ , ‖P_L v_L‖_∞ , ‖P_U v_U‖_∞ )

∇L is the sum of exactly these terms, so dual_inf / D is the fraction of them that failed to cancel: 1 at a point where nothing cancelled (min -exp(x) s.t. x >= 0 running away, ∇f = −8.8e47 with no multiplier to meet it), and ~eps at a point where the cancellation was as complete as the arithmetic allows. That ratio is the scale-invariant statement of stationarity: it is unchanged by multiplying the objective — and hence every multiplier — by a positive constant, which is the map an absolute bound on dual_inf is not invariant under.

The projections are applied rather than assumed away: P_L/P_U are 0/1 expansion matrices in the main NLP, where the scatter leaves the max-norm alone, but the term’s own norm is what this measures and the restoration NLP supplies its own operators.

No has_valid_numbers sweep, unlike Self::curr_nlp_error (gh #292): amax drops NaN, so a NaN gradient reads here as a finite scale. That cannot launder anything, because the only caller pairs this with the aggregate nlp_err <= tol test, and nlp_err carries that sweep — a NaN anywhere in ∇L makes it NaN, and NaN <= tol is false.

Repeats the ∇f and the two transpose products Self::curr_grad_lag_x already performs on the same iterate, plus four scatters. The evaluations themselves hit OrigIpoptNLP’s per-iterate caches, so the marginal cost is the products — but it is still a second pass, and the caller reads this only where a termination certificate is otherwise on the table. See OptErrorConvCheck::dual_inf_bound.

Source

pub fn curr_unscaled_dual_infeasibility_scale_max(&self) -> Number

Self::curr_dual_infeasibility_scale_max in the unscaled (user-original) space. Every term of the scaled Lagrangian gradient is df times its user-space counterpart — ∇f_scaled = df·∇f, J_cᵀ_scaled y_c_scaled = Jᵀ(dc ⊙ y_c_scaled) = df·Jᵀ y_c since dc ⊙ y_scaled = df·y_user, and likewise for the bound blocks, POUNCE applying no variable scaling — so the unscaling is the single divide by |df| that Self::curr_unscaled_dual_infeasibility_max performs on the residual, term for term and row scaling included. Magnitude, for the reason documented there: df is signed, a max-norm is not.

Source

pub fn infeasibility_descent_available(&self) -> bool

Scaled stationarity of the infeasibility measure ½‖(c, d−s)‖²‖J_cᵀ c + J_dᵀ (d−s)‖_∞ / max(1, ‖(c, d−s)‖_∞). The numerator is the x-gradient of the squared constraint violation; a value near zero with the violation itself bounded away from zero marks an iterate converging to a stationary point of the infeasibility — i.e. a locally infeasible problem. No linear solve: two transpose-products. Mirrors the gradient term behind Ipopt’s IpRestoConvCheck.cpp LOCALLY_INFEASIBLE test, applied here in the main loop. Does a short step along −∇θ actually reduce the constraint violation?

LocalInfeasibility asserts the iterate has converged to a stationary point of the constraint violation — that no local move reduces it. That is a checkable claim, and this checks it directly instead of trusting a threshold on a proxy.

Why a probe rather than a better proxy: the detector’s surrogate is ‖Jᵀc‖ / max(1, ‖c‖) against an absolute tolerance, and no variant of it separates the cases. Measured over 800 MINLPLib models plus targeted infeasible problems, the scaled form produces a confirmed false verdict (HS13 from x₀ = (1e4, 1e4), where the constraint scaling dc ≈ 3.3e-7 drives the surrogate to 5e-14 at a point whose violation is 0.51); the unscaled form needs a tolerance ≥ 1e-2 to fire at all, which introduces new false infeasibility on 3+ corpus models while still losing 2 correct detections; and a scale-invariant ‖Jᵀc‖ / ‖c‖² is not separable even on the targeted set. A single absolute threshold on a surrogate cannot do this job.

Comparing θ at two points is scale-free by construction — the row scaling cancels out of the ratio — so this needs no calibration at all.

Costs one eval_c/eval_d pair per probed step, and runs only where the detector was about to fire (both gates already passed for a full streak), which is rare. Steps are clamped to the variable bounds, so descent that only exists outside the box is correctly not counted — that direction would suppress a correct infeasibility verdict.

Returns true when descent is available, i.e. the iterate is not stationary and LocalInfeasibility must not be declared.

Source

pub fn curr_infeasibility_stationarity(&self) -> Number

Source

pub fn curr_avrg_compl(&self) -> Number

(z_L · s_L + z_U · s_U + v_L · s_L^d + v_U · s_U^d) / N where N is the total number of bound multipliers (IpIpoptCalculatedQuantities.cpp:3553-3606).

Source

pub fn curr_complementarity_min(&self) -> Number

min_i (s_i · z_i) over all four bound complementarity blocks. Mirrors IpIpoptCalculatedQuantities.cpp:CurrComplxMin (lines 3608-3640) — the smallest pairwise product s · z, signalling how close the iterate is to the central path. Empty bound sets contribute +∞; returns 0 if no bounds at all.

Source

pub fn curr_complementarity_max(&self) -> Number

Max-norm of the unbarriered complementarity blocks max_i |s_i · z_i| across all four (x_L, x_U, s_L, s_U) pairs. Mirrors upstream IpIpoptCalculatedQuantities.cpp:CurrComplementarity(0., NORM_MAX) — used by OptimalityErrorConvergenceCheck to gate the per-component compl_inf_tol test independently of the scaled scalar curr_nlp_error.

Source

pub fn curr_centrality_measure(&self) -> Number

Centrality measure ξ = min_i(s_i z_i) / avrg(s · z). Mirrors IpIpoptCalculatedQuantities.cpp:CurrCentralityMeasure. Used by crate::mu::oracle::loqo::LoqoMuOracle to bias σ toward the central path when the iterate is unbalanced. Returns 1.0 (perfectly central) when there are no bound multipliers.

Source

pub fn curr_barrier_error(&self) -> Number

Barriered KKT error E_μ(x,y,z) — port of IpIpoptCalculatedQuantities.cpp:CurrBarrierError. Same as Self::curr_nlp_error but uses the relaxed complementarity s ⊙ z − μ so the residual is zero when the iterate sits on the μ-perturbed central path. The monotone barrier-update strategy reduces μ only once this error drops below barrier_tol_factor · μ.

Source

pub fn curr_nlp_error(&self) -> Number

Optimality-scaled max-norm KKT error — port of IpIpoptCalculatedQuantities.cpp:3050-3104.

  E = max( ||∇_x L, ∇_s L||_∞ / s_d ,
           ||c, d − s||_∞ ,
           ||compl||_∞ / s_c )

where s_d / s_c are the asum-based scalings from ComputeOptimalityErrorScaling (see §4 of MAIN_LOOP.md). Uses mu_target = 0 (the unbarriered KKT residual). The barriered variant is curr_barrier_error (TODO in Phase 7).

Source

pub fn curr_nlp_error_above_primal_noise(&self, kappa: Number) -> Number

Self::curr_nlp_error with the primal-infeasibility term replaced by Self::curr_primal_infeasibility_above_noise — i.e. counting a constraint row’s residual only where it rises above the finest value that row’s residual can take in floating point (gh #528).

Never larger than Self::curr_nlp_error, and equal to it whenever no row is at its own resolution limit — which is every problem whose data is O(1), so the common path is unchanged. It exists because the other two terms of the KKT error are already normalised (s_d, s_c) while the primal one is a bare absolute residual: ‖c‖_∞ and ‖d − s‖_∞ are quantised in units of eps · the rows’ own magnitude, so on a model whose constraint values reach ~1e8 the smallest nonzero value the term can take already exceeds the default tol = 1e-8. Judging that term absolutely there asks for a residual no iterate can represent.

Read only by the strict convergence gate, which pairs it with the unscaled constr_viol_tol test on the full, unfloored residual — so what this admits is bounded by the user’s own feasibility tolerance, never by the noise floor alone.

kappa is the safety factor on the per-row floor — [ROW_NOISE_KAPPA] by default, from the primal_noise_floor_kappa option. 0 switches the floor off entirely, making this identical to Self::curr_nlp_error and the strict gate bit-for-bit upstream’s.

Source

pub fn trial_jac_c(&self) -> Rc<dyn Matrix>

Source

pub fn trial_jac_d(&self) -> Rc<dyn Matrix>

Source

pub fn trial_grad_lag_x(&self) -> Rc<dyn Vector>

∇_x L at the trial iterate — analog of Self::curr_grad_lag_x.

Source

pub fn trial_grad_lag_s(&self) -> Rc<dyn Vector>

∇_s L at the trial iterate — analog of Self::curr_grad_lag_s.

Source

pub fn trial_compl_x_l(&self) -> Rc<dyn Vector>

Source

pub fn trial_compl_x_u(&self) -> Rc<dyn Vector>

Source

pub fn trial_compl_s_l(&self) -> Rc<dyn Vector>

Source

pub fn trial_compl_s_u(&self) -> Rc<dyn Vector>

Source

pub fn curr_primal_dual_system_error(&self, mu: Number) -> Number

Unscaled primal-dual KKT system error at the current iterate — port of IpIpoptCalculatedQuantities.cpp:curr_primal_dual_system_error. Each block uses the 1-norm scaled by its entry count; the result is the sum of the dual-infeasibility, primal-infeasibility, and complementarity terms. Used by the soft restoration phase’s sufficient-reduction test.

Source

pub fn trial_primal_dual_system_error(&self, mu: Number) -> Number

Unscaled primal-dual KKT system error at the trial iterate — trial-side analog of Self::curr_primal_dual_system_error.

Source

pub fn curr_grad_lag_with_damping_x(&self) -> Rc<dyn Vector>

curr_grad_lag_x plus the kappa_d · μ · (Px_L · 1 − Px_U · 1) damping term on singly-bounded primals — port of IpIpoptCalculatedQuantities.cpp:2131-2180. When kappa_d == 0 returns the un-damped gradient.

Source

pub fn curr_grad_lag_with_damping_s(&self) -> Rc<dyn Vector>

Source

pub fn grad_kappa_times_damping_x(&self) -> Rc<dyn Vector>

kappa_d · (P_L · damping_l − P_U · damping_u) in the full x space — port of IpIpoptCalculatedQuantities.cpp::grad_kappa_times_damping_x (lines 912-949). Unlike curr_grad_lag_with_damping_x this does NOT include grad_lag_x and is NOT scaled by mu; the centering RHS in the quality-function oracle multiplies the returned vector by -avrg_compl per upstream IpQualityFunctionMuOracle.cpp:229.

Source

pub fn grad_kappa_times_damping_s(&self) -> Rc<dyn Vector>

Source

pub fn aff_step_alpha_primal_max( &self, delta_aff: &IteratesVector, tau: Number, ) -> Number

Max primal step that keeps s + α · Δs > 0 for the four slack blocks (x_L, x_U, s_L, s_U), bounded by the fraction-to-the- boundary parameter τ ∈ (0, 1]. Mirrors CalcFracToBound against the projected step P_L^T Δx, −P_U^T Δx, P_L^T Δs, −P_U^T Δs.

Source

pub fn aff_step_alpha_dual_max( &self, delta_aff: &IteratesVector, tau: Number, ) -> Number

Max dual step that keeps z + α · Δz > 0 (and same for v).

Source

pub fn aff_step_compl_avrg( &self, delta_aff: &IteratesVector, alpha_primal: Number, alpha_dual: Number, ) -> Number

Predicted average complementarity after the affine step: (1/N) · Σ (s + α_pri · Δs) · (z + α_du · Δz) summed over the four bound blocks. Returns 0 when there are no bounds.

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 = 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