A domain-specific language for modeling convex optimization problems in Python.
—
Solver interface, status constants, and configuration options for controlling optimization behavior and accessing different solver backends in CVXPY.
Problem status values returned after solving.
# Optimal solutions
OPTIMAL: str = "optimal"
OPTIMAL_INACCURATE: str = "optimal_inaccurate"
# Infeasible problems
INFEASIBLE: str = "infeasible"
INFEASIBLE_INACCURATE: str = "infeasible_inaccurate"
# Unbounded problems
UNBOUNDED: str = "unbounded"
UNBOUNDED_INACCURATE: str = "unbounded_inaccurate"
# Solver errors and limits
SOLVER_ERROR: str = "solver_error"
USER_LIMIT: str = "user_limit"Usage examples:
import cvxpy as cp
x = cp.Variable()
problem = cp.Problem(cp.Minimize(x), [x >= 1])
problem.solve()
if problem.status == cp.OPTIMAL:
print(f"Optimal solution: {x.value}")
elif problem.status == cp.INFEASIBLE:
print("Problem is infeasible")
elif problem.status == cp.UNBOUNDED:
print("Problem is unbounded")
else:
print(f"Solver status: {problem.status}")Constants for different optimization solvers supported by CVXPY.
# Open-source solvers
CLARABEL: str = "CLARABEL"
SCS: str = "SCS"
OSQP: str = "OSQP"
ECOS: str = "ECOS"
ECOS_BB: str = "ECOS_BB"
CVXOPT: str = "CVXOPT"
SCIPY: str = "SCIPY"
GLPK: str = "GLPK"
GLPK_MI: str = "GLPK_MI"
CBC: str = "CBC"
SCIP: str = "SCIP"
HIGHS: str = "HIGHS"
# GPU-accelerated solvers
CUCLARABEL: str = "CUCLARABEL"
CUOPT: str = "CUOPT"
# Commercial solvers
GUROBI: str = "GUROBI"
CPLEX: str = "CPLEX"
MOSEK: str = "MOSEK"
XPRESS: str = "XPRESS"
COPT: str = "COPT"
# Specialized solvers
DIFFCP: str = "DIFFCP" # Differentiable optimization
NAG: str = "NAG"
PDLP: str = "PDLP" # Primal-dual interior point
SDPA: str = "SDPA" # Semidefinite programming
PIQP: str = "PIQP"
PROXQP: str = "PROXQP"
QOCO: str = "QOCO"
DAQP: str = "DAQP"
GLOP: str = "GLOP" # Google Linear Optimization Package
MPAX: str = "MPAX"Usage examples:
import cvxpy as cp
x = cp.Variable(5)
A = cp.Parameter((3, 5))
b = cp.Parameter(3)
objective = cp.Minimize(cp.sum_squares(A @ x - b))
constraints = [x >= 0]
problem = cp.Problem(objective, constraints)
# Try different solvers
try:
problem.solve(solver=cp.OSQP)
print(f"OSQP solution: {x.value}")
except cp.SolverError:
print("OSQP failed")
try:
problem.solve(solver=cp.CLARABEL)
print(f"Clarabel solution: {x.value}")
except cp.SolverError:
print("Clarabel failed")
# Use commercial solver if available
try:
problem.solve(solver=cp.GUROBI)
print(f"Gurobi solution: {x.value}")
except cp.SolverError:
print("Gurobi not available or failed")Constants for different canonicalization backends.
CPP_CANON_BACKEND: str = "CPP"
RUST_CANON_BACKEND: str = "RUST"
SCIPY_CANON_BACKEND: str = "SCIPY"
ROBUST_KKTSOLVER: str = "ROBUST_KKTSOLVER"Usage examples:
import cvxpy as cp
x = cp.Variable()
problem = cp.Problem(cp.Minimize(x**2), [x >= 1])
# Use different backends
problem.solve(canon_backend=cp.CPP_CANON_BACKEND)
problem.solve(canon_backend=cp.RUST_CANON_BACKEND)Functions for managing solver availability and configuration.
def installed_solvers():
"""
Get list of installed and available solvers.
Returns:
- list: names of available solvers
"""
...
def get_num_threads():
"""
Get number of threads used for parallel computation.
Returns:
- int: number of threads
"""
...
def set_num_threads(num_threads):
"""
Set number of threads for parallel computation.
Parameters:
- num_threads: int, number of threads to use
"""
...Usage examples:
import cvxpy as cp
# Check available solvers
available = cp.installed_solvers()
print(f"Available solvers: {available}")
# Check if specific solver is available
if cp.GUROBI in available:
print("Gurobi is available")
else:
print("Gurobi not installed")
# Configure threading
original_threads = cp.get_num_threads()
cp.set_num_threads(4) # Use 4 threads
print(f"Using {cp.get_num_threads()} threads")
# Restore original setting
cp.set_num_threads(original_threads)Different solvers support various configuration options passed as keyword arguments to solve().
import cvxpy as cp
x = cp.Variable(100)
A = cp.Parameter((50, 100))
b = cp.Parameter(50)
problem = cp.Problem(cp.Minimize(cp.sum_squares(A @ x - b)), [x >= 0])
# OSQP solver options
problem.solve(
solver=cp.OSQP,
eps_abs=1e-8, # absolute tolerance
eps_rel=1e-8, # relative tolerance
max_iter=10000, # maximum iterations
verbose=True, # print solver output
warm_start=True, # use previous solution as starting point
polish=True, # polish solution
adaptive_rho=True # adaptive penalty parameter
)
# SCS solver options
problem.solve(
solver=cp.SCS,
eps=1e-6, # convergence tolerance
max_iters=10000, # maximum iterations
normalize=True, # normalize problem data
verbose=True, # print solver output
use_indirect=True # use indirect method
)
# Clarabel solver options
problem.solve(
solver=cp.CLARABEL,
tol_feas=1e-8, # feasibility tolerance
tol_gap_abs=1e-8, # absolute gap tolerance
tol_gap_rel=1e-8, # relative gap tolerance
max_iter=200, # maximum iterations
verbose=True # print solver output
)
# Gurobi solver options (if available)
try:
problem.solve(
solver=cp.GUROBI,
TimeLimit=30, # time limit in seconds
MIPGap=1e-4, # MIP optimality gap
Threads=4, # number of threads
Method=2, # barrier method
verbose=True
)
except cp.SolverError:
print("Gurobi not available")
# ECOS solver options
problem.solve(
solver=cp.ECOS,
abstol=1e-8, # absolute tolerance
reltol=1e-8, # relative tolerance
feastol=1e-8, # feasibility tolerance
max_iters=100, # maximum iterations
verbose=True
)import cvxpy as cp
def solve_with_fallback(problem, preferred_solvers=None):
"""
Solve problem with fallback solver strategy.
"""
if preferred_solvers is None:
preferred_solvers = [cp.CLARABEL, cp.OSQP, cp.SCS, cp.ECOS]
available = cp.installed_solvers()
for solver in preferred_solvers:
if solver in available:
try:
result = problem.solve(solver=solver, verbose=False)
if problem.status in [cp.OPTIMAL, cp.OPTIMAL_INACCURATE]:
print(f"Solved successfully with {solver}")
return result
else:
print(f"{solver} failed with status: {problem.status}")
except Exception as e:
print(f"{solver} threw exception: {e}")
continue
# Try automatic solver selection as last resort
try:
result = problem.solve()
print(f"Solved with automatic selection: {problem.solver_stats.solver_name}")
return result
except Exception as e:
print(f"All solvers failed: {e}")
return None
# Example usage
x = cp.Variable(5)
objective = cp.Minimize(cp.sum_squares(x))
constraints = [cp.sum(x) == 1, x >= 0]
problem = cp.Problem(objective, constraints)
# Try to solve with fallback
result = solve_with_fallback(problem)
if result is not None:
print(f"Solution: {x.value}")
print(f"Objective: {result}")
print(f"Solver time: {problem.solver_stats.solve_time:.3f}s")
else:
print("Could not solve problem")After solving, access detailed solver statistics through problem.solver_stats:
import cvxpy as cp
x = cp.Variable(10)
problem = cp.Problem(cp.Minimize(cp.sum_squares(x)), [cp.sum(x) == 1])
problem.solve(solver=cp.OSQP)
stats = problem.solver_stats
print(f"Solver: {stats.solver_name}")
print(f"Status: {stats.status}")
print(f"Setup time: {stats.setup_time:.3f}s")
print(f"Solve time: {stats.solve_time:.3f}s")
print(f"Iterations: {stats.num_iters}")
# Some solvers provide additional statistics
if hasattr(stats, 'extra_stats'):
print(f"Extra statistics: {stats.extra_stats}")Install with Tessl CLI
npx tessl i tessl/pypi-cvxpy