cs_dmperm.c
Go to the documentation of this file.
00001 #include "cs.h"
00002 /* breadth-first search for coarse decomposition (C0,C1,R1 or R0,R3,C3) */
00003 static int cs_bfs (const cs *A, int n, int *wi, int *wj, int *queue,
00004     const int *imatch, const int *jmatch, int mark)
00005 {
00006     int *Ap, *Ai, head = 0, tail = 0, j, i, p, j2 ;
00007     cs *C ;
00008     for (j = 0 ; j < n ; j++)           /* place all unmatched nodes in queue */
00009     {
00010         if (imatch [j] >= 0) continue ; /* skip j if matched */
00011         wj [j] = 0 ;                    /* j in set C0 (R0 if transpose) */
00012         queue [tail++] = j ;            /* place unmatched col j in queue */
00013     }
00014     if (tail == 0) return (1) ;         /* quick return if no unmatched nodes */
00015     C = (mark == 1) ? ((cs *) A) : cs_transpose (A, 0) ;
00016     if (!C) return (0) ;                /* bfs of C=A' to find R3,C3 from R0 */
00017     Ap = C->p ; Ai = C->i ;
00018     while (head < tail)                 /* while queue is not empty */
00019     {
00020         j = queue [head++] ;            /* get the head of the queue */
00021         for (p = Ap [j] ; p < Ap [j+1] ; p++)
00022         {
00023             i = Ai [p] ;
00024             if (wi [i] >= 0) continue ; /* skip if i is marked */
00025             wi [i] = mark ;             /* i in set R1 (C3 if transpose) */
00026             j2 = jmatch [i] ;           /* traverse alternating path to j2 */
00027             if (wj [j2] >= 0) continue ;/* skip j2 if it is marked */
00028             wj [j2] = mark ;            /* j2 in set C1 (R3 if transpose) */
00029             queue [tail++] = j2 ;       /* add j2 to queue */
00030         }
00031     }
00032     if (mark != 1) cs_spfree (C) ;      /* free A' if it was created */
00033     return (1) ;
00034 }
00035 
00036 /* collect matched rows and columns into p and q */
00037 static void cs_matched (int n, const int *wj, const int *imatch, int *p, int *q,
00038     int *cc, int *rr, int set, int mark)
00039 {
00040     int kc = cc [set], j ;
00041     int kr = rr [set-1] ;
00042     for (j = 0 ; j < n ; j++)
00043     {
00044         if (wj [j] != mark) continue ;      /* skip if j is not in C set */
00045         p [kr++] = imatch [j] ;
00046         q [kc++] = j ;
00047     }
00048     cc [set+1] = kc ;
00049     rr [set] = kr ;
00050 }
00051 
00052 /* collect unmatched rows into the permutation vector p */
00053 static void cs_unmatched (int m, const int *wi, int *p, int *rr, int set)
00054 {
00055     int i, kr = rr [set] ;
00056     for (i = 0 ; i < m ; i++) if (wi [i] == 0) p [kr++] = i ;
00057     rr [set+1] = kr ;
00058 }
00059 
00060 /* return 1 if row i is in R2 */
00061 static int cs_rprune (int i, int j, double aij, void *other)
00062 {
00063     int *rr = (int *) other ;
00064     return (i >= rr [1] && i < rr [2]) ;
00065 }
00066 
00067 /* Given A, compute coarse and then fine dmperm */
00068 csd *cs_dmperm (const cs *A, int seed)
00069 {
00070     int m, n, i, j, k, cnz, nc, *jmatch, *imatch, *wi, *wj, *pinv, *Cp, *Ci,
00071         *ps, *rs, nb1, nb2, *p, *q, *cc, *rr, *r, *s, ok ;
00072     cs *C ;
00073     csd *D, *scc ;
00074     /* --- Maximum matching ------------------------------------------------- */
00075     if (!CS_CSC (A)) return (NULL) ;            /* check inputs */
00076     m = A->m ; n = A->n ;
00077     D = cs_dalloc (m, n) ;                      /* allocate result */
00078     if (!D) return (NULL) ;
00079     p = D->p ; q = D->q ; r = D->r ; s = D->s ; cc = D->cc ; rr = D->rr ;
00080     jmatch = cs_maxtrans (A, seed) ;            /* max transversal */
00081     imatch = jmatch + m ;                       /* imatch = inverse of jmatch */
00082     if (!jmatch) return (cs_ddone (D, NULL, jmatch, 0)) ;
00083     /* --- Coarse decomposition --------------------------------------------- */
00084     wi = r ; wj = s ;                           /* use r and s as workspace */
00085     for (j = 0 ; j < n ; j++) wj [j] = -1 ;     /* unmark all cols for bfs */
00086     for (i = 0 ; i < m ; i++) wi [i] = -1 ;     /* unmark all rows for bfs */
00087     cs_bfs (A, n, wi, wj, q, imatch, jmatch, 1) ;       /* find C1, R1 from C0*/
00088     ok = cs_bfs (A, m, wj, wi, p, jmatch, imatch, 3) ;  /* find R3, C3 from R0*/
00089     if (!ok) return (cs_ddone (D, NULL, jmatch, 0)) ;
00090     cs_unmatched (n, wj, q, cc, 0) ;                    /* unmatched set C0 */
00091     cs_matched (n, wj, imatch, p, q, cc, rr, 1, 1) ;    /* set R1 and C1 */
00092     cs_matched (n, wj, imatch, p, q, cc, rr, 2, -1) ;   /* set R2 and C2 */
00093     cs_matched (n, wj, imatch, p, q, cc, rr, 3, 3) ;    /* set R3 and C3 */
00094     cs_unmatched (m, wi, p, rr, 3) ;                    /* unmatched set R0 */
00095     cs_free (jmatch) ;
00096     /* --- Fine decomposition ----------------------------------------------- */
00097     pinv = cs_pinv (p, m) ;         /* pinv=p' */
00098     if (!pinv) return (cs_ddone (D, NULL, NULL, 0)) ;
00099     C = cs_permute (A, pinv, q, 0) ;/* C=A(p,q) (it will hold A(R2,C2)) */
00100     cs_free (pinv) ;
00101     if (!C) return (cs_ddone (D, NULL, NULL, 0)) ;
00102     Cp = C->p ;
00103     nc = cc [3] - cc [2] ;          /* delete cols C0, C1, and C3 from C */
00104     if (cc [2] > 0) for (j = cc [2] ; j <= cc [3] ; j++) Cp [j-cc[2]] = Cp [j] ;
00105     C->n = nc ;
00106     if (rr [2] - rr [1] < m)        /* delete rows R0, R1, and R3 from C */
00107     {
00108         cs_fkeep (C, cs_rprune, rr) ;
00109         cnz = Cp [nc] ;
00110         Ci = C->i ;
00111         if (rr [1] > 0) for (k = 0 ; k < cnz ; k++) Ci [k] -= rr [1] ;
00112     }
00113     C->m = nc ;
00114     scc = cs_scc (C) ;              /* find strongly connected components of C*/
00115     if (!scc) return (cs_ddone (D, C, NULL, 0)) ;
00116     /* --- Combine coarse and fine decompositions --------------------------- */
00117     ps = scc->p ;                   /* C(ps,ps) is the permuted matrix */
00118     rs = scc->r ;                   /* kth block is rs[k]..rs[k+1]-1 */
00119     nb1 = scc->nb  ;                /* # of blocks of A(R2,C2) */
00120     for (k = 0 ; k < nc ; k++) wj [k] = q [ps [k] + cc [2]] ;
00121     for (k = 0 ; k < nc ; k++) q [k + cc [2]] = wj [k] ;
00122     for (k = 0 ; k < nc ; k++) wi [k] = p [ps [k] + rr [1]] ;
00123     for (k = 0 ; k < nc ; k++) p [k + rr [1]] = wi [k] ;
00124     nb2 = 0 ;                       /* create the fine block partitions */
00125     r [0] = s [0] = 0 ;
00126     if (cc [2] > 0) nb2++ ;         /* leading coarse block A (R1, [C0 C1]) */
00127     for (k = 0 ; k < nb1 ; k++)     /* coarse block A (R2,C2) */
00128     {
00129         r [nb2] = rs [k] + rr [1] ; /* A (R2,C2) splits into nb1 fine blocks */
00130         s [nb2] = rs [k] + cc [2] ;
00131         nb2++ ;
00132     }
00133     if (rr [2] < m)
00134     {
00135         r [nb2] = rr [2] ;          /* trailing coarse block A ([R3 R0], C3) */
00136         s [nb2] = cc [3] ;
00137         nb2++ ;
00138     }
00139     r [nb2] = m ;
00140     s [nb2] = n ;
00141     D->nb = nb2 ;
00142     cs_dfree (scc) ;
00143     return (cs_ddone (D, C, NULL, 1)) ;
00144 }


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:30:59