0
# Core Solving Functions
1
2
The main interface functions for solving quadratic programming problems with qpsolvers. These functions provide a unified API that abstracts different solver backends and handles matrix format conversions automatically.
3
4
## Capabilities
5
6
### Primary QP Solving
7
8
The main function for solving quadratic programs with automatic solver selection and format handling.
9
10
```python { .api }
11
def solve_qp(
12
P: Union[np.ndarray, spa.csc_matrix],
13
q: np.ndarray,
14
G: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
15
h: Optional[np.ndarray] = None,
16
A: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
17
b: Optional[np.ndarray] = None,
18
lb: Optional[np.ndarray] = None,
19
ub: Optional[np.ndarray] = None,
20
solver: Optional[str] = None,
21
initvals: Optional[np.ndarray] = None,
22
verbose: bool = False,
23
**kwargs
24
) -> Optional[np.ndarray]:
25
"""
26
Solve a quadratic program using the specified solver.
27
28
The QP is formulated as:
29
minimize 1/2 x^T P x + q^T x
30
subject to G x <= h
31
A x = b
32
lb <= x <= ub
33
34
Parameters:
35
- P: Symmetric cost matrix (positive semi-definite)
36
- q: Cost vector
37
- G: Linear inequality constraint matrix
38
- h: Linear inequality constraint vector
39
- A: Linear equality constraint matrix
40
- b: Linear equality constraint vector
41
- lb: Lower bound constraint vector (can contain -np.inf)
42
- ub: Upper bound constraint vector (can contain +np.inf)
43
- solver: Solver name from available_solvers (required)
44
- initvals: Initial values for warm-starting
45
- verbose: Enable solver output
46
- **kwargs: Solver-specific parameters
47
48
Returns:
49
Optimal solution vector if found, None if infeasible/unbounded
50
51
Raises:
52
- NoSolverSelected: If solver parameter is not specified
53
- SolverNotFound: If specified solver is not available
54
- SolverError: If solver encounters an error
55
"""
56
```
57
58
Usage example:
59
60
```python
61
import numpy as np
62
from qpsolvers import solve_qp, available_solvers
63
64
# Check available solvers
65
print("Available solvers:", available_solvers)
66
67
# Define QP matrices
68
P = np.array([[2.0, 0.0], [0.0, 2.0]])
69
q = np.array([1.0, 1.0])
70
G = np.array([[-1.0, 0.0], [0.0, -1.0]])
71
h = np.array([0.0, 0.0])
72
73
# Solve with different solvers
74
x1 = solve_qp(P, q, G, h, solver="osqp")
75
x2 = solve_qp(P, q, G, h, solver="cvxopt")
76
x3 = solve_qp(P, q, G, h, solver="proxqp", verbose=True)
77
```
78
79
### Problem-Based Solving
80
81
Alternative interface that uses Problem objects and returns complete Solution objects with dual multipliers.
82
83
```python { .api }
84
def solve_problem(
85
problem: Problem,
86
solver: str,
87
initvals: Optional[np.ndarray] = None,
88
verbose: bool = False,
89
**kwargs
90
) -> Solution:
91
"""
92
Solve a quadratic program using a Problem object.
93
94
Parameters:
95
- problem: Problem instance containing QP formulation
96
- solver: Solver name from available_solvers
97
- initvals: Initial values for warm-starting
98
- verbose: Enable solver output
99
- **kwargs: Solver-specific parameters
100
101
Returns:
102
Solution object with primal/dual variables and optimality information
103
104
Raises:
105
- SolverNotFound: If specified solver is not available
106
- ValueError: If problem is malformed or non-convex
107
"""
108
```
109
110
Usage example:
111
112
```python
113
from qpsolvers import Problem, solve_problem
114
115
# Create a problem instance
116
problem = Problem(P, q, G, h, A, b)
117
problem.check_constraints() # Validate problem formulation
118
119
# Solve and get complete solution
120
solution = solve_problem(problem, solver="osqp")
121
122
if solution.found:
123
print(f"Optimal value: {solution.obj}")
124
print(f"Primal solution: {solution.x}")
125
print(f"Dual multipliers (inequalities): {solution.z}")
126
print(f"Dual multipliers (equalities): {solution.y}")
127
print(f"Is optimal: {solution.is_optimal(eps_abs=1e-6)}")
128
```
129
130
### Least Squares Solving
131
132
Specialized function for solving linear least squares problems as quadratic programs.
133
134
```python { .api }
135
def solve_ls(
136
R: Union[np.ndarray, spa.csc_matrix],
137
s: np.ndarray,
138
G: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
139
h: Optional[np.ndarray] = None,
140
A: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
141
b: Optional[np.ndarray] = None,
142
lb: Optional[np.ndarray] = None,
143
ub: Optional[np.ndarray] = None,
144
W: Optional[Union[np.ndarray, spa.csc_matrix]] = None,
145
solver: Optional[str] = None,
146
initvals: Optional[np.ndarray] = None,
147
verbose: bool = False,
148
sparse_conversion: Optional[bool] = None,
149
**kwargs
150
) -> Optional[np.ndarray]:
151
"""
152
Solve a linear least squares problem with optional constraints.
153
154
Formulated as:
155
minimize 1/2 ||R x - s||^2_W
156
subject to G x <= h
157
A x = b
158
lb <= x <= ub
159
160
Where ||·||_W is the weighted norm with weight matrix W.
161
162
Parameters:
163
- R: Regression matrix
164
- s: Target vector
165
- G: Linear inequality constraint matrix
166
- h: Linear inequality constraint vector
167
- A: Linear equality constraint matrix
168
- b: Linear equality constraint vector
169
- lb: Lower bound constraint vector
170
- ub: Upper bound constraint vector
171
- W: Weight matrix for the least squares objective
172
- solver: Solver name from available_solvers
173
- initvals: Initial values for warm-starting
174
- verbose: Enable solver output
175
- sparse_conversion: Force sparse (True) or dense (False) conversion, auto if None
176
- **kwargs: Solver-specific parameters
177
178
Returns:
179
Optimal solution vector if found, None if infeasible
180
"""
181
```
182
183
Usage example:
184
185
```python
186
import numpy as np
187
from qpsolvers import solve_ls
188
189
# Define least squares problem: minimize ||Rx - s||^2
190
R = np.random.randn(100, 10) # 100 observations, 10 variables
191
s = np.random.randn(100) # target values
192
193
# Solve unconstrained least squares
194
x_unconstrained = solve_ls(R, s, solver="osqp")
195
196
# Solve with non-negativity constraints
197
lb = np.zeros(10)
198
x_nonneg = solve_ls(R, s, lb=lb, solver="osqp")
199
200
# Solve with weighted least squares
201
W = np.diag(np.random.rand(100)) # diagonal weight matrix
202
x_weighted = solve_ls(R, s, W=W, solver="osqp")
203
```
204
205
### Unconstrained QP Solving
206
207
Specialized function for solving unconstrained quadratic programs using SciPy's LSQR.
208
209
```python { .api }
210
def solve_unconstrained(problem: Problem) -> Solution:
211
"""
212
Solve an unconstrained quadratic program with SciPy's LSQR.
213
214
Only works for problems with no constraints (G, h, A, b, lb, ub all None).
215
216
Parameters:
217
- problem: Unconstrained Problem instance
218
219
Returns:
220
Solution object with the optimal point
221
222
Raises:
223
- ProblemError: If the problem is unbounded below or has constraints
224
"""
225
```
226
227
Usage example:
228
229
```python
230
from qpsolvers import Problem, solve_unconstrained
231
import numpy as np
232
233
# Define unconstrained QP: minimize 1/2 x^T P x + q^T x
234
P = np.array([[2.0, 1.0], [1.0, 2.0]])
235
q = np.array([1.0, -1.0])
236
237
# Create unconstrained problem
238
problem = Problem(P, q) # No constraints specified
239
240
# Solve directly
241
solution = solve_unconstrained(problem)
242
print(f"Unconstrained optimum: {solution.x}")
243
```
244
245
## Matrix Format Support
246
247
All solving functions accept both dense and sparse matrix formats:
248
249
- **Dense matrices**: `numpy.ndarray` for smaller problems or when dense solvers are preferred
250
- **Sparse matrices**: `scipy.sparse.csc_matrix` for large sparse problems
251
252
The functions automatically handle format conversions based on the selected solver's requirements.
253
254
```python
255
import numpy as np
256
import scipy.sparse as spa
257
from qpsolvers import solve_qp
258
259
# Dense format
260
P_dense = np.eye(3)
261
solution1 = solve_qp(P_dense, q, solver="quadprog") # dense solver
262
263
# Sparse format
264
P_sparse = spa.eye(3, format="csc")
265
solution2 = solve_qp(P_sparse, q, solver="osqp") # sparse solver
266
```