Exemple #1
0
        // breadth-first search for coarse decomposition (C0,C1,R1 or R0,R3,C3)
        private bool BreadthFirstSearch(SymbolicColumnStorage A, int n, int[] wi, int[] wj, int[] queue,
                                        int[] jimatch, int imatch_offset, int jmatch_offset, int mark)
        {
            // cs_bfs
            int[] Ap, Ai;
            int   head = 0, tail = 0, j, i, p, j2;

            for (j = 0; j < n; j++) // place all unmatched nodes in queue
            {
                if (jimatch[imatch_offset + j] >= 0)
                {
                    continue;      // skip j if matched
                }
                wj[j]         = 0; // j in set C0 (R0 if transpose)
                queue[tail++] = j; // place unmatched col j in queue
            }
            if (tail == 0)
            {
                return(true);           // quick return if no unmatched nodes
            }
            // Transpose if requested
            SymbolicColumnStorage C = (mark == 1) ? A.Clone() : A.Transpose();

            if (C == null)
            {
                return(false);           // bfs of C=A' to find R3,C3 from R0
            }
            Ap = C.ColumnPointers;
            Ai = C.RowIndices;
            while (head < tail)    // while queue is not empty
            {
                j = queue[head++]; // get the head of the queue
                for (p = Ap[j]; p < Ap[j + 1]; p++)
                {
                    i = Ai[p];
                    if (wi[i] >= 0)
                    {
                        continue;                       // skip if i is marked
                    }
                    wi[i] = mark;                       // i in set R1 (C3 if transpose)
                    j2    = jimatch[jmatch_offset + i]; // traverse alternating path to j2
                    if (wj[j2] >= 0)
                    {
                        continue;         // skip j2 if it is marked
                    }
                    wj[j2]        = mark; // j2 in set C1 (R3 if transpose)
                    queue[tail++] = j2;   // add j2 to queue
                }
            }
            //if (mark != 1) SparseMatrix.spfree(C); // free A' if it was created
            return(true);
        }
        /// <summary>
        /// Find a maximum transveral (zero-free diagonal). Seed optionally selects a
        /// randomized algorithm.
        /// </summary>
        /// <param name="A">column-compressed matrix</param>
        /// <param name="seed">0: natural, -1: reverse, randomized otherwise</param>
        /// <returns>row and column matching, size m+n</returns>
        public static int[] Generate(SymbolicColumnStorage A, int seed)
        {
            int i, j, k, p, n2 = 0, m2 = 0;

            int[] jimatch, w, cheap, js, iss, ps, Cp, q;

            int n = A.ColumnCount;
            int m = A.RowCount;

            int[] Ap = A.ColumnPointers;
            int[] Ai = A.RowIndices;

            //[jmatch [0..m-1]; imatch [0..n-1]]
            w = jimatch = new int[m + n];  // allocate result

            for (k = 0, j = 0; j < n; j++) // count nonempty rows and columns
            {
                n2 += (Ap[j] < Ap[j + 1]) ? 1 : 0;
                for (p = Ap[j]; p < Ap[j + 1]; p++)
                {
                    w[Ai[p]] = 1;
                    k       += (j == Ai[p]) ? 1 : 0; // count entries already on diagonal
                }
            }


            if (k == Math.Min(m, n)) // quick return if diagonal zero-free
            {
                for (i = 0; i < k; i++)
                {
                    jimatch[i] = i;
                }
                for (; i < m; i++)
                {
                    jimatch[i] = -1;
                }
                for (j = 0; j < k; j++)
                {
                    jimatch[m + j] = j;
                }
                for (; j < n; j++)
                {
                    jimatch[m + j] = -1;
                }

                return(jimatch);
            }

            for (i = 0; i < m; i++)
            {
                m2 += w[i];
            }

            // Transpose if needed
            SymbolicColumnStorage C = (m2 < n2) ? A.Transpose() : A.Clone();

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

            n  = C.ColumnCount;
            m  = C.RowCount;
            Cp = C.ColumnPointers;

            int jmatch_offset = (m2 < n2) ? n : 0;
            int imatch_offset = (m2 < n2) ? 0 : m;

            w = new int[n]; // get workspace

            cheap = new int[n];
            js    = new int[n];
            iss   = new int[n];
            ps    = new int[n];

            for (j = 0; j < n; j++)
            {
                cheap[j] = Cp[j];                     // for cheap assignment
            }
            for (j = 0; j < n; j++)
            {
                w[j] = -1;                     // all columns unflagged
            }
            for (i = 0; i < m; i++)
            {
                jimatch[jmatch_offset + i] = -1; // nothing matched yet
            }
            q = Permutation.Create(n, seed);     // q = random permutation
            for (k = 0; k < n; k++)              // augment, starting at column q[k]
            {
                Augment(q[k], C.ColumnPointers, C.RowIndices, jimatch, jmatch_offset, cheap, w, js, iss, ps);
            }

            for (j = 0; j < n; j++)
            {
                jimatch[imatch_offset + j] = -1; // find row match
            }

            for (i = 0; i < m; i++)
            {
                if (jimatch[jmatch_offset + i] >= 0)
                {
                    jimatch[imatch_offset + jimatch[jmatch_offset + i]] = i;
                }
            }

            return(jimatch);
        }