Quadratic programming solvers in Python with a unified API
npx @tessl/cli install tessl/pypi-qpsolvers@4.8.0A comprehensive Python library providing a unified interface for solving convex quadratic programming problems. qpsolvers supports over 20 different backend solvers including OSQP, CVXOPT, Gurobi, MOSEK, and others, abstracting away solver-specific APIs and matrix format requirements.
pip install qpsolvers or pip install qpsolvers[open_source_solvers]import qpsolversCommon imports for solving:
from qpsolvers import solve_qp, solve_problem, available_solversImport specific solver functions:
from qpsolvers import osqp_solve_qp, cvxopt_solve_qp, proxqp_solve_qpImport data structures:
from qpsolvers import Problem, Solution, ActiveSetimport numpy as np
from qpsolvers import solve_qp
# Define a quadratic program: minimize 1/2 x^T P x + q^T x
# subject to G x <= h, A x = b, lb <= x <= ub
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 # positive definite cost matrix
q = np.array([3.0, 2.0, 3.0]) @ M
# Inequality constraints: G x <= h
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])
# Equality constraints: A x = b
A = np.array([1.0, 1.0, 1.0])
b = np.array([1.0])
# Solve the QP
x = solve_qp(P, q, G, h, A, b, solver="proxqp")
print(f"Solution: {x}")qpsolvers provides a unified interface that abstracts different QP solver APIs:
solve_qp, solve_problem) that accept standard QP formulationsProblem class for QP representation, Solution class for results with optimality checksThis architecture enables seamless switching between solvers and automatic format conversion while maintaining compatibility with the scientific Python ecosystem.
Main functions for solving quadratic programs with the unified API. These provide the primary interface for QP solving with automatic solver selection and matrix format handling.
def 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]: ...
def solve_problem(
problem: Problem,
solver: str,
initvals: Optional[np.ndarray] = None,
verbose: bool = False,
**kwargs
) -> Solution: ...
def solve_ls(
R: Union[np.ndarray, spa.csc_matrix],
s: 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,
W: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
solver: Optional[str] = None,
initvals: Optional[np.ndarray] = None,
verbose: bool = False,
sparse_conversion: Optional[bool] = None,
**kwargs
) -> Optional[np.ndarray]: ...
def solve_unconstrained(problem: Problem) -> Solution: ...Direct access to specific QP solver implementations. Each solver function provides solver-specific parameters and optimizations while maintaining the unified API structure.
def osqp_solve_qp(...) -> Optional[np.ndarray]: ...
def cvxopt_solve_qp(...) -> Optional[np.ndarray]: ...
def proxqp_solve_qp(...) -> Optional[np.ndarray]: ...
def gurobi_solve_qp(...) -> Optional[np.ndarray]: ...
def mosek_solve_qp(...) -> Optional[np.ndarray]: ...
# ... and 16 more solver functions
available_solvers: List[str]
dense_solvers: List[str]
sparse_solvers: List[str]Core classes for representing quadratic programs, solutions, and active constraint sets. These provide structured data handling with validation and optimality checking.
class Problem:
P: Union[np.ndarray, spa.csc_matrix]
q: np.ndarray
G: Optional[Union[np.ndarray, spa.csc_matrix]]
h: Optional[np.ndarray]
A: Optional[Union[np.ndarray, spa.csc_matrix]]
b: Optional[np.ndarray]
lb: Optional[np.ndarray]
ub: Optional[np.ndarray]
def check_constraints(self) -> None: ...
def condition_number(self) -> float: ...
class Solution:
problem: Problem
found: Optional[bool]
obj: Optional[float]
x: Optional[np.ndarray]
y: Optional[np.ndarray]
z: Optional[np.ndarray]
z_box: Optional[np.ndarray]
extras: dict
def is_optimal(self, eps_abs: float) -> bool: ...
class ActiveSet:
G_indices: Sequence[int]
lb_indices: Sequence[int]
ub_indices: Sequence[int]Helper functions for matrix conversions, problem transformations, error handling, and debugging support.
# Conversion utilities
def combine_linear_box_inequalities(...): ...
def linear_from_box_inequalities(...): ...
def ensure_sparse_matrices(...): ...
def socp_from_qp(...): ...
def split_dual_linear_box(...): ...
# Utility functions
def print_matrix_vector(...) -> None: ...
# Exception classes
class QPError(Exception): ...
class NoSolverSelected(QPError): ...
class ParamError(QPError): ...
class ProblemError(QPError): ...
class SolverNotFound(QPError): ...
class SolverError(QPError): ...__version__: str # "4.8.1"