예제 #1
0
        /// <summary>
        /// Sparse QR factorization [V,beta,pinv,R] = qr (A)
        /// </summary>
        static NumericFactorization Factorize(SparseMatrix A, SymbolicFactorization S)
        {
            double[] Beta;
            int      i, p, p1, top, len, col;

            int m = A.m;
            int n = A.n;

            int[]     Ap = A.p;
            int[]     Ai = A.i;
            Complex[] Ax = A.x;

            int[] q      = S.q;
            int[] parent = S.parent;
            int[] pinv   = S.pinv;
            int   m2     = S.m2;

            int vnz = S.lnz;
            int rnz = S.unz;

            int[] leftmost = S.leftmost;

            int[]     w = new int[m2 + n]; // get int workspace
            Complex[] x = new Complex[m2]; // get double workspace

            int s = m2;                    // offset into w

            SparseMatrix         R, V;
            NumericFactorization N = new NumericFactorization(); // allocate result

            N.L = V = new SparseMatrix(m2, n, vnz, true);        // allocate result V
            N.U = R = new SparseMatrix(m2, n, rnz, true);        // allocate result R
            N.B = Beta = new double[n];                          // allocate result Beta

            int[]     Rp = R.p;
            int[]     Ri = R.i;
            Complex[] Rx = R.x;

            int[]     Vp = V.p;
            int[]     Vi = V.i;
            Complex[] Vx = V.x;

            for (i = 0; i < m2; i++)
            {
                w[i] = -1; // clear w, to mark nodes
            }

            rnz = 0; vnz = 0;
            for (int k = 0; k < n; k++) // compute V and R
            {
                Rp[k]     = rnz;        // R(:,k) starts here
                Vp[k]     = p1 = vnz;   // V(:,k) starts here
                w[k]      = k;          // add V(k,k) to pattern of V
                Vi[vnz++] = k;
                top       = n;
                col       = q != null ? q[k] : k;
                for (p = Ap[col]; p < Ap[col + 1]; p++)     // find R(:,k) pattern
                {
                    i = leftmost[Ai[p]];                    // i = min(find(A(i,q)))
                    for (len = 0; w[i] != k; i = parent[i]) // traverse up to k
                    {
                        //len++;
                        w[s + len++] = i;
                        w[i]         = k;
                    }
                    while (len > 0)
                    {
                        --top;
                        --len;
                        w[s + top] = w[s + len]; // push path on stack
                    }
                    i    = pinv[Ai[p]];          // i = permuted row of A(:,col)
                    x[i] = Ax[p];                // x (i) = A(:,col)
                    if (i > k && w[i] < k)       // pattern of V(:,k) = x (k+1:m)
                    {
                        Vi[vnz++] = i;           // add i to pattern of V(:,k)
                        w[i]      = k;
                    }
                }
                for (p = top; p < n; p++)               // for each i in pattern of R(:,k)
                {
                    i = w[s + p];                       // R(i,k) is nonzero
                    ApplyHouseholder(V, i, Beta[i], x); // apply (V(i),Beta(i)) to x
                    Ri[rnz]   = i;                      // R(i,k) = x(i)
                    Rx[rnz++] = x[i];
                    x[i]      = 0;
                    if (parent[i] == k)
                    {
                        vnz = V.Scatter(i, 0, w, null, k, V, vnz);
                    }
                }
                for (p = p1; p < vnz; p++) // gather V(:,k) = x
                {
                    Vx[p]    = x[Vi[p]];
                    x[Vi[p]] = 0;
                }
                Ri[rnz]   = k;                                                // R(k,k) = norm (x)
                Rx[rnz++] = CreateHouseholder(Vx, p1, ref Beta[k], vnz - p1); // [v,beta]=house(x)
            }
            Rp[n] = rnz;                                                      // finalize R
            Vp[n] = vnz;                                                      // finalize V

            return(N);                                                        // success
        }
