QP Solvers for Python
Unified interface to Quadratic Programming (QP) solvers available in Python.
Installation
To install both the library and a starter set of free QP solvers:
pip install qpsolvers[open_source_solvers]
To only install the library:
pip install qpsolvers
Check out the documentation for Python 2 or Windows instructions.
Usage
The library provides a one-stop shop solve_qp
function with a solver
keyword argument to select the backend solver. It solves convex quadratic programs in standard form:
Vector inequalities are taken coordinate by coordinate. For most solvers, the matrix
📢 With v2.5, tolerances for OSQP and SCS have been reverted to the solvers' defaults. For the previous setting, pass the additional keyword arguments eps_abs=1e-4
, eps_rel=1e-4
to OSQP or eps_abs=1e-7
, eps_rel=1e-7
to SCS. Changes to the API are reported in the Announcements.
Example
To solve a quadratic program, build the matrices that define it and call the solve_qp
function:
from numpy import array, dot
from qpsolvers import solve_qp
M = array([[1., 2., 0.], [-8., 3., 2.], [0., 1., 1.]])
P = dot(M.T, M) # this is a positive definite matrix
q = dot(array([3., 2., 3.]), M)
G = array([[1., 2., 1.], [2., 0., 1.], [-1., 2., -1.]])
h = array([3., 2., -2.])
A = array([1., 1., 1.])
b = array([1.])
x = solve_qp(P, q, G, h, A, b, solver="osqp")
print(f"QP solution: x = {x}")
This example outputs the solution [0.30769231, -0.69230769, 1.38461538]
.
Solvers
Solver | Keyword | Algorithm | Matrices | License | Warm-start |
---|---|---|---|---|---|
CVXOPT | cvxopt |
Interior point | Dense | GPL-3.0 | ✔️ |
ECOS | ecos |
Interior point | Sparse | GPL-3.0 | ✖️ |
Gurobi | gurobi |
Interior point | Sparse | Commercial | ✖️ |
HiGHS | highs |
Active set | Sparse | MIT | ✖️ |
MOSEK | mosek |
Interior point | Sparse | Commercial | ✔️ |
OSQP | osqp |
Augmented Lagrangian | Sparse | Apache-2.0 | ✔️ |
ProxQP | proxqp |
Augmented Lagrangian | Dense & Sparse | BSD-2-Clause | ✔️ |
qpOASES | qpoases |
Active set | Dense | LGPL-2.1 | ➖ |
qpSWIFT | qpswift |
Interior point | Sparse | GPL-3.0 | ✖️ |
quadprog | quadprog |
Active set | Dense | GPL-2.0 | ✖️ |
SCS | scs |
Augmented Lagrangian | Sparse | MIT | ✔️ |
Matrix arguments are NumPy arrays for dense solvers and SciPy Compressed Sparse Column (CSC) matrices for sparse ones.
Frequently Asked Questions
- Can I print the list of solvers available on my machine?
- Absolutely:
print(qpsolvers.available_solvers)
- Absolutely:
- Is it possible to solve a least squares rather than a quadratic program?
- Yes, there is also a
solve_ls
function.
- Yes, there is also a
- I have a squared norm in my cost function, how can I apply a QP solver to my problem?
- You can cast squared norms to QP matrices and feed the result to
solve_qp
.
- You can cast squared norms to QP matrices and feed the result to
- I have a non-convex quadratic program. Is there a solver I can use?
- I get the following build error on Windows when running
pip install qpsolvers
.- You will need to install the Visual C++ Build Tools to build all package dependencies.
- Can I help?
- Absolutely! The first step is to install the library and use it. Report any bug in the issue tracker.
- If you're a developer looking to hack on open source, check out the contribution guidelines for suggestions.
Benchmark
On a dense problem, the performance of all solvers (as measured by IPython's %timeit
on an Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz) is:
Solver | Type | Time (ms) |
---|---|---|
qpswift | Dense | 0.008 |
quadprog | Dense | 0.01 |
qpoases | Dense | 0.02 |
osqp | Sparse | 0.03 |
scs | Sparse | 0.03 |
ecos | Sparse | 0.27 |
cvxopt | Dense | 0.44 |
gurobi | Sparse | 1.74 |
mosek | Sparse | 7.17 |
On a sparse problem with n = 500 optimization variables, these performances become:
Solver | Type | Time (ms) |
---|---|---|
osqp | Sparse | 1 |
qpswift | Dense | 2 |
scs | Sparse | 4 |
mosek | Sparse | 17 |
ecos | Sparse | 33 |
cvxopt | Dense | 51 |
gurobi | Sparse | 221 |
quadprog | Dense | 427 |
qpoases | Dense | 1560 |
On a model predictive control problem for robot locomotion, we get:
Solver | Type | Time (ms) |
---|---|---|
quadprog | Dense | 0.03 |
qpswift | Dense | 0.08 |
qpoases | Dense | 0.36 |
osqp | Sparse | 0.48 |
ecos | Sparse | 0.69 |
scs | Sparse | 0.76 |
cvxopt | Dense | 2.75 |
Finally, here is a small benchmark of random dense problems (each data point corresponds to an average over 10 runs):
Note that performances of QP solvers largely depend on the problem solved. For instance, MOSEK performs an automatic conversion to Second-Order Cone Programming (SOCP) which the documentation advises bypassing for better performance. Similarly, ECOS reformulates from QP to SOCP and works best on small problems.