0
# Error Handling
1
2
Exception classes for different types of optimization and solver errors, plus warning control functions for managing CVXPY's diagnostic output.
3
4
## Capabilities
5
6
### Core Exception Classes
7
8
CVXPY-specific exceptions that indicate problems with problem formulation or solving.
9
10
```python { .api }
11
class DCPError(Exception):
12
"""
13
Disciplined Convex Programming (DCP) rule violation.
14
15
Raised when:
16
- Non-convex objective in minimization problem
17
- Non-concave objective in maximization problem
18
- Non-convex constraint expressions
19
- Invalid composition of atoms that breaks convexity
20
"""
21
pass
22
23
class DGPError(Exception):
24
"""
25
Disciplined Geometric Programming (DGP) rule violation.
26
27
Raised when:
28
- Invalid geometric programming formulation
29
- Non-log-convex expressions in geometric programs
30
- Incorrect monomial/posynomial structure
31
"""
32
pass
33
34
class DPPError(Exception):
35
"""
36
Disciplined Parametrized Programming (DPP) rule violation.
37
38
Raised when:
39
- Parameter appears in invalid position for DPP
40
- Parameterized expressions violate disciplined rules
41
- Invalid parameter-dependent problem structure
42
"""
43
pass
44
45
class SolverError(Exception):
46
"""
47
Solver encountered an error during optimization.
48
49
Raised when:
50
- Solver fails to find solution
51
- Numerical issues prevent convergence
52
- Solver-specific errors occur
53
- Invalid solver options provided
54
"""
55
pass
56
```
57
58
### Warning Control Functions
59
60
Functions to control CVXPY's warning system for diagnostic messages.
61
62
```python { .api }
63
def disable_warnings():
64
"""
65
Disable CVXPY warning messages.
66
67
Suppresses warnings about:
68
- DCP rule violations (when ignore_dcp=True)
69
- Solver selection and performance
70
- Parameter value issues
71
- Numerical precision concerns
72
"""
73
...
74
75
def enable_warnings():
76
"""
77
Enable CVXPY warning messages (default state).
78
79
Shows warnings about potential issues that don't
80
prevent problem solving but may affect results.
81
"""
82
...
83
84
def warnings_enabled():
85
"""
86
Check if CVXPY warnings are currently enabled.
87
88
Returns:
89
- bool: True if warnings are enabled, False otherwise
90
"""
91
...
92
```
93
94
## Usage Examples
95
96
### Handling DCP Violations
97
98
```python
99
import cvxpy as cp
100
import numpy as np
101
102
# Example 1: DCP violation in objective
103
x = cp.Variable()
104
y = cp.Variable()
105
106
try:
107
# This violates DCP: minimizing concave function
108
problem = cp.Problem(cp.Minimize(cp.log(x)), [x >= 1])
109
problem.solve()
110
except cp.DCPError as e:
111
print(f"DCP Error: {e}")
112
# Solution: use Maximize instead or reformulate
113
correct_problem = cp.Problem(cp.Maximize(cp.log(x)), [x >= 1])
114
correct_problem.solve()
115
print(f"Corrected solution: x = {x.value}")
116
117
# Example 2: DCP violation in constraints
118
try:
119
# This violates DCP: convex function <= 0 (should be >= 0)
120
problem = cp.Problem(cp.Minimize(x), [cp.square(x) <= 1])
121
problem.solve()
122
except cp.DCPError as e:
123
print(f"DCP Error in constraint: {e}")
124
# Solution: flip constraint or use sqrt
125
correct_problem = cp.Problem(cp.Minimize(x), [cp.abs(x) <= 1])
126
correct_problem.solve()
127
print(f"Corrected solution: x = {x.value}")
128
129
# Example 3: Ignore DCP rules (use with caution)
130
x = cp.Variable(pos=True)
131
try:
132
# Non-convex problem: minimize x^1.5 (neither convex nor concave)
133
nonconvex_obj = cp.power(x, 1.5)
134
problem = cp.Problem(cp.Minimize(nonconvex_obj), [x >= 0.1, x <= 10])
135
136
# This will raise DCPError
137
problem.solve()
138
except cp.DCPError:
139
print("Problem is not DCP compliant")
140
# Try solving anyway (solver may still succeed for some problems)
141
try:
142
problem.solve(ignore_dcp=True)
143
if problem.status == cp.OPTIMAL:
144
print(f"Non-convex optimization succeeded: x = {x.value}")
145
else:
146
print(f"Solver status: {problem.status}")
147
except cp.SolverError as e:
148
print(f"Solver failed on non-convex problem: {e}")
149
```
150
151
### Handling Geometric Programming Violations
152
153
```python
154
import cvxpy as cp
155
156
# DGP requires positive variables and specific structure
157
x = cp.Variable(pos=True)
158
y = cp.Variable(pos=True)
159
160
try:
161
# Invalid DGP: negative coefficient
162
problem = cp.Problem(cp.Minimize(-x * y), [x + y <= 1])
163
problem.solve(gp=True)
164
except cp.DGPError as e:
165
print(f"DGP Error: {e}")
166
# Solution: use proper geometric programming form
167
correct_problem = cp.Problem(cp.Minimize(x * y), [x + y <= 1])
168
correct_problem.solve(gp=True)
169
print(f"Corrected GP solution: x={x.value}, y={y.value}")
170
171
# Valid geometric program
172
try:
173
# Minimize surface area subject to volume constraint
174
# min 2(xy + xz + yz) s.t. xyz >= V, x,y,z > 0
175
x, y, z = cp.Variable(pos=True), cp.Variable(pos=True), cp.Variable(pos=True)
176
V = 1.0 # required volume
177
178
surface_area = 2 * (x*y + x*z + y*z)
179
volume_constraint = x * y * z >= V
180
181
gp_problem = cp.Problem(cp.Minimize(surface_area), [volume_constraint])
182
gp_problem.solve(gp=True)
183
184
print(f"Optimal box dimensions: x={x.value:.3f}, y={y.value:.3f}, z={z.value:.3f}")
185
print(f"Minimum surface area: {surface_area.value:.3f}")
186
187
except cp.DGPError as e:
188
print(f"Geometric programming error: {e}")
189
```
190
191
### Handling Solver Errors
192
193
```python
194
import cvxpy as cp
195
import numpy as np
196
197
def robust_solve(problem, solvers=None, **kwargs):
198
"""
199
Attempt to solve problem with multiple solvers.
200
"""
201
if solvers is None:
202
solvers = [cp.CLARABEL, cp.OSQP, cp.SCS, cp.ECOS]
203
204
last_error = None
205
206
for solver in solvers:
207
if solver not in cp.installed_solvers():
208
continue
209
210
try:
211
result = problem.solve(solver=solver, **kwargs)
212
if problem.status in [cp.OPTIMAL, cp.OPTIMAL_INACCURATE]:
213
return result
214
else:
215
last_error = f"{solver}: {problem.status}"
216
except cp.SolverError as e:
217
last_error = f"{solver}: {e}"
218
continue
219
except Exception as e:
220
last_error = f"{solver}: unexpected error {e}"
221
continue
222
223
raise cp.SolverError(f"All solvers failed. Last error: {last_error}")
224
225
# Example: ill-conditioned problem
226
n = 100
227
A = np.random.randn(n, n)
228
A = A @ A.T + 1e-12 * np.eye(n) # Nearly singular
229
b = np.random.randn(n)
230
x = cp.Variable(n)
231
232
problem = cp.Problem(cp.Minimize(cp.sum_squares(A @ x - b)))
233
234
try:
235
result = robust_solve(problem, verbose=False)
236
print(f"Problem solved successfully: {result:.6f}")
237
except cp.SolverError as e:
238
print(f"All solvers failed: {e}")
239
240
# Try with different tolerances
241
try:
242
result = robust_solve(problem, eps_abs=1e-12, eps_rel=1e-12)
243
print(f"Solved with tighter tolerances: {result:.6f}")
244
except cp.SolverError:
245
print("Problem is likely ill-conditioned")
246
247
# Example: infeasible problem detection
248
x = cp.Variable()
249
infeasible_problem = cp.Problem(cp.Minimize(x), [x >= 1, x <= 0])
250
251
try:
252
infeasible_problem.solve()
253
if infeasible_problem.status == cp.INFEASIBLE:
254
print("Problem is infeasible (expected)")
255
else:
256
print(f"Unexpected status: {infeasible_problem.status}")
257
except cp.SolverError as e:
258
print(f"Solver error on infeasible problem: {e}")
259
260
# Example: unbounded problem detection
261
y = cp.Variable()
262
unbounded_problem = cp.Problem(cp.Minimize(y)) # No constraints
263
264
try:
265
unbounded_problem.solve()
266
if unbounded_problem.status == cp.UNBOUNDED:
267
print("Problem is unbounded (expected)")
268
else:
269
print(f"Status: {unbounded_problem.status}")
270
except cp.SolverError as e:
271
print(f"Solver error on unbounded problem: {e}")
272
```
273
274
### Warning Management
275
276
```python
277
import cvxpy as cp
278
import numpy as np
279
280
# Check initial warning state
281
print(f"Warnings enabled: {cp.warnings_enabled()}")
282
283
# Example with warnings
284
x = cp.Variable()
285
problem = cp.Problem(cp.Minimize(x**2), [x >= 1])
286
287
# Solve with warnings (may show solver selection info)
288
problem.solve()
289
print(f"Solution with warnings: {x.value}")
290
291
# Disable warnings for cleaner output
292
cp.disable_warnings()
293
print(f"Warnings enabled: {cp.warnings_enabled()}")
294
295
# Solve without warnings
296
problem.solve()
297
print(f"Solution without warnings: {x.value}")
298
299
# Re-enable warnings
300
cp.enable_warnings()
301
print(f"Warnings enabled: {cp.warnings_enabled()}")
302
303
# Example: Parameter without value warning
304
p = cp.Parameter() # No initial value
305
x = cp.Variable()
306
307
try:
308
# This might generate warnings about unset parameter
309
problem = cp.Problem(cp.Minimize(x + p), [x >= 0])
310
problem.solve() # Will fail because p has no value
311
except Exception as e:
312
print(f"Expected error with unset parameter: {e}")
313
314
# Set parameter value and retry
315
p.value = 1.0
316
problem.solve()
317
print(f"Solution with parameter set: {x.value}")
318
319
# Example: Numerical precision warnings
320
# Create nearly infeasible problem
321
epsilon = 1e-15
322
x = cp.Variable()
323
nearly_infeasible = cp.Problem(
324
cp.Minimize(x),
325
[x >= 1, x <= 1 + epsilon]
326
)
327
328
try:
329
nearly_infeasible.solve()
330
if nearly_infeasible.status == cp.OPTIMAL_INACCURATE:
331
print("Solution found but may be inaccurate due to numerical precision")
332
print(f"Solution: {x.value}")
333
except cp.SolverError as e:
334
print(f"Numerical precision caused solver error: {e}")
335
```
336
337
### Exception Handling Best Practices
338
339
```python
340
import cvxpy as cp
341
import numpy as np
342
343
def safe_optimization(objective, constraints, **solve_kwargs):
344
"""
345
Safely solve optimization problem with comprehensive error handling.
346
"""
347
try:
348
# Create problem
349
problem = cp.Problem(objective, constraints)
350
351
# Check DCP compliance
352
if not problem.is_dcp():
353
print("Warning: Problem is not DCP compliant")
354
solve_kwargs['ignore_dcp'] = True
355
356
# Attempt to solve
357
result = problem.solve(**solve_kwargs)
358
359
# Check solution status
360
if problem.status == cp.OPTIMAL:
361
return result, "optimal"
362
elif problem.status == cp.OPTIMAL_INACCURATE:
363
return result, "optimal_inaccurate"
364
elif problem.status == cp.INFEASIBLE:
365
return None, "infeasible"
366
elif problem.status == cp.UNBOUNDED:
367
return None, "unbounded"
368
else:
369
return None, f"solver_issue_{problem.status}"
370
371
except cp.DCPError as e:
372
return None, f"dcp_error: {e}"
373
except cp.DGPError as e:
374
return None, f"dgp_error: {e}"
375
except cp.SolverError as e:
376
return None, f"solver_error: {e}"
377
except Exception as e:
378
return None, f"unexpected_error: {e}"
379
380
# Example usage
381
x = cp.Variable(2)
382
A = np.random.randn(3, 2)
383
b = np.random.randn(3)
384
385
result, status = safe_optimization(
386
cp.Minimize(cp.sum_squares(x)),
387
[A @ x == b, x >= 0],
388
solver=cp.OSQP
389
)
390
391
print(f"Optimization result: {result}")
392
print(f"Status: {status}")
393
394
if result is not None:
395
print(f"Optimal x: {x.value}")
396
else:
397
print("Optimization failed")
398
```