Esempio n. 1
0
        /// <summary>
        /// Convert a coordinate storage to compressed sparse column (CSC) format.
        /// </summary>
        /// <param name="storage">Coordinate storage.</param>
        /// <param name="cleanup">Remove and sum duplicate entries.</param>
        /// <returns>Compressed sparse column storage.</returns>
        public static CompressedColumnStorage <T> ToCompressedColumnStorage <T>(CoordinateStorage <T> storage,
                                                                                bool cleanup = true) where T : struct, IEquatable <T>, IFormattable
        {
            int nrows = storage.RowCount;
            int ncols = storage.ColumnCount;

            var values = storage.Values;
            var rowind = storage.RowIndices;
            var colind = storage.ColumnIndices;

            int p, k, nz = storage.NonZerosCount;

            var columnPointers = new int[ncols + 1];
            var columnCounts   = new int[ncols];

            for (k = 0; k < nz; k++)
            {
                // Count columns
                columnCounts[colind[k]]++;
            }

            // Get row pointers
            int valueCount = Helper.CumulativeSum(columnPointers, columnCounts, ncols);

            var result = CompressedColumnStorage <T> .Create(nrows, ncols);

            var rowIndices    = new int[valueCount];
            var storageValues = new T[valueCount];

            for (k = 0; k < nz; k++)
            {
                p                = columnCounts[colind[k]]++;
                rowIndices[p]    = rowind[k];
                storageValues[p] = values[k];
            }

            result.RowIndices     = rowIndices;
            result.ColumnPointers = columnPointers;
            result.Values         = storageValues;

            result.SortIndices();

            if (cleanup)
            {
                result.Cleanup();
            }

            return(result);
        }
