slsqp_jax.slsqp.bounds¶
NLP-level bound machinery: clipping iterates, building the bound Jacobian, and post-line-search bound-multiplier recovery.
slsqp_jax.slsqp.bounds
NLP-level box-bound machinery for the SLSQP outer loop.
These helpers handle the three points where bounds enter the outer
SQP iteration (the reduced-space QP-level bound-fixing loop lives in
slsqp_jax.qp.bound_fixing instead):
clip_to_bounds()— defensively project an iterate onto the feasible box (used ininitand after every line search).compute_bound_constraint_values()— evaluatec(x) = x − lb/ub − xfor the finite bound rows; the result is appended to the user inequality vector.build_bound_jacobian()— build the constant[I; −I]Jacobian rows for the bound constraints. Computed once duringinitand stored onSLSQPState.recover_bound_multipliers()— post-line-search refresh of the bound multipliers from the partial Lagrangian gradient atx_{k+1}. SeeAGENTS.mdfor the rationale.
All functions are pure and free of solver-class state; they take the
precomputed lower_indices / upper_indices tuples and the
bounds array directly so they can be reused outside SLSQP
(e.g. by the eventual standalone QP solver).
- slsqp_jax.slsqp.bounds.build_bound_jacobian(n, bounds, lower_indices, upper_indices)[source]¶
Constant Jacobian of the bound constraints.
+Irows for lower bounds,−Irows for upper bounds. Empty matrix when no finite bounds are present.
- slsqp_jax.slsqp.bounds.clip_to_bounds(y, bounds)[source]¶
Project
yonto the box defined bybounds.Returns
yunchanged whenboundsisNone.- Return type:
Float[Array, 'n']- Parameters:
y (Float[Array, 'n'])
bounds (Float[Array, 'n 2'] | None)
- slsqp_jax.slsqp.bounds.compute_bound_constraint_values(y, bounds, lower_indices, upper_indices)[source]¶
Compute bound constraint values
c(x) >= 0for finite bounds.Returns the empty vector when no finite bounds are present.
- slsqp_jax.slsqp.bounds.recover_bound_multipliers(*, y_new, grad_new, eq_jac_new, ineq_jac_new, mult_eq, mult_ineq_general, bounds, lower_indices, upper_indices, m_general)[source]¶
Post-line-search NLP-level bound-multiplier refresh.
Reads off the bound multiplier at the active bounds from the partial Lagrangian gradient at
x_{k+1}, with the sign conventionμ_lower = +partial_grad_L/μ_upper = -partial_grad_Linherited frombuild_bound_jacobian()(+I/−I). Clamped to≥ 0for dual feasibility.See
AGENTS.mdfor the full motivation; in short, the QP-level bound multipliers were recovered fromB d + g − Aᵀ λatx_kusing the L-BFGS HVP and the QP active set, so they inherit anO(L-BFGS) + O(line-search) + O(active-set)error budget that on bound-heavy problems pins||∇L|| / |L|abovertoleven at a true KKT point. Splicing the partial-gradient recovery zeros that residual exactly at the bound-active indices by construction.- Return type:
tuple[Float[Array, 'n_lower'],Float[Array, 'n_upper']]- Parameters:
y_new (Float[Array, 'n'])
grad_new (Float[Array, 'n'])
eq_jac_new (Float[Array, 'm_eq n'])
ineq_jac_new (Float[Array, 'm_ineq n'])
mult_eq (Float[Array, 'm_eq'])
mult_ineq_general (Float[Array, 'm_general'])
bounds (Float[Array, 'n 2'] | None)
m_general (int)