Beispiel #1
0
        /// <summary>
        /// Symbolic ordering and analysis for QR.
        /// </summary>
        /// <param name="A">Matrix to factorize.</param>
        /// <param name="p">Permutation.</param>
        protected void SymbolicAnalysis(CompressedColumnStorage <T> A, int[] p, bool natural)
        {
            int m = A.RowCount;
            int n = A.ColumnCount;

            var sym = this.S = new SymbolicFactorization();

            // Fill-reducing ordering
            sym.q = p;

            var C = natural ? SymbolicColumnStorage.Create(A) : Permute(A, null, sym.q);

            // etree of C'*C, where C=A(:,q)
            sym.parent = GraphHelper.EliminationTree(m, n, C.ColumnPointers, C.RowIndices, true);
            int[] post = GraphHelper.TreePostorder(sym.parent, n);
            sym.cp = GraphHelper.ColumnCounts(C, sym.parent, post, true); // col counts chol(C'*C)

            bool ok = C != null && sym.parent != null && sym.cp != null && CountV(C, sym);

            if (ok)
            {
                sym.unz = 0;
                for (int k = 0; k < n; k++)
                {
                    sym.unz += sym.cp[k];
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Compute nnz(V) = S.lnz, S.pinv, S.leftmost, S.m2 from A and S.parent
        /// </summary>
        private bool CountV(SymbolicColumnStorage A, SymbolicFactorization S)
        {
            int i, k, p, pa;

            int[] pinv, leftmost, parent = S.parent;

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

            int[] ap = A.ColumnPointers;
            int[] ai = A.RowIndices;

            S.pinv     = pinv = new int[m + n]; // allocate pinv,
            S.leftmost = leftmost = new int[m]; // and leftmost

            var w    = new int[m];              // get workspace
            var head = new int[n];
            var tail = new int[n];
            var nque = new int[n]; // Initialized to 0's

            for (k = 0; k < n; k++)
            {
                head[k] = -1;                     // queue k is empty
            }
            for (k = 0; k < n; k++)
            {
                tail[k] = -1;
            }
            for (i = 0; i < m; i++)
            {
                leftmost[i] = -1;
            }
            for (k = n - 1; k >= 0; k--)
            {
                for (p = ap[k]; p < ap[k + 1]; p++)
                {
                    leftmost[ai[p]] = k; // leftmost[i] = min(find(A(i,:)))
                }
            }
            for (i = m - 1; i >= 0; i--) // scan rows in reverse order
            {
                pinv[i] = -1;            // row i is not yet ordered
                k       = leftmost[i];
                if (k == -1)
                {
                    continue;          // row i is empty
                }
                if (nque[k]++ == 0)
                {
                    tail[k] = i;   // first row in queue k
                }
                w[i]    = head[k]; // put i at head of queue k
                head[k] = i;
            }
            S.lnz = 0;
            S.m2  = m;
            for (k = 0; k < n; k++) // find row permutation and nnz(V)
            {
                i = head[k];        // remove row i from queue k
                S.lnz++;            // count V(k,k) as nonzero
                if (i < 0)
                {
                    i = S.m2++; // add a fictitious row
                }
                pinv[i] = k;    // associate row i with V(:,k)
                if (--nque[k] <= 0)
                {
                    continue;               // skip if V(k+1:m,k) is empty
                }
                S.lnz += nque[k];           // nque [k] is nnz (V(k+1:m,k))
                if ((pa = parent[k]) != -1) // move all rows to parent of k
                {
                    if (nque[pa] == 0)
                    {
                        tail[pa] = tail[k];
                    }
                    w[tail[k]] = head[pa];
                    head[pa]   = w[i];
                    nque[pa]  += nque[k];
                }
            }
            for (i = 0; i < m; i++)
            {
                if (pinv[i] < 0)
                {
                    pinv[i] = k++;
                }
            }

            return(true);
        }