slsqp_jax.qp.active_set

Single shared run_active_set_loop (add / drop / EXPAND / ping-pong) consumed by every QP strategy.

slsqp_jax.qp.active_set

Shared add / drop / EXPAND / ping-pong active-set loop.

The legacy slsqp_jax/qp_solver.py carried three near-identical copies of this loop body — one in _solve_qp_proximal, one in _solve_qp_direct, and one inlined in solve_qp’s ineq-only path. This module hosts the single implementation; the three QP-strategy modules now build their own initial state and inner-solve closure and delegate to run_active_set_loop().

The loop is parameterised by the inner solve closure:

inner_solve_fn(state) -> ActiveSetInnerResult

which packages the new direction, equality / inequality multipliers, projection diagnostics, and the inner-failure flag. Callers control how the inner solver is wired (proximal-stabilised HVP vs. direct projection) by what they put in this closure.

class slsqp_jax.qp.active_set.ActiveSetInnerResult[source]

Bases: NamedTuple

Per-iteration payload returned by the caller’s inner-solve closure.

Attributes:

d: New search direction. multipliers_eq: Recovered (or absorbed) equality multipliers

for this iteration. Pass an empty (0,) vector when no equality constraints are present.

multipliers_ineq: Recovered inequality multipliers (length

m_ineq); zero on inactive entries.

inner_failed: Whether the inner solve produced a non-finite

direction.

proj_residual: Latest M-metric projection residual from the

inner solver (MinresQLPSolver); always 0 for null-space CG / CRAIG.

n_proj_refinements: Refinement rounds applied by the inner

solver on this call. Accumulated by the loop into the running QPState count.

projected_grad_norm: Latest projected-gradient norm from the

inner solver (HRInexactSTCG only; inf otherwise).

d: Float[Array, 'n']

Alias for field number 0

multipliers_eq: Float[Array, 'm_eq']

Alias for field number 1

multipliers_ineq: Float[Array, 'm_ineq']

Alias for field number 2

inner_failed: Bool[Array, '']

Alias for field number 3

proj_residual: Float[Array, '']

Alias for field number 4

n_proj_refinements: Array

Alias for field number 5

projected_grad_norm: Float[Array, '']

Alias for field number 6

slsqp_jax.qp.active_set.run_active_set_loop(init_state, inner_solve_fn, A_ineq, b_ineq, max_iter, base_tol, effective_tau, drop_floor, ping_pong_threshold)[source]

Run the shared add / drop / EXPAND / ping-pong active-set loop.

The body, identical across all three QP strategies:

  1. Compute the working tolerance working_tol = base_tol + iteration * effective_tau (EXPAND ramp).

  2. Call the caller-supplied inner_solve_fn() with the current active set; receive a new direction, multipliers, and projection diagnostics.

  3. Compute violation scores A_ineq d - b_ineq and drop scores mult_ineq < -max(working_tol, drop_floor).

  4. Branch on add / drop / mark_converged with the same ping-pong short-circuit logic that the legacy bodies used.

Args:

init_state: Initial active-set state. inner_solve_fn: Closure performing the per-iteration inner

equality-constrained QP solve. Receives the current QPState and the current working_tol (some callers ignore it).

A_ineq: Inequality constraint matrix used for the violation

check. Must match what inner_solve_fn consumes.

b_ineq: Inequality RHS for the violation check. max_iter: Iteration budget (matches while_loop cond). base_tol: Outer SQP-level base tolerance. effective_tau: Per-iteration EXPAND increment. 0.0

disables the ramp.

drop_floor: Floor on the drop test so multiplier-recovery noise

does not flip a negligible negative multiplier into a drop.

ping_pong_threshold: Threshold for the explicit add/drop

ping-pong short-circuit (2**31 - 1 effectively disables it).

Returns:

The final QPState after the active-set loop terminates.

Return type:

QPState

Parameters:
  • init_state (QPState)

  • inner_solve_fn (Callable[[QPState, Float[Array, '']], ActiveSetInnerResult])

  • A_ineq (Float[Array, 'm_ineq n'])

  • b_ineq (Float[Array, 'm_ineq'])

  • max_iter (int)

  • base_tol (Float[Array, ''])

  • effective_tau (Float[Array, ''] | float)

  • drop_floor (Float[Array, ''])

  • ping_pong_threshold (int)