Epigraph
Convex Optimization in C++
constraint.hpp
Go to the documentation of this file.
1 
6 #pragma once
7 
8 #include "expressions.hpp"
9 
10 #include <variant>
11 
12 namespace cvx
13 {
14  namespace internal
15  {
16 
17  struct EqualityConstraint
18  {
19  Affine affine;
20  friend std::ostream &operator<<(std::ostream &os, const EqualityConstraint &constraint);
21  };
22 
23  struct PositiveConstraint
24  {
25  Affine affine;
26  friend std::ostream &operator<<(std::ostream &os, const PositiveConstraint &constraint);
27  };
28 
29  struct BoxConstraint
30  {
31  Affine lower;
32  Affine middle;
33  Affine upper;
34  friend std::ostream &operator<<(std::ostream &os, const BoxConstraint &constraint);
35  };
36 
37  struct SecondOrderConeConstraint
38  {
39  std::vector<Affine> norm;
40  Affine affine;
41  friend std::ostream &operator<<(std::ostream &os, const SecondOrderConeConstraint &constraint);
42  };
43 
44  } // namespace internal
45 
46  class Constraint
47  {
48  public:
49  enum Type
50  {
51  Equality,
52  Positive,
53  Box,
54  SecondOrderCone
55  };
56 
57  Type getType() const;
58 
59  friend std::ostream &operator<<(std::ostream &os, const Constraint &constraint);
60 
61  friend OptimizationProblem;
62 
63  friend Constraint equalTo(const Scalar &lhs, const Scalar &rhs);
64  friend Constraint lessThan(const Scalar &lhs, const Scalar &rhs);
65  friend Constraint greaterThan(const Scalar &lhs, const Scalar &rhs);
66  friend Constraint box(const Scalar &lower, const Scalar &middle, const Scalar &upper);
67 
68  private:
69  void asEquality(const internal::Affine &affine);
70  void asPositive(const internal::Affine &affine);
71  void asBox(const internal::Affine &lower, const internal::Affine &middle, const internal::Affine &upper);
72  void asSecondOrderCone(const std::vector<internal::Affine> &norm, const internal::Affine &affine);
73 
74  using constraint_variant_t = std::variant<internal::EqualityConstraint,
75  internal::PositiveConstraint,
76  internal::BoxConstraint,
77  internal::SecondOrderConeConstraint>;
78  constraint_variant_t data;
79  };
80 
88  Constraint equalTo(const Scalar &lhs, const Scalar &rhs);
89 
97  Constraint greaterThan(const Scalar &lhs, const Scalar &rhs);
98 
106  Constraint lessThan(const Scalar &lhs, const Scalar &rhs);
107 
116  Constraint box(const Scalar &lower, const Scalar &middle, const Scalar &upper);
117 
118  template <typename Derived>
119  std::vector<Constraint> equalTo(const Eigen::MatrixBase<Derived> &lhs, const Scalar &rhs)
120  {
121  static_assert(std::is_same_v<typename Eigen::MatrixBase<Derived>::Scalar, Scalar>);
122 
123  std::vector<Constraint> constraints;
124 
125  for (int row = 0; row < lhs.rows(); row++)
126  {
127  for (int col = 0; col < lhs.cols(); col++)
128  {
129  constraints.push_back(equalTo(lhs(row, col), rhs));
130  }
131  }
132 
133  return constraints;
134  }
135 
144  template <typename Derived>
145  std::vector<Constraint> equalTo(const Scalar &lhs, const Eigen::MatrixBase<Derived> &rhs)
146  {
147  return equalTo(rhs, lhs);
148  }
149 
159  template <typename DerivedLhs, typename DerivedRhs>
160  std::vector<Constraint> equalTo(const Eigen::MatrixBase<DerivedLhs> &lhs, const Eigen::MatrixBase<DerivedRhs> &rhs)
161  {
162  static_assert(std::is_same_v<typename Eigen::MatrixBase<DerivedLhs>::Scalar, Scalar>);
163  static_assert(std::is_same_v<typename Eigen::MatrixBase<DerivedRhs>::Scalar, Scalar>);
164 
165  std::vector<Constraint> constraints;
166 
167  // If they are both matrices then the dimensions have to match
168  if (lhs.rows() != rhs.rows() or lhs.cols() != rhs.cols())
169  {
170  throw std::runtime_error("Invalid dimensions in constraint.");
171  }
172 
173  for (int row = 0; row < rhs.rows(); row++)
174  {
175  for (int col = 0; col < rhs.cols(); col++)
176  {
177  constraints.push_back(equalTo(lhs(row, col), rhs(row, col)));
178  }
179  }
180 
181  return constraints;
182  }
183 
192  template <typename Derived>
193  std::vector<Constraint> lessThan(const Eigen::MatrixBase<Derived> &lhs, const Scalar &rhs)
194  {
195  static_assert(std::is_same_v<typename Eigen::MatrixBase<Derived>::Scalar, Scalar>);
196 
197  std::vector<Constraint> constraints;
198 
199  for (int row = 0; row < lhs.rows(); row++)
200  {
201  for (int col = 0; col < lhs.cols(); col++)
202  {
203  constraints.push_back(lessThan(lhs(row, col), rhs));
204  }
205  }
206 
207  return constraints;
208  }
209 
218  template <typename Derived>
219  std::vector<Constraint> lessThan(const Scalar &lhs, const Eigen::MatrixBase<Derived> &rhs)
220  {
221  static_assert(std::is_same_v<typename Eigen::MatrixBase<Derived>::Scalar, Scalar>);
222 
223  std::vector<Constraint> constraints;
224 
225  for (int row = 0; row < rhs.rows(); row++)
226  {
227  for (int col = 0; col < rhs.cols(); col++)
228  {
229  constraints.push_back(lessThan(lhs, rhs(row, col)));
230  }
231  }
232 
233  return constraints;
234  }
235 
245  template <typename DerivedLhs, typename DerivedRhs>
246  std::vector<Constraint> lessThan(const Eigen::MatrixBase<DerivedLhs> &lhs, const Eigen::MatrixBase<DerivedRhs> &rhs)
247  {
248  static_assert(std::is_same_v<typename Eigen::MatrixBase<DerivedLhs>::Scalar, Scalar>);
249  static_assert(std::is_same_v<typename Eigen::MatrixBase<DerivedRhs>::Scalar, Scalar>);
250 
251  std::vector<Constraint> constraints;
252 
253  if ((lhs.rows() != rhs.rows()) or
254  (lhs.cols() != rhs.cols()))
255  {
256  throw std::runtime_error("Invalid dimensions in constraint.");
257  }
258 
259  for (int row = 0; row < rhs.rows(); row++)
260  {
261  for (int col = 0; col < rhs.cols(); col++)
262  {
263  constraints.push_back(lessThan(lhs(row, col), rhs(row, col)));
264  }
265  }
266 
267  return constraints;
268  }
269 
279  template <typename DerivedLhs, typename DerivedRhs>
280  std::vector<Constraint> greaterThan(const Eigen::MatrixBase<DerivedLhs> &lhs, const Eigen::MatrixBase<DerivedRhs> &rhs)
281  {
282  return lessThan(rhs, lhs);
283  }
284 
293  template <typename Derived>
294  std::vector<Constraint> greaterThan(const Scalar &lhs, const Eigen::MatrixBase<Derived> &rhs)
295  {
296  return lessThan(rhs, lhs);
297  }
298 
307  template <typename Derived>
308  std::vector<Constraint> greaterThan(const Eigen::MatrixBase<Derived> &lhs, const Scalar &rhs)
309  {
310  return lessThan(rhs, lhs);
311  }
312 
324  template <typename DerivedLower, typename DerivedMiddle, typename DerivedUpper>
325  std::vector<Constraint> box(const Eigen::MatrixBase<DerivedLower> &lower,
326  const Eigen::MatrixBase<DerivedMiddle> &middle,
327  const Eigen::MatrixBase<DerivedUpper> &upper)
328  {
329  static_assert(std::is_same_v<typename Eigen::MatrixBase<DerivedLower>::Scalar, Scalar>);
330  static_assert(std::is_same_v<typename Eigen::MatrixBase<DerivedMiddle>::Scalar, Scalar>);
331  static_assert(std::is_same_v<typename Eigen::MatrixBase<DerivedUpper>::Scalar, Scalar>);
332 
333  if (lower.rows() != middle.rows() or middle.rows() != upper.rows() or
334  lower.cols() != middle.cols() or middle.cols() != upper.cols())
335  {
336  throw std::runtime_error("Invalid dimensions in constraint.");
337  }
338 
339  std::vector<Constraint> constraints;
340 
341  for (int row = 0; row < middle.rows(); row++)
342  {
343  for (int col = 0; col < middle.cols(); col++)
344  {
345  constraints.push_back(box(lower(row, col),
346  middle(row, col),
347  upper(row, col)));
348  }
349  }
350 
351  return constraints;
352  }
353 
363  template <typename Derived>
364  std::vector<Constraint> box(const Scalar &lower,
365  const Eigen::MatrixBase<Derived> &middle,
366  const Scalar &upper)
367  {
368  static_assert(std::is_same_v<typename Eigen::MatrixBase<Derived>::Scalar, Scalar>);
369 
370  std::vector<Constraint> constraints;
371 
372  for (int row = 0; row < middle.rows(); row++)
373  {
374  for (int col = 0; col < middle.cols(); col++)
375  {
376  constraints.push_back(box(lower,
377  middle(row, col),
378  upper));
379  }
380  }
381 
382  return constraints;
383  }
384 
385 } // namespace cvx
cvx::greaterThan
Constraint greaterThan(const Scalar &lhs, const Scalar &rhs)
Create a greater than or equal constraint: lhs >= rhs.
cvx::equalTo
Constraint equalTo(const Scalar &lhs, const Scalar &rhs)
Create an equality constraint: lhs == rhs.
cvx::Constraint::greaterThan
friend Constraint greaterThan(const Scalar &lhs, const Scalar &rhs)
Create a greater than or equal constraint: lhs >= rhs.
cvx::Constraint::equalTo
friend Constraint equalTo(const Scalar &lhs, const Scalar &rhs)
Create an equality constraint: lhs == rhs.
cvx::box
Constraint box(const Scalar &lower, const Scalar &middle, const Scalar &upper)
Create a box constraint: lower <= middle <= upper.
cvx::Constraint
Definition: constraint.hpp:47
cvx::lessThan
Constraint lessThan(const Scalar &lhs, const Scalar &rhs)
Create a less than or equal constraint: lhs <= rhs.
cvx::OptimizationProblem
Definition: problem.hpp:14
expressions.hpp
cvx::Scalar
Definition: expressions.hpp:117
cvx::Constraint::lessThan
friend Constraint lessThan(const Scalar &lhs, const Scalar &rhs)
Create a less than or equal constraint: lhs <= rhs.
cvx::Constraint::box
friend Constraint box(const Scalar &lower, const Scalar &middle, const Scalar &upper)
Create a box constraint: lower <= middle <= upper.