Blender V2.61 - r43446

sp_coletree.c

Go to the documentation of this file.
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 */