Blender V2.61 - r43446
|
00001 00005 /* Elimination tree computation and layout routines */ 00006 00007 #include <stdio.h> 00008 #include <stdlib.h> 00009 #include "ssp_defs.h" 00010 00011 /* 00012 * Implementation of disjoint set union routines. 00013 * Elements are integers in 0..n-1, and the 00014 * names of the sets themselves are of type int. 00015 * 00016 * Calls are: 00017 * initialize_disjoint_sets (n) initial call. 00018 * s = make_set (i) returns a set containing only i. 00019 * s = link (t, u) returns s = t union u, destroying t and u. 00020 * s = find (i) return name of set containing i. 00021 * finalize_disjoint_sets final call. 00022 * 00023 * This implementation uses path compression but not weighted union. 00024 * See Tarjan's book for details. 00025 * John Gilbert, CMI, 1987. 00026 * 00027 * Implemented path-halving by XSL 07/05/95. 00028 */ 00029 00030 static int *pp; /* parent array for sets */ 00031 00032 static 00033 int *mxCallocInt(int n) 00034 { 00035 register int i; 00036 int *buf; 00037 00038 buf = (int *) SUPERLU_MALLOC( n * sizeof(int) ); 00039 if ( !buf ) { 00040 ABORT("SUPERLU_MALLOC fails for buf in mxCallocInt()"); 00041 } 00042 for (i = 0; i < n; i++) buf[i] = 0; 00043 return (buf); 00044 } 00045 00046 static 00047 void initialize_disjoint_sets ( 00048 int n 00049 ) 00050 { 00051 pp = mxCallocInt(n); 00052 } 00053 00054 00055 static 00056 int make_set ( 00057 int i 00058 ) 00059 { 00060 pp[i] = i; 00061 return i; 00062 } 00063 00064 00065 static 00066 int link ( 00067 int s, 00068 int t 00069 ) 00070 { 00071 pp[s] = t; 00072 return t; 00073 } 00074 00075 00076 /* PATH HALVING */ 00077 static 00078 int find (int i) 00079 { 00080 register int p, gp; 00081 00082 p = pp[i]; 00083 gp = pp[p]; 00084 while (gp != p) { 00085 pp[i] = gp; 00086 i = gp; 00087 p = pp[i]; 00088 gp = pp[p]; 00089 } 00090 return (p); 00091 } 00092 00093 #if 0 00094 /* PATH COMPRESSION */ 00095 static 00096 int find ( 00097 int i 00098 ) 00099 { 00100 if (pp[i] != i) 00101 pp[i] = find (pp[i]); 00102 return pp[i]; 00103 } 00104 #endif 00105 00106 static 00107 void finalize_disjoint_sets ( 00108 void 00109 ) 00110 { 00111 SUPERLU_FREE(pp); 00112 } 00113 00114 00115 /* 00116 * Find the elimination tree for A'*A. 00117 * This uses something similar to Liu's algorithm. 00118 * It runs in time O(nz(A)*log n) and does not form A'*A. 00119 * 00120 * Input: 00121 * Sparse matrix A. Numeric values are ignored, so any 00122 * explicit zeros are treated as nonzero. 00123 * Output: 00124 * Integer array of parents representing the elimination 00125 * tree of the symbolic product A'*A. Each vertex is a 00126 * column of A, and nc means a root of the elimination forest. 00127 * 00128 * John R. Gilbert, Xerox, 10 Dec 1990 00129 * Based on code by JRG dated 1987, 1988, and 1990. 00130 */ 00131 00132 /* 00133 * Nonsymmetric elimination tree 00134 */ 00135 int 00136 sp_coletree( 00137 int *acolst, int *acolend, /* column start and end past 1 */ 00138 int *arow, /* row indices of A */ 00139 int nr, int nc, /* dimension of A */ 00140 int *parent /* parent in elim tree */ 00141 ) 00142 { 00143 int *root; /* root of subtee of etree */ 00144 int *firstcol; /* first nonzero col in each row*/ 00145 int rset, cset; 00146 int row, col; 00147 int rroot; 00148 int p; 00149 00150 root = mxCallocInt (nc); 00151 initialize_disjoint_sets (nc); 00152 00153 /* Compute firstcol[row] = first nonzero column in row */ 00154 00155 firstcol = mxCallocInt (nr); 00156 for (row = 0; row < nr; firstcol[row++] = nc); 00157 for (col = 0; col < nc; col++) 00158 for (p = acolst[col]; p < acolend[col]; p++) { 00159 row = arow[p]; 00160 firstcol[row] = SUPERLU_MIN(firstcol[row], col); 00161 } 00162 00163 /* Compute etree by Liu's algorithm for symmetric matrices, 00164 except use (firstcol[r],c) in place of an edge (r,c) of A. 00165 Thus each row clique in A'*A is replaced by a star 00166 centered at its first vertex, which has the same fill. */ 00167 00168 for (col = 0; col < nc; col++) { 00169 cset = make_set (col); 00170 root[cset] = col; 00171 parent[col] = nc; /* Matlab */ 00172 for (p = acolst[col]; p < acolend[col]; p++) { 00173 row = firstcol[arow[p]]; 00174 if (row >= col) continue; 00175 rset = find (row); 00176 rroot = root[rset]; 00177 if (rroot != col) { 00178 parent[rroot] = col; 00179 cset = link (cset, rset); 00180 root[cset] = col; 00181 } 00182 } 00183 } 00184 00185 SUPERLU_FREE (root); 00186 SUPERLU_FREE (firstcol); 00187 finalize_disjoint_sets (); 00188 return 0; 00189 } 00190 00191 /* 00192 * q = TreePostorder (n, p); 00193 * 00194 * Postorder a tree. 00195 * Input: 00196 * p is a vector of parent pointers for a forest whose 00197 * vertices are the integers 0 to n-1; p[root]==n. 00198 * Output: 00199 * q is a vector indexed by 0..n-1 such that q[i] is the 00200 * i-th vertex in a postorder numbering of the tree. 00201 * 00202 * ( 2/7/95 modified by X.Li: 00203 * q is a vector indexed by 0:n-1 such that vertex i is the 00204 * q[i]-th vertex in a postorder numbering of the tree. 00205 * That is, this is the inverse of the previous q. ) 00206 * 00207 * In the child structure, lower-numbered children are represented 00208 * first, so that a tree which is already numbered in postorder 00209 * will not have its order changed. 00210 * 00211 * Written by John Gilbert, Xerox, 10 Dec 1990. 00212 * Based on code written by John Gilbert at CMI in 1987. 00213 */ 00214 00215 static int *first_kid, *next_kid; /* Linked list of children. */ 00216 static int *post, postnum; 00217 00218 static 00219 /* 00220 * Depth-first search from vertex v. 00221 */ 00222 void etdfs ( 00223 int v 00224 ) 00225 { 00226 int w; 00227 00228 for (w = first_kid[v]; w != -1; w = next_kid[w]) { 00229 etdfs (w); 00230 } 00231 /* post[postnum++] = v; in Matlab */ 00232 post[v] = postnum++; /* Modified by X.Li on 2/14/95 */ 00233 } 00234 00235 00236 /* 00237 * Post order a tree 00238 */ 00239 int *TreePostorder( 00240 int n, 00241 int *parent 00242 ) 00243 { 00244 int v, dad; 00245 00246 /* Allocate storage for working arrays and results */ 00247 first_kid = mxCallocInt (n+1); 00248 next_kid = mxCallocInt (n+1); 00249 post = mxCallocInt (n+1); 00250 00251 /* Set up structure describing children */ 00252 for (v = 0; v <= n; first_kid[v++] = -1); 00253 for (v = n-1; v >= 0; v--) { 00254 dad = parent[v]; 00255 next_kid[v] = first_kid[dad]; 00256 first_kid[dad] = v; 00257 } 00258 00259 /* Depth-first search from dummy root vertex #n */ 00260 postnum = 0; 00261 etdfs (n); 00262 00263 SUPERLU_FREE (first_kid); 00264 SUPERLU_FREE (next_kid); 00265 return post; 00266 } 00267 00268 00269 /* 00270 * p = spsymetree (A); 00271 * 00272 * Find the elimination tree for symmetric matrix A. 00273 * This uses Liu's algorithm, and runs in time O(nz*log n). 00274 * 00275 * Input: 00276 * Square sparse matrix A. No check is made for symmetry; 00277 * elements below and on the diagonal are ignored. 00278 * Numeric values are ignored, so any explicit zeros are 00279 * treated as nonzero. 00280 * Output: 00281 * Integer array of parents representing the etree, with n 00282 * meaning a root of the elimination forest. 00283 * Note: 00284 * This routine uses only the upper triangle, while sparse 00285 * Cholesky (as in spchol.c) uses only the lower. Matlab's 00286 * dense Cholesky uses only the upper. This routine could 00287 * be modified to use the lower triangle either by transposing 00288 * the matrix or by traversing it by rows with auxiliary 00289 * pointer and link arrays. 00290 * 00291 * John R. Gilbert, Xerox, 10 Dec 1990 00292 * Based on code by JRG dated 1987, 1988, and 1990. 00293 * Modified by X.S. Li, November 1999. 00294 */ 00295 00296 /* 00297 * Symmetric elimination tree 00298 */ 00299 int 00300 sp_symetree( 00301 int *acolst, int *acolend, /* column starts and ends past 1 */ 00302 int *arow, /* row indices of A */ 00303 int n, /* dimension of A */ 00304 int *parent /* parent in elim tree */ 00305 ) 00306 { 00307 int *root; /* root of subtree of etree */ 00308 int rset, cset; 00309 int row, col; 00310 int rroot; 00311 int p; 00312 00313 root = mxCallocInt (n); 00314 initialize_disjoint_sets (n); 00315 00316 for (col = 0; col < n; col++) { 00317 cset = make_set (col); 00318 root[cset] = col; 00319 parent[col] = n; /* Matlab */ 00320 for (p = acolst[col]; p < acolend[col]; p++) { 00321 row = arow[p]; 00322 if (row >= col) continue; 00323 rset = find (row); 00324 rroot = root[rset]; 00325 if (rroot != col) { 00326 parent[rroot] = col; 00327 cset = link (cset, rset); 00328 root[cset] = col; 00329 } 00330 } 00331 } 00332 SUPERLU_FREE (root); 00333 finalize_disjoint_sets (); 00334 return 0; 00335 } /* SP_SYMETREE */