private bool performDecomposition(DMatrixSparseCSC A)
        {
            int[]    c = TriangularSolver_DSCC.adjust(gw, N);
            int[]    s = TriangularSolver_DSCC.adjust(gs, N);
            double[] x = TriangularSolver_DSCC.adjust(gx, N);

            Array.Copy(L.col_idx, 0, c, 0, N);

            for (int k = 0; k < N; k++)
            {
                //----  Nonzero pattern of L(k,:)
                int top = TriangularSolver_DSCC.searchNzRowsElim(A, k, parent, s, c);

                // x(0:k) is now zero
                x[k] = 0;
                int idx0 = A.col_idx[k];
                int idx1 = A.col_idx[k + 1];

                // x = full(triu(C(:,k)))
                for (int q = idx0; q < idx1; q++)
                {
                    if (A.nz_rows[q] <= k)
                    {
                        x[A.nz_rows[q]] = A.nz_values[q];
                    }
                }
                double d = x[k]; // d = C(k,k)
                x[k] = 0;        // clear x for k+1 iteration

                //---- Triangular Solve
                for (; top < N; top++)
                {
                    int    i   = s[top];
                    double lki = x[i] / L.nz_values[L.col_idx[i]]; // L(k,i) = x(i) / L(i,i)
                    x[i] = 0;
                    for (int r = L.col_idx[i] + 1; r < c[i]; r++)
                    {
                        x[L.nz_rows[r]] -= L.nz_values[r] * lki;
                    }
                    d -= lki * lki;     // d = d - L(k,i)**L(k,i)
                    int t = c[i]++;
                    L.nz_rows[t]   = k; // store L(k,i) in column i
                    L.nz_values[t] = lki;
                }

                //----- Compute L(k,k)
                if (d <= 0)
                {
                    // it's not positive definite
                    return(false);
                }
                int p = c[k]++;
                L.nz_rows[p]   = k;
                L.nz_values[p] = Math.Sqrt(d);
            }

            return(true);
        }
        public void performSymbolic(DMatrixSparseCSC A)
        {
            init(A.numCols);

            TriangularSolver_DSCC.eliminationTree(A, false, parent, gw);
            TriangularSolver_DSCC.postorder(parent, N, post, gw);
            columnCounter.process(A, parent, post, counts);
            L.reshape(A.numRows, A.numCols, 0);
            L.colsum(counts);
        }
 /**
  * Count the number of non-zero elements in R
  */
 void countNonZeroInR(int[] parent)
 {
     TriangularSolver_DSCC.postorder(parent, n, post, gwork);
     columnCounts.process(A, parent, post, countsR);
     nz_in_R = 0;
     for (int k = 0; k < n; k++)
     {
         nz_in_R += countsR[k];
     }
     if (nz_in_R < 0)
     {
         throw new InvalidOperationException("Too many elements. Numerical overflow in R counts");
     }
 }
