0
# Solvers and Settings
1
2
Solver interface, status constants, and configuration options for controlling optimization behavior and accessing different solver backends in CVXPY.
3
4
## Capabilities
5
6
### Status Constants
7
8
Problem status values returned after solving.
9
10
```python { .api }
11
# Optimal solutions
12
OPTIMAL: str = "optimal"
13
OPTIMAL_INACCURATE: str = "optimal_inaccurate"
14
15
# Infeasible problems
16
INFEASIBLE: str = "infeasible"
17
INFEASIBLE_INACCURATE: str = "infeasible_inaccurate"
18
19
# Unbounded problems
20
UNBOUNDED: str = "unbounded"
21
UNBOUNDED_INACCURATE: str = "unbounded_inaccurate"
22
23
# Solver errors and limits
24
SOLVER_ERROR: str = "solver_error"
25
USER_LIMIT: str = "user_limit"
26
```
27
28
Usage examples:
29
30
```python
31
import cvxpy as cp
32
33
x = cp.Variable()
34
problem = cp.Problem(cp.Minimize(x), [x >= 1])
35
problem.solve()
36
37
if problem.status == cp.OPTIMAL:
38
print(f"Optimal solution: {x.value}")
39
elif problem.status == cp.INFEASIBLE:
40
print("Problem is infeasible")
41
elif problem.status == cp.UNBOUNDED:
42
print("Problem is unbounded")
43
else:
44
print(f"Solver status: {problem.status}")
45
```
46
47
### Solver Names
48
49
Constants for different optimization solvers supported by CVXPY.
50
51
```python { .api }
52
# Open-source solvers
53
CLARABEL: str = "CLARABEL"
54
SCS: str = "SCS"
55
OSQP: str = "OSQP"
56
ECOS: str = "ECOS"
57
ECOS_BB: str = "ECOS_BB"
58
CVXOPT: str = "CVXOPT"
59
SCIPY: str = "SCIPY"
60
GLPK: str = "GLPK"
61
GLPK_MI: str = "GLPK_MI"
62
CBC: str = "CBC"
63
SCIP: str = "SCIP"
64
HIGHS: str = "HIGHS"
65
66
# GPU-accelerated solvers
67
CUCLARABEL: str = "CUCLARABEL"
68
CUOPT: str = "CUOPT"
69
70
# Commercial solvers
71
GUROBI: str = "GUROBI"
72
CPLEX: str = "CPLEX"
73
MOSEK: str = "MOSEK"
74
XPRESS: str = "XPRESS"
75
COPT: str = "COPT"
76
77
# Specialized solvers
78
DIFFCP: str = "DIFFCP" # Differentiable optimization
79
NAG: str = "NAG"
80
PDLP: str = "PDLP" # Primal-dual interior point
81
SDPA: str = "SDPA" # Semidefinite programming
82
PIQP: str = "PIQP"
83
PROXQP: str = "PROXQP"
84
QOCO: str = "QOCO"
85
DAQP: str = "DAQP"
86
GLOP: str = "GLOP" # Google Linear Optimization Package
87
MPAX: str = "MPAX"
88
```
89
90
Usage examples:
91
92
```python
93
import cvxpy as cp
94
95
x = cp.Variable(5)
96
A = cp.Parameter((3, 5))
97
b = cp.Parameter(3)
98
99
objective = cp.Minimize(cp.sum_squares(A @ x - b))
100
constraints = [x >= 0]
101
problem = cp.Problem(objective, constraints)
102
103
# Try different solvers
104
try:
105
problem.solve(solver=cp.OSQP)
106
print(f"OSQP solution: {x.value}")
107
except cp.SolverError:
108
print("OSQP failed")
109
110
try:
111
problem.solve(solver=cp.CLARABEL)
112
print(f"Clarabel solution: {x.value}")
113
except cp.SolverError:
114
print("Clarabel failed")
115
116
# Use commercial solver if available
117
try:
118
problem.solve(solver=cp.GUROBI)
119
print(f"Gurobi solution: {x.value}")
120
except cp.SolverError:
121
print("Gurobi not available or failed")
122
```
123
124
### Backend Constants
125
126
Constants for different canonicalization backends.
127
128
```python { .api }
129
CPP_CANON_BACKEND: str = "CPP"
130
RUST_CANON_BACKEND: str = "RUST"
131
SCIPY_CANON_BACKEND: str = "SCIPY"
132
ROBUST_KKTSOLVER: str = "ROBUST_KKTSOLVER"
133
```
134
135
Usage examples:
136
137
```python
138
import cvxpy as cp
139
140
x = cp.Variable()
141
problem = cp.Problem(cp.Minimize(x**2), [x >= 1])
142
143
# Use different backends
144
problem.solve(canon_backend=cp.CPP_CANON_BACKEND)
145
problem.solve(canon_backend=cp.RUST_CANON_BACKEND)
146
```
147
148
### Solver Utility Functions
149
150
Functions for managing solver availability and configuration.
151
152
```python { .api }
153
def installed_solvers():
154
"""
155
Get list of installed and available solvers.
156
157
Returns:
158
- list: names of available solvers
159
"""
160
...
161
162
def get_num_threads():
163
"""
164
Get number of threads used for parallel computation.
165
166
Returns:
167
- int: number of threads
168
"""
169
...
170
171
def set_num_threads(num_threads):
172
"""
173
Set number of threads for parallel computation.
174
175
Parameters:
176
- num_threads: int, number of threads to use
177
"""
178
...
179
```
180
181
Usage examples:
182
183
```python
184
import cvxpy as cp
185
186
# Check available solvers
187
available = cp.installed_solvers()
188
print(f"Available solvers: {available}")
189
190
# Check if specific solver is available
191
if cp.GUROBI in available:
192
print("Gurobi is available")
193
else:
194
print("Gurobi not installed")
195
196
# Configure threading
197
original_threads = cp.get_num_threads()
198
cp.set_num_threads(4) # Use 4 threads
199
print(f"Using {cp.get_num_threads()} threads")
200
201
# Restore original setting
202
cp.set_num_threads(original_threads)
203
```
204
205
### Solver-Specific Options
206
207
Different solvers support various configuration options passed as keyword arguments to `solve()`.
208
209
```python
210
import cvxpy as cp
211
212
x = cp.Variable(100)
213
A = cp.Parameter((50, 100))
214
b = cp.Parameter(50)
215
216
problem = cp.Problem(cp.Minimize(cp.sum_squares(A @ x - b)), [x >= 0])
217
218
# OSQP solver options
219
problem.solve(
220
solver=cp.OSQP,
221
eps_abs=1e-8, # absolute tolerance
222
eps_rel=1e-8, # relative tolerance
223
max_iter=10000, # maximum iterations
224
verbose=True, # print solver output
225
warm_start=True, # use previous solution as starting point
226
polish=True, # polish solution
227
adaptive_rho=True # adaptive penalty parameter
228
)
229
230
# SCS solver options
231
problem.solve(
232
solver=cp.SCS,
233
eps=1e-6, # convergence tolerance
234
max_iters=10000, # maximum iterations
235
normalize=True, # normalize problem data
236
verbose=True, # print solver output
237
use_indirect=True # use indirect method
238
)
239
240
# Clarabel solver options
241
problem.solve(
242
solver=cp.CLARABEL,
243
tol_feas=1e-8, # feasibility tolerance
244
tol_gap_abs=1e-8, # absolute gap tolerance
245
tol_gap_rel=1e-8, # relative gap tolerance
246
max_iter=200, # maximum iterations
247
verbose=True # print solver output
248
)
249
250
# Gurobi solver options (if available)
251
try:
252
problem.solve(
253
solver=cp.GUROBI,
254
TimeLimit=30, # time limit in seconds
255
MIPGap=1e-4, # MIP optimality gap
256
Threads=4, # number of threads
257
Method=2, # barrier method
258
verbose=True
259
)
260
except cp.SolverError:
261
print("Gurobi not available")
262
263
# ECOS solver options
264
problem.solve(
265
solver=cp.ECOS,
266
abstol=1e-8, # absolute tolerance
267
reltol=1e-8, # relative tolerance
268
feastol=1e-8, # feasibility tolerance
269
max_iters=100, # maximum iterations
270
verbose=True
271
)
272
```
273
274
### Solver Selection Strategy
275
276
```python
277
import cvxpy as cp
278
279
def solve_with_fallback(problem, preferred_solvers=None):
280
"""
281
Solve problem with fallback solver strategy.
282
"""
283
if preferred_solvers is None:
284
preferred_solvers = [cp.CLARABEL, cp.OSQP, cp.SCS, cp.ECOS]
285
286
available = cp.installed_solvers()
287
288
for solver in preferred_solvers:
289
if solver in available:
290
try:
291
result = problem.solve(solver=solver, verbose=False)
292
if problem.status in [cp.OPTIMAL, cp.OPTIMAL_INACCURATE]:
293
print(f"Solved successfully with {solver}")
294
return result
295
else:
296
print(f"{solver} failed with status: {problem.status}")
297
except Exception as e:
298
print(f"{solver} threw exception: {e}")
299
continue
300
301
# Try automatic solver selection as last resort
302
try:
303
result = problem.solve()
304
print(f"Solved with automatic selection: {problem.solver_stats.solver_name}")
305
return result
306
except Exception as e:
307
print(f"All solvers failed: {e}")
308
return None
309
310
# Example usage
311
x = cp.Variable(5)
312
objective = cp.Minimize(cp.sum_squares(x))
313
constraints = [cp.sum(x) == 1, x >= 0]
314
problem = cp.Problem(objective, constraints)
315
316
# Try to solve with fallback
317
result = solve_with_fallback(problem)
318
319
if result is not None:
320
print(f"Solution: {x.value}")
321
print(f"Objective: {result}")
322
print(f"Solver time: {problem.solver_stats.solve_time:.3f}s")
323
else:
324
print("Could not solve problem")
325
```
326
327
### Solver Statistics
328
329
After solving, access detailed solver statistics through `problem.solver_stats`:
330
331
```python
332
import cvxpy as cp
333
334
x = cp.Variable(10)
335
problem = cp.Problem(cp.Minimize(cp.sum_squares(x)), [cp.sum(x) == 1])
336
problem.solve(solver=cp.OSQP)
337
338
stats = problem.solver_stats
339
print(f"Solver: {stats.solver_name}")
340
print(f"Status: {stats.status}")
341
print(f"Setup time: {stats.setup_time:.3f}s")
342
print(f"Solve time: {stats.solve_time:.3f}s")
343
print(f"Iterations: {stats.num_iters}")
344
345
# Some solvers provide additional statistics
346
if hasattr(stats, 'extra_stats'):
347
print(f"Extra statistics: {stats.extra_stats}")
348
```