/// <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); }
/// <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 }