Amesos Package Browser (Single Doxygen Collection)  Development
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_etree.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Cholesky/cholmod_etree =============================================== */
3 /* ========================================================================== */
4 
5 /* -----------------------------------------------------------------------------
6  * CHOLMOD/Cholesky Module. Copyright (C) 2005-2006, Timothy A. Davis
7  * The CHOLMOD/Cholesky Module is licensed under Version 2.1 of the GNU
8  * Lesser General Public License. See lesser.txt for a text of the license.
9  * CHOLMOD is also available under other licenses; contact authors for details.
10  * http://www.cise.ufl.edu/research/sparse
11  * -------------------------------------------------------------------------- */
12 
13 /* Compute the elimination tree of A or A'*A
14  *
15  * In the symmetric case, the upper triangular part of A is used. Entries not
16  * in this part of the matrix are ignored. Computing the etree of a symmetric
17  * matrix from just its lower triangular entries is not supported.
18  *
19  * In the unsymmetric case, all of A is used, and the etree of A'*A is computed.
20  *
21  * References:
22  *
23  * J. Liu, "A compact row storage scheme for Cholesky factors", ACM Trans.
24  * Math. Software, vol 12, 1986, pp. 127-148.
25  *
26  * J. Liu, "The role of elimination trees in sparse factorization", SIAM J.
27  * Matrix Analysis & Applic., vol 11, 1990, pp. 134-172.
28  *
29  * J. Gilbert, X. Li, E. Ng, B. Peyton, "Computing row and column counts for
30  * sparse QR and LU factorization", BIT, vol 41, 2001, pp. 693-710.
31  *
32  * workspace: symmetric: Iwork (nrow), unsymmetric: Iwork (nrow+ncol)
33  *
34  * Supports any xtype (pattern, real, complex, or zomplex)
35  */
36 
37 #ifndef NCHOLESKY
38 
41 
42 /* ========================================================================== */
43 /* === update_etree ========================================================= */
44 /* ========================================================================== */
45 
46 static void amesos_update_etree
47 (
48  /* inputs, not modified */
49  Int k, /* process the edge (k,i) in the input graph */
50  Int i,
51  /* inputs, modified on output */
52  Int Parent [ ], /* Parent [t] = p if p is the parent of t */
53  Int Ancestor [ ] /* Ancestor [t] is the ancestor of node t in the
54  partially-constructed etree */
55 )
56 {
57  Int a ;
58  for ( ; ; ) /* traverse the path from k to the root of the tree */
59  {
60  a = Ancestor [k] ;
61  if (a == i)
62  {
63  /* final ancestor reached; no change to tree */
64  return ;
65  }
66  /* perform path compression */
67  Ancestor [k] = i ;
68  if (a == EMPTY)
69  {
70  /* final ancestor undefined; this is a new edge in the tree */
71  Parent [k] = i ;
72  return ;
73  }
74  /* traverse up to the ancestor of k */
75  k = a ;
76  }
77 }
78 
79 /* ========================================================================== */
80 /* === cholmod_etree ======================================================== */
81 /* ========================================================================== */
82 
83 /* Find the elimination tree of A or A'*A */
84 
85 int CHOLMOD(etree)
86 (
87  /* ---- input ---- */
89  /* ---- output --- */
90  Int *Parent, /* size ncol. Parent [j] = p if p is the parent of j */
91  /* --------------- */
92  cholmod_common *Common
93 )
94 {
95  Int *Ap, *Ai, *Anz, *Ancestor, *Prev, *Iwork ;
96  Int i, j, jprev, p, pend, nrow, ncol, packed, stype ;
97  size_t s ;
98  int ok = TRUE ;
99 
100  /* ---------------------------------------------------------------------- */
101  /* check inputs */
102  /* ---------------------------------------------------------------------- */
103 
105  RETURN_IF_NULL (A, FALSE) ;
106  RETURN_IF_NULL (Parent, FALSE) ;
108  Common->status = CHOLMOD_OK ;
109 
110  /* ---------------------------------------------------------------------- */
111  /* allocate workspace */
112  /* ---------------------------------------------------------------------- */
113 
114  stype = A->stype ;
115 
116  /* s = A->nrow + (stype ? 0 : A->ncol) */
117  s = CHOLMOD(add_size_t) (A->nrow, (stype ? 0 : A->ncol), &ok) ;
118  if (!ok)
119  {
120  ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
121  return (FALSE) ;
122  }
123 
124  CHOLMOD(allocate_work) (0, s, 0, Common) ;
125  if (Common->status < CHOLMOD_OK)
126  {
127  return (FALSE) ; /* out of memory */
128  }
129 
130  ASSERT (CHOLMOD(dump_sparse) (A, "etree", Common) >= 0) ;
131  Iwork = Common->Iwork ;
132 
133  /* ---------------------------------------------------------------------- */
134  /* get inputs */
135  /* ---------------------------------------------------------------------- */
136 
137  ncol = A->ncol ; /* the number of columns of A */
138  nrow = A->nrow ; /* the number of rows of A */
139  Ap = A->p ; /* size ncol+1, column pointers for A */
140  Ai = A->i ; /* the row indices of A */
141  Anz = A->nz ; /* number of nonzeros in each column of A */
142  packed = A->packed ;
143  Ancestor = Iwork ; /* size ncol (i/i/l) */
144 
145  for (j = 0 ; j < ncol ; j++)
146  {
147  Parent [j] = EMPTY ;
148  Ancestor [j] = EMPTY ;
149  }
150 
151  /* ---------------------------------------------------------------------- */
152  /* compute the etree */
153  /* ---------------------------------------------------------------------- */
154 
155  if (stype > 0)
156  {
157 
158  /* ------------------------------------------------------------------ */
159  /* symmetric (upper) case: compute etree (A) */
160  /* ------------------------------------------------------------------ */
161 
162  for (j = 0 ; j < ncol ; j++)
163  {
164  /* for each row i in column j of triu(A), excluding the diagonal */
165  p = Ap [j] ;
166  pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
167  for ( ; p < pend ; p++)
168  {
169  i = Ai [p] ;
170  if (i < j)
171  {
172  amesos_update_etree (i, j, Parent, Ancestor) ;
173  }
174  }
175  }
176 
177  }
178  else if (stype == 0)
179  {
180 
181  /* ------------------------------------------------------------------ */
182  /* unsymmetric case: compute etree (A'*A) */
183  /* ------------------------------------------------------------------ */
184 
185  Prev = Iwork + ncol ; /* size nrow (i/i/l) */
186  for (i = 0 ; i < nrow ; i++)
187  {
188  Prev [i] = EMPTY ;
189  }
190  for (j = 0 ; j < ncol ; j++)
191  {
192  /* for each row i in column j of A */
193  p = Ap [j] ;
194  pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
195  for ( ; p < pend ; p++)
196  {
197  /* a graph is constructed dynamically with one path per row
198  * of A. If the ith row of A contains column indices
199  * (j1,j2,j3,j4) then the new graph has edges (j1,j2), (j2,j3),
200  * and (j3,j4). When at node i of this path-graph, all edges
201  * (jprev,j) are considered, where jprev<j */
202  i = Ai [p] ;
203  jprev = Prev [i] ;
204  if (jprev != EMPTY)
205  {
206  amesos_update_etree (jprev, j, Parent, Ancestor) ;
207  }
208  Prev [i] = j ;
209  }
210  }
211 
212  }
213  else
214  {
215 
216  /* ------------------------------------------------------------------ */
217  /* symmetric case with lower triangular part not supported */
218  /* ------------------------------------------------------------------ */
219 
220  ERROR (CHOLMOD_INVALID, "symmetric lower not supported") ;
221  return (FALSE) ;
222  }
223 
224  ASSERT (CHOLMOD(dump_parent) (Parent, ncol, "Parent", Common)) ;
225  return (TRUE) ;
226 }
227 #endif
#define CHOLMOD_TOO_LARGE
#define EMPTY
#define Int
size_t CHOLMOD() add_size_t(size_t a, size_t b, int *ok)
#define FALSE
#define RETURN_IF_NULL_COMMON(result)
#define CHOLMOD_PATTERN
#define CHOLMOD(name)
#define ASSERT(expression)
int CHOLMOD() etree(cholmod_sparse *A, Int *Parent, cholmod_common *Common)
static void amesos_update_etree(Int k, Int i, Int Parent[], Int Ancestor[])
#define CHOLMOD_INVALID
#define CHOLMOD_OK
int CHOLMOD() allocate_work(size_t nrow, size_t iworksize, size_t xworksize, cholmod_common *Common)
#define RETURN_IF_NULL(A, result)
int CHOLMOD() dump_parent(Int *Parent, size_t n, char *name, cholmod_common *Common)
#define ERROR(status, msg)
#define TRUE
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define CHOLMOD_ZOMPLEX