slsqp_jax.slsqp.termination

Single source of truth for the granular termination classification and its mapping to the coarse optx.RESULTS.

slsqp_jax.slsqp.termination

Single source of truth for SLSQP termination classification.

Both SLSQP.step and SLSQP.terminate need to decide whether the run should stop and why. Historically these were two near-identical bodies (the step mirror existed because Optimistix’s iterate_solve driver requires the coarse optx.RESULTS enum while we want to expose the granular slsqp_jax.RESULTS). This module collapses both into a pair of small pure helpers that share their inputs by structure.

  • classify_outcome() — given primal-feasibility / stationarity / failure flags, return the granular slsqp_jax.RESULTS code. Used by step to populate state.termination_code.

  • coarse_outcome() — collapse the same flags onto the optx.RESULTS enum that the Optimistix driver requires. Used by terminate.

  • compute_mu_max() — filterSQP’s normalisation denominator (Fletcher & Leyffer, User manual for filterSQP, eq. 5) used as the reference scale for the relative-stationarity convergence test. See the docstring for the exact formula.

Both classification helpers are thin pattern-matchers over the same flag set; refactoring either one in the future should preserve their structural symmetry.

class slsqp_jax.slsqp.termination.TerminationFlags[source]

Bases: NamedTuple

Flag bundle classify_outcome / coarse_outcome both consume.

converged: Bool[Array, '']

Alias for field number 0

nonfinite: Bool[Array, '']

Alias for field number 1

diverging: Bool[Array, '']

Alias for field number 2

ls_fatal: Bool[Array, '']

Alias for field number 3

qp_fatal: Bool[Array, '']

Alias for field number 4

merit_stagnation: Bool[Array, '']

Alias for field number 5

max_iters_reached: Bool[Array, '']

Alias for field number 6

primal_feasible: Bool[Array, '']

Alias for field number 7

slsqp_jax.slsqp.termination.classify_outcome(flags)[source]

Granular slsqp_jax.RESULTS classification.

Priority order (highest wins):

  1. successful

  2. nonfinite

  3. infeasible (override on any non-success termination at an infeasible iterate)

  4. iterate_blowup (best-iterate divergence rollback)

  5. line_search_failure

  6. qp_subproblem_failure

  7. merit_stagnation

  8. nonlinear_max_steps_reached

Return type:

RESULTS

Parameters:

flags (TerminationFlags)

slsqp_jax.slsqp.termination.coarse_outcome(flags)[source]

Coarse (done, result) for the Optimistix driver.

The driver requires the parent optx.RESULTS enum class (subclass instances would crash RESULTS.where), so we only expose the four codes it knows about: successful, nonfinite, nonlinear_divergence (catch-all for stagnation / LS / QP / blowup), and nonlinear_max_steps_reached.

Return type:

tuple[Bool[Array, ''], RESULTS]

Parameters:

flags (TerminationFlags)

slsqp_jax.slsqp.termination.compute_mu_max(grad_f, eq_jac, ineq_jac_general, mult_eq, mult_ineq_general, mult_bound)[source]

filterSQP normalisation denominator (eq. 5 of the manual).

Computes:

μ_max = max_i { ‖∇f‖₂, |ν_i|, ‖a_i‖₂ · |λ_i| }

where the max is over the objective-gradient norm (one term), every bound multiplier ν_i (one term per active bound), and every general-constraint contribution ‖a_i‖₂ · |λ_i| (one term per equality and per general inequality, a_i being the Jacobian row). The result is the largest single contributor to the residual ‖∇f Jᵀλ νᵀI_b‖ and is exactly the reference scale filterSQP uses in eq. (6).

Bound rows are not passed via a Jacobian: by construction the bound block of build_bound_jacobian() has rows ±e_i of L2 norm 1, so ‖a_i‖₂·|ν_i| = |ν_i| and we can feed the bound multipliers in directly. This also matches the Fletcher–Leyffer split of λ (general) and ν (bound) multipliers in the manual.

The empty-constraint case reduces cleanly to ‖∇f‖₂.

Return type:

Float[Array, '']

Parameters:
  • grad_f (Float[Array, 'n'])

  • eq_jac (Float[Array, 'm_eq n'])

  • ineq_jac_general (Float[Array, 'm_ineq_general n'])

  • mult_eq (Float[Array, 'm_eq'])

  • mult_ineq_general (Float[Array, 'm_ineq_general'])

  • mult_bound (Float[Array, 'm_bound'])

Args:

grad_f: Objective gradient ∇f(x), shape (n,). eq_jac: Equality-constraint Jacobian, shape (m_eq, n).

May be empty (m_eq == 0).

ineq_jac_general: General-inequality-constraint Jacobian,

shape (m_ineq_general, n). Excludes the bound block — bound contributions are passed via mult_bound. May be empty.

mult_eq: Equality multipliers λ_eq, shape (m_eq,). mult_ineq_general: General-inequality multipliers

λ_ineq, shape (m_ineq_general,).

mult_bound: Bound multipliers ν (lower bounds stacked on

upper bounds, matching the layout of the bound block of state.multipliers_ineq_ls), shape (m_bound,).

Returns:

Scalar μ_max. Has the dtype of grad_f.