コード例 #1
0
        public virtual void invert(DMatrixRBlock A_inv)
        {
            DMatrixRBlock T = decomposer.getT(null);

            if (A_inv.numRows != T.numRows || A_inv.numCols != T.numCols)
            {
                throw new ArgumentException("Unexpected number or rows and/or columns");
            }


            if (temp == null || temp.Length < blockLength * blockLength)
            {
                temp = new double[blockLength * blockLength];
            }

            // zero the upper triangular portion of A_inv
            MatrixOps_DDRB.zeroTriangle(true, A_inv);

            DSubmatrixD1 L = new DSubmatrixD1(T);
            DSubmatrixD1 B = new DSubmatrixD1(A_inv);

            // invert L from cholesky decomposition and write the solution into the lower
            // triangular portion of A_inv
            // B = inv(L)
            TriangularSolver_DDRB.invert(blockLength, false, L, B, temp);

            // B = L^-T * B
            // todo could speed up by taking advantage of B being lower triangular
            // todo take advantage of symmetry
            TriangularSolver_DDRB.solveL(blockLength, L, B, true);
        }
コード例 #2
0
        public virtual bool decompose(DMatrixRMaj A)
        {
            Ablock.numRows     = A.numRows;
            Ablock.numCols     = A.numCols;
            Ablock.blockLength = blockLength;
            Ablock.data        = A.data;

            int tmpLength = Math.Min(Ablock.blockLength, A.numRows) * A.numCols;

            if (tmp == null || tmp.Length < tmpLength)
            {
                tmp = new double[tmpLength];
            }

            // doing an in-place convert is much more memory efficient at the cost of a little
            // but of CPU
            MatrixOps_DDRB.convertRowToBlock(A.numRows, A.numCols, Ablock.blockLength, A.data, tmp);

            bool ret = alg.decompose(Ablock);

            // convert it back to the normal format if it wouldn't have been modified
            if (!alg.inputModified())
            {
                MatrixOps_DDRB.convertBlockToRow(A.numRows, A.numCols, Ablock.blockLength, A.data, tmp);
            }

            return(ret);
        }
コード例 #3
0
        public virtual DMatrixRBlock getR(DMatrixRBlock R, bool compact)
        {
            int min = Math.Min(dataA.numRows, dataA.numCols);

            if (R == null)
            {
                if (compact)
                {
                    R = new DMatrixRBlock(min, dataA.numCols, blockLength);
                }
                else
                {
                    R = new DMatrixRBlock(dataA.numRows, dataA.numCols, blockLength);
                }
            }
            else
            {
                if (compact)
                {
                    if (R.numCols != dataA.numCols || R.numRows != min)
                    {
                        throw new ArgumentException("Unexpected dimension.");
                    }
                }
                else if (R.numCols != dataA.numCols || R.numRows != dataA.numRows)
                {
                    throw new ArgumentException("Unexpected dimension.");
                }
            }

            MatrixOps_DDRB.zeroTriangle(false, R);
            MatrixOps_DDRB.copyTriangle(true, dataA, R);

            return(R);
        }
コード例 #4
0
        /**
         * Converts 'A' into a block matrix and call setA() on the block matrix solver.
         *
         * @param A The A matrix in the linear equation. Not modified. Reference saved.
         * @return true if it can solve the system.
         */
        public virtual bool setA(DMatrixRMaj A)
        {
            blockA.reshape(A.numRows, A.numCols, false);
            MatrixOps_DDRB.convert(A, blockA);

            return(alg.setA(blockA));
        }
コード例 #5
0
        /**
         * Creates a block matrix the same size as A_inv, inverts the matrix and copies the results back
         * onto A_inv.
         *
         * @param A_inv Where the inverted matrix saved. Modified.
         */
        public virtual void invert(DMatrixRMaj A_inv)
        {
            blockB.reshape(A_inv.numRows, A_inv.numCols, false);

            alg.invert(blockB);

            MatrixOps_DDRB.convert(blockB, A_inv);
        }
コード例 #6
0
        /**
         * Only converts the B matrix and passes that onto solve.  Te result is then copied into
         * the input 'X' matrix.
         *
         * @param B A matrix &real; <sup>m &times; p</sup>.  Not modified.
         * @param X A matrix &real; <sup>n &times; p</sup>, where the solution is written to.  Modified.
         */
        public override void solve(DMatrixRMaj B, DMatrixRMaj X)
        {
            blockB.reshape(B.numRows, B.numCols, false);
            MatrixOps_DDRB.convert(B, blockB);

            // since overwrite B is true X does not need to be passed in
            alg.solve(blockB, null);

            MatrixOps_DDRB.convert(blockB, X);
        }
