HerculesABQP
HerculesABQP is a solver for convex box-constrained quadratic programs of the form
minimize 1/2 x^T Q x + c^T x
subject to l <= x <= u
It is especially useful when the same quadratic model is solved many times with changing bounds and warm starts.
How It Works
The solver does two things:
- It takes accelerated projected gradient steps on the box-constrained QP, with adaptive restart and optional diagonal scaling.
- Once the first-order phase is close, (optionally) it applies a small number of active-set polishing steps in the style of ProxQP to clean up the final solution. This is based on the main iteration idea from proxqp.
Features
- accelerated projected gradient descent with adaptive gradient restart
- Gershgorin or auto Lipschitz estimation
- optional Hessian-diagonal scaling
- active-set polishing with reduced solves
- dense and sparse matrix support
- warm starts and a
PreparedSolverpath for repeated solves - explicit and implicit operator interfaces
- benchmarks and validation tests
Quick Start
Run the Criterion benchmarks:
Build the Python extension in a virtual environment:
Install Python test dependencies and run the binding tests:
Example Use
Solve one box-constrained QP directly:
use QuadraticMatrix;
use ;
use arr2;
Prepare a solver once and reuse it for repeated solves with changing bounds:
use QuadraticMatrix;
use ;
use arr2;
PreparedSolver is the right entry point when Q and c stay fixed across many solves. It prepares the matrix-side work once, then lets later solves vary only in the bounds and optional warm start.
Python Interface
The optional Python bindings support:
- dense
numpy.ndarrayinputs forQ - sparse SciPy matrices or arrays for
Qthrough theirtocsr()interface - dense NumPy vectors for
c,lb,ub, and optionalx0 - Python-defined implicit operators with
nandmatvec(x)
The main Python entry points are:
herculesabqp.solve_box_qp(...)for one-off solvesherculesabqp.PreparedSolver(...)for repeated solves with sharedQandcherculesabqp.solve_box_qp_implicit(...)for Python-defined implicit operatorsherculesabqp.PreparedImplicitSolver(...)for repeated implicit solves
Notes
- The solver assumes a convex QP.
- By default the solver symmetrizes the supplied matrix. Set
options.assume_symmetric = trueifQis already symmetric and you want to skip that preprocessing step. - For repeated solves, prefer the prepared solver APIs.
- For implicit operators, diagonal scaling is only available when the operator exposes
diagonal(). Ifscaling="hessian_diag"is requested without a diagonal, the implicit path falls back to an unscaled solve. - The implicit path is first-order only and currently skips the final polishing phase.
- Additional examples live in examples/.
- Core references are collected in references.bib.