Exemple #4
0
        //@Override
        public void solve(DMatrixRMaj B, DMatrixRMaj X)
        {
            double[] b  = TriangularSolver_DSCC.adjust(gb, B.numRows);
            double[] bp = TriangularSolver_DSCC.adjust(gbp, B.numRows);
            double[] x  = TriangularSolver_DSCC.adjust(gx, X.numRows);

            int[] pinv = qr.getStructure().getPinv();

            // process each column in X and B individually
            for (int colX = 0; colX < X.numCols; colX++)
            {
                int index = colX;
                for (int i = 0; i < B.numRows; i++, index += X.numCols)
                {
                    b[i] = B.data[index];
                }

                // apply row pivots
                CommonOps_DSCC.permuteInv(pinv, b, bp, m);

                // apply Householder reflectors
                for (int j = 0; j < n; j++)
                {
                    QrHelperFunctions_DSCC.applyHouseholder(qr.getV(), j, qr.getBeta(j), bp);
                }
                // Solve for R*x = b
                TriangularSolver_DSCC.solveU(qr.getR(), bp);

                // undo the permutation
                double[] output;
                if (qr.isFillPermutated())
                {
                    CommonOps_DSCC.permute(qr.getFillPermutation(), bp, x, X.numRows);
                    output = x;
                }
                else
                {
                    output = bp;
                }

                index = colX;
                for (int i = 0; i < X.numRows; i++, index += X.numCols)
                {
                    X.data[index] = output[i];
                }
            }
        }
        //@Override
        public void solve(DMatrixRMaj B, DMatrixRMaj X)
        {
//        if( B.numCols != X.numCols || B.numRows != numRows || X.numRows != numCols) {
//            throw new ArgumentException("Unexpected matrix size");
//        }

            int[]    pinv = decomposition.getPinv();
            int[]    q    = decomposition.getReducePermutation();
            double[] x    = TriangularSolver_DSCC.adjust(gx, X.numRows);
            double[] b    = TriangularSolver_DSCC.adjust(gb, B.numRows);

            DMatrixSparseCSC L = decomposition.getL();
            DMatrixSparseCSC U = decomposition.getU();

            bool reduceFill = decomposition.getReduceFill() != null;

            // process each column in X and B individually
            for (int colX = 0; colX < X.numCols; colX++)
            {
                int index = colX;
                for (int i = 0; i < B.numRows; i++, index += X.numCols)
                {
                    b[i] = B.data[index];
                }

                CommonOps_DSCC.permuteInv(pinv, b, x, X.numRows);
                TriangularSolver_DSCC.solveL(L, x);
                TriangularSolver_DSCC.solveU(U, x);
                double[] d;
                if (reduceFill)
                {
                    CommonOps_DSCC.permute(q, x, b, X.numRows);
                    d = b;
                }
                else
                {
                    d = x;
                }
                index = colX;
                for (int i = 0; i < X.numRows; i++, index += X.numCols)
                {
                    X.data[index] = d[i];
                }
            }
        }
Exemple #6
0
        public static void main(string[] args)
        {
            // create a random matrix that can be solved
            int N = 5;
            IMersenneTwister rand = new MersenneTwisterFast(234);

            DMatrixSparseCSC A = RandomMatrices_DSCC.rectangle(N, N, N * N / 4, rand);

            RandomMatrices_DSCC.ensureNotSingular(A, rand);

            // Create the LU decomposition
            LUSparseDecomposition_F64 <DMatrixSparseCSC> decompose =
                DecompositionFactory_DSCC.lu(FillReducing.NONE);

            // Decompose the matrix.
            // If you care about the A matrix being modified call decompose.inputModified()
            if (!decompose.decompose(A))
            {
                throw new InvalidOperationException("The matrix is singular");
            }

            // Extract new copies of the L and U matrices
            DMatrixSparseCSC L = decompose.getLower(null);
            DMatrixSparseCSC U = decompose.getUpper(null);
            DMatrixSparseCSC P = decompose.getRowPivot(null);

            // Storage for an intermediate step
            DMatrixSparseCSC tmp = (DMatrixSparseCSC)A.createLike();

            // Storage for the inverse matrix
            DMatrixSparseCSC Ainv = (DMatrixSparseCSC)A.createLike();

            // Solve for the inverse: P*I = L*U*inv(A)
            TriangularSolver_DSCC.solve(L, true, P, tmp, null, null, null);
            TriangularSolver_DSCC.solve(U, false, tmp, Ainv, null, null, null);

            // Make sure the inverse has been found. A*inv(A) = identity should be an identity matrix
            DMatrixSparseCSC found = (DMatrixSparseCSC)A.createLike();

            CommonOps_DSCC.mult(A, Ainv, found);
            found.print();
        }