Esempio n. 2
0
        /// <summary>
        /// Compute the numeric LDL' factorization of PAP'.
        /// </summary>
        void Factorize(CompressedColumnStorage <double> A)
        {
            int n = A.ColumnCount;

            var ap = A.ColumnPointers;
            var ai = A.RowIndices;
            var ax = A.Values;

            int[] parent = S.parent;
            int[] P      = S.q;
            int[] Pinv   = S.pinv;

            this.D = new double[n];
            this.L = CompressedColumnStorage <double> .Create(n, n, S.cp[n]);

            Array.Copy(S.cp, L.ColumnPointers, n + 1);

            var lp = L.ColumnPointers;
            var li = L.RowIndices;
            var lx = L.Values;

            // Workspace
            var y       = new double[n];
            var pattern = new int[n];
            var flag    = new int[n];
            var lnz     = new int[n];

            double yi, l_ki;
            int    i, k, p, kk, p2, len, top;

            for (k = 0; k < n; k++)
            {
                // compute nonzero Pattern of kth row of L, in topological order
                y[k]    = 0.0;                        // Y(0:k) is now all zero
                top     = n;                          // stack for pattern is empty
                flag[k] = k;                          // mark node k as visited
                lnz[k]  = 0;                          // count of nonzeros in column k of L
                kk      = (P != null) ? (P[k]) : (k); // kth original, or permuted, column
                p2      = ap[kk + 1];
                for (p = ap[kk]; p < p2; p++)
                {
                    i = (Pinv != null) ? (Pinv[ai[p]]) : (ai[p]); // get A(i,k)
                    if (i <= k)
                    {
                        y[i] += ax[p]; // scatter A(i,k) into Y (sum duplicates)
                        for (len = 0; flag[i] != k; i = parent[i])
                        {
                            pattern[len++] = i; // L(k,i) is nonzero
                            flag[i]        = k; // mark i as visited
                        }
                        while (len > 0)
                        {
                            pattern[--top] = pattern[--len];
                        }
                    }
                }

                // compute numerical values kth row of L (a sparse triangular solve)
                D[k] = y[k]; // get D(k,k) and clear Y(k)
                y[k] = 0.0;
                for (; top < n; top++)
                {
                    i    = pattern[top]; // Pattern [top:n-1] is pattern of L(:,k)
                    yi   = y[i];         // get and clear Y(i)
                    y[i] = 0.0;
                    p2   = lp[i] + lnz[i];
                    for (p = lp[i]; p < p2; p++)
                    {
                        y[li[p]] -= lx[p] * yi;
                    }
                    l_ki  = yi / D[i]; // the nonzero entry L(k,i)
                    D[k] -= l_ki * yi;
                    li[p] = k;         // store L(k,i) in column form of L
                    lx[p] = l_ki;
                    lnz[i]++;          // increment count of nonzeros in col i
                }

                if (D[k] == 0.0)
                {
                    // failure, D(k,k) is zero
                    throw new Exception("Diagonal element is zero.");
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Sparse QR factorization [V,beta,pinv,R] = qr(A)
        /// </summary>
        protected void Factorize(CompressedColumnStorage <T> A, IProgress progress)
        {
            T zero = Helper.ZeroOf <T>();

            int i, p, p1, top, len, col;

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

            var ap = A.ColumnPointers;
            var ai = A.RowIndices;
            var ax = A.Values;

            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
            T[]   x = new T[m2];       // get double workspace

            int s = m2;                // offset into w

            // Allocate result V, R and beta
            var V = this.Q = CompressedColumnStorage <T> .Create(m2, n, vnz);

            var R = this.R = CompressedColumnStorage <T> .Create(m2, n, rnz);

            var b = this.beta = new double[n];

            var rp = R.ColumnPointers;
            var ri = R.RowIndices;
            var rx = R.Values;

            var vp = V.ColumnPointers;
            var vi = V.RowIndices;
            var vx = V.Values;

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

            double current = 0.0;
            double step    = n / 100.0;

            rnz = 0; vnz = 0;
            for (int k = 0; k < n; k++) // compute V and R
            {
                // Progress reporting.
                if (k >= current)
                {
                    current += step;

                    if (progress != null)
                    {
                        progress.Report(k / (double)n);
                    }
                }

                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, b[i], x); // apply (V(i),Beta(i)) to x
                    ri[rnz]   = i;                   // R(i,k) = x(i)
                    rx[rnz++] = x[i];
                    x[i]      = zero;
                    if (parent[i] == k)
                    {
                        vnz = V.Scatter(i, zero, w, null, k, V, vnz);
                    }
                }
                for (p = p1; p < vnz; p++) // gather V(:,k) = x
                {
                    vx[p]    = x[vi[p]];
                    x[vi[p]] = zero;
                }
                ri[rnz]   = k;                                             // R(k,k) = norm (x)
                rx[rnz++] = CreateHouseholder(vx, p1, ref b[k], vnz - p1); // [v,beta]=house(x)
            }

            rp[n] = rnz; // finalize R
            vp[n] = vnz; // finalize V
        }
Esempio n. 4
0
        /// <summary>
        /// Compute the Numeric Cholesky factorization, L = chol (A, [pinv parent cp]).
        /// </summary>
        /// <returns>Numeric Cholesky factorization</returns>
        private void Factorize(CompressedColumnStorage <Complex> A, IProgress <double> progress)
        {
            Complex d, lki;
            int     top, i, p, k, cci;

            int n = A.ColumnCount;

            // Allocate workspace.
            var c = new int[n];
            var s = new int[n];

            var x = this.temp;

            var colp   = S.cp;
            var pinv   = S.pinv;
            var parent = S.parent;

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

            var cp = C.ColumnPointers;
            var ci = C.RowIndices;
            var cx = C.Values;

            this.L = CompressedColumnStorage <Complex> .Create(n, n, colp[n]);

            var lp = L.ColumnPointers;
            var li = L.RowIndices;
            var lx = L.Values;

            for (k = 0; k < n; k++)
            {
                lp[k] = c[k] = colp[k];
            }

            double current = 0.0;
            double step    = n / 100.0;

            for (k = 0; k < n; k++) // compute L(k,:) for L*L' = C
            {
                // Progress reporting.
                if (k >= current)
                {
                    current += step;

                    if (progress != null)
                    {
                        progress.Report(k / (double)n);
                    }
                }

                // Find nonzero pattern of L(k,:)
                top  = GraphHelper.EtreeReach(SymbolicColumnStorage.Create(C, false), k, parent, s, c);
                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
                    cci  = c[i];
                    for (p = lp[i] + 1; p < cci; 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)
                {
                    throw new Exception(Resources.MatrixSymmetricPositiveDefinite);
                }

                p     = c[k]++;
                li[p] = k; // store L(k,k) = sqrt (d) in column k
                lx[p] = Complex.Sqrt(d);
            }
            lp[n] = colp[n]; // finalize L
        }
Esempio n. 5
0
        /// <summary>
        /// Compute the Numeric Cholesky factorization, L = chol (A, [pinv parent cp]).
        /// </summary>
        /// <returns>Numeric Cholesky factorization</returns>
        private void Factorize(CompressedColumnStorage <double> A)
        {
            double d, lki;
            int    top, i, p, k;

            int n = A.ColumnCount;

            // Allocate workspace.
            var c = new int[n];
            var s = new int[n];
            var x = new double[n];

            var colp   = symFactor.cp;
            var pinv   = symFactor.pinv;
            var parent = symFactor.parent;

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

            var cp = C.ColumnPointers;
            var ci = C.RowIndices;
            var cx = C.Values;

            this.L = CompressedColumnStorage <double> .Create(n, n, colp[n]);

            var lp = L.ColumnPointers;
            var li = L.RowIndices;
            var lx = L.Values;

            //var lst = new List<int>();

            var percent = 0;

            for (k = 0; k < n; k++)
            {
                lp[k] = c[k] = colp[k];
            }
            for (k = 0; k < n; k++) // compute L(k,:) for L*L' = C
            {
                if (100 * k / n != percent)
                {
                    Progress = percent = (100 * k) / n;

                    //Console.WriteLine("{0}% solve", percent);
                }

                // Find nonzero pattern of L(k,:)
                top  = GraphHelper.EtreeReach(SymbolicColumnStorage.Create(C, false), k, parent, s, c);
                x[k] = 0;                           // x (0:k) is now zero

                var tmp = cp[k + 1];
                for (p = cp[k]; p < tmp; 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

                    p = lp[i] + 1;

                    var cci = c[i];
                    for (p = lp[i] + 1; p < cci; 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)
                {
                    throw new NotPositiveDefiniteException("not pos def"); // TODO: ex
                }

                p     = c[k]++;
                li[p] = k; // store L(k,k) = sqrt (d) in column k
                lx[p] = Math.Sqrt(d);
            }

            lp[n] = colp[n]; // finalize L
        }
Esempio n. 6
0
        /// <summary>
        /// [L,U,pinv] = lu(A, [q lnz unz]). lnz and unz can be guess.
        /// </summary>
        private void Factorize(CompressedColumnStorage <Complex> A, double tol, IProgress <double> progress)
        {
            int[] q = S.q;

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

            this.L = CompressedColumnStorage <Complex> .Create(n, n, lnz);

            this.U = CompressedColumnStorage <Complex> .Create(n, n, unz);

            this.pinv = new int[n];

            // Workspace
            var x  = this.temp;
            var xi = new int[2 * n];

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

            lnz = unz = 0;

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

            int[]     li, ui;
            int[]     lp = L.ColumnPointers;
            int[]     up = U.ColumnPointers;
            Complex[] lx, ux;

            double current = 0.0;
            double step    = n / 100.0;

            // Now compute L(:,k) and U(:,k)
            for (int k = 0; k < n; k++)
            {
                // Progress reporting.
                if (k >= current)
                {
                    current += step;

                    if (progress != null)
                    {
                        progress.Report(k / (double)n);
                    }
                }

                // Triangular solve
                lp[k] = lnz; // L(:,k) starts here
                up[k] = unz; // U(:,k) starts here

                if (lnz + n > L.Values.Length)
                {
                    L.Resize(2 * L.Values.Length + n);
                }
                if (unz + n > U.Values.Length)
                {
                    U.Resize(2 * U.Values.Length + n);
                }

                li  = L.RowIndices;
                ui  = U.RowIndices;
                lx  = L.Values;
                ux  = U.Values;
                col = q != null ? (q[k]) : k;
                top = 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.0)
                {
                    throw new Exception("No pivot element found.");
                }

                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.0;
                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.0;                   // x [0..n-1] = 0 for next k
                }
            }

            // Finalize L and U
            lp[n] = lnz;
            up[n] = unz;
            li    = L.RowIndices; // fix row indices of L for final pinv
            for (p = 0; p < lnz; p++)
            {
                li[p] = pinv[li[p]];
            }

            // Remove extra space from L and U
            L.Resize(0);
            U.Resize(0);
        }
