Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_l_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 
39 /* This file should make the long int version of CHOLMOD */
40 #define DLONG 1
41 
44 
45 /* ========================================================================== */
46 /* === update_etree ========================================================= */
47 /* ========================================================================== */
48 
49 static void amesos_update_etree
50 (
51  /* inputs, not modified */
52  Int k, /* process the edge (k,i) in the input graph */
53  Int i,
54  /* inputs, modified on output */
55  Int Parent [ ], /* Parent [t] = p if p is the parent of t */
56  Int Ancestor [ ] /* Ancestor [t] is the ancestor of node t in the
57  partially-constructed etree */
58 )
59 {
60  Int a ;
61  for ( ; ; ) /* traverse the path from k to the root of the tree */
62  {
63  a = Ancestor [k] ;
64  if (a == i)
65  {
66  /* final ancestor reached; no change to tree */
67  return ;
68  }
69  /* perform path compression */
70  Ancestor [k] = i ;
71  if (a == EMPTY)
72  {
73  /* final ancestor undefined; this is a new edge in the tree */
74  Parent [k] = i ;
75  return ;
76  }
77  /* traverse up to the ancestor of k */
78  k = a ;
79  }
80 }
81 
82 /* ========================================================================== */
83 /* === cholmod_etree ======================================================== */
84 /* ========================================================================== */
85 
86 /* Find the elimination tree of A or A'*A */
87 
88 int CHOLMOD(etree)
89 (
90  /* ---- input ---- */
92  /* ---- output --- */
93  Int *Parent, /* size ncol. Parent [j] = p if p is the parent of j */
94  /* --------------- */
95  cholmod_common *Common
96 )
97 {
98  Int *Ap, *Ai, *Anz, *Ancestor, *Prev, *Iwork ;
99  Int i, j, jprev, p, pend, nrow, ncol, packed, stype ;
100  size_t s ;
101  int ok = TRUE ;
102 
103  /* ---------------------------------------------------------------------- */
104  /* check inputs */
105  /* ---------------------------------------------------------------------- */
106 
108  RETURN_IF_NULL (A, FALSE) ;
109  RETURN_IF_NULL (Parent, FALSE) ;
111  Common->status = CHOLMOD_OK ;
112 
113  /* ---------------------------------------------------------------------- */
114  /* allocate workspace */
115  /* ---------------------------------------------------------------------- */
116 
117  stype = A->stype ;
118 
119  /* s = A->nrow + (stype ? 0 : A->ncol) */
120  s = CHOLMOD(add_size_t) (A->nrow, (stype ? 0 : A->ncol), &ok) ;
121  if (!ok)
122  {
123  ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
124  return (FALSE) ;
125  }
126 
127  CHOLMOD(allocate_work) (0, s, 0, Common) ;
128  if (Common->status < CHOLMOD_OK)
129  {
130  return (FALSE) ; /* out of memory */
131  }
132 
133  ASSERT (CHOLMOD(dump_sparse) (A, "etree", Common) >= 0) ;
134  Iwork = Common->Iwork ;
135 
136  /* ---------------------------------------------------------------------- */
137  /* get inputs */
138  /* ---------------------------------------------------------------------- */
139 
140  ncol = A->ncol ; /* the number of columns of A */
141  nrow = A->nrow ; /* the number of rows of A */
142  Ap = A->p ; /* size ncol+1, column pointers for A */
143  Ai = A->i ; /* the row indices of A */
144  Anz = A->nz ; /* number of nonzeros in each column of A */
145  packed = A->packed ;
146  Ancestor = Iwork ; /* size ncol (i/i/l) */
147 
148  for (j = 0 ; j < ncol ; j++)
149  {
150  Parent [j] = EMPTY ;
151  Ancestor [j] = EMPTY ;
152  }
153 
154  /* ---------------------------------------------------------------------- */
155  /* compute the etree */
156  /* ---------------------------------------------------------------------- */
157 
158  if (stype > 0)
159  {
160 
161  /* ------------------------------------------------------------------ */
162  /* symmetric (upper) case: compute etree (A) */
163  /* ------------------------------------------------------------------ */
164 
165  for (j = 0 ; j < ncol ; j++)
166  {
167  /* for each row i in column j of triu(A), excluding the diagonal */
168  p = Ap [j] ;
169  pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
170  for ( ; p < pend ; p++)
171  {
172  i = Ai [p] ;
173  if (i < j)
174  {
175  amesos_update_etree (i, j, Parent, Ancestor) ;
176  }
177  }
178  }
179 
180  }
181  else if (stype == 0)
182  {
183 
184  /* ------------------------------------------------------------------ */
185  /* unsymmetric case: compute etree (A'*A) */
186  /* ------------------------------------------------------------------ */
187 
188  Prev = Iwork + ncol ; /* size nrow (i/i/l) */
189  for (i = 0 ; i < nrow ; i++)
190  {
191  Prev [i] = EMPTY ;
192  }
193  for (j = 0 ; j < ncol ; j++)
194  {
195  /* for each row i in column j of A */
196  p = Ap [j] ;
197  pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
198  for ( ; p < pend ; p++)
199  {
200  /* a graph is constructed dynamically with one path per row
201  * of A. If the ith row of A contains column indices
202  * (j1,j2,j3,j4) then the new graph has edges (j1,j2), (j2,j3),
203  * and (j3,j4). When at node i of this path-graph, all edges
204  * (jprev,j) are considered, where jprev<j */
205  i = Ai [p] ;
206  jprev = Prev [i] ;
207  if (jprev != EMPTY)
208  {
209  amesos_update_etree (jprev, j, Parent, Ancestor) ;
210  }
211  Prev [i] = j ;
212  }
213  }
214 
215  }
216  else
217  {
218 
219  /* ------------------------------------------------------------------ */
220  /* symmetric case with lower triangular part not supported */
221  /* ------------------------------------------------------------------ */
222 
223  ERROR (CHOLMOD_INVALID, "symmetric lower not supported") ;
224  return (FALSE) ;
225  }
226 
227  ASSERT (CHOLMOD(dump_parent) (Parent, ncol, "Parent", Common)) ;
228  return (TRUE) ;
229 }
230 #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)
#define CHOLMOD_INVALID
#define CHOLMOD_OK
static void amesos_update_etree(Int k, Int i, Int Parent[], Int Ancestor[])
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