MatrixDiag.hh
Go to the documentation of this file.
00001 #ifndef RIVET_MATH_MATRIXDIAG 00002 #define RIVET_MATH_MATRIXDIAG 00003 00004 #include "Rivet/Math/MathHeader.hh" 00005 #include "Rivet/Math/MatrixN.hh" 00006 00007 #include "gsl/gsl_vector.h" 00008 #include "gsl/gsl_matrix.h" 00009 #include "gsl/gsl_eigen.h" 00010 00011 namespace Rivet { 00012 00013 00014 template <size_t N> 00015 class EigenSystem; 00016 template <size_t N> 00017 EigenSystem<N> diagonalize(const Matrix<N>& m); 00018 00019 00020 /// Handy object containing results of a diagonalization. 00021 template <size_t N> 00022 class EigenSystem { 00023 template <size_t M> 00024 friend EigenSystem<M> diagonalize(const Matrix<M>&); 00025 00026 public: 00027 00028 typedef pair<double, Vector<N> > EigenPair; 00029 typedef vector<EigenPair> EigenPairs; 00030 00031 Vector<N> getDiagVector() const { 00032 assert(_eigenPairs.size() == N); 00033 Vector<N> ret; 00034 for (size_t i = 0; i < N; ++i) { 00035 ret.set(i, _eigenPairs[i].first); 00036 } 00037 return ret; 00038 } 00039 00040 Matrix<N> getDiagMatrix() const { 00041 return Matrix<N>::mkDiag(getDiagVector()); 00042 } 00043 00044 EigenPairs getEigenPairs() const { 00045 return _eigenPairs; 00046 } 00047 00048 vector<double> getEigenValues() const { 00049 assert(_eigenPairs.size() == N); 00050 vector<double> ret; 00051 for (size_t i = 0; i < N; ++i) { 00052 ret.push_back(_eigenPairs[i].first); 00053 } 00054 return ret; 00055 } 00056 00057 vector<Vector<N> > getEigenVectors() const { 00058 assert(_eigenPairs.size() == N); 00059 vector<Vector<N> > ret; 00060 for (size_t i = 0; i < N; ++i) { 00061 ret.push_back(_eigenPairs[i].second); 00062 } 00063 return ret; 00064 } 00065 00066 private: 00067 00068 EigenPairs _eigenPairs; 00069 00070 }; 00071 00072 00073 /// Comparison functor for "eigen-pairs". 00074 template <size_t N> 00075 struct EigenPairCmp : 00076 public std::binary_function<const typename EigenSystem<N>::EigenPair&, 00077 const typename EigenSystem<N>::EigenPair&, bool> { 00078 bool operator()(const typename EigenSystem<N>::EigenPair& a, 00079 const typename EigenSystem<N>::EigenPair& b) { 00080 return a.first < b.first; 00081 } 00082 }; 00083 00084 00085 /// Diagonalize an NxN matrix, returning a collection of pairs of 00086 /// eigenvalues and eigenvectors, ordered decreasing in eigenvalue. 00087 template <size_t N> 00088 EigenSystem<N> diagonalize(const Matrix<N>& m) { 00089 EigenSystem<N> esys; 00090 00091 // Make a GSL matrix. 00092 gsl_matrix* A = gsl_matrix_alloc(N, N); 00093 for (size_t i = 0; i < N; ++i) { 00094 for (size_t j = 0; j < N; ++j) { 00095 gsl_matrix_set(A, i, j, m.get(i, j)); 00096 } 00097 } 00098 00099 // Use GSL diagonalization. 00100 gsl_matrix* vecs = gsl_matrix_alloc(N, N); 00101 gsl_vector* vals = gsl_vector_alloc(N); 00102 gsl_eigen_symmv_workspace* workspace = gsl_eigen_symmv_alloc(N); 00103 gsl_eigen_symmv(A, vals, vecs, workspace); 00104 gsl_eigen_symmv_sort(vals, vecs, GSL_EIGEN_SORT_VAL_DESC); 00105 00106 // Build the vector of "eigen-pairs". 00107 typename EigenSystem<N>::EigenPairs eigensolns; 00108 for (size_t i = 0; i < N; ++i) { 00109 typename EigenSystem<N>::EigenPair ep; 00110 ep.first = gsl_vector_get(vals, i); 00111 Vector<N> ev; 00112 for (size_t j = 0; j < N; ++j) { 00113 ev.set(j, gsl_matrix_get(vecs, j, i)); 00114 } 00115 ep.second = ev; 00116 eigensolns.push_back(ep); 00117 } 00118 00119 // Free GSL memory. 00120 gsl_eigen_symmv_free(workspace); 00121 gsl_matrix_free(A); 00122 gsl_matrix_free(vecs); 00123 gsl_vector_free(vals); 00124 00125 // Populate the returned object. 00126 esys._eigenPairs = eigensolns; 00127 return esys; 00128 } 00129 00130 00131 template <size_t N> 00132 inline const string toString(const typename EigenSystem<N>::EigenPair& e) { 00133 ostringstream ss; 00134 //for (typename EigenSystem<N>::EigenPairs::const_iterator i = e.begin(); i != e.end(); ++i) { 00135 ss << e->first << " -> " << e->second; 00136 // if (i+1 != e.end()) ss << endl; 00137 //} 00138 return ss.str(); 00139 } 00140 00141 template <size_t N> 00142 inline ostream& operator<<(std::ostream& out, const typename EigenSystem<N>::EigenPair& e) { 00143 out << toString(e); 00144 return out; 00145 } 00146 00147 00148 } 00149 00150 #endif Generated on Tue Mar 24 2015 17:35:27 for The Rivet MC analysis system by ![]() |