vnl_symmetric_eigensystem.h
Go to the documentation of this file.
1 // This is core/vnl/algo/vnl_symmetric_eigensystem.h
2 #ifndef vnl_symmetric_eigensystem_h_
3 #define vnl_symmetric_eigensystem_h_
4 //:
5 // \file
6 // \brief Find eigenvalues of a symmetric matrix
7 //
8 // vnl_symmetric_eigensystem_compute()
9 // solves the eigenproblem $A x = \lambda x$, with $A$ symmetric.
10 // The resulting eigenvectors and values are sorted in increasing order
11 // so <CODE> V.column(0) </CODE> is the eigenvector corresponding to the
12 // smallest eigenvalue.
13 //
14 // As a matrix decomposition, this is $A = V D V^t$
15 //
16 // Uses the EISPACK routine RS, which in turn calls TRED2 to reduce A
17 // to tridiagonal form, followed by TQL2, to find the eigensystem.
18 // This is summarized in Golub and van Loan, pgf 8.2. The following are
19 // the original subroutine headers:
20 //
21 // \remark TRED2 is a translation of the Algol procedure tred2,
22 // Num. Math. 11, 181-195(1968) by Martin, Reinsch, and Wilkinson.
23 // Handbook for Auto. Comp., Vol.ii-Linear Algebra, 212-226(1971).
24 //
25 // \remark This subroutine reduces a real symmetric matrix to a
26 // symmetric tridiagonal matrix using and accumulating
27 // orthogonal similarity transformations.
28 //
29 // \remark TQL2 is a translation of the Algol procedure tql2,
30 // Num. Math. 11, 293-306(1968) by Bowdler, Martin, Reinsch, and Wilkinson.
31 // Handbook for Auto. Comp., Vol.ii-Linear Algebra, 227-240(1971).
32 //
33 // \remark This subroutine finds the eigenvalues and eigenvectors
34 // of a symmetric tridiagonal matrix by the QL method.
35 // the eigenvectors of a full symmetric matrix can also
36 // be found if tred2 has been used to reduce this
37 // full matrix to tridiagonal form.
38 //
39 // \author Andrew W. Fitzgibbon, Oxford RRG
40 // \date 29 Aug 96
41 //
42 // \verbatim
43 // Modifications
44 // fsm, 5 March 2000: templated
45 // dac (Manchester) 28/03/2001: tidied up documentation
46 // Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line
47 // Jan.2003 - Peter Vanroose - added missing implementation for solve(b,x)
48 // Mar.2010 - Peter Vanroose - also made vnl_symmetric_eigensystem_compute()
49 // & vnl_symmetric_eigensystem_compute_eigenvals() templated
50 // \endverbatim
51 
52 #include <vnl/vnl_matrix.h>
53 #include <vnl/vnl_diag_matrix.h>
54 #include <vnl/algo/vnl_algo_export.h>
55 
56 //: Find eigenvalues of a symmetric 3x3 matrix
57 // Eigenvalues will be returned so that l1 <= l2 <= l3.
58 // \verbatim
59 // Matrix is M11 M12 M13
60 // M12 M22 M23
61 // M13 M23 M33
62 // \endverbatim
63 template <class T>
65  T M11, T M12, T M13,
66  T M22, T M23,
67  T M33,
68  T &l1, T &l2, T &l3);
69 
70 //: Find eigenvalues of a symmetric matrix
71 template <class T>
73  vnl_matrix<T> & V,
74  vnl_vector<T> & D);
75 
76 //: Computes and stores the eigensystem decomposition of a symmetric matrix.
77 
78 template <class T>
80 {
81  public:
82  //: Solve real symmetric eigensystem $A x = \lambda x$
84 
85  protected:
86  // need this here to get inits in correct order, but still keep gentex
87  // in the right order.
88  int n_;
89 
90  public:
91  //: Public eigenvectors.
92  // After construction, the columns of V are the eigenvectors, sorted by
93  // increasing eigenvalue, from most negative to most positive.
95 
96  //: Public eigenvalues.
97  // After construction, D contains the eigenvalues, sorted as described above.
98  // Note that D is a vnl_diag_matrix, and is therefore stored as a std::vector while behaving as a matrix.
100 
101  //: Recover specified eigenvector after computation.
102  vnl_vector<T> get_eigenvector(int i) const;
103 
104  //: Recover specified eigenvalue after computation.
105  T get_eigenvalue(int i) const;
106 
107  //: Convenience method to get least-squares nullvector.
108  // It is deliberate that the signature is the same as on vnl_svd<T>.
109  vnl_vector<T> nullvector() const { return get_eigenvector(0); }
110 
111  //: Return the matrix $V D V^\top$.
112  // This can be useful if you've modified $D$. So an inverse is obtained using
113  // \code
114  // vnl_symmetric_eigensystem} eig(A);
115  // eig.D.invert_in_place}();
116  // vnl_matrix<double> Ainverse = eig.recompose();
117  // \endcode
118 
119  vnl_matrix<T> recompose() const { return V * D * V.transpose(); }
120 
121  //: return product of eigenvalues.
122  T determinant() const;
123 
124  //: return the pseudoinverse.
125  vnl_matrix<T> pinverse() const;
126 
127  //: return the square root, if positive semi-definite.
128  vnl_matrix<T> square_root() const;
129 
130  //: return the inverse of the square root, if positive semi-definite.
132 
133  //: Solve LS problem M x = b
134  vnl_vector<T> solve(vnl_vector<T> const & b);
135 
136  //: Solve LS problem M x = b
137  void solve(vnl_vector<T> const & b, vnl_vector<T> * x) { *x = solve(b); }
138 };
139 
140 #define VNL_SYMMETRIC_EIGENSYSTEM_INSTANTIATE(T) \
141 extern "please include vnl/algo/vnl_symmetric_eigensystem.hxx first"
142 
143 #endif // vnl_symmetric_eigensystem_h_
An ordinary mathematical matrix.
vnl_matrix< T > V
Public eigenvectors.
vnl_diag_matrix< T > D
Public eigenvalues.
vnl_matrix< T > square_root() const
return the square root, if positive semi-definite.
Computes and stores the eigensystem decomposition of a symmetric matrix.
Definition: vnl_algo_fwd.h:9
vnl_symmetric_eigensystem(vnl_matrix< T > const &M)
Solve real symmetric eigensystem $A x = \lambda x$.
T get_eigenvalue(int i) const
Recover specified eigenvalue after computation.
An ordinary mathematical matrix.
Definition: vnl_adjugate.h:22
vnl_matrix< T > recompose() const
Return the matrix $V D V^\top$.
vnl_vector< T > get_eigenvector(int i) const
Recover specified eigenvector after computation.
void solve(vnl_vector< T > const &b, vnl_vector< T > *x)
Solve LS problem M x = b.
Mathematical vector class, templated by type of element.
Definition: vnl_fwd.h:16
vnl_matrix< T > pinverse() const
return the pseudoinverse.
void vnl_symmetric_eigensystem_compute_eigenvals(T M11, T M12, T M13, T M22, T M23, T M33, T &l1, T &l2, T &l3)
Find eigenvalues of a symmetric 3x3 matrix.
T determinant() const
return product of eigenvalues.
stores a diagonal matrix as a single vector.
vnl_vector< T > nullvector() const
Convenience method to get least-squares nullvector.
vnl_matrix< T > inverse_square_root() const
return the inverse of the square root, if positive semi-definite.
Contains class for diagonal matrices.
vnl_vector< T > solve(vnl_vector< T > const &b)
Solve LS problem M x = b.
bool vnl_symmetric_eigensystem_compute(vnl_matrix< T > const &A, vnl_matrix< T > &V, vnl_vector< T > &D)
Find eigenvalues of a symmetric matrix.