qpmad
Eigen-based C++ QP solver.
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 
17 namespace 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,
206  MatrixConstRef A,
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_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
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
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
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 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, t_Args &&...args)
Definition: solver.h:294
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
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
VectorEnablerReturnType< t_h > solve2(t_primal &primal, t_H &H, const t_h &h, t_Args &&...args)
Definition: solver.h:78
const Eigen::Ref< const Eigen::Matrix< t_Scalar, Eigen::Dynamic, 1 > > VectorConstRef
Definition: solver.h:37
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 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_lb > solve3(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, t_Args &&...args)
Definition: solver.h:92
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_primal > solve0(t_primal &primal, t_Args &&...args)
Definition: solver.h:50
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
MatrixEnablerReturnType< t_H > solve1(t_primal &primal, t_H &H, t_Args &&...args)
Definition: solver.h:64
ReturnStatus solve4(t_primal &primal, t_H &H, const t_h &h, const t_lb &lb, VectorConstRef ub)
Definition: solver.h:151
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
const typename std::enable_if< t_Type::IsVectorAtCompileTime, ReturnStatus >::type VectorEnablerReturnType
Definition: solver.h:29
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
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
ReturnStatus solve0(VectorRef primal, t_Args &&...args)
Definition: solver.h:56
#define QPMAD_UTILS_PERSISTENT_ASSERT(condition,...)
Definition: exception.h:22
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