1 #ifndef SOPT_POWER_METHO_H
2 #define SOPT_POWER_METHO_H
4 #include "sopt/config.h"
24 const t_real relative_difference,
const T &initial_vector) {
30 if (niters <= 0)
return std::make_tuple(1., initial_vector);
31 t_real estimate_eigen_value = 1;
33 T estimate_eigen_vector = initial_vector;
34 estimate_eigen_vector = estimate_eigen_vector / estimate_eigen_vector.matrix().stableNorm();
36 SOPT_DEBUG(
" -[PM] Iteration: 0, norm = {}", estimate_eigen_value);
37 bool converged =
false;
39 for (
t_int i = 0; i < niters; ++i) {
40 estimate_eigen_vector = op.
adjoint() *
static_cast<T
>(op * estimate_eigen_vector);
41 estimate_eigen_value = estimate_eigen_vector.matrix().stableNorm();
42 if (estimate_eigen_value <= 0)
throw std::runtime_error(
"Error in operator.");
43 if (estimate_eigen_value != estimate_eigen_value)
44 throw std::runtime_error(
"Error in operator or data corrupted.");
45 estimate_eigen_vector = estimate_eigen_vector / estimate_eigen_value;
46 SOPT_DEBUG(
" -[PM] Iteration: {}, norm = {}", i + 1, estimate_eigen_value);
47 converged = scalvar(std::sqrt(estimate_eigen_value));
48 old_value = estimate_eigen_value;
50 SOPT_DEBUG(
"Converged to norm = {}, relative difference < {}", std::sqrt(old_value),
55 return std::make_tuple(std::sqrt(old_value), estimate_eigen_vector);
61 const t_real &relative_difference,
const T &initial_vector) {
62 const auto result =
power_method(*op, niters, relative_difference, initial_vector.derived());
63 const t_real norm = std::get<0>(result);
64 return std::make_tuple(
65 std::get<0>(result), std::get<1>(result),
67 [op, norm](T &output,
const T &input) { output =
static_cast<T
>(*op * input) / norm; },
69 [op, norm](T &output,
const T &input) {
70 output =
static_cast<T
>(op->adjoint() * input) / norm;
72 op->adjoint().sizes()));
77 const T &initial_vector) {
78 const std::shared_ptr<sopt::LinearTransform<T>> shared_op =
79 std::make_shared<sopt::LinearTransform<T>>(std::move(op));
80 const auto result = normalise_operator<T>(shared_op, niters, relative_difference, initial_vector);
81 const auto normed_shared_op = std::get<2>(result);
82 return std::make_tuple(std::get<0>(result), std::get<1>(result), *normed_shared_op);
87 std::tuple<t_real, T> all_sum_all_power_method(
const sopt::mpi::Communicator &comm,
90 const t_real &relative_difference,
91 const T &initial_vector) {
93 [&op](T &output,
const T &input) { output =
static_cast<T
>(op * input); }, op.
sizes(),
94 [&op, comm](T &output,
const T &input) {
95 output = comm.all_sum_all(
static_cast<T
>(op.
adjoint() * input));
98 return power_method(all_sum_all_op, niters, relative_difference, initial_vector.derived());
100 template <
typename T>
101 std::tuple<t_real, T, std::shared_ptr<sopt::LinearTransform<T>>> all_sum_all_normalise_operator(
103 const t_uint &niters,
const t_real &relative_difference,
const T &initial_vector) {
105 [op](T &output,
const T &input) { output =
static_cast<T
>(*op * input); }, op->
sizes(),
106 [op, comm](T &output,
const T &input) {
107 output = comm.all_sum_all(
static_cast<T
>(op->
adjoint() * input));
111 power_method(all_sum_all_op, niters, relative_difference, initial_vector.derived());
112 const t_real norm = std::get<0>(result);
113 return std::make_tuple(
114 std::get<0>(result), std::get<1>(result),
116 [op, norm](T &output,
const T &input) { output =
static_cast<T
>(*op * input) / norm; },
118 [op, norm](T &output,
const T &input) {
119 output =
static_cast<T
>(op->
adjoint() * input) / norm;
123 template <
typename T>
124 std::tuple<t_real, T, sopt::LinearTransform<T>> all_sum_all_normalise_operator(
126 const t_real &relative_difference,
const T &initial_vector) {
127 const std::shared_ptr<sopt::LinearTransform<T>> shared_op =
128 std::make_shared<sopt::LinearTransform<T>>(std::move(op));
130 normalise_operator<T>(comm, shared_op, niters, relative_difference, initial_vector);
131 const auto normed_shared_op = std::get<2>(result);
132 return std::make_tuple(std::get<0>(result), std::get<1>(result), *normed_shared_op);
136 template <
typename SCALAR>
168 #define SOPT_MACRO(NAME, TYPE) \
169 TYPE const &NAME() const { return NAME##_; } \
170 PowerMethod<SCALAR> &NAME(TYPE const &(NAME)) { \
189 template <
typename DERIVED>
190 DiagnosticAndResult
operator()(Eigen::DenseBase<DERIVED>
const &A,
t_Vector const &input)
const;
193 DiagnosticAndResult
operator()(OperatorFunction<t_Vector>
const &op,
t_Vector const &input)
const;
198 template <
typename SCALAR>
204 return operator()(op, input);
207 template <
typename SCALAR>
208 template <
typename DERIVED>
210 Eigen::DenseBase<DERIVED>
const &A,
t_Vector const &input)
const {
212 auto const op = [&Ad](
t_Vector &out,
t_Vector const &input) ->
void { out = Ad * input; };
213 return operator()(op, input);
216 template <
typename SCALAR>
219 SOPT_INFO(
"Computing the upper bound of a given operator");
220 SOPT_INFO(
" - input vector {}", input.transpose());
221 t_Vector eigenvector = input.normalized();
222 SOPT_INFO(
" - eigenvector norm {}", eigenvector.stableNorm());
224 bool converged =
false;
227 for (; niters < itermax() and converged ==
false; ++niters) {
228 op(eigenvector, eigenvector);
230 eigenvector.stableNorm() /
static_cast<Real>(eigenvector.size());
231 auto const rel_val = std::abs((magnitude - previous_magnitude) / previous_magnitude);
232 converged = rel_val < tolerance();
233 SOPT_INFO(
" - [PM] iteration {}/{} -- norm: {}", niters, itermax(), magnitude);
235 eigenvector /= magnitude;
236 previous_magnitude = magnitude;
240 SOPT_WARN(
" - [PM] did not converge within {} iterations", itermax());
242 SOPT_INFO(
" - [PM] converged in {} of {} iterations", niters, itermax());
244 return DiagnosticAndResult{itermax(), converged, previous_magnitude, eigenvector.normalized()};
sopt::Vector< Scalar > t_Vector
Eigenvalue and eigenvector for eigenvalue with largest magnitude.
typename real_type< Scalar >::type Real
Real type.
value_type Scalar
Scalar type.
PowerMethod()
Setups ProximalADMM.
DiagnosticAndResult AtA(t_LinearTransform const &A, t_Vector const &input) const
Maximum number of iterations.
DiagnosticAndResult operator()(Eigen::DenseBase< DERIVED > const &A, t_Vector const &input) const
Calls the power method for A, with A a matrix.
SCALAR value_type
Scalar type.
Vector< Scalar > t_Vector
Type of then underlying vectors.
std::array< t_int, 3 > const & sizes() const
Defines relation-ship between input and output sizes.
Computes inner-most element type.
#define SOPT_WARN(...)
\macro Something might be going wrong
#define SOPT_INFO(...)
\macro Verbose informational message about normal condition
#define SOPT_DEBUG(...)
\macro Output some debugging
std::tuple< t_real, T, std::shared_ptr< sopt::LinearTransform< T > > > normalise_operator(const std::shared_ptr< sopt::LinearTransform< T > const > &op, const t_uint &niters, const t_real &relative_difference, const T &initial_vector)
std::tuple< t_real, T > power_method(const sopt::LinearTransform< T > &op, const t_uint niters, const t_real relative_difference, const T &initial_vector)
Returns the eigenvalue and eigenvector for eigenvalue of the Linear Transform with largest magnitude.
int t_int
Root of the type hierarchy for signed integers.
double t_real
Root of the type hierarchy for real numbers.
size_t t_uint
Root of the type hierarchy for unsigned integers.
std::function< void(VECTOR &, VECTOR const &)> OperatorFunction
Typical function out = A*x.
Eigen::Matrix< T, Eigen::Dynamic, 1 > Vector
A vector of a given type.
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > Matrix
A matrix of a given type.
#define SOPT_MACRO(NAME, TYPE)
Holds result vector as well.
bool good
Wether convergence was achieved.
t_uint niters
Number of iterations.
Vector< Scalar > eigenvector
Corresponding eigenvector if converged.
Scalar magnitude
Magnitude of the eigenvalue.