Quadratic programming solvers in Python with a unified API
—
Direct access to specific QP solver implementations. Each solver function provides solver-specific parameters and optimizations while maintaining compatibility with the unified API structure.
Functions and variables for discovering available solvers and their capabilities.
available_solvers: List[str] # All solvers available on the system
dense_solvers: List[str] # Solvers that work with dense matrices
sparse_solvers: List[str] # Solvers that work with sparse matricesUsage example:
from qpsolvers import available_solvers, dense_solvers, sparse_solvers
print("All available solvers:", available_solvers)
print("Dense matrix solvers:", dense_solvers)
print("Sparse matrix solvers:", sparse_solvers)
# Check if a specific solver is available
if "osqp" in available_solvers:
print("OSQP solver is available")
# Select solver based on matrix format
import numpy as np
P = np.eye(100) # dense matrix
solver = "proxqp" if "proxqp" in dense_solvers else dense_solvers[0]High-performance open source QP solvers with different algorithmic approaches.
def osqp_solve_qp(
P: Union[np.ndarray, spa.csc_matrix],
q: np.ndarray,
G: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
h: Optional[np.ndarray] = None,
A: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
b: Optional[np.ndarray] = None,
lb: Optional[np.ndarray] = None,
ub: Optional[np.ndarray] = None,
initvals: Optional[np.ndarray] = None,
verbose: bool = False,
**kwargs
) -> Optional[np.ndarray]:
"""
OSQP solver interface (Augmented Lagrangian, sparse matrices).
Solver-specific parameters via **kwargs:
- eps_abs: Absolute tolerance (default: 1e-3)
- eps_rel: Relative tolerance (default: 1e-3)
- max_iter: Maximum iterations (default: 4000)
- polish: Enable solution polishing (default: True)
- adaptive_rho: Enable adaptive penalty parameter (default: True)
"""
def proxqp_solve_qp(
P: Union[np.ndarray, spa.csc_matrix],
q: Union[np.ndarray, spa.csc_matrix],
G: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
h: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
A: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
b: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
lb: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
ub: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
initvals: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
verbose: bool = False,
backend: Optional[str] = None,
**kwargs
) -> Optional[np.ndarray]:
"""
ProxQP solver interface (Augmented Lagrangian, dense & sparse).
Solver-specific parameters:
- backend: "dense" or "sparse" (auto-detected if None)
- eps_abs: Absolute tolerance (default: 1e-9)
- eps_rel: Relative tolerance (default: 0.0)
- max_iter: Maximum iterations (default: 10000)
"""
def clarabel_solve_qp(
P: Union[np.ndarray, spa.csc_matrix],
q: np.ndarray,
G: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
h: Optional[np.ndarray] = None,
A: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
b: Optional[np.ndarray] = None,
lb: Optional[np.ndarray] = None,
ub: Optional[np.ndarray] = None,
initvals: Optional[np.ndarray] = None,
verbose: bool = False,
**kwargs
) -> Optional[np.ndarray]:
"""
Clarabel solver interface (Interior point, sparse matrices).
Written in Rust with Python bindings for high performance.
"""
def daqp_solve_qp(
P: np.ndarray,
q: np.ndarray,
G: Optional[np.ndarray] = None,
h: Optional[np.ndarray] = None,
A: Optional[np.ndarray] = None,
b: Optional[np.ndarray] = None,
lb: Optional[np.ndarray] = None,
ub: Optional[np.ndarray] = None,
initvals: Optional[np.ndarray] = None,
verbose: bool = False,
**kwargs
) -> Optional[np.ndarray]:
"""
DAQP solver interface (Active set, dense matrices).
Dual Active Set algorithm optimized for dense problems.
"""Well-established QP solvers widely used in academia and industry.
def cvxopt_solve_qp(
P: Union[np.ndarray, spa.csc_matrix],
q: np.ndarray,
G: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
h: Optional[np.ndarray] = None,
A: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
b: Optional[np.ndarray] = None,
lb: Optional[np.ndarray] = None,
ub: Optional[np.ndarray] = None,
solver: Optional[str] = None,
initvals: Optional[np.ndarray] = None,
verbose: bool = False,
**kwargs
) -> Optional[np.ndarray]:
"""
CVXOPT solver interface (Interior point, dense & sparse).
Parameters:
- solver: CVXOPT solver backend ("conelp" default)
"""
def quadprog_solve_qp(
P: np.ndarray,
q: np.ndarray,
G: Optional[np.ndarray] = None,
h: Optional[np.ndarray] = None,
A: Optional[np.ndarray] = None,
b: Optional[np.ndarray] = None,
lb: Optional[np.ndarray] = None,
ub: Optional[np.ndarray] = None,
initvals: Optional[np.ndarray] = None,
verbose: bool = False,
**kwargs
) -> Optional[np.ndarray]:
"""
quadprog solver interface (Active set, dense matrices).
Requires positive definite P matrix.
"""
def qpoases_solve_qp(
P: np.ndarray,
q: np.ndarray,
G: Optional[np.ndarray] = None,
h: Optional[np.ndarray] = None,
A: Optional[np.ndarray] = None,
b: Optional[np.ndarray] = None,
lb: Optional[np.ndarray] = None,
ub: Optional[np.ndarray] = None,
initvals: Optional[np.ndarray] = None,
verbose: bool = False,
max_wsr: int = 1000,
time_limit: Optional[float] = None,
**kwargs
) -> Optional[np.ndarray]:
"""
qpOASES solver interface (Active set, dense matrices).
Parameters:
- max_wsr: Maximum working set recalculations
- time_limit: Time limit in seconds
"""High-performance commercial solvers for production use.
def gurobi_solve_qp(
P: np.ndarray,
q: np.ndarray,
G: Optional[np.ndarray] = None,
h: Optional[np.ndarray] = None,
A: Optional[np.ndarray] = None,
b: Optional[np.ndarray] = None,
lb: Optional[np.ndarray] = None,
ub: Optional[np.ndarray] = None,
initvals: Optional[np.ndarray] = None,
verbose: bool = False,
**kwargs
) -> Optional[np.ndarray]:
"""
Gurobi solver interface (Interior point, sparse matrices).
Requires Gurobi license. High performance for large problems.
"""
def mosek_solve_qp(
P: Union[np.ndarray, spa.csc_matrix],
q: np.ndarray,
G: Union[np.ndarray, spa.csc_matrix],
h: np.ndarray,
A: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
b: Optional[np.ndarray] = None,
lb: Optional[np.ndarray] = None,
ub: Optional[np.ndarray] = None,
initvals: Optional[np.ndarray] = None,
verbose: bool = False,
**kwargs
) -> Optional[np.ndarray]:
"""
MOSEK solver interface (Interior point, sparse matrices).
Requires MOSEK license. Note: G and h parameters are required.
"""Solvers with specific algorithmic focuses or integration features.
def highs_solve_qp(
P: Union[np.ndarray, spa.csc_matrix],
q: np.ndarray,
G: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
h: Optional[np.ndarray] = None,
A: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
b: Optional[np.ndarray] = None,
lb: Optional[np.ndarray] = None,
ub: Optional[np.ndarray] = None,
initvals: Optional[np.ndarray] = None,
verbose: bool = False,
**kwargs
) -> Optional[np.ndarray]:
"""
HiGHS solver interface (Active set, sparse matrices).
Open source solver known for linear and mixed-integer programming.
"""
def jaxopt_osqp_solve_qp(
P: Union[np.ndarray, spa.csc_matrix],
q: np.ndarray,
G: Optional[np.ndarray] = None,
h: Optional[np.ndarray] = None,
A: Optional[np.ndarray] = None,
b: Optional[np.ndarray] = None,
lb: Optional[np.ndarray] = None,
ub: Optional[np.ndarray] = None,
initvals: Optional[np.ndarray] = None,
verbose: bool = False,
**kwargs
) -> Optional[np.ndarray]:
"""
jaxopt.OSQP solver interface (Augmented Lagrangian, dense matrices).
JAX-based implementation with automatic differentiation support.
"""
def qpax_solve_qp(
P: Union[np.ndarray, spa.csc_matrix],
q: np.ndarray,
G: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
h: Optional[np.ndarray] = None,
A: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
b: Optional[np.ndarray] = None,
lb: Optional[np.ndarray] = None,
ub: Optional[np.ndarray] = None,
initvals: Optional[np.ndarray] = None,
verbose: bool = False,
**kwargs
) -> Optional[np.ndarray]:
"""
qpax solver interface (Interior point, dense matrices).
JAX-based QP solver with GPU acceleration support.
"""def piqp_solve_qp(...) -> Optional[np.ndarray]:
"""PIQP solver (Proximal interior point, dense & sparse)."""
def qpalm_solve_qp(...) -> Optional[np.ndarray]:
"""QPALM solver (Augmented Lagrangian, sparse matrices)."""
def scs_solve_qp(...) -> Optional[np.ndarray]:
"""SCS solver (Augmented Lagrangian, sparse matrices)."""
def sip_solve_qp(...) -> Optional[np.ndarray]:
"""SIP solver (Barrier Augmented Lagrangian, sparse matrices)."""
def ecos_solve_qp(...) -> Optional[np.ndarray]:
"""ECOS solver (Interior point, converts to SOCP)."""
def hpipm_solve_qp(...) -> Optional[np.ndarray]:
"""HPIPM solver (Interior point, dense matrices)."""
def kvxopt_solve_qp(...) -> Optional[np.ndarray]:
"""KVXOPT solver (Interior point, dense & sparse)."""
def qpswift_solve_qp(...) -> Optional[np.ndarray]:
"""qpSWIFT solver (Interior point, sparse matrices)."""
def nppro_solve_qp(...) -> Optional[np.ndarray]:
"""NPPro solver (Active set, dense matrices, unsupported)."""from qpsolvers import available_solvers, solve_qp
import numpy as np
# Define problem
P = np.eye(10)
q = np.ones(10)
# Try solvers in order of preference
preferred_solvers = ["proxqp", "osqp", "cvxopt"]
solver = next((s for s in preferred_solvers if s in available_solvers), available_solvers[0])
x = solve_qp(P, q, solver=solver)from qpsolvers import osqp_solve_qp, proxqp_solve_qp
# OSQP with custom parameters
x_osqp = osqp_solve_qp(
P, q, G, h,
eps_abs=1e-6, # tighter tolerance
max_iter=10000, # more iterations
polish=True, # solution polishing
adaptive_rho=True # adaptive penalty
)
# ProxQP with backend selection
x_proxqp = proxqp_solve_qp(
P, q, G, h,
backend="sparse", # force sparse backend
eps_abs=1e-9, # very tight tolerance
max_iter=50000 # many iterations
)import time
from qpsolvers import solve_qp, available_solvers
# Compare solver performance
results = {}
for solver in available_solvers:
try:
start_time = time.time()
x = solve_qp(P, q, G, h, solver=solver)
solve_time = time.time() - start_time
results[solver] = {
'time': solve_time,
'solution': x,
'success': x is not None
}
except Exception as e:
results[solver] = {'error': str(e)}
# Find fastest successful solver
successful = {k: v for k, v in results.items() if v.get('success', False)}
fastest = min(successful.items(), key=lambda x: x[1]['time'])
print(f"Fastest solver: {fastest[0]} ({fastest[1]['time']:.4f}s)")Install with Tessl CLI
npx tessl i tessl/pypi-qpsolvers