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  * NOTE: This file is the modified version of sp_coletree.c file in SuperLU
13 
14  * -- SuperLU routine (version 3.1) --
15  * Univ. of California Berkeley, Xerox Palo Alto Research Center,
16  * and Lawrence Berkeley National Lab.
17  * August 1, 2008
18  *
19  * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
20  *
21  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
22  * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
23  *
24  * Permission is hereby granted to use or copy this program for any
25  * purpose, provided the above notices are retained on all copies.
26  * Permission to modify the code and to distribute modified code is
27  * granted, provided the above notices are retained, and a notice that
28  * the code was modified is included with the above copyright notice.
29  */
30 #ifndef SPARSE_COLETREE_H
31 #define SPARSE_COLETREE_H
32 
33 // IWYU pragma: private
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  Index p = pp(i); // Parent
44  Index gp = pp(p); // Grand parent
45  while (gp != p) {
46  pp(i) = gp; // Parent pointer on find path is changed to former grand parent
47  i = gp;
48  p = pp(i);
49  gp = pp(p);
50  }
51  return p;
52 }
53 
60 template <typename MatrixType, typename IndexVector>
61 int coletree(const MatrixType& mat, IndexVector& parent, IndexVector& firstRowElt,
62  typename MatrixType::StorageIndex* perm = 0) {
63  typedef typename MatrixType::StorageIndex StorageIndex;
64  StorageIndex nc = convert_index<StorageIndex>(mat.cols()); // Number of columns
65  StorageIndex m = convert_index<StorageIndex>(mat.rows());
66  StorageIndex diagSize = (std::min)(nc, m);
67  IndexVector root(nc); // root of subtree of etree
68  root.setZero();
69  IndexVector pp(nc); // disjoint sets
70  pp.setZero(); // Initialize disjoint sets
71  parent.resize(mat.cols());
72  // Compute first nonzero column in each row
73  firstRowElt.resize(m);
74  firstRowElt.setConstant(nc);
75  firstRowElt.segment(0, diagSize).setLinSpaced(diagSize, 0, diagSize - 1);
76  bool found_diag;
77  for (StorageIndex col = 0; col < nc; col++) {
78  StorageIndex pcol = col;
79  if (perm) pcol = perm[col];
80  for (typename MatrixType::InnerIterator it(mat, pcol); it; ++it) {
81  Index row = it.row();
82  firstRowElt(row) = (std::min)(firstRowElt(row), col);
83  }
84  }
85  /* Compute etree by Liu's algorithm for symmetric matrices,
86  except use (firstRowElt[r],c) in place of an edge (r,c) of A.
87  Thus each row clique in A'*A is replaced by a star
88  centered at its first vertex, which has the same fill. */
89  StorageIndex rset, cset, rroot;
90  for (StorageIndex col = 0; col < nc; col++) {
91  found_diag = col >= m;
92  pp(col) = col;
93  cset = col;
94  root(cset) = col;
95  parent(col) = nc;
96  /* The diagonal element is treated here even if it does not exist in the matrix
97  * hence the loop is executed once more */
98  StorageIndex pcol = col;
99  if (perm) pcol = perm[col];
100  for (typename MatrixType::InnerIterator it(mat, pcol); it || !found_diag;
101  ++it) { // A sequence of interleaved find and union is performed
102  Index i = col;
103  if (it) i = it.index();
104  if (i == col) found_diag = true;
105 
106  StorageIndex row = firstRowElt(i);
107  if (row >= col) continue;
108  rset = internal::etree_find(row, pp); // Find the name of the set containing row
109  rroot = root(rset);
110  if (rroot != col) {
111  parent(rroot) = col;
112  pp(cset) = rset;
113  cset = rset;
114  root(cset) = col;
115  }
116  }
117  }
118  return 0;
119 }
120 
125 template <typename IndexVector>
126 void nr_etdfs(typename IndexVector::Scalar n, IndexVector& parent, IndexVector& first_kid, IndexVector& next_kid,
127  IndexVector& post, typename IndexVector::Scalar postnum) {
128  typedef typename IndexVector::Scalar StorageIndex;
129  StorageIndex current = n, first, next;
130  while (postnum != n) {
131  // No kid for the current node
132  first = first_kid(current);
133 
134  // no kid for the current node
135  if (first == -1) {
136  // Numbering this node because it has no kid
137  post(current) = postnum++;
138 
139  // looking for the next kid
140  next = next_kid(current);
141  while (next == -1) {
142  // No more kids : back to the parent node
143  current = parent(current);
144  // numbering the parent node
145  post(current) = postnum++;
146 
147  // Get the next kid
148  next = next_kid(current);
149  }
150  // stopping criterion
151  if (postnum == n + 1) return;
152 
153  // Updating current node
154  current = next;
155  } else {
156  current = first;
157  }
158  }
159 }
160 
167 template <typename IndexVector>
168 void treePostorder(typename IndexVector::Scalar n, IndexVector& parent, IndexVector& post) {
169  typedef typename IndexVector::Scalar StorageIndex;
170  IndexVector first_kid, next_kid; // Linked list of children
171  StorageIndex postnum;
172  // Allocate storage for working arrays and results
173  first_kid.resize(n + 1);
174  next_kid.setZero(n + 1);
175  post.setZero(n + 1);
176 
177  // Set up structure describing children
178  first_kid.setConstant(-1);
179  for (StorageIndex v = n - 1; v >= 0; v--) {
180  StorageIndex dad = parent(v);
181  next_kid(v) = first_kid(dad);
182  first_kid(dad) = v;
183  }
184 
185  // Depth-first search from dummy root vertex #n
186  postnum = 0;
187  internal::nr_etdfs(n, parent, first_kid, next_kid, post, postnum);
188 }
189 
190 } // end namespace internal
191 
192 } // end namespace Eigen
193 
194 #endif // SPARSE_COLETREE_H
Array< int, Dynamic, 1 > v
Definition: Array_initializer_list_vector_cxx11.cpp:1
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
m col(1)
m row(1)
float * p
Definition: Tutorial_Map_using.cpp:9
SCALAR Scalar
Definition: bench_gemm.cpp:45
MatrixXf MatrixType
Definition: benchmark-blocking-sizes.cpp:52
Index cols() const
Definition: SparseMatrix.h:161
Index rows() const
Definition: SparseMatrix.h:159
#define min(a, b)
Definition: datatypes.h:22
int * m
Definition: level2_cplx_impl.h:294
int coletree(const MatrixType &mat, IndexVector &parent, IndexVector &firstRowElt, typename MatrixType::StorageIndex *perm=0)
Definition: SparseColEtree.h:61
void treePostorder(typename IndexVector::Scalar n, IndexVector &parent, IndexVector &post)
Post order a tree.
Definition: SparseColEtree.h:168
void nr_etdfs(typename IndexVector::Scalar n, IndexVector &parent, IndexVector &first_kid, IndexVector &next_kid, IndexVector &post, typename IndexVector::Scalar postnum)
Definition: SparseColEtree.h:126
Index etree_find(Index i, IndexVector &pp)
Definition: SparseColEtree.h:42
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:70
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83
Definition: Eigen_Colamd.h:49