STIR  6.2.0
max_eigenvector.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2005 - 2007-10-08, Hammersmith Imanet Ltd
3  This file is part of STIR.
4 
5  SPDX-License-Identifier: Apache-2.0
6 
7  See STIR/LICENSE.txt for details
8 */
9 #ifndef __stir_numerics_max_eigenvector_H__
10 #define __stir_numerics_max_eigenvector_H__
11 
21 #include "stir/numerics/norm.h"
22 #include "stir/more_algorithms.h"
23 #include "stir/Succeeded.h"
24 #include "stir/error.h"
25 
26 START_NAMESPACE_STIR
27 
69 template <class elemT>
70 inline Succeeded
72  Array<1, elemT>& max_eigenvector,
73  const Array<2, elemT>& m,
74  const Array<1, elemT>& start,
75  const double tolerance = .01,
76  const unsigned long max_num_iterations = 10000UL)
77 {
78  assert(m.is_regular());
79  if (m.size() == 0)
80  {
81  max_eigenvalue = 0;
82  max_eigenvector = start;
83  return Succeeded::yes;
84  }
85 
86  const double tolerance_squared = square(tolerance);
87  Array<1, elemT> current = start;
88  current /= (*abs_max_element(current.begin(), current.end()));
89  unsigned long remaining_num_iterations = max_num_iterations;
90 
91  double change;
92  do
93  {
94  max_eigenvector = matrix_multiply(m, current);
95  const elemT norm_factor = *abs_max_element(max_eigenvector.begin(), max_eigenvector.end());
96  max_eigenvector /= norm_factor;
97  change = norm_squared(max_eigenvector - current);
98  current = max_eigenvector;
99  --remaining_num_iterations;
100  } while (change > tolerance_squared && remaining_num_iterations != 0);
101 
102  current /= static_cast<elemT>(norm(current));
103  max_eigenvector = matrix_multiply(m, current);
104  // compute eigenvalue using Rayleigh quotient
105  max_eigenvalue = static_cast<elemT>(inner_product(current, max_eigenvector) / norm_squared(current));
106  max_eigenvector /= static_cast<elemT>(norm(max_eigenvector));
107 
108  return remaining_num_iterations == 0 ? Succeeded::no : Succeeded::yes;
109 
110  /*norm( max_eigenvector*max_eigenvalue -
111  matrix_multiply(m, max_eigenvector));*/
112 }
113 
128 template <class elemT>
129 inline Succeeded
131  Array<1, elemT>& max_eigenvector,
132  const Array<2, elemT>& m,
133  const Array<1, elemT>& start,
134  const elemT shift,
135  const double tolerance = .03,
136  const unsigned long max_num_iterations = 10000UL)
137 {
138  if (m.get_min_index() != 0 || m[0].get_min_index() != 0)
139  error("absolute_max_eigenvector_using_shifted_power_method:\n"
140  " implementation needs work for indices that don't start from 0. sorry");
141 
142  Succeeded success
144  max_eigenvector,
145  // sadly need to explicitly convert result of subtraction back to Array
146  Array<2, elemT>(m - diagonal_matrix(static_cast<unsigned>(m.size()), shift)),
147  start,
148  tolerance,
149  max_num_iterations);
150  max_eigenvalue += shift;
151  return success;
152 }
153 
173 template <class elemT>
174 inline Succeeded
176  Array<1, elemT>& max_eigenvector,
177  const Array<2, elemT>& m,
178  const Array<1, elemT>& start,
179  const double tolerance = .03,
180  const unsigned long max_num_iterations = 10000UL)
181 {
182 
183  Succeeded success
184  = absolute_max_eigenvector_using_power_method(max_eigenvalue, max_eigenvector, m, start, tolerance, max_num_iterations);
185  if (success == Succeeded::no)
186  return Succeeded::no;
187 
188  if (max_eigenvalue >= 0) // TODO would need to take real value for complex case
189  return Succeeded::yes;
190 
191  // we found a negative eigenvalue
192  // try again with a shift equal to the previously found max_eigenvalue
193  // this shift will effectively put that eigenvalue to 0 during the
194  // power method iterations
195  // also it will make all eigenvalues positive (as we subtract the
196  // smallest negative eigenvalue)
198  max_eigenvalue, max_eigenvector, m, start, max_eigenvalue, tolerance, max_num_iterations);
199  if (success == Succeeded::no)
200  return Succeeded::no;
201 
202  assert(max_eigenvalue >= 0);
203  return Succeeded::yes;
204 }
205 
206 END_NAMESPACE_STIR
207 
208 #endif
Declaration of some functions missing from std::algorithm.
Declaration of class stir::Succeeded.
Array< 1, elemT > matrix_multiply(const Array< 2, elemT > &m, const Array< 1, elemT > &vec)
matrix with vector multiplication
Definition: MatrixFunction.inl:106
int get_min_index() const
get value of first valid index
Definition: VectorWithOffset.inl:116
iterator end()
iterator &#39;past&#39; the last element of the vector
Definition: VectorWithOffset.inl:198
iterT abs_max_element(iterT start, iterT end)
Like std::max_element, but comparing after taking absolute value.
Definition: more_algorithms.inl:28
Declaration of the stir::norm(), stir::norm_squared() functions and stir::NormSquared unary function...
Array< 2, elemT > diagonal_matrix(const unsigned dimension, const elemT value)
construct a diagonal matrix with all elements on the diagonal equal
Definition: MatrixFunction.inl:182
Declaration of stir::error()
iterator begin()
use to initialise an iterator to the first element of the vector
Definition: VectorWithOffset.inl:182
Succeeded absolute_max_eigenvector_using_power_method(elemT &max_eigenvalue, Array< 1, elemT > &max_eigenvector, const Array< 2, elemT > &m, const Array< 1, elemT > &start, const double tolerance=.01, const unsigned long max_num_iterations=10000UL)
Compute the eigenvalue with the largest absolute value and corresponding eigenvector of a matrix by u...
Definition: max_eigenvector.h:71
double norm_squared(const BasicCoordinate< num_dimensions, coordT > &p1)
compute (inner_product(p1,p1))
Definition: BasicCoordinate.inl:415
coordT inner_product(const BasicCoordinate< num_dimensions, coordT > &p1, const BasicCoordinate< num_dimensions, coordT > &p2)
compute sum_i p1[i] * p2[i]
Definition: BasicCoordinate.inl:408
NUMBER square(const NUMBER &x)
returns the square of a number, templated.
Definition: common.h:146
The 1-dimensional (partial) specialisation of Array.
Definition: Array.h:339
double norm(const BasicCoordinate< num_dimensions, coordT > &p1)
compute sqrt(inner_product(p1,p1))
Definition: BasicCoordinate.inl:426
void error(const char *const s,...)
Print error with format string a la printf and throw exception.
Definition: error.cxx:42
Succeeded absolute_max_eigenvector_using_shifted_power_method(elemT &max_eigenvalue, Array< 1, elemT > &max_eigenvector, const Array< 2, elemT > &m, const Array< 1, elemT > &start, const elemT shift, const double tolerance=.03, const unsigned long max_num_iterations=10000UL)
Compute the eigenvalue with the largest absolute value and corresponding eigenvector of a matrix by u...
Definition: max_eigenvector.h:130
size_t size() const
return number of elements in this vector
Definition: VectorWithOffset.inl:542
Declaration of functions for matrices.
a class containing an enumeration type that can be used by functions to signal successful operation o...
Definition: Succeeded.h:43
bool is_regular() const
checks if the index range is &#39;regular&#39;
Definition: Array.inl:446
Succeeded max_eigenvector_using_power_method(elemT &max_eigenvalue, Array< 1, elemT > &max_eigenvector, const Array< 2, elemT > &m, const Array< 1, elemT > &start, const double tolerance=.03, const unsigned long max_num_iterations=10000UL)
Compute the eigenvalue with the largest value and corresponding eigenvector of a matrix by using the ...
Definition: max_eigenvector.h:175