예제 #1
0
        /// <summary>
        /// Ordering and symbolic analysis for a Cholesky factorization
        /// </summary>
        /// <param name="order"></param>
        /// <param name="A"></param>
        /// <returns></returns>
        static SymbolicFactorization SymbolicAnalysis(int order, SparseMatrix A)
        {
            int n = A.n;

            int[] c, post, P;

            SymbolicFactorization S = new SymbolicFactorization(); // allocate result S

            P      = Ordering.AMD(order, A);                       // P = amd(A+A'), or natural
            S.pinv = Common.InversePermutation(P, n);              // find inverse permutation

            if (order != 0 && S.pinv == null)
            {
                return(null);
            }

            SparseMatrix C = A.PermuteSym(S.pinv, false);             // C = spones(triu(A(P,P)))

            S.parent = Common.EliminationTree(C, false);              // find etree of C
            post     = Common.TreePostorder(S.parent, n);             // postorder the etree
            c        = Common.ColumnCounts(C, S.parent, post, false); // find column counts of chol(C)

            S.cp  = new int[n + 1];                                   // allocate result S.cp
            S.unz = S.lnz = Common.CumulativeSum(S.cp, c, n);         // find column pointers for L

            return(S);
        }
예제 #2
0
        /// <summary>
        /// Compute the Numeric Cholesky factorization, L = chol (A, [pinv parent cp]).
        /// </summary>
        /// <returns>Numeric Cholesky factorization</returns>
        public static NumericFactorization Factorize(SparseMatrix A, SymbolicFactorization S)
        {
            double d, lki;

            double[] Lx, x, Cx;
            int      top, i, p, k;

            int[] Li, Lp, cp, pinv, s, c, parent, Cp, Ci;

            SparseMatrix         L, C;
            NumericFactorization N = new NumericFactorization(); // allocate result

            int n = A.n;

            c = new int[n];    // get int workspace
            s = new int[n];
            x = new double[n]; // get double workspace

            cp     = S.cp;
            pinv   = S.pinv;
            parent = S.parent;

            C = pinv != null?A.PermuteSym(pinv, true) : A;

            Cp = C.p;
            Ci = C.i;
            Cx = C.x;

            N.L = L = new SparseMatrix(n, n, cp[n], true); // allocate result
            Lp  = L.p;
            Li  = L.i;
            Lx  = L.x;

            for (k = 0; k < n; k++)
            {
                Lp[k] = c[k] = cp[k];
            }
            for (k = 0; k < n; k++) // compute L(k,:) for L*L' = C
            {
                // Nonzero pattern of L(k,:)
                top  = Common.EReach(C, k, parent, s, c); // find pattern of L(k,:)
                x[k] = 0;                                 // x (0:k) is now zero
                for (p = Cp[k]; p < Cp[k + 1]; p++)       // x = full(triu(C(:,k)))
                {
                    if (Ci[p] <= k)
                    {
                        x[Ci[p]] = Cx[p];
                    }
                }
                d    = x[k]; // d = C(k,k)
                x[k] = 0;    // clear x for k+1st iteration

                // Triangular solve
                for (; top < n; top++)       // solve L(0:k-1,0:k-1) * x = C(:,k)
                {
                    i    = s[top];           // s [top..n-1] is pattern of L(k,:)
                    lki  = x[i] / Lx[Lp[i]]; // L(k,i) = x (i) / L(i,i)
                    x[i] = 0;                // clear x for k+1st iteration
                    for (p = Lp[i] + 1; p < c[i]; p++)
                    {
                        x[Li[p]] -= Lx[p] * lki;
                    }
                    d    -= lki * lki; // d = d - L(k,i)*L(k,i)
                    p     = c[i]++;
                    Li[p] = k;         // store L(k,i) in column i
                    Lx[p] = lki;
                }
                // Compute L(k,k)
                if (d <= 0)
                {
                    return(null); // not pos def
                }

                p     = c[k]++;
                Li[p] = k; // store L(k,k) = sqrt (d) in column k
                Lx[p] = Math.Sqrt(d);
            }
            Lp[n] = cp[n]; // finalize L

            return(N);     // success
        }