コード例 #7
0
        public virtual /**/ double quality()
        {
            return(alg.quality());
        }

        /**
         * Converts B and X into block matrices and calls the block matrix solve routine.
         *
         * @param B A matrix &real; <sup>m &times; p</sup>.  Not modified.
         * @param X A matrix &real; <sup>n &times; p</sup>, where the solution is written to.  Modified.
         */
        public virtual void solve(DMatrixRMaj B, DMatrixRMaj X)
        {
            blockB.reshape(B.numRows, B.numCols, false);
            blockX.reshape(X.numRows, X.numCols, false);
            MatrixOps_DDRB.convert(B, blockB);

            alg.solve(blockB, blockX);

            MatrixOps_DDRB.convert(blockX, X);
        }
コード例 #8
0
        public virtual void convertBlockToRow(int numRows, int numCols, int blockLength,
                                              double[] data)
        {
            int tmpLength = Math.Min(blockLength, numRows) * numCols;

            if (tmp == null || tmp.Length < tmpLength)
            {
                tmp = new double[tmpLength];
            }

            MatrixOps_DDRB.convertBlockToRow(numRows, numCols, Ablock.blockLength, data, tmp);
        }
コード例 #9
0
        public virtual DMatrixRMaj getT(DMatrixRMaj T)
        {
            DMatrixRBlock T_block = ((CholeskyOuterForm_DDRB)alg).getT(null);

            if (T == null)
            {
                T = new DMatrixRMaj(T_block.numRows, T_block.numCols);
            }

            MatrixOps_DDRB.convert(T_block, T);
            // todo set zeros
            return(T);
        }
コード例 #10
0
        //@Override
        public DMatrixRMaj getR(DMatrixRMaj R, bool compact)
        {
            DMatrixRBlock Rblock;

            Rblock = ((QRDecompositionHouseholder_DDRB)alg).getR(null, compact);

            if (R == null)
            {
                R = new DMatrixRMaj(Rblock.numRows, Rblock.numCols);
            }
            MatrixOps_DDRB.convert(Rblock, R);

            return(R);
        }
コード例 #11
0
        /**
         * Sanity checks the input or declares a new matrix.  Return matrix is an identity matrix.
         */
        public static DMatrixRBlock initializeQ(DMatrixRBlock Q,
                                                int numRows, int numCols, int blockLength,
                                                bool compact)
        {
            int minLength = Math.Min(numRows, numCols);

            if (compact)
            {
                if (Q == null)
                {
                    Q = new DMatrixRBlock(numRows, minLength, blockLength);
                    MatrixOps_DDRB.setIdentity(Q);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != minLength)
                    {
                        throw new ArgumentException("Unexpected matrix dimension. Found " + Q.numRows + " " +
                                                    Q.numCols);
                    }
                    else
                    {
                        MatrixOps_DDRB.setIdentity(Q);
                    }
                }
            }
            else
            {
                if (Q == null)
                {
                    Q = new DMatrixRBlock(numRows, numRows, blockLength);
                    MatrixOps_DDRB.setIdentity(Q);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != numRows)
                    {
                        throw new ArgumentException("Unexpected matrix dimension. Found " + Q.numRows + " " +
                                                    Q.numCols);
                    }
                    else
                    {
                        MatrixOps_DDRB.setIdentity(Q);
                    }
                }
            }
            return(Q);
        }
コード例 #12
0
        private bool decomposeLower()
        {
            int blockLength = T.blockLength;

            subA.set(T);
            subB.set(T);
            subC.set(T);

            for (int i = 0; i < T.numCols; i += blockLength)
            {
                int widthA = Math.Min(blockLength, T.numCols - i);

                subA.col0 = i;
                subA.col1 = i + widthA;
                subA.row0 = subA.col0;
                subA.row1 = subA.col1;

                subB.col0 = i;
                subB.col1 = i + widthA;
                subB.row0 = i + widthA;
                subB.row1 = T.numRows;

                subC.col0 = i + widthA;
                subC.col1 = T.numRows;
                subC.row0 = i + widthA;
                subC.row1 = T.numRows;

                // cholesky on inner block A
                if (!InnerCholesky_DDRB.lower(subA))
                {
                    return(false);
                }

                // on the last block these operations are not needed.
                if (widthA == blockLength)
                {
                    // B = L^-1 B
                    TriangularSolver_DDRB.solveBlock(blockLength, false, subA, subB, false, true);

                    // C = C - B * B^T
                    InnerRankUpdate_DDRB.symmRankNMinus_L(blockLength, subC, subB);
                }
            }

            MatrixOps_DDRB.zeroTriangle(true, T);

            return(true);
        }
