Choosing a Solver
POUNCE is not a single solver but a small family of them sharing one numerical backbone. This page is the map: what each solver is, when to reach for it, and how they fit together.
The one-sentence version: convex and conic problems are solved to the global
optimum; nonconvex problems are solved locally by default, or to a certified
global optimum via the SOS (polynomial) and spatial branch-and-bound (general)
paths. Every solver, whatever its flavor, ultimately factorizes a symmetric
KKT system through the shared pounce-linsol layer, which in turn drives a
pluggable backend (FERAL by default, HSL MA57 optionally).
The solvers at a glance
| Solver | Problem class | Optimum | Crate | Entry points |
|---|---|---|---|---|
| NLP filter-IPM | general smooth NLP (nonconvex OK) | local (KKT) | pounce-algorithm + pounce-nlp | CLI default; Python Problem/minimize; solver_selection=nlp |
| NLP active-set SQP | general smooth NLP | local | pounce-algorithm (subproblems via pounce-qp) | algorithm=active-set-sqp |
| Convex IPM (LP/QP) | LP, convex QP | global | pounce-convex | solve_qp_ipm; pounce.qp.solve_qp; solver_selection=lp-ipm/qp-ipm |
| Convex IPM (conic) | SOCP, exp/power/PSD cones, convex QCQP | global | pounce-convex | solve_socp_ipm; pounce.qp.solve_socp; minimize (convex QCQP); solver_selection=socp; pounce <file>.cbf |
| Active-set QP | QP, convex or indefinite | local | pounce-qp | ParametricActiveSetSolver; solver_selection=qp-active-set — opt-in only; auto never picks it (see note) |
| SOS / Lasserre | polynomial (nonconvex) | global | pounce-convex | sos_minimize; pounce.sos_minimize |
When to reach for the active-set QP.
autonever selects it: a cold, one-shot convex QP goes to the interior-point path, which is materially more robust on that workload (137 of the 138 Maros-Mészáros problems, against substantially fewer for a cold active-set solve). That is the character of the method rather than a defect — an active-set iteration count is combinatorial in the size of the active set, while an interior-point count is nearly independent of problem size. Choosesolver_selection=qp-active-setwhen you want an exact vertex solution, or when you are solving a sequence of similar QPs — MPC steps, branch-and-bound nodes, continuation — where the working set carries across solves andsolve_parametriccan trace the homotopy from the previous solution instead of starting over.
POUNCE has no spatial branch-and-bound solver for general factorable nonconvex NLPs — no
solver_selection=globalCLI route, nominimize_globalPython entry point. The only certified-global path for a nonconvex problem is SOS / Lasserre, and it covers polynomials only.
When to choose each
General nonlinear program (the common case) → NLP filter-IPM
If your model has nonlinear objective or constraints and you don’t know (or can’t assume) convexity, this is the default and the most mature path. It is POUNCE’s port of Ipopt’s filter line-search interior-point method: robust on nonconvex problems, with a feasibility restoration phase for hard starts and exact or limited-memory Hessians. It returns a local KKT point — for a nonconvex problem there is no global guarantee.
- CLI:
pounce model.nl(or a built-in problem). - Python: the cyipopt-style
Problemclass, or the scipy-styleminimizefacade. - Reach for limited-memory Hessians (
hessian_approximation=limited-memory) when second derivatives are unavailable or expensive.
A sequence of related NLPs, or a stable active set → NLP active-set SQP
Selected with algorithm=active-set-sqp. It solves the NLP as a sequence
of quadratic subproblems (handed to pounce-qp), which warm-starts
extremely well when the active set is stable across solves — e.g. a
parametric sweep or a control loop. For a single cold solve of a general
NLP, prefer the filter-IPM.
Linear or convex quadratic program → Convex IPM (LP/QP)
If P ⪰ 0 (or P = 0 for an LP), use the convex interior-point solver:
it returns the global optimum, detects primal/dual infeasibility, and
offers warm-starting, batched and multiple-RHS solving, a build-once /
solve-many QpFactorization handle, and post-optimal sensitivity
(QpSensitivity — the sIPOPT analog). The CLI’s auto routing classifies
an .nl and sends LP/convex-QP problems here automatically.
- Python:
pounce.qp.solve_qp(andsolve_qp_batch,solve_qp_multi_rhs).
Second-order, exponential, or power cones → Convex IPM (conic)
The same convex solver handles conic programs: second-order cones, the
exponential and power cones that express geometric programming,
entropy / log-sum-exp, logistic models, and p-norm constraints, and the
positive-semidefinite cone for small dense SDPs. Also global. This
is the path to use when you can cast a nominally-nonconvex problem into a
convex cone — you trade modeling effort for a global guarantee. (The PSD
cone is self-scaled and runs on the symmetric driver; the exp/power cones
run on the non-symmetric HSDE driver, so the two families can’t yet be
mixed in one problem.)
A common special case routes here automatically: a convex
quadratically-constrained QP (QCQP). When auto routing finds a
convex-quadratic inequality ½xᵀHx + aᵀx + b ≤ 0 (H ⪰ 0), it reformulates
each such constraint to one second-order cone (H = FᵀF) and sends the whole
problem to the conic solver — no .cbf and no manual cone bookkeeping needed.
This works from a .nl/Pyomo model on the CLI and from minimize() in Python
(which probes each constraint’s Hessian and only routes when it can prove the
feasible set is convex). See LP / QP Solver Routing.
- Python:
pounce.qp.solve_socp(..., cones=[("exp", 3), ("pow", 0.5), ...])for an explicit cone program, or justminimize(...)for a convex QCQP. - CLI: a Conic Benchmark Format file,
pounce model.cbf(see the CBLIB benchmark tier), or any convex-QCQP.nlunderautorouting.
Nonconvex problem, global optimum required → SOS (polynomials only)
When the problem is genuinely nonconvex and a local optimum is not good enough, the one path to a certified global optimum is for polynomials:
- Polynomial objective/constraints → SOS / Lasserre (
sos_minimize, orpounce.sos_minimize). A single semidefinite program certifies the global minimum (the largestγwithp − γin the Putinar cone), and the global minimizers are recovered from the moment matrix — even multiple ones, via a facial-reduction step. Best for modest degree and dimension; the SDP grows with the relaxation order.
If the problem is nonconvex and not polynomial (exp/ln/trig), POUNCE
cannot certify a global optimum. Reformulate into the convex cone library if
you can; otherwise multistart the local NLP solver and accept that the result
is uncertified.
See Global Optimization for the SOS path in depth, and for the multistart fallback.
Indefinite QP, or a QP inner-solver → Active-set QP
pounce-qp is a sparse parametric active-set solver that accepts an
indefinite Hessian (via inertia control), with two-sided bounds and
factorization-reuse across a homotopy. It is the engine behind the
active-set SQP path, and is the right choice for MPC-style problems or any
setting where you re-solve a slowly-changing QP many times. Use the convex
IPM instead when P ⪰ 0 and you want a single robust solve with
infeasibility certificates.
How to override the automatic routing
The CLI classifies each .nl problem and picks a solver, but you can force
the choice:
pounce model.nl solver_selection=auto # default: classify, then route
pounce model.nl solver_selection=nlp # filter-IPM (or active-set-sqp via algorithm=)
pounce model.nl solver_selection=lp-ipm # convex LP interior-point
pounce model.nl solver_selection=qp-ipm # convex QP interior-point
pounce model.nl solver_selection=socp # conic interior-point (convex QCQP)
pounce model.nl solver_selection=qp-active-set # active-set QP
solver_selection is an ordinary POUNCE option, not a command-line flag:
it is passed as a trailing KEY=VALUE pair (the ipopt CLI convention), and
so also works from an options file, the pounce_options environment
variable, or Pyomo’s solver.options. Forcing a value the problem class
does not support is rejected with a message rather than silently ignored.
See LP / QP Solver Routing for how classification works and when it falls back to the more general solver.
The shared backbone
Every interior-point and active-set solver above assembles a symmetric KKT
system and factorizes it through pounce-linsol. That trait layer is
backend-agnostic:
- FERAL (
pounce-feral) — a pure-Rust sparse symmetric LDLᵀ factorization. The default; no external dependencies. - HSL MA57 (
pounce-hsl) — the well-known Harwell solver vialibcoinhsl, enabled with thema57build feature for large or ill-conditioned systems.
Because the backend is pluggable, the same solver code runs on either without change.
Cross-cutting layers
These are not solvers you select, but stages and tools the solvers share:
- Presolve (
pounce-presolve) — an optional front-end that tightens bounds (feasibility-based bound tightening), removes redundant rows, and repairs LICQ degeneracies before the solve. - Restoration (
pounce-restoration) — the feasibility-recovery phase the filter-IPM enters when a step cannot reduce both infeasibility and the objective;pounce-l1penaltyoffers an ℓ₁-exact penalty reformulation for degenerate / LICQ-violating problems. - Sensitivity —
pounce-sensitivitygives sIPOPT-style parametric steps and reduced Hessians for the NLP;QpSensitivitydoes the same for the convex QP. See Sensitivity Analysis. - Cone library (
pounce-convex) — nonnegative, second-order, exponential, power, and (for small dense problems) positive-semidefinite cones, so small SDPs solve as a convex class. The PSD cone cannot yet be mixed with the exponential/power cones in one problem (they use different drivers). - Solve report — every path can emit the machine-readable
pounce.solve-report/v1JSON (status, iterations, residuals, timing). See JSON Solve Report.
Global vs. local — the honest summary
POUNCE settles a problem globally along two routes, and locally along one:
- Global by convexity — LP, convex QP, SOCP, and the exponential / power / PSD cone classes. Local is global, so a convex or conic reformulation buys the guarantee outright.
- Global by certificate (polynomials) — the SOS / Lasserre optimizer certifies the global minimum of a nonconvex polynomial from a single SDP; see Global Optimization.
- Local for general NLP — the filter-IPM and SQP paths converge to a KKT point, which for a nonconvex problem carries no global guarantee.
There is no third route: a nonconvex, non-polynomial problem gets a local answer, and no certificate.
Two practical levers for a “global” answer: modeling (cast as much as you can into the convex cone library) and, when that is not possible, the SOS / Lasserre optimizer for polynomials.