SOPT
Sparse OPTimisation
linear_transform.h
Go to the documentation of this file.
1 #ifndef SOPT_OPERATORS_H
2 #define SOPT_OPERATORS_H
3 
4 #include "sopt/config.h"
5 #include <array>
6 #include <memory>
7 #include <type_traits>
8 #include <utility> // for std::move<>
9 #include <Eigen/Core>
10 #include "sopt/logging.h"
11 #include "sopt/maths.h"
12 #include "sopt/types.h"
13 #include "sopt/wrapper.h"
14 
15 namespace sopt {
16 
17 namespace details {
21 template <typename EIGEN>
24 template <typename EIGEN>
26 } // namespace details
27 
29 template <typename VECTOR>
30 class LinearTransform : public details::WrapFunction<VECTOR> {
31  public:
34 
43  LinearTransform(t_Function const &direct, t_Function const &indirect,
44  std::array<t_int, 3> sizes = {{1, 1, 0}})
46  direct, sizes, indirect,
47  {{sizes[1], sizes[0], sizes[0] == 0 ? 0 : -(sizes[2] * sizes[1]) / sizes[0]}}) {
48  assert(sizes[0] != 0);
49  }
59  LinearTransform(t_Function const &direct, std::array<t_int, 3> dsizes, t_Function const &indirect,
60  std::array<t_int, 3> isizes)
61  : LinearTransform(details::wrap(direct, dsizes), details::wrap(indirect, isizes)) {}
63  details::WrapFunction<VECTOR> const &indirect)
64  : details::WrapFunction<VECTOR>(direct), indirect_(indirect) {}
66  : details::WrapFunction<VECTOR>(c), indirect_(c.indirect_), norm_(c.norm_), sq_norm_(c.sq_norm_) {}
68  : details::WrapFunction<VECTOR>(std::move(c)), indirect_(std::move(c.indirect_)), norm_(c.norm_), sq_norm_(c.sq_norm_) {}
69  void operator=(LinearTransform const &c) {
71  indirect_ = c.indirect_;
72  norm_ = c.norm_;
73  sq_norm_ = c.sq_norm_;
74  }
77  indirect_ = std::move(c.indirect_);
78  norm_ = c.norm_;
79  sq_norm_ = c.sq_norm_;
80  }
81 
84  return LinearTransform<VECTOR>(indirect_, static_cast<details::WrapFunction<VECTOR> const &>(*this));
85  }
86 
90 
92  {
93  norm_ = n;
94  sq_norm_ = n*n;
95  }
96 
98  {
99  return norm_;
100  }
101 
103  {
104  return sq_norm_;
105  }
106 
107  private:
110 
111  sopt::t_real norm_ = 1.0;
112  sopt::t_real sq_norm_ = 1.0;
113 };
114 
123 template <typename VECTOR>
125  OperatorFunction<VECTOR> const &indirect,
126  std::array<t_int, 3> const &sizes = {{1, 1, 0}}) {
127  return {direct, indirect, sizes};
128 }
138 template <typename VECTOR>
140  std::array<t_int, 3> const &dsizes,
141  OperatorFunction<VECTOR> const &indirect,
142  std::array<t_int, 3> const &isizes) {
143  return {direct, dsizes, indirect, isizes};
144 }
145 
147 template <typename VECTOR>
149  return passthrough;
150 }
152 template <typename VECTOR>
154  details::WrapFunction<VECTOR> const &adjoint) {
155  return {direct, adjoint};
156 }
157 
158 namespace details {
159 
160 template <typename EIGEN>
163  using Raw = typename std::remove_const<typename std::remove_reference<EIGEN>::type>::type;
165  using PlainMatrix = typename Raw::PlainObject;
166 
167  public:
169  using PlainObject =
170  typename std::conditional<std::is_base_of<Eigen::MatrixBase<PlainMatrix>, PlainMatrix>::value,
176  template <typename T0>
177  MatrixToLinearTransform(Eigen::MatrixBase<T0> const &A) : matrix(std::make_shared<EIGEN>(A)) {}
179  MatrixToLinearTransform(std::shared_ptr<EIGEN> const &x) : matrix(x){}
180 
182  void operator()(PlainObject &out, PlainObject const &x) const {
183 #ifndef NDEBUG
184  if ((*matrix).cols() != x.size())
185  SOPT_THROW("Input vector and matrix do not match: ")
186  << out.cols() << " columns for " << x.size() << " elements.";
187 #endif
188  out = (*matrix) * x;
189  }
194  }
195 
196  private:
198  std::shared_ptr<EIGEN> matrix;
199 };
200 
201 template <typename EIGEN>
203  public:
208  template <typename T0>
209  MatrixAdjointToLinearTransform(Eigen::MatrixBase<T0> const &A)
210  : matrix(std::make_shared<EIGEN>(A)) {}
212  MatrixAdjointToLinearTransform(std::shared_ptr<EIGEN> const &x) : matrix(x){}
213 
215  void operator()(PlainObject &out, PlainObject const &x) const {
216 #ifndef NDEBUG
217  if ((*matrix).rows() != x.size())
218  SOPT_THROW("Input vector and matrix adjoint do not match: ")
219  << out.cols() << " rows for " << x.size() << " elements.";
220 #endif
221  out = matrix->adjoint() * x;
222  }
226 
227  private:
228  std::shared_ptr<EIGEN> matrix;
229 };
230 } // namespace details
231 
233 template <typename DERIVED>
235  Eigen::MatrixBase<DERIVED> const &A) {
237  if (A.rows() == A.cols())
238  return {matrix, matrix.adjoint()};
239  else {
240  t_int const gcd = details::gcd(A.cols(), A.rows());
241  t_int const a = A.cols() / gcd;
242  t_int const b = A.rows() / gcd;
243  return {matrix, matrix.adjoint(), {{b, a, 0}}};
244  }
245 }
246 
248 template <typename SCALAR>
250  return {[](Vector<SCALAR> &out, Vector<SCALAR> const &in) { out = in; },
251  [](Vector<SCALAR> &out, Vector<SCALAR> const &in) { out = in; }};
252 }
253 } // namespace sopt
254 #endif
constexpr auto n
Definition: wavelets.cc:56
constexpr Scalar b
constexpr Scalar a
Joins together direct and indirect operators.
void operator=(LinearTransform const &c)
LinearTransform(LinearTransform &&c)
LinearTransform(t_Function const &direct, std::array< t_int, 3 > dsizes, t_Function const &indirect, std::array< t_int, 3 > isizes)
OperatorFunction< VECTOR > t_Function
Type of the wrapped functions.
LinearTransform(t_Function const &direct, t_Function const &indirect, std::array< t_int, 3 > sizes={{1, 1, 0}})
void operator=(LinearTransform &&c)
sopt::t_real sq_norm() const
void set_norm(t_real n)
LinearTransform(LinearTransform const &c)
sopt::t_real norm() const
LinearTransform(details::WrapFunction< VECTOR > const &direct, details::WrapFunction< VECTOR > const &indirect)
LinearTransform< VECTOR > adjoint() const
Indirect transform.
Wraps a tranposed matrix into a function and its conjugate transpose.
MatrixAdjointToLinearTransform(std::shared_ptr< EIGEN > const &x)
Creates from a shared matrix.
MatrixToLinearTransform< EIGEN > adjoint() const
Returns adjoint operator.
MatrixAdjointToLinearTransform(Eigen::MatrixBase< T0 > const &A)
Creates from an expression.
typename MatrixToLinearTransform< EIGEN >::PlainObject PlainObject
void operator()(PlainObject &out, PlainObject const &x) const
Performs operation.
Wraps a matrix into a function and its conjugate transpose.
MatrixToLinearTransform(std::shared_ptr< EIGEN > const &x)
Creates from a shared matrix.
MatrixAdjointToLinearTransform< EIGEN > adjoint() const
Returns conjugate transpose operator.
void operator()(PlainObject &out, PlainObject const &x) const
Performs operation.
MatrixToLinearTransform(Eigen::MatrixBase< T0 > const &A)
Creates from an expression.
typename std::conditional< std::is_base_of< Eigen::MatrixBase< PlainMatrix >, PlainMatrix >::value, Vector< typename PlainMatrix::Scalar >, Array< typename PlainMatrix::Scalar > >::type PlainObject
The output type.
Wraps an std::function to return an expression.
Definition: wrapper.h:46
void operator=(WrapFunction const &c)
Definition: wrapper.h:63
WrapFunction(t_Function const &func, std::array< t_int, 3 > sizes={{1, 1, 0}})
Definition: wrapper.h:56
std::array< t_int, 3 > const & sizes() const
Defines relation-ship between input and output sizes.
Definition: wrapper.h:106
#define SOPT_THROW(MSG)
Definition: exception.h:46
t_int gcd(t_int a, t_int b)
Greatest common divisor.
Definition: maths.h:207
WrapFunction< VECTOR > wrap(OperatorFunction< VECTOR > const &func, std::array< t_int, 3 > sizes={{1, 1, 0}})
Helper function to wrap functor into expression-able object.
Definition: wrapper.h:131
LinearTransform< VECTOR > linear_transform(OperatorFunction< VECTOR > const &direct, OperatorFunction< VECTOR > const &indirect, std::array< t_int, 3 > const &sizes={{1, 1, 0}})
int t_int
Root of the type hierarchy for signed integers.
Definition: types.h:13
double t_real
Root of the type hierarchy for real numbers.
Definition: types.h:17
Eigen::Array< T, Eigen::Dynamic, 1 > Array
A 1-dimensional list of elements of given type.
Definition: types.h:34
std::function< void(VECTOR &, VECTOR const &)> OperatorFunction
Typical function out = A*x.
Definition: types.h:43
LinearTransform< Vector< SCALAR > > linear_transform_identity()
Helper function to create a linear transform that's just the identity.
Eigen::Matrix< T, Eigen::Dynamic, 1 > Vector
A vector of a given type.
Definition: types.h:24