qpmad
Eigen-based C++ QP solver.
Loading...
Searching...
No Matches
solver.h
Go to the documentation of this file.
1/**
2 @file
3 @author Alexander Sherikov
4
5 @copyright 2017 Alexander Sherikov. Licensed under the Apache License,
6 Version 2.0. (see LICENSE or http://www.apache.org/licenses/LICENSE-2.0)
7
8 @brief Solver API layer
9*/
10
11
12#pragma once
13
14#include "implementation.h"
15
16
17namespace qpmad
18{
19 template <typename t_Scalar, int... t_Parameters>
20 class SolverTemplate : public SolverBase<t_Scalar, t_Parameters...>
21 {
22 public:
23 using typename SolverBase<t_Scalar, t_Parameters...>::ReturnStatus;
24
25
26 protected:
27 template <typename t_Type>
29 const typename std::enable_if<t_Type::IsVectorAtCompileTime, ReturnStatus>::type;
30 template <typename t_Type>
32 const typename std::enable_if<t_Type::ColsAtCompileTime != 1, ReturnStatus>::type;
33
34 using typename SolverBase<t_Scalar, t_Parameters...>::MatrixRef;
35 using typename SolverBase<t_Scalar, t_Parameters...>::VectorRef;
36 using MatrixConstRef = const Eigen::Ref<const Eigen::Matrix<t_Scalar, Eigen::Dynamic, Eigen::Dynamic> >;
37 using VectorConstRef = const Eigen::Ref<const Eigen::Matrix<t_Scalar, Eigen::Dynamic, 1> >;
38
39
40 const struct InputPlaceholders
41 {
42 Eigen::Matrix<t_Scalar, Eigen::Dynamic, 1> empty_vector_;
43 Eigen::Matrix<t_Scalar, Eigen::Dynamic, Eigen::Dynamic> empty_matrix_;
46
47
48 protected:
49 template <class t_primal, class... t_Args>
50 VectorEnablerReturnType<t_primal> solve0(t_primal &primal, t_Args &&...args)
51 {
52 return (solve1(primal, std::forward<t_Args>(args)...));
53 }
54
55 template <class... t_Args>
56 ReturnStatus solve0(VectorRef primal, t_Args &&...args)
57 {
58 return (solve1(primal, std::forward<t_Args>(args)...));
59 }
60
61 // ---
62
63 template <class t_primal, class t_H, class... t_Args>
64 MatrixEnablerReturnType<t_H> solve1(t_primal &primal, t_H &H, t_Args &&...args)
65 {
66 return (solve2(primal, H, std::forward<t_Args>(args)...));
67 }
68
69 template <class t_primal, class... t_Args>
70 ReturnStatus solve1(t_primal &primal, MatrixRef H, t_Args &&...args)
71 {
72 return (solve2(primal, H, std::forward<t_Args>(args)...));
73 }
74
75 // ---
76
77 template <class t_primal, class t_H, class t_h, class... t_Args>
78 VectorEnablerReturnType<t_h> solve2(t_primal &primal, t_H &H, const t_h &h, t_Args &&...args)
79 {
80 return (solve3(primal, H, h, std::forward<t_Args>(args)...));
81 }
82
83 template <class t_primal, class t_H, class... t_Args>
84 ReturnStatus solve2(t_primal &primal, t_H &H, VectorConstRef h, t_Args &&...args)
85 {
86 return (solve3(primal, H, h, std::forward<t_Args>(args)...));
87 }
88
89 // ---
90
91 template <class t_primal, class t_H, class t_h, class t_lb, class... t_Args>
92 VectorEnablerReturnType<t_lb> solve3(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, t_Args &&...args)
93 {
94 return (solve4(primal, H, h, lb, std::forward<t_Args>(args)...));
95 }
96
97 template <class t_primal, class t_H, class t_h, class t_lb, class... t_Args>
98 ReturnStatus solve3(t_primal &primal, t_H &H, const t_h &h, VectorConstRef lb, t_Args &&...args)
99 {
100 return (solve4(primal, H, h, lb, std::forward<t_Args>(args)...));
101 }
102
103 template <class t_primal, class t_H, class t_h, class t_A, class... t_Args>
104 MatrixEnablerReturnType<t_A> solve3(t_primal &primal, t_H &H, const t_h &h, const t_A &A, t_Args &&...args)
105 {
106 return (
107 solve5(primal,
108 H,
109 h,
112 A,
113 std::forward<t_Args>(args)...));
114 }
115
116 template <class t_primal, class t_H, class t_h, class... t_Args>
117 ReturnStatus solve3(t_primal &primal, t_H &H, const t_h &h, MatrixConstRef A, t_Args &&...args)
118 {
119 return (
120 solve5(primal,
121 H,
122 h,
125 A,
126 std::forward<t_Args>(args)...));
127 }
128
129 // ---
130
131 template <class t_primal, class t_H, class t_h, class t_lb, class t_ub>
132 VectorEnablerReturnType<t_ub> solve4(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub)
133 {
134 return (solve5(primal, H, h, lb, ub, input_placeholders_.solver_parameters_));
135 }
136
137
138 template <class t_primal, class t_H, class t_h, class t_lb, class t_ub, class... t_Args>
140 t_primal &primal,
141 t_H &H,
142 const t_h &h,
143 const t_lb &lb,
144 const t_ub &ub,
145 t_Args &&...args)
146 {
147 return (solve5(primal, H, h, lb, ub, std::forward<t_Args>(args)...));
148 }
149
150 template <class t_primal, class t_H, class t_h, class t_lb>
151 ReturnStatus solve4(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, VectorConstRef ub)
152 {
153 return (solve5(primal, H, h, lb, ub, input_placeholders_.solver_parameters_));
154 }
155
156
157 template <class t_primal, class t_H, class t_h, class t_lb, class... t_Args>
158 ReturnStatus solve4(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, VectorConstRef ub, t_Args &&...args)
159 {
160 return (solve5(primal, H, h, lb, ub, std::forward<t_Args>(args)...));
161 }
162
163 // ---
164
165 template <class t_primal, class t_H, class t_h, class t_lb, class t_ub>
167 t_primal &primal,
168 t_H &H,
169 const t_h &h,
170 const t_lb &lb,
171 const t_ub &ub,
172 const SolverParameters &param)
173 {
174 return (
175 solve8(primal,
176 H,
177 h,
178 lb,
179 ub,
183 param));
184 }
185
186 template <class t_primal, class t_H, class t_h, class t_lb, class t_ub, class t_A, class... t_Args>
188 t_primal &primal,
189 t_H &H,
190 const t_h &h,
191 const t_lb &lb,
192 const t_ub &ub,
193 const t_A &A,
194 t_Args &&...args)
195 {
196 return (solve6(primal, H, h, lb, ub, A, std::forward<t_Args>(args)...));
197 }
198
199 template <class t_primal, class t_H, class t_h, class t_lb, class t_ub, class... t_Args>
201 t_primal &primal,
202 t_H &H,
203 const t_h &h,
204 const t_lb &lb,
205 const t_ub &ub,
207 t_Args &&...args)
208 {
209 return (solve6(primal, H, h, lb, ub, A, std::forward<t_Args>(args)...));
210 }
211
212 // ---
213
214 template <class t_primal, class t_H, class t_h, class t_lb, class t_ub, class t_A, class t_Alb>
216 t_primal &primal,
217 t_H &H,
218 const t_h &h,
219 const t_lb &lb,
220 const t_ub &ub,
221 const t_A &A,
222 const t_Alb &Alb)
223 {
224 return (solve8(primal, H, h, lb, ub, A, Alb, Alb, input_placeholders_.solver_parameters_));
225 }
226
227 template <class t_primal, class t_H, class t_h, class t_lb, class t_ub, class t_A, class t_Alb, class... t_Args>
229 t_primal &primal,
230 t_H &H,
231 const t_h &h,
232 const t_lb &lb,
233 const t_ub &ub,
234 const t_A &A,
235 const t_Alb &Alb,
236 t_Args &&...args)
237 {
238 return (solve7(primal, H, h, lb, ub, A, Alb, std::forward<t_Args>(args)...));
239 }
240
241 template <class t_primal, class t_H, class t_h, class t_lb, class t_ub, class t_A>
243 t_primal &primal,
244 t_H &H,
245 const t_h &h,
246 const t_lb &lb,
247 const t_ub &ub,
248 const t_A &A,
249 VectorConstRef Alb)
250 {
251 return (solve8(primal, H, h, lb, ub, A, Alb, Alb, input_placeholders_.solver_parameters_));
252 }
253
254 template <class t_primal, class t_H, class t_h, class t_lb, class t_ub, class t_A, class... t_Args>
256 t_primal &primal,
257 t_H &H,
258 const t_h &h,
259 const t_lb &lb,
260 const t_ub &ub,
261 const t_A &A,
262 VectorConstRef Alb,
263 t_Args &&...args)
264 {
265 return (solve7(primal, H, h, lb, ub, A, Alb, std::forward<t_Args>(args)...));
266 }
267
268 // ---
269
270 template <class t_primal, class t_H, class t_h, class t_lb, class t_ub, class t_A, class t_Alb, class t_Aub>
272 t_primal &primal,
273 t_H &H,
274 const t_h &h,
275 const t_lb &lb,
276 const t_ub &ub,
277 const t_A &A,
278 const t_Alb &Alb,
279 const t_Aub &Aub)
280 {
281 return (solve8(primal, H, h, lb, ub, A, Alb, Aub, input_placeholders_.solver_parameters_));
282 }
283
284 template <
285 class t_primal,
286 class t_H,
287 class t_h,
288 class t_lb,
289 class t_ub,
290 class t_A,
291 class t_Alb,
292 class t_Aub,
293 class... t_Args>
295 t_primal &primal,
296 t_H &H,
297 const t_h &h,
298 const t_lb &lb,
299 const t_ub &ub,
300 const t_A &A,
301 const t_Alb &Alb,
302 const t_Aub &Aub,
303 t_Args &&...args)
304 {
305 return (solve8(primal, H, h, lb, ub, A, Alb, Aub, std::forward<t_Args>(args)...));
306 }
307
308 template <class t_primal, class t_H, class t_h, class t_lb, class t_ub, class t_A, class t_Alb>
310 t_primal &primal,
311 t_H &H,
312 const t_h &h,
313 const t_lb &lb,
314 const t_ub &ub,
315 const t_A &A,
316 const t_Alb &Alb,
317 VectorConstRef Aub)
318 {
319 return (solve8(primal, H, h, lb, ub, A, Alb, Aub, input_placeholders_.solver_parameters_));
320 }
321
322 template <class t_primal, class t_H, class t_h, class t_lb, class t_ub, class t_A, class t_Alb, class... t_Args>
324 t_primal &primal,
325 t_H &H,
326 const t_h &h,
327 const t_lb &lb,
328 const t_ub &ub,
329 const t_A &A,
330 const t_Alb &Alb,
331 VectorConstRef Aub,
332 t_Args &&...args)
333 {
334 return (solve8(primal, H, h, lb, ub, A, Alb, Aub, std::forward<t_Args>(args)...));
335 }
336
337 // ---
338
339 template <class t_primal, class t_H, class t_h, class t_lb, class t_ub, class t_A, class t_Alb, class t_Aub>
341 t_primal &primal,
342 t_H &H,
343 const t_h &h,
344 const t_lb &lb,
345 const t_ub &ub,
346 const t_A &A,
347 const t_Alb &Alb,
348 const t_Aub &Aub,
349 const SolverParameters &param)
350 {
351 this->primal_size_ = H.rows();
352 this->h_size_ = h.rows();
353
354 QPMAD_UTILS_PERSISTENT_ASSERT(this->primal_size_ > 0, "Hessian must not be empty.");
355 QPMAD_UTILS_PERSISTENT_ASSERT(this->primal_size_ == H.cols(), "Hessian must be square.");
357 ((this->primal_size_ == this->h_size_) && (1 == h.cols())) || (0 == this->h_size_),
358 "Wrong size of h.");
359
360
361 this->num_simple_bounds_ = lb.rows();
362
364 (0 == this->num_simple_bounds_) || (this->primal_size_ == this->num_simple_bounds_),
365 "Vector of lower simple bounds has wrong size (1).");
367 ub.rows() == this->num_simple_bounds_, "Vector of upper simple bounds has wrong size (1).");
368
370 ((this->num_simple_bounds_ > 0) && (1 == lb.cols())) || (1 == lb.cols()),
371 "Vector of lower simple bounds has wrong size (2).");
373 ((this->num_simple_bounds_ > 0) && (1 == ub.cols())) || (1 == ub.cols()),
374 "Vector of upper simple bounds has wrong size (2).");
375
376
377 this->num_general_constraints_ = A.rows();
378
380 (A.cols() == this->primal_size_) || ((0 == this->num_general_constraints_) && (0 == A.cols())),
381 "Matrix of general constraints has wrong size.");
382
384 Alb.rows() == this->num_general_constraints_,
385 "Vector of lower bounds of general constraints has wrong size (1).");
387 Aub.rows() == this->num_general_constraints_,
388 "Vector of upper bounds of general constraints has wrong size (1).");
389
391 ((this->num_general_constraints_ > 0) && (1 == Alb.cols())) || (0 == Alb.rows()),
392 "Vector of lower bounds of general constraints has wrong size (2).");
394 ((this->num_general_constraints_ > 0) && (1 == Aub.cols())) || (0 == Aub.rows()),
395 "Vector of upper bounds of general constraints has wrong size (2).");
396
397 return (this->solveGeneric(primal, H, h, lb, ub, A, Alb, Aub, param));
398 }
399
400
401 public:
403 {
404 }
405
406 /**
407 * @brief Solve QP
408 *
409 * Inputs:
410 * - [out] Vector primal -- solution vector, mandatory, allocated if needed
411 * - [in,out] Matrix H -- Hessian, mandatory, non-empty, factorized in-place
412 * - [in] Vector h -- objective vector, mandatory, may be empty
413 * - [in] Vector lb -- vector of lower bounds, may be omitted or may be empty consistently with ub
414 * - [in] Vector ub -- vector of upper bounds, may be omitted or may be empty consistently with lb
415 * - [in] Matrix A -- general constraints matrix, may be omitted with all general constraints, may be empty
416 * - [in] Vector Alb -- lower bounds of general constraints, may be omitted with all general constraints, may
417 * be empty
418 * - [in] Vector Aub -- upper bounds of general constraints, may be omitted (if A and Alb are present they
419 * are assumed to be equality constraints), may be empty
420 * - [in] SolverParameters param -- solver parameters, may be omitted
421 */
422 template <class... t_Args>
423 ReturnStatus solve(t_Args &&...args)
424 {
425 return (solve0(std::forward<t_Args>(args)...));
426 }
427 };
428
429
431} // namespace qpmad
ReturnStatus solveGeneric(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, const t_A &A, const t_Alb &Alb, const t_Aub &Aub, const SolverParameters &param)
Eigen::Ref< Eigen::Matrix< t_Scalar, Eigen::Dynamic, Eigen::Dynamic > > MatrixRef
Eigen::Ref< Eigen::Matrix< t_Scalar, Eigen::Dynamic, 1 > > VectorRef
VectorEnablerReturnType< t_ub > solve4(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, t_Args &&...args)
Definition: solver.h:139
const struct qpmad::SolverTemplate::InputPlaceholders input_placeholders_
ReturnStatus solve6(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, const t_A &A, VectorConstRef Alb, t_Args &&...args)
Definition: solver.h:255
ReturnStatus solve3(t_primal &primal, t_H &H, const t_h &h, MatrixConstRef A, t_Args &&...args)
Definition: solver.h:117
VectorEnablerReturnType< t_Aub > solve7(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, const t_A &A, const t_Alb &Alb, const t_Aub &Aub)
Definition: solver.h:271
ReturnStatus solve2(t_primal &primal, t_H &H, VectorConstRef h, t_Args &&...args)
Definition: solver.h:84
ReturnStatus solve3(t_primal &primal, t_H &H, const t_h &h, VectorConstRef lb, t_Args &&...args)
Definition: solver.h:98
MatrixEnablerReturnType< t_H > solve1(t_primal &primal, t_H &H, t_Args &&...args)
Definition: solver.h:64
const Eigen::Ref< const Eigen::Matrix< t_Scalar, Eigen::Dynamic, 1 > > VectorConstRef
Definition: solver.h:37
VectorEnablerReturnType< t_h > solve2(t_primal &primal, t_H &H, const t_h &h, t_Args &&...args)
Definition: solver.h:78
ReturnStatus solve5(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, MatrixConstRef A, t_Args &&...args)
Definition: solver.h:200
const typename std::enable_if< t_Type::ColsAtCompileTime !=1, ReturnStatus >::type MatrixEnablerReturnType
Definition: solver.h:32
ReturnStatus solve7(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, const t_A &A, const t_Alb &Alb, VectorConstRef Aub, t_Args &&...args)
Definition: solver.h:323
VectorEnablerReturnType< t_primal > solve0(t_primal &primal, t_Args &&...args)
Definition: solver.h:50
MatrixEnablerReturnType< t_A > solve3(t_primal &primal, t_H &H, const t_h &h, const t_A &A, t_Args &&...args)
Definition: solver.h:104
ReturnStatus solve4(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, VectorConstRef ub, t_Args &&...args)
Definition: solver.h:158
ReturnStatus solve7(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, const t_A &A, const t_Alb &Alb, VectorConstRef Aub)
Definition: solver.h:309
VectorEnablerReturnType< t_ub > solve4(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub)
Definition: solver.h:132
ReturnStatus solve1(t_primal &primal, MatrixRef H, t_Args &&...args)
Definition: solver.h:70
ReturnStatus solve5(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, const SolverParameters &param)
Definition: solver.h:166
ReturnStatus solve8(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, const t_A &A, const t_Alb &Alb, const t_Aub &Aub, const SolverParameters &param)
Definition: solver.h:340
ReturnStatus solve(t_Args &&...args)
Solve QP.
Definition: solver.h:423
VectorEnablerReturnType< t_Alb > solve6(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, const t_A &A, const t_Alb &Alb, t_Args &&...args)
Definition: solver.h:228
ReturnStatus solve4(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, VectorConstRef ub)
Definition: solver.h:151
const typename std::enable_if< t_Type::IsVectorAtCompileTime, ReturnStatus >::type VectorEnablerReturnType
Definition: solver.h:29
const Eigen::Ref< const Eigen::Matrix< t_Scalar, Eigen::Dynamic, Eigen::Dynamic > > MatrixConstRef
Definition: solver.h:36
ReturnStatus solve6(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, const t_A &A, VectorConstRef Alb)
Definition: solver.h:242
VectorEnablerReturnType< t_lb > solve3(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, t_Args &&...args)
Definition: solver.h:92
MatrixEnablerReturnType< t_A > solve5(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, const t_A &A, t_Args &&...args)
Definition: solver.h:187
ReturnStatus solve0(VectorRef primal, t_Args &&...args)
Definition: solver.h:56
VectorEnablerReturnType< t_Aub > solve7(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, const t_A &A, const t_Alb &Alb, const t_Aub &Aub, t_Args &&...args)
Definition: solver.h:294
VectorEnablerReturnType< t_Alb > solve6(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, const t_ub &ub, const t_A &A, const t_Alb &Alb)
Definition: solver.h:215
#define QPMAD_UTILS_PERSISTENT_ASSERT(condition, message)
Solver implementation.
Eigen::Matrix< t_Scalar, Eigen::Dynamic, 1 > empty_vector_
Definition: solver.h:42
Eigen::Matrix< t_Scalar, Eigen::Dynamic, Eigen::Dynamic > empty_matrix_
Definition: solver.h:43