예제 #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)
        {
            Complex d, lki;

            Complex[] 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 Complex[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 * Complex.Conjugate(lki); // d = d - L(k,i)*L(k,i)
                    p     = c[i]++;
                    Li[p] = k;                            // store L(k,i) in column i
                    Lx[p] = Complex.Conjugate(lki);
                }
                // Compute L(k,k)
                if (d.Real <= 0 || d.Imaginary != 0)
                {
                    return(null); // not pos def
                }

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

            return(N);     // success
        }
예제 #3
0
        // [L,U,pinv]=lu(A, [q lnz unz]). lnz and unz can be guess
        static NumericFactorization Factorize(SparseMatrix A, SymbolicFactorization S, double tol)
        {
            int i, n = A.n;

            int[] q = S.q;

            int lnz = S.lnz;
            int unz = S.unz;

            int[] pinv;

            NumericFactorization N = new NumericFactorization(); // allocate result

            SparseMatrix L, U;

            N.L    = L = new SparseMatrix(n, n, lnz, true); // allocate result L
            N.U    = U = new SparseMatrix(n, n, unz, true); // allocate result U
            N.pinv = pinv = new int[n];                     // allocate result pinv

            Complex[] x  = new Complex[n];                  // get double workspace
            int[]     xi = new int[2 * n];                  // get int workspace

            for (i = 0; i < n; i++)
            {
                pinv[i] = -1; // no rows pivotal yet
            }

            lnz = unz = 0;

            int     ipiv, top, p, col;
            Complex pivot;
            double  a, t;

            int[]     Li, Ui, Lp = L.p, Up = U.p;
            Complex[] Lx, Ux;

            for (int k = 0; k < n; k++) // compute L(:,k) and U(:,k)
            {
                // Triangular solve
                Lp[k] = lnz; // L(:,k) starts here
                Up[k] = unz; // U(:,k) starts here
                if ((lnz + n > L.nzmax && !L.Resize(2 * L.nzmax + n)) ||
                    (unz + n > U.nzmax && !U.Resize(2 * U.nzmax + n)))
                {
                    return(null);
                }
                Li  = L.i;
                Lx  = L.x;
                Ui  = U.i;
                Ux  = U.x;
                col = q != null ? (q[k]) : k;
                top = Triangular.SolveSp(L, A, col, xi, x, pinv, true);  // x = L\A(:,col)

                // Find pivot
                ipiv = -1;
                a    = -1;
                for (p = top; p < n; p++)
                {
                    i = xi[p];       // x(i) is nonzero
                    if (pinv[i] < 0) // row i is not yet pivotal
                    {
                        if ((t = Complex.Abs(x[i])) > a)
                        {
                            a    = t; // largest pivot candidate so far
                            ipiv = i;
                        }
                    }
                    else // x(i) is the entry U(pinv[i],k)
                    {
                        Ui[unz]   = pinv[i];
                        Ux[unz++] = x[i];
                    }
                }
                if (ipiv == -1 || a <= 0)
                {
                    return(null);
                }

                if (pinv[col] < 0 && Complex.Abs(x[col]) >= a * tol)
                {
                    ipiv = col;
                }

                // Divide by pivot
                pivot      = x[ipiv];     // the chosen pivot
                Ui[unz]    = k;           // last entry in U(:,k) is U(k,k)
                Ux[unz++]  = pivot;
                pinv[ipiv] = k;           // ipiv is the kth pivot row
                Li[lnz]    = ipiv;        // first entry in L(:,k) is L(k,k) = 1
                Lx[lnz++]  = 1;
                for (p = top; p < n; p++) // L(k+1:n,k) = x / pivot
                {
                    i = xi[p];
                    if (pinv[i] < 0)              // x(i) is an entry in L(:,k)
                    {
                        Li[lnz]   = i;            // save unpermuted row in L
                        Lx[lnz++] = x[i] / pivot; // scale pivot column
                    }
                    x[i] = 0;                     // x [0..n-1] = 0 for next k
                }
            }

            // Finalize L and U
            Lp[n] = lnz;
            Up[n] = unz;
            Li    = L.i; // fix row indices of L for final pinv
            for (p = 0; p < lnz; p++)
            {
                Li[p] = pinv[Li[p]];
            }
            L.Resize(0); // remove extra space from L and U
            U.Resize(0);

            return(N); // success
        }