Unified interface to Quadratic Programming (QP) solvers available in Python.
qpsolvers v3 is coming out on February 28, 2023.
To install both the library and a starter set of open-source QP solvers:
pip install "qpsolvers[open_source_solvers]"
To install just the library:
pip install qpsolvers
conda install qpsolvers -c conda-forge
Check out the documentation for Python 2 or Windows instructions.
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 apply coordinate by coordinate. The function returns the solution None
in case of failure/unfeasible problem. For most solvers, the matrix
📢 New with v2.7: get dual multipliers at the solution using the solve_problem
function.
To solve a quadratic program, build the matrices that define it and call the solve_qp
function:
import numpy as np
from qpsolvers import solve_qp
M = np.array([[1.0, 2.0, 0.0], [-8.0, 3.0, 2.0], [0.0, 1.0, 1.0]])
P = M.T @ M # this is a positive definite matrix
q = np.array([3.0, 2.0, 3.0]) @ M
G = np.array([[1.0, 2.0, 1.0], [2.0, 0.0, 1.0], [-1.0, 2.0, -1.0]])
h = np.array([3.0, 2.0, -2.0])
A = np.array([1.0, 1.0, 1.0])
b = np.array([1.0])
x = solve_qp(P, q, G, h, A, b, solver="proxqp")
print(f"QP solution: x = {x}")
This example outputs the solution [0.30769231, -0.69230769, 1.38461538]
. It is also possible to get dual multipliers at the solution, as shown in this example.
Solver | Keyword | Algorithm | API | 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.
- 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.
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.