$search
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 }