Eigen  3.4.90 (git rev a4098ac676528a83cfb73d4d26ce1b42ec05f47c)
SparseColEtree.h
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
36namespace Eigen {
37
38namespace internal {
39
41template<typename Index, typename IndexVector>
42Index 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
62template <typename MatrixType, typename IndexVector>
63int 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
131template <typename IndexVector>
132void 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
179template <typename IndexVector>
180void 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
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:59