SparseColEtree.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 
11 /*
12 
13  * NOTE: This file is the modified version of sp_coletree.c file in SuperLU
14 
15  * -- SuperLU routine (version 3.1) --
16  * Univ. of California Berkeley, Xerox Palo Alto Research Center,
17  * and Lawrence Berkeley National Lab.
18  * August 1, 2008
19  *
20  * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
21  *
22  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
23  * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
24  *
25  * Permission is hereby granted to use or copy this program for any
26  * purpose, provided the above notices are retained on all copies.
27  * Permission to modify the code and to distribute modified code is
28  * granted, provided the above notices are retained, and a notice that
29  * the code was modified is included with the above copyright notice.
30  */
31 #ifndef SPARSE_COLETREE_H
32 #define SPARSE_COLETREE_H
33 
34 #include "./InternalHeaderCheck.h"
35 
36 namespace Eigen {
37 
38 namespace internal {
39 
41 template<typename Index, typename IndexVector>
42 Index etree_find (Index i, IndexVector& pp)
43 {
44  Index p = pp(i); // Parent
45  Index gp = pp(p); // Grand parent
46  while (gp != p)
47  {
48  pp(i) = gp; // Parent pointer on find path is changed to former grand parent
49  i = gp;
50  p = pp(i);
51  gp = pp(p);
52  }
53  return p;
54 }
55 
62 template <typename MatrixType, typename IndexVector>
63 int coletree(const MatrixType& mat, IndexVector& parent, IndexVector& firstRowElt, typename MatrixType::StorageIndex *perm=0)
64 {
65  typedef typename MatrixType::StorageIndex StorageIndex;
66  StorageIndex nc = convert_index<StorageIndex>(mat.cols()); // Number of columns
67  StorageIndex m = convert_index<StorageIndex>(mat.rows());
68  StorageIndex diagSize = (std::min)(nc,m);
69  IndexVector root(nc); // root of subtree of etree
70  root.setZero();
71  IndexVector pp(nc); // disjoint sets
72  pp.setZero(); // Initialize disjoint sets
73  parent.resize(mat.cols());
74  //Compute first nonzero column in each row
75  firstRowElt.resize(m);
76  firstRowElt.setConstant(nc);
77  firstRowElt.segment(0, diagSize).setLinSpaced(diagSize, 0, diagSize-1);
78  bool found_diag;
79  for (StorageIndex col = 0; col < nc; col++)
80  {
81  StorageIndex pcol = col;
82  if(perm) pcol = perm[col];
83  for (typename MatrixType::InnerIterator it(mat, pcol); it; ++it)
84  {
85  Index row = it.row();
86  firstRowElt(row) = (std::min)(firstRowElt(row), col);
87  }
88  }
89  /* Compute etree by Liu's algorithm for symmetric matrices,
90  except use (firstRowElt[r],c) in place of an edge (r,c) of A.
91  Thus each row clique in A'*A is replaced by a star
92  centered at its first vertex, which has the same fill. */
93  StorageIndex rset, cset, rroot;
94  for (StorageIndex col = 0; col < nc; col++)
95  {
96  found_diag = col>=m;
97  pp(col) = col;
98  cset = col;
99  root(cset) = col;
100  parent(col) = nc;
101  /* The diagonal element is treated here even if it does not exist in the matrix
102  * hence the loop is executed once more */
103  StorageIndex pcol = col;
104  if(perm) pcol = perm[col];
105  for (typename MatrixType::InnerIterator it(mat, pcol); it||!found_diag; ++it)
106  { // A sequence of interleaved find and union is performed
107  Index i = col;
108  if(it) i = it.index();
109  if (i == col) found_diag = true;
110 
111  StorageIndex row = firstRowElt(i);
112  if (row >= col) continue;
113  rset = internal::etree_find(row, pp); // Find the name of the set containing row
114  rroot = root(rset);
115  if (rroot != col)
116  {
117  parent(rroot) = col;
118  pp(cset) = rset;
119  cset = rset;
120  root(cset) = col;
121  }
122  }
123  }
124  return 0;
125 }
126 
131 template <typename IndexVector>
132 void nr_etdfs (typename IndexVector::Scalar n, IndexVector& parent, IndexVector& first_kid, IndexVector& next_kid, IndexVector& post, typename IndexVector::Scalar postnum)
133 {
134  typedef typename IndexVector::Scalar StorageIndex;
135  StorageIndex current = n, first, next;
136  while (postnum != n)
137  {
138  // No kid for the current node
139  first = first_kid(current);
140 
141  // no kid for the current node
142  if (first == -1)
143  {
144  // Numbering this node because it has no kid
145  post(current) = postnum++;
146 
147  // looking for the next kid
148  next = next_kid(current);
149  while (next == -1)
150  {
151  // No more kids : back to the parent node
152  current = parent(current);
153  // numbering the parent node
154  post(current) = postnum++;
155 
156  // Get the next kid
157  next = next_kid(current);
158  }
159  // stopping criterion
160  if (postnum == n+1) return;
161 
162  // Updating current node
163  current = next;
164  }
165  else
166  {
167  current = first;
168  }
169  }
170 }
171 
172 
179 template <typename IndexVector>
180 void treePostorder(typename IndexVector::Scalar n, IndexVector& parent, IndexVector& post)
181 {
182  typedef typename IndexVector::Scalar StorageIndex;
183  IndexVector first_kid, next_kid; // Linked list of children
184  StorageIndex postnum;
185  // Allocate storage for working arrays and results
186  first_kid.resize(n+1);
187  next_kid.setZero(n+1);
188  post.setZero(n+1);
189 
190  // Set up structure describing children
191  first_kid.setConstant(-1);
192  for (StorageIndex v = n-1; v >= 0; v--)
193  {
194  StorageIndex dad = parent(v);
195  next_kid(v) = first_kid(dad);
196  first_kid(dad) = v;
197  }
198 
199  // Depth-first search from dummy root vertex #n
200  postnum = 0;
201  internal::nr_etdfs(n, parent, first_kid, next_kid, post, postnum);
202 }
203 
204 } // end namespace internal
205 
206 } // end namespace Eigen
207 
208 #endif // SPARSE_COLETREE_H
Matrix3f m
Array< int, Dynamic, 1 > v
int n
RowXpr row(Index i)
This is the const version of row(). *‍/.
ColXpr col(Index i)
This is the const version of col().
float * p
Matrix< float, 1, Dynamic > MatrixType
bfloat16() min(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:684
int coletree(const MatrixType &mat, IndexVector &parent, IndexVector &firstRowElt, typename MatrixType::StorageIndex *perm=0)
EIGEN_CONSTEXPR Index first(const T &x) EIGEN_NOEXCEPT
void treePostorder(typename IndexVector::Scalar n, IndexVector &parent, IndexVector &post)
Post order a tree.
void nr_etdfs(typename IndexVector::Scalar n, IndexVector &parent, IndexVector &first_kid, IndexVector &next_kid, IndexVector &post, typename IndexVector::Scalar postnum)
Index etree_find(Index i, IndexVector &pp)
: InteropHeaders
Definition: Core:139
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82