Exemple #7
0
        //@Override
        public void solve(DMatrixRMaj B, DMatrixRMaj X)
        {
            DMatrixSparseCSC L = cholesky.getL();

            int N = L.numRows;

            double[] b = TriangularSolver_DSCC.adjust(gb, N);
            double[] x = TriangularSolver_DSCC.adjust(gx, N);

            int[] Pinv = reduce.getArrayPinv();

            for (int col = 0; col < B.numCols; col++)
            {
                int index = col;
                for (int i = 0; i < N; i++, index += B.numCols)
                {
                    b[i] = B.data[index];
                }

                if (Pinv != null)
                {
                    CommonOps_DSCC.permuteInv(Pinv, b, x, N);
                    TriangularSolver_DSCC.solveL(L, x);
                    TriangularSolver_DSCC.solveTranL(L, x);
                    CommonOps_DSCC.permute(Pinv, x, b, N);
                }
                else
                {
                    TriangularSolver_DSCC.solveL(L, b);
                    TriangularSolver_DSCC.solveTranL(L, b);
                }

                index = col;
                for (int i = 0; i < N; i++, index += X.numCols)
                {
                    X.data[index] = b[i];
                }
            }
        }
        /**
         * Examins the structure of A for QR decomposition
         * @param A matrix which is to be decomposed
         * @return true if the solution is valid or false if the decomposition can't be performed (i.e. requires column pivots)
         */
        public bool process(DMatrixSparseCSC A)
        {
            init(A);

            TriangularSolver_DSCC.eliminationTree(A, true, parent, gwork);

            countNonZeroInR(parent);
            countNonZeroInV(parent);

            // if more columns than rows it's possible that Q*R != A. That's because a householder
            // would need to be created that's outside the  m by m Q matrix. In reality it has
            // a partial solution. Column pivot are needed.
            if (m < n)
            {
                for (int row = 0; row < m; row++)
                {
                    if (gwork.data[head + row] < 0)
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Exemple #9
0
 //@Override
 public /**/ double quality()
 {
     return(TriangularSolver_DSCC.qualityTriangular(qr.getR()));
 }
Exemple #10
0
        /**
         * Applies the permutation to upper triangular symmetric matrices. Typically a symmetric matrix only stores the
         * upper triangular part, so normal permutation will have undesirable results, e.g. the zeros will get mixed
         * in and will no longer be symmetric. This algorithm will handle the implicit lower triangular and construct
         * new upper triangular matrix.
         *
         * <p>See page cs_symperm() on Page 22 of "Direct Methods for Sparse Linear Systems"</p>
         *
         * @param input (Input) Upper triangular symmetric matrix which is to be permuted.
         *              Entries below the diagonal are ignored.
         * @param permInv (Input) Inverse permutation vector.  Specifies new order of the rows and columns.
         * @param output (Output) Upper triangular symmetric matrix which has the permutation stored in it.  Reshaped.
         * @param gw (Optional) Storage for internal workspace.  Can be null.
         */
        public static void permuteSymmetric(DMatrixSparseCSC input, int[] permInv, DMatrixSparseCSC output,
                                            IGrowArray gw)
        {
            if (input.numRows != input.numCols)
            {
                throw new ArgumentException("Input must be a square matrix");
            }
            if (input.numRows != permInv.Length)
            {
                throw new ArgumentException("Number of column in input must match length of permInv");
            }
            if (input.numCols != permInv.Length)
            {
                throw new ArgumentException("Number of rows in input must match length of permInv");
            }

            int N = input.numCols;

            int[] w = TriangularSolver_DSCC.adjustClear(gw, N); // histogram with column counts

            output.reshape(N, N, 0);
            output.indicesSorted = false;
            output.col_idx[0]    = 0;

            // determine column counts for output
            for (int j = 0; j < N; j++)
            {
                int j2   = permInv[j];
                int idx0 = input.col_idx[j];
                int idx1 = input.col_idx[j + 1];

                for (int p = idx0; p < idx1; p++)
                {
                    int i = input.nz_rows[p];
                    if (i > j) // ignore the lower triangular portion
                    {
                        continue;
                    }
                    int i2 = permInv[i];

                    w[i2 > j2 ? i2 : j2]++;
                }
            }

            // update structure of output
            output.colsum(w);

            for (int j = 0; j < N; j++)
            {
                // column j of Input is row j2 of Output
                int j2   = permInv[j];
                int idx0 = input.col_idx[j];
                int idx1 = input.col_idx[j + 1];

                for (int p = idx0; p < idx1; p++)
                {
                    int i = input.nz_rows[p];
                    if (i > j) // ignore the lower triangular portion
                    {
                        continue;
                    }

                    int i2 = permInv[i];
                    // row i of Input is row i2 of Output
                    int q = w[i2 > j2 ? i2 : j2]++;
                    output.nz_rows[q]   = i2 < j2 ? i2 : j2;
                    output.nz_values[q] = input.nz_values[p];
                }
            }
        }
Exemple #11
0
        private bool performLU(DMatrixSparseCSC A)
        {
            int m = A.numRows;
            int n = A.numCols;

            int[] q = applyReduce.getArrayP();

            // main loop for computing L and U
            for (int k = 0; k < n; k++)
            {
                //--------- Triangular Solve
                L.col_idx[k] = L.nz_length; // start of column k
                U.col_idx[k] = U.nz_length;

                // grow storage in L and U if needed
                if (L.nz_length + n > L.nz_values.Length)
                {
                    L.growMaxLength(2 * L.nz_values.Length + n, true);
                }
                if (U.nz_length + n > U.nz_values.Length)
                {
                    U.growMaxLength(2 * U.nz_values.Length + n, true);
                }

                int   col = q != null ? q[k] : k;
                int   top = TriangularSolver_DSCC.solve(L, true, A, col, x, pinv, gxi, gw);
                int[] xi  = gxi.data;

                //--------- Find the Next Pivot. That will be the row with the largest value
                //
                int    ipiv = -1;
                double a    = -double.MaxValue;
                for (int p = top; p < n; p++)
                {
                    int i = xi[p]; // x(i) is nonzero
                    if (pinv[i] < 0)
                    {
                        double t;
                        if ((t = Math.Abs(x[i])) > a)
                        {
                            a    = t;
                            ipiv = i;
                        }
                    }
                    else
                    {
                        U.nz_rows[U.nz_length]     = pinv[i];
                        U.nz_values[U.nz_length++] = x[i];
                    }
                }
                if (ipiv == -1 || a <= 0)
                {
                    singular = true;
                    return(false);
                }

                // NOTE: The line is commented out below. It can cause a poor pivot to be selected. Instead of the largest
                //       row it will pick whatever is in this column. it does try to make sure it's not zero, but I'm not
                //       sure what it's purpose is.
//            if( pinv[col] < 0 && Math.Abs(x[col]) >= a*tol ) {
//                ipiv = col;
//            }

                //---------- Divide by the pivot
                double pivot = x[ipiv];
                U.nz_rows[U.nz_length]     = k;
                U.nz_values[U.nz_length++] = pivot; // last entry in U(:k) us U(k,k)
                pinv[ipiv]                 = k;
                L.nz_rows[L.nz_length]     = ipiv;  // First entry L(:,k) is L(k,k) = 1
                L.nz_values[L.nz_length++] = 1;

                for (int p = top; p < n; p++)
                {
                    int i = xi[p];
                    if (pinv[i] < 0)
                    {
                        // x(i) is entry in L(:,k)
                        L.nz_rows[L.nz_length]     = i;
                        L.nz_values[L.nz_length++] = x[i] / pivot;
                    }
                    x[i] = 0;
                }
            }
            //----------- Finalize L and U
            L.col_idx[n] = L.nz_length;
            U.col_idx[n] = U.nz_length;
            for (int p = 0; p < L.nz_length; p++)
            {
                L.nz_rows[p] = pinv[L.nz_rows[p]];
            }

//        Console.WriteLine("  reduce "+(reduceFill!=null));
//        System.out.print("  pinv[ ");
//        for (int i = 0; i < A.numCols; i++) {
//            System.out.printf("%2d ",pinv[i]);
//        }
//        Console.WriteLine(" ]");

            return(true);
        }
 //@Override
 public double quality()
 {
     return(TriangularSolver_DSCC.qualityTriangular(decomposition.getU()));
 }
Exemple #13
0
 //@Override
 public double quality()
 {
     return(TriangularSolver_DSCC.qualityTriangular(cholesky.getL()));
 }