Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef SPARSE_COLETREE_H
00032 #define SPARSE_COLETREE_H
00033
00034 namespace Eigen {
00035
00036 namespace internal {
00037
00039 template<typename Index, typename IndexVector>
00040 Index etree_find (Index i, IndexVector& pp)
00041 {
00042 Index p = pp(i);
00043 Index gp = pp(p);
00044 while (gp != p)
00045 {
00046 pp(i) = gp;
00047 i = gp;
00048 p = pp(i);
00049 gp = pp(p);
00050 }
00051 return p;
00052 }
00053
00060 template <typename MatrixType, typename IndexVector>
00061 int coletree(const MatrixType& mat, IndexVector& parent, IndexVector& firstRowElt, typename MatrixType::Index *perm=0)
00062 {
00063 typedef typename MatrixType::Index Index;
00064 Index nc = mat.cols();
00065 Index m = mat.rows();
00066 Index diagSize = (std::min)(nc,m);
00067 IndexVector root(nc);
00068 root.setZero();
00069 IndexVector pp(nc);
00070 pp.setZero();
00071 parent.resize(mat.cols());
00072
00073 Index row,col;
00074 firstRowElt.resize(m);
00075 firstRowElt.setConstant(nc);
00076 firstRowElt.segment(0, diagSize).setLinSpaced(diagSize, 0, diagSize-1);
00077 bool found_diag;
00078 for (col = 0; col < nc; col++)
00079 {
00080 Index pcol = col;
00081 if(perm) pcol = perm[col];
00082 for (typename MatrixType::InnerIterator it(mat, pcol); it; ++it)
00083 {
00084 row = it.row();
00085 firstRowElt(row) = (std::min)(firstRowElt(row), col);
00086 }
00087 }
00088
00089
00090
00091
00092 Index rset, cset, rroot;
00093 for (col = 0; col < nc; col++)
00094 {
00095 found_diag = col>=m;
00096 pp(col) = col;
00097 cset = col;
00098 root(cset) = col;
00099 parent(col) = nc;
00100
00101
00102 Index pcol = col;
00103 if(perm) pcol = perm[col];
00104 for (typename MatrixType::InnerIterator it(mat, pcol); it||!found_diag; ++it)
00105 {
00106 Index i = col;
00107 if(it) i = it.index();
00108 if (i == col) found_diag = true;
00109
00110 row = firstRowElt(i);
00111 if (row >= col) continue;
00112 rset = internal::etree_find(row, pp);
00113 rroot = root(rset);
00114 if (rroot != col)
00115 {
00116 parent(rroot) = col;
00117 pp(cset) = rset;
00118 cset = rset;
00119 root(cset) = col;
00120 }
00121 }
00122 }
00123 return 0;
00124 }
00125
00130 template <typename Index, typename IndexVector>
00131 void nr_etdfs (Index n, IndexVector& parent, IndexVector& first_kid, IndexVector& next_kid, IndexVector& post, Index postnum)
00132 {
00133 Index current = n, first, next;
00134 while (postnum != n)
00135 {
00136
00137 first = first_kid(current);
00138
00139
00140 if (first == -1)
00141 {
00142
00143 post(current) = postnum++;
00144
00145
00146 next = next_kid(current);
00147 while (next == -1)
00148 {
00149
00150 current = parent(current);
00151
00152 post(current) = postnum++;
00153
00154
00155 next = next_kid(current);
00156 }
00157
00158 if (postnum == n+1) return;
00159
00160
00161 current = next;
00162 }
00163 else
00164 {
00165 current = first;
00166 }
00167 }
00168 }
00169
00170
00177 template <typename Index, typename IndexVector>
00178 void treePostorder(Index n, IndexVector& parent, IndexVector& post)
00179 {
00180 IndexVector first_kid, next_kid;
00181 Index postnum;
00182
00183 first_kid.resize(n+1);
00184 next_kid.setZero(n+1);
00185 post.setZero(n+1);
00186
00187
00188 Index v, dad;
00189 first_kid.setConstant(-1);
00190 for (v = n-1; v >= 0; v--)
00191 {
00192 dad = parent(v);
00193 next_kid(v) = first_kid(dad);
00194 first_kid(dad) = v;
00195 }
00196
00197
00198 postnum = 0;
00199 internal::nr_etdfs(n, parent, first_kid, next_kid, post, postnum);
00200 }
00201
00202 }
00203
00204 }
00205
00206 #endif // SPARSE_COLETREE_H