vpdt_eigen_sym_matrix.h
Go to the documentation of this file.
1 // This is core/vpdl/vpdt/vpdt_eigen_sym_matrix.h
2 #ifndef vpdt_eigen_sym_matrix_h_
3 #define vpdt_eigen_sym_matrix_h_
4 //:
5 // \file
6 // \author Matthew Leotta
7 // \date March 5, 2009
8 // \brief A symmetric matrix represented in eigenvalue decomposition
9 //
10 // \verbatim
11 // Modifications
12 // <None yet>
13 // \endverbatim
14 
15 #include <limits>
19 #include <vpdl/vpdt/vpdt_access.h>
20 #ifdef _MSC_VER
21 # include <vcl_msvc_warnings.h>
22 #endif
23 #include <cassert>
24 
25 
26 //: wrapper for the vnl eigensystem function for fixed size data
27 template<class T, unsigned int n>
31 {
32  vnl_matrix_ref<T> Vr(n,n,V.data_block());
33  vnl_vector_ref<T> Dr(n,D.data_block());
35 }
36 
37 
38 //: A symmetric matrix represented in eigenvalue decomposition
39 template<class T, unsigned int n=0>
41 {
42  public:
43  //: the data type used for vectors
45  //: the data type used for matrices
47 
48  //: Constructor
49  // Optionally initialize the dimension for when n==0.
50  // Otherwise var_dim is ignored
51  vpdt_eigen_sym_matrix(unsigned int var_dim = n)
52  {
53  vpdt_set_size(eigen_vec_,var_dim);
54  vpdt_set_size(eigen_val_,var_dim);
55  eigen_vec_.set_identity();
56  eigen_val_.fill(T(0));
57  }
58 
59  //: Constructor - from eigenvectors and eigenvalues
60  vpdt_eigen_sym_matrix(const matrix& evec, const vector& eval)
61  : eigen_vec_(evec), eigen_val_(eval)
62  {
63  assert(are_evec_orthonormal());
64  }
65 
66  //: Constructor - from symmetric matrix
68  {
69  set_matrix(m);
70  }
71 
72  //: Return the dimension
73  unsigned int dimension() const { return eigen_val_.size(); }
74 
75  //: Access to the eigenvectors
76  const matrix& eigenvectors() const { return eigen_vec_; }
77 
78  //: Access to the eigenvalues
79  const vector& eigenvalues() const { return eigen_val_; }
80 
81  //: Set the eigenvectors
82  void set_eigenvectors(const matrix& m)
83  {
84  eigen_vec_ = m;
85  assert(are_evec_orthonormal());
86  }
87 
88  //: set the eigenvalues
89  void set_eigenvalues(const vector& v) { eigen_val_ = v; }
90 
91  //: Set the size (if variable) and reset to default
92  void set_size(unsigned int dim)
93  {
96  eigen_vec_.set_identity();
97  eigen_val_.fill(T(0));
98  }
99 
100  //: set the eigenvectors and eigen values by decomposing m
101  void set_matrix(const matrix& m)
102  {
103  const unsigned int dim = vpdt_size(m);
107  }
108 
109  //: multiply the matrix by a scalar
111  {
112  const unsigned int dim = eigen_val_.size();
113  for (unsigned int i=0; i<dim; ++i)
114  eigen_val_[i] *= val;
115  return *this;
116  }
117 
118  //: Reform the matrix
119  // m = eigen_vec_ * diag(eigen_val_) * eigen_vec_.transpose()
120  void form_matrix(matrix& m) const
121  {
122  const unsigned int dim = eigen_val_.size();
123  vpdt_set_size(m,dim);
124  m.fill(T(0));
125 
126  for (unsigned int i = 0; i < dim; ++i)
127  for (unsigned int k = 0; k < dim; ++k){
128  T tmp = eigen_vec_[i][k] * eigen_val_[k];
129  for (unsigned int j = i; j < dim; ++j)
130  m[i][j] += tmp * eigen_vec_[j][k];
131  }
132 
133  // fill in other side of diagonal
134  for (unsigned int i = 0; i < dim; ++i)
135  for (unsigned int j = i+1; j < dim; ++j)
136  m[j][i] = m[i][j];
137  }
138 
139  //: compute the matrix inverse
140  // m = eigen_vec_ * inverse(diag(eigen_val_)) * eigen_vec_.transpose()
141  void form_inverse(matrix& m) const
142  {
143  const unsigned int dim = eigen_val_.size();
144  vpdt_set_size(m,dim);
145  m.fill(T(0));
146 
147  for (unsigned int k = 0; k < dim; ++k){
148  if (eigen_val_[k] <= T(0))
149  continue;
150  for (unsigned int i = 0; i < dim; ++i){
151  T tmp = eigen_vec_[i][k] / eigen_val_[k];
152  for (unsigned int j = i; j < dim; ++j)
153  m[i][j] += tmp * eigen_vec_[j][k];
154  }
155  }
156 
157  // fill in other side of diagonal
158  for (unsigned int i = 0; i < dim; ++i)
159  for (unsigned int j = i+1; j < dim; ++j)
160  m[j][i] = m[i][j];
161  }
162 
163  //: evaluate y = M * x
164  void product(const vector& x, vector& y) const
165  {
166  const unsigned int dim = eigen_val_.size();
167  vpdt_set_size(y,dim);
168  vpdt_fill(y,T(0));
169  for (unsigned int i = 0; i < dim; ++i){
170  T t_i = T(0);
171  for (unsigned int j = 0; j < dim; ++j){
172  t_i += eigen_vec_[j][i] * x[j];
173  }
174  t_i *= eigen_val_[i];
175  for (unsigned int j = 0; j < dim; ++j){
176  y[j] += eigen_vec_[j][i] * t_i;
177  }
178  }
179  }
180 
181  //: evaluate y = M^-1 * x
182  void inverse_product(const vector& x, vector& y) const
183  {
184  const unsigned int dim = eigen_val_.size();
185  vpdt_set_size(y,dim);
186  vpdt_fill(y,T(0));
187  for (unsigned int i = 0; i < dim; ++i){
188  T t_i = T(0);
189  for (unsigned int j = 0; j < dim; ++j){
190  t_i += eigen_vec_[j][i] * x[j];
191  }
192  t_i /= eigen_val_[i];
193  for (unsigned int j = 0; j < dim; ++j){
194  y[j] += eigen_vec_[j][i] * t_i;
195  }
196  }
197  }
198 
199  //: evaluate the Quadratic form x^t * M * x
200  T quad_form(const vector& x) const
201  {
202  const unsigned int dim = eigen_val_.size();
203  T val = T(0);
204  for (unsigned int i = 0; i < dim; ++i){
205  T tmp = T(0);
206  for (unsigned int j = 0; j < dim; ++j){
207  tmp += eigen_vec_[j][i] * x[j];
208  }
209  val += tmp*tmp*eigen_val_[i];
210  }
211  return val;
212  }
213 
214  //: evaluate the inverse Quadratic form x^t * M^-1 * x
215  T inverse_quad_form(const vector& x) const
216  {
217  const unsigned int dim = eigen_val_.size();
218  T val = T(0);
219  for (unsigned int i = 0; i < dim; ++i){
220  if (eigen_val_[i] <= T(0))
221  return std::numeric_limits<T>::infinity();
222  T tmp = T(0);
223  for (unsigned int j = 0; j < dim; ++j){
224  tmp += eigen_vec_[j][i] * x[j];
225  }
226  val += tmp*tmp/eigen_val_[i];
227  }
228  return val;
229  }
230 
231  //: compute the determinant
232  T determinant() const
233  {
234  const unsigned int dim = eigen_val_.size();
235  T det = T(1);
236  for (unsigned int i=0; i<dim; ++i)
237  det *= eigen_val_[i];
238  return det;
239  }
240 
241  private:
242  //: the matrix of eigenvectors
244  //: the vector of eigenvalues
246 
247  //: return true if the eigenvectors are (approximately) orthonormal
248  bool are_evec_orthonormal() const
249  {
250  // FIXME: implement this
251  return false;
252  }
253 };
254 
255 
256 //: A symmetric matrix represented in eigenvalue decomposition
257 // This partial specialization for the scalar case is no longer needed
258 // If you get an error related to this, you should be using a scalar instead.
259 template<class T>
260 class vpdt_eigen_sym_matrix<T,1> {};
261 
262 
263 //==============================================================================
264 // These type generators produce a vpdt_eigen_sym_matrix for a field type
265 
266 //: generate the vpdt_eigen_sys_matrix type from a field type
267 template <class F, class Disambiguate= void>
269 
270 //: generate the vpdt_eigen_sys_matrix type from a field type
271 template <class F>
272 struct vpdt_eigen_sym_matrix_gen<F,typename vpdt_field_traits<F>::type_is_vector>
273 {
276 };
277 
278 //: generate the vpdt_eigen_sys_matrix type from a field type
279 template <class F>
280 struct vpdt_eigen_sym_matrix_gen<F,typename vpdt_field_traits<F>::type_is_scalar>
281 {
283 };
284 
285 
286 //==============================================================================
287 // universal access functions (See vpdt_access.h)
288 
289 //: Set the size of a vpdt_eigen_sym_matrix
290 template <class T>
291 inline void vpdt_set_size(vpdt_eigen_sym_matrix<T,0>& m, unsigned int s)
292 {
293  m.set_size(s);
294 }
295 
296 
297 //: Fill a vpdt_eigen_sym_matrix
298 template <class T, unsigned int n>
299 inline void vpdt_fill(vpdt_eigen_sym_matrix<T,n>& m, const T& val)
300 {
302  vpdt_set_size(v,m.dimension());
303  vpdt_fill(v,val);
304  m.set_eigenvalues(v);
305 }
306 
307 
308 #endif // vpdt_eigen_sym_matrix_h_
void inverse_product(const vector &x, vector &y) const
evaluate y = M^-1 * x.
vpdt_field_default< T, n >::type vector
the data type used for vectors.
vnl_matrix_ref< T > as_ref()
T inverse_quad_form(const vector &x) const
evaluate the inverse Quadratic form x^t * M^-1 * x.
vpdt_eigen_sym_matrix< T, n > & operator *=(const T &val)
multiply the matrix by a scalar.
void vnl_symmetric_eigensystem_compute(const vnl_matrix_fixed< T, n, n > &A, vnl_matrix_fixed< T, n, n > &V, vnl_vector_fixed< T, n > &D)
wrapper for the vnl eigensystem function for fixed size data.
unsigned int dimension() const
Return the dimension.
void set_size(unsigned int dim)
Set the size (if variable) and reset to default.
void vpdt_fill(vpdt_eigen_sym_matrix< T, n > &m, const T &val)
Fill a vpdt_eigen_sym_matrix.
T const * data_block() const
#define m
A type generator for the default types (those used in vpdl)
unsigned int size() const
vnl_vector_fixed & fill(T const &v)
void product(const vector &x, vector &y) const
evaluate y = M * x.
vpdt_eigen_sym_matrix(const matrix &evec, const vector &eval)
Constructor - from eigenvectors and eigenvalues.
vpdt_field_traits< vector >::matrix_type matrix
the data type used for matrices.
#define v
matrix eigen_vec_
the matrix of eigenvectors.
void form_inverse(matrix &m) const
compute the matrix inverse.
bool are_evec_orthonormal() const
return true if the eigenvectors are (approximately) orthonormal.
void set_matrix(const matrix &m)
set the eigenvectors and eigen values by decomposing m.
T determinant() const
compute the determinant.
vpdt_eigen_sym_matrix(const matrix &m)
Constructor - from symmetric matrix.
T const * data_block() const
specialized template trait classes for properties of a field type
vpdt_eigen_sym_matrix< typename vpdt_field_traits< F >::scalar_type, vpdt_field_traits< F >::dimension > type
const matrix & eigenvectors() const
Access to the eigenvectors.
The field traits class (scalar).
generate the vpdt_eigen_sys_matrix type from a field type.
vpdt_eigen_sym_matrix(unsigned int var_dim=n)
Constructor.
void form_matrix(matrix &m) const
Reform the matrix.
Overloaded functions to allow uniform API access to various field types.
A symmetric matrix represented in eigenvalue decomposition.
void vpdt_set_size(vpdt_eigen_sym_matrix< T, 0 > &m, unsigned int s)
Set the size of a vpdt_eigen_sym_matrix.
unsigned int vpdt_size(const vnl_vector< T > &v)
Access the size of a vnl_vector.
Definition: vpdt_access.h:36
void set_eigenvectors(const matrix &m)
Set the eigenvectors.
T quad_form(const vector &x) const
evaluate the Quadratic form x^t * M * x.
vector eigen_val_
the vector of eigenvalues.
const vector & eigenvalues() const
Access to the eigenvalues.
void set_eigenvalues(const vector &v)
set the eigenvalues.