Esempio n. 7
0
        /// <summary>
        /// Convert a coordinate storage to compressed sparse column (CSC) format.
        /// </summary>
        /// <param name="storage">Coordinate storage.</param>
        /// <param name="cleanup">Remove and sum duplicate entries.</param>
        /// <param name="inplace">Do the conversion in place (re-using the coordinate storage arrays).</param>
        /// <returns>Compressed sparse column storage.</returns>
        internal static CompressedColumnStorage <T> ToCompressedColumnStorage_ <T>(CoordinateStorage <T> storage,
                                                                                   bool cleanup = true, bool inplace = false) where T : struct, IEquatable <T>, IFormattable
        {
            int nrows = storage.RowCount;
            int ncols = storage.ColumnCount;

            int nz = storage.NonZerosCount;

            var result = CompressedColumnStorage <T> .Create(nrows, ncols);

            var ap = result.ColumnPointers = new int[ncols + 1];

            if (nz == 0)
            {
                return(result);
            }

            var values = storage.Values;
            var rowind = storage.RowIndices;
            var colind = storage.ColumnIndices;

            if (inplace)
            {
                ConvertInPlace(ncols, nz, values, rowind, colind, ap);

                result.RowIndices = rowind;
                result.Values     = values;

                // Make sure the data can't be accessed through the coordinate storage.
                storage.Invalidate();
            }
            else
            {
                var columnCounts = new int[ncols];

                for (int k = 0; k < nz; k++)
                {
                    // Count columns
                    columnCounts[colind[k]]++;
                }

                // Get column pointers
                int valueCount = Helper.CumulativeSum(ap, columnCounts, ncols);

                var ai = new int[valueCount];
                var ax = new T[valueCount];

                for (int k = 0; k < nz; k++)
                {
                    int p = columnCounts[colind[k]]++;
                    ai[p] = rowind[k];
                    ax[p] = values[k];
                }

                result.RowIndices = ai;
                result.Values     = ax;
            }

            Helper.SortIndices(result);

            if (cleanup)
            {
                result.Cleanup();
            }

            return(result);
        }