示例#1
0
        /// <summary>
        /// Compute coarse and then fine Dulmage-Mendelsohn decomposition. seed
        /// optionally selects a randomized algorithm.
        /// </summary>
        /// <param name="A">column-compressed matrix</param>
        /// <param name="seed">0: natural, -1: reverse, random order oterwise</param>
        /// <returns>Dulmage-Mendelsohn analysis, null on error</returns>
        public static Decomposition Analyse(Matrix A, int seed)
        {
            int i, j, k, cnz, nc, nb1, nb2;

            int[] Cp, ps, rs;
            bool  ok;

            // Maximum matching
            int m = A.m;
            int n = A.n;

            Decomposition D = new Decomposition(m, n); // allocate result

            int[] p  = D.p;
            int[] q  = D.q;
            int[] r  = D.r;
            int[] s  = D.s;
            int[] cc = D.cc;
            int[] rr = D.rr;

            int[] jimatch = MaximumTransveral(A, seed); // max transversal

            if (jimatch == null)
            {
                return(null);
            }

            // Coarse decomposition
            for (j = 0; j < n; j++)
            {
                s[j] = -1;                     // unmark all cols for bfs
            }
            for (i = 0; i < m; i++)
            {
                r[i] = -1;                                            // unmark all rows for bfs
            }
            BreadthFirstSearch(A, n, r, s, q, jimatch, m, 0, 1);      // find C1, R1 from C0*/
            ok = BreadthFirstSearch(A, m, s, r, p, jimatch, 0, m, 3); // find R3, C3 from R0*/

            if (!ok)
            {
                return(null);
            }

            Unmatched(n, s, q, cc, 0);                      // unmatched set C0
            Matched(n, s, jimatch, m, p, q, cc, rr, 1, 1);  // set R1 and C1
            Matched(n, s, jimatch, m, p, q, cc, rr, 2, -1); // set R2 and C2
            Matched(n, s, jimatch, m, p, q, cc, rr, 3, 3);  // set R3 and C3
            Unmatched(m, r, p, rr, 3);                      // unmatched set R0

            // Fine decomposition
            int[] pinv = Common.InversePermutation(p, m); // pinv=p'

            Matrix C = A.Permute(pinv, q, false);         // C=A(p,q) (it will hold A(R2,C2))

            Cp = C.p;
            nc = cc[3] - cc[2]; // delete cols C0, C1, and C3 from C
            if (cc[2] > 0)
            {
                for (j = cc[2]; j <= cc[3]; j++)
                {
                    Cp[j - cc[2]] = Cp[j];
                }
            }
            C.n = nc;
            if (rr[2] - rr[1] < m) // delete rows R0, R1, and R3 from C
            {
                C.KeepSymbolic(RowPrune, rr);
                cnz = Cp[nc];
                int[] Ci = C.i;
                if (rr[1] > 0)
                {
                    for (k = 0; k < cnz; k++)
                    {
                        Ci[k] -= rr[1];
                    }
                }
            }
            C.m = nc;
            Decomposition scc = FindScc(C); // find strongly connected components of C*/

            // Combine coarse and fine decompositions
            ps  = scc.p;  // C(ps,ps) is the permuted matrix
            rs  = scc.r;  // kth block is rs[k]..rs[k+1]-1
            nb1 = scc.nb; // # of blocks of A(R2,C2)
            for (k = 0; k < nc; k++)
            {
                s[k] = q[ps[k] + cc[2]];
            }
            for (k = 0; k < nc; k++)
            {
                q[k + cc[2]] = s[k];
            }
            for (k = 0; k < nc; k++)
            {
                r[k] = p[ps[k] + rr[1]];
            }
            for (k = 0; k < nc; k++)
            {
                p[k + rr[1]] = r[k];
            }
            nb2  = 0; // create the fine block partitions
            r[0] = s[0] = 0;
            if (cc[2] > 0)
            {
                nb2++;                  // leading coarse block A (R1, [C0 C1])
            }
            for (k = 0; k < nb1; k++)   // coarse block A (R2,C2)
            {
                r[nb2] = rs[k] + rr[1]; // A (R2,C2) splits into nb1 fine blocks
                s[nb2] = rs[k] + cc[2];
                nb2++;
            }
            if (rr[2] < m)
            {
                r[nb2] = rr[2]; // trailing coarse block A ([R3 R0], C3)
                s[nb2] = cc[3];
                nb2++;
            }
            r[nb2] = m;
            s[nb2] = n;
            D.nb   = nb2;

            return(D);
        }
示例#2
0
        /// <summary>
        /// Finds the strongly connected components of a square matrix.
        /// </summary>
        /// <param name="A">column-compressed matrix (A.p modified then restored)</param>
        /// <returns>strongly connected components, null on error</returns>
        static Decomposition FindScc(Matrix A)
        {
            // matrix A temporarily modified, then restored

            int n, i, k, b, nb = 0, top;

            int[]  xi, p, r, Ap, ATp;
            Matrix AT;

            n  = A.n;
            Ap = A.p;

            AT  = A.Transpose(false); // AT = A'
            ATp = AT.p;

            xi = new int[2 * n + 1];                   // get workspace

            Decomposition D = new Decomposition(n, 0); // allocate result

            p = D.p;
            r = D.r;

            top = n;
            for (i = 0; i < n; i++) // first dfs(A) to find finish times (xi)
            {
                if (!(Ap[i] < 0))
                {
                    top = Common.DepthFirstSearch(i, A, top, xi, xi, n, null);
                }
            }
            for (i = 0; i < n; i++)
            {
                //CS_MARK(Ap, i);
                Ap[i] = -(Ap[i]) - 2; // restore A; unmark all nodes
            }
            top = n;
            nb  = n;
            for (k = 0; k < n; k++) // dfs(A') to find strongly connnected comp
            {
                i = xi[k];          // get i in reverse order of finish times
                if (ATp[i] < 0)
                {
                    continue;  // skip node i if already ordered
                }
                r[nb--] = top; // node i is the start of a component in p
                top     = Common.DepthFirstSearch(i, AT, top, p, xi, n, null);
            }
            r[nb] = 0; // first block starts at zero; shift r up
            for (k = nb; k <= n; k++)
            {
                r[k - nb] = r[k];
            }
            D.nb = nb = n - nb;      // nb = # of strongly connected components
            for (b = 0; b < nb; b++) // sort each block in natural order
            {
                for (k = r[b]; k < r[b + 1]; k++)
                {
                    xi[p[k]] = b;
                }
            }
            for (b = 0; b <= nb; b++)
            {
                xi[n + b] = r[b];
            }
            for (i = 0; i < n; i++)
            {
                p[xi[n + xi[i]]++] = i;
            }
            return(D);
        }