Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
Loading...
Searching...
No Matches
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 <[email protected]>
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
36namespace Eigen {
37
38namespace internal {
39
41template <typename Index, typename IndexVector>
42Index 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
60template <typename MatrixType, typename IndexVector>
61int 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
125template <typename IndexVector>
126void 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
167template <typename IndexVector>
168void 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
Namespace containing all symbols from the Eigen library.
Definition Core:137