コード例 #13
0
        public virtual /**/ double quality()
        {
            return(SpecializedOps_DDRM.qualityTriangular(decomposer.getT(null)));
        }

        /**
         * If X == null then the solution is written into B.  Otherwise the solution is copied
         * from B into X.
         */
        public virtual void solve(DMatrixRBlock B, DMatrixRBlock X)
        {
            if (B.blockLength != blockLength)
            {
                throw new ArgumentException("Unexpected blocklength in B.");
            }

            DSubmatrixD1 L = new DSubmatrixD1(decomposer.getT(null));

            if (X != null)
            {
                if (X.blockLength != blockLength)
                {
                    throw new ArgumentException("Unexpected blocklength in X.");
                }
                if (X.numRows != L.col1)
                {
                    throw new ArgumentException("Not enough rows in X");
                }
            }

            if (B.numRows != L.col1)
            {
                throw new ArgumentException("Not enough rows in B");
            }

            //  L * L^T*X = B

            // Solve for Y:  L*Y = B
            TriangularSolver_DDRB.solve(blockLength, false, L, new DSubmatrixD1(B), false);

            // L^T * X = Y
            TriangularSolver_DDRB.solve(blockLength, false, L, new DSubmatrixD1(B), true);

            if (X != null)
            {
                // copy the solution from B into X
                MatrixOps_DDRB.extractAligned(B, X);
            }
        }
コード例 #14
0
        public virtual /**/ double quality()
        {
            return(SpecializedOps_DDRM.qualityTriangular(decomposer.getQR()));
        }

        public virtual void solve(DMatrixRBlock B, DMatrixRBlock X)
        {
            if (B.numCols != X.numCols)
            {
                throw new ArgumentException("Columns of B and X do not match");
            }
            if (QR.numCols != X.numRows)
            {
                throw new ArgumentException("Rows in X do not match the columns in A");
            }
            if (QR.numRows != B.numRows)
            {
                throw new ArgumentException("Rows in B do not match the rows in A.");
            }
            if (B.blockLength != QR.blockLength || X.blockLength != QR.blockLength)
            {
                throw new ArgumentException("All matrices must have the same block length.");
            }

            // The system being solved for can be described as:
            // Q*R*X = B

            // First apply householder reflectors to B
            // Y = Q^T*B
            decomposer.applyQTran(B);

            // Second solve for Y using the upper triangle matrix R and the just computed Y
            // X = R^-1 * Y
            MatrixOps_DDRB.extractAligned(B, X);

            // extract a block aligned matrix
            int M = Math.Min(QR.numRows, QR.numCols);

            TriangularSolver_DDRB.solve(QR.blockLength, true,
                                        new DSubmatrixD1(QR, 0, M, 0, M), new DSubmatrixD1(X), false);
        }

        /**
         * Invert by solving for against an identity matrix.
         *
         * @param A_inv Where the inverted matrix saved. Modified.
         */
        public virtual void invert(DMatrixRBlock A_inv)
        {
            int M = Math.Min(QR.numRows, QR.numCols);

            if (A_inv.numRows != M || A_inv.numCols != M)
            {
                throw new ArgumentException("A_inv must be square an have dimension " + M);
            }


            // Solve for A^-1
            // Q*R*A^-1 = I

            // Apply householder reflectors to the identity matrix
            // y = Q^T*I = Q^T
            MatrixOps_DDRB.setIdentity(A_inv);
            decomposer.applyQTran(A_inv);

            // Solve using upper triangular R matrix
            // R*A^-1 = y
            // A^-1 = R^-1*y
            TriangularSolver_DDRB.solve(QR.blockLength, true,
                                        new DSubmatrixD1(QR, 0, M, 0, M), new DSubmatrixD1(A_inv), false);
        }