STIR 6.4.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__
21#include "stir/numerics/norm.h"
23#include "stir/Succeeded.h"
24#include "stir/error.h"
25
26START_NAMESPACE_STIR
27
69template <class elemT>
70inline 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
128template <class elemT>
129inline 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
173template <class elemT>
174inline 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
206END_NAMESPACE_STIR
207
208#endif
Declaration of functions for matrices.
Declaration of class stir::Succeeded.
This class defines multi-dimensional (numeric) arrays.
Definition Array.h:78
bool is_regular() const
checks if the index range is 'regular'
Definition Array.inl:469
a class containing an enumeration type that can be used by functions to signal successful operation o...
Definition Succeeded.h:44
iterator begin()
use to initialise an iterator to the first element of the vector
Definition VectorWithOffset.inl:190
int get_min_index() const
get value of first valid index
Definition VectorWithOffset.inl:124
iterator end()
iterator 'past' the last element of the vector
Definition VectorWithOffset.inl:206
size_t size() const
return number of elements in this vector
Definition VectorWithOffset.inl:546
Declaration of stir::error()
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
double norm(const BasicCoordinate< num_dimensions, coordT > &p1)
compute sqrt(inner_product(p1,p1))
Definition BasicCoordinate.inl:426
double norm_squared(const BasicCoordinate< num_dimensions, coordT > &p1)
compute (inner_product(p1,p1))
Definition BasicCoordinate.inl:415
void error(const char *const s,...)
Print error with format string a la printf and throw exception.
Definition error.cxx:42
iterT abs_max_element(iterT start, iterT end)
Like std::max_element, but comparing after taking absolute value.
Definition more_algorithms.inl:28
NUMBER square(const NUMBER &x)
returns the square of a number, templated.
Definition common.h:154
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
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
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
Declaration of some functions missing from std::algorithm.
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
Array< 1, elemT > matrix_multiply(const Array< 2, elemT > &m, const Array< 1, elemT > &vec)
matrix with vector multiplication
Definition MatrixFunction.inl:106
Declaration of the stir::norm(), stir::norm_squared() functions and stir::NormSquared unary function.