예제 #1
0
        /**
         * <p>
         * Computes W from the householder reflectors stored in the columns of the row block
         * submatrix Y.
         * </p>
         *
         * <p>
         * Y = v<sup>(1)</sup><br>
         * W = -&beta;<sub>1</sub>v<sup>(1)</sup><br>
         * for j=2:r<br>
         * &nbsp;&nbsp;z = -&beta;(I +WY<sup>T</sup>)v<sup>(j)</sup> <br>
         * &nbsp;&nbsp;W = [W z]<br>
         * &nbsp;&nbsp;Y = [Y v<sup>(j)</sup>]<br>
         * end<br>
         * <br>
         * where v<sup>(.)</sup> are the house holder vectors, and r is the block length.  Note that
         * Y already contains the householder vectors so it does not need to be modified.
         * </p>
         *
         * <p>
         * Y and W are assumed to have the same number of rows and columns.
         * </p>
         */
        public static void computeW_row(int blockLength,
                                        DSubmatrixD1 Y, DSubmatrixD1 W,
                                        double[] beta, int betaIndex)
        {
            int heightY = Y.row1 - Y.row0;

            CommonOps_DDRM.fill(W.original, 0);

            // W = -beta*v(1)
            BlockHouseHolder_DDRB.scale_row(blockLength, Y, W, 0, 1, -beta[betaIndex++]);

            int min = Math.Min(heightY, W.col1 - W.col0);

            // set up rest of the rows
            for (int i = 1; i < min; i++)
            {
                // w=-beta*(I + W*Y^T)*u
                double b = -beta[betaIndex++];

                // w = w -beta*W*(Y^T*u)
                for (int j = 0; j < i; j++)
                {
                    double yv = BlockHouseHolder_DDRB.innerProdRow(blockLength, Y, i, Y, j, 1);
                    VectorOps_DDRB.add_row(blockLength, W, i, 1, W, j, b * yv, W, i, 1, Y.col1 - Y.col0);
                }

                //w=w -beta*u + stuff above
                BlockHouseHolder_DDRB.add_row(blockLength, Y, i, b, W, i, 1, W, i, 1, Y.col1 - Y.col0);
            }
        }
예제 #2
0
        /**
         * <p>
         * Creates a pivot matrix that exchanges the rows in a matrix:
         * <br>
         * A' = P*A<br>
         * </p>
         * <p>
         * For example, if element 0 in 'pivots' is 2 then the first row in A' will be the 3rd row in A.
         * </p>
         *
         * @param ret If null then a new matrix is declared otherwise the results are written to it.  Is modified.
         * @param pivots Specifies the new order of rows in a matrix.
         * @param numPivots How many elements in pivots are being used.
         * @param transposed If the transpose of the matrix is returned.
         * @return A pivot matrix.
         */
        public static DMatrixRMaj pivotMatrix(DMatrixRMaj ret, int[] pivots, int numPivots, bool transposed)
        {
            if (ret == null)
            {
                ret = new DMatrixRMaj(numPivots, numPivots);
            }
            else
            {
                if (ret.numCols != numPivots || ret.numRows != numPivots)
                {
                    throw new ArgumentException("Unexpected matrix dimension");
                }
                CommonOps_DDRM.fill(ret, 0);
            }

            if (transposed)
            {
                for (int i = 0; i < numPivots; i++)
                {
                    ret.set(pivots[i], i, 1);
                }
            }
            else
            {
                for (int i = 0; i < numPivots; i++)
                {
                    ret.set(i, pivots[i], 1);
                }
            }

            return(ret);
        }
        public virtual DMatrixRBlock getT(DMatrixRBlock T)
        {
            if (T == null)
            {
                T = new DMatrixRBlock(A.numRows, A.numCols, A.blockLength);
            }
            else
            {
                if (T.numRows != A.numRows || T.numCols != A.numCols)
                {
                    throw new ArgumentException("T must have the same dimensions as the input matrix");
                }

                CommonOps_DDRM.fill(T, 0);
            }

            T.set(0, 0, A.data[0]);
            for (int i = 1; i < A.numRows; i++)
            {
                double d = A.get(i - 1, i);
                T.set(i, i, A.get(i, i));
                T.set(i - 1, i, d);
                T.set(i, i - 1, d);
            }

            return(T);
        }
        public virtual DMatrixRMaj getT(DMatrixRMaj T)
        {
            int N = Ablock.numRows;

            if (T == null)
            {
                T = new DMatrixRMaj(N, N);
            }
            else
            {
                CommonOps_DDRM.fill(T, 0);
            }

            double[] diag = new double[N];
            double[] off  = new double[N];

            ((TridiagonalDecompositionHouseholder_DDRB)alg).getDiagonal(diag, off);

            T.unsafe_set(0, 0, diag[0]);
            for (int i = 1; i < N; i++)
            {
                T.unsafe_set(i, i, diag[i]);
                T.unsafe_set(i, i - 1, off[i - 1]);
                T.unsafe_set(i - 1, i, off[i - 1]);
            }

            return(T);
        }
예제 #5
0
        /**
         * An alternative implementation of {@link #multTransA_small} that performs well on large
         * matrices.  There is a relative performance hit when used on small matrices.
         *
         * @param A A matrix that is m by n. Not modified.
         * @param B A Vector that has length m. Not modified.
         * @param C A column vector that has length n. Modified.
         */
        public static void multTransA_reorder(DMatrix1Row A, DMatrixD1 B, DMatrixD1 C)
        {
            if (C.numCols != 1)
            {
                throw new MatrixDimensionException("C is not a column vector");
            }
            else if (C.numRows != A.numCols)
            {
                throw new MatrixDimensionException("C is not the expected length");
            }
            if (B.numRows == 1)
            {
                if (A.numRows != B.numCols)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else if (B.numCols == 1)
            {
                if (A.numRows != B.numRows)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else
            {
                throw new MatrixDimensionException("B is not a vector");
            }

            if (A.numRows == 0)
            {
                CommonOps_DDRM.fill(C, 0);
                return;
            }

            double B_val = B.get(0);

            for (int i = 0; i < A.numCols; i++)
            {
                C.set(i, A.get(i) * B_val);
            }

            int indexA = A.numCols;

            for (int i = 1; i < A.numRows; i++)
            {
                B_val = B.get(i);
                for (int j = 0; j < A.numCols; j++)
                {
                    C.plus(j, A.get(indexA++) * B_val);
                }
            }
        }
예제 #6
0
        /**
         * <p>
         * Performs a matrix vector multiply.<br>
         * <br>
         * c = A * b <br>
         * and<br>
         * c = A * b<sup>T</sup> <br>
         * <br>
         * c<sub>i</sub> = Sum{ j=1:n, a<sub>ij</sub> * b<sub>j</sub>}<br>
         * <br>
         * where A is a matrix, b is a column or transposed row vector, and c is a column vector.
         * </p>
         *
         * @param A A matrix that is m by n. Not modified.
         * @param B A vector that has length n. Not modified.
         * @param C A column vector that has length m. Modified.
         */
        public static void mult(DMatrix1Row A, DMatrixD1 B, DMatrixD1 C)
        {
            if (C.numCols != 1)
            {
                throw new MatrixDimensionException("C is not a column vector");
            }
            else if (C.numRows != A.numRows)
            {
                throw new MatrixDimensionException("C is not the expected length");
            }

            if (B.numRows == 1)
            {
                if (A.numCols != B.numCols)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else if (B.numCols == 1)
            {
                if (A.numCols != B.numRows)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else
            {
                throw new MatrixDimensionException("B is not a vector");
            }

            if (A.numCols == 0)
            {
                CommonOps_DDRM.fill(C, 0);
                return;
            }

            int    indexA = 0;
            int    cIndex = 0;
            double b0     = B.get(0);

            for (int i = 0; i < A.numRows; i++)
            {
                double total = A.get(indexA++) * b0;

                for (int j = 1; j < A.numCols; j++)
                {
                    total += A.get(indexA++) * B.get(j);
                }

                C.set(cIndex++, total);
            }
        }
        /**
         * @see CommonOps_DDRM#mult(double, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row)
         */
        public static void mult_reorder(double alpha, DMatrix1Row A, DMatrix1Row B, DMatrix1Row C)
        {
            UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'");
            UtilEjml.assertShape(A.numCols, B.numRows, "The 'A' and 'B' matrices do not have compatible dimensions");
            C.reshape(A.numRows, B.numCols);

            if (A.numCols == 0 || A.numRows == 0)
            {
                CommonOps_DDRM.fill(C, 0);
                return;
            }
            int endOfKLoop = B.numRows * B.numCols;

            //CONCURRENT_BELOW EjmlConcurrency.loopFor(0, A.numRows, i -> {
            for (int i = 0; i < A.numRows; i++)
            {
                int indexCbase = i * C.numCols;
                int indexA     = i * A.numCols;

                // need to assign C.data to a value initially
                int indexB = 0;
                int indexC = indexCbase;
                int end    = indexB + B.numCols;

                double valA = alpha * A.data[indexA++];

                while (indexB < end)
                {
                    C.set(indexC++, valA * B.data[indexB++]);
                }

                // now add to it
                while (indexB != endOfKLoop)
                { // k loop
                    indexC = indexCbase;
                    end    = indexB + B.numCols;

                    valA = alpha * A.data[indexA++];

                    while (indexB < end)
                    { // j loop
                        C.data[indexC++] += valA * B.data[indexB++];
                    }
                }
            }
            //CONCURRENT_ABOVE });
        }
        //CONCURRENT_OMIT_END

        /**
         * @see CommonOps_DDRM#multTransA(double, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row)
         */
        public static void multTransA_reorder(double alpha, DMatrix1Row A, DMatrix1Row B, DMatrix1Row C)
        {
            UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'");
            UtilEjml.assertShape(A.numRows, B.numRows, "The 'A' and 'B' matrices do not have compatible dimensions");
            C.reshape(A.numCols, B.numCols);

            if (A.numCols == 0 || A.numRows == 0)
            {
                CommonOps_DDRM.fill(C, 0);
                return;
            }
            //CONCURRENT_BELOW EjmlConcurrency.loopFor(0, A.numRows, i -> {
            for (int i = 0; i < A.numCols; i++)
            {
                int indexC_start = i * C.numCols;

                // first assign R
                double valA   = alpha * A.data[i];
                int    indexB = 0;
                int    end    = indexB + B.numCols;
                int    indexC = indexC_start;
                while (indexB < end)
                {
                    C.set(indexC++, valA * B.data[indexB++]);
                }
                // now increment it
                for (int k = 1; k < A.numRows; k++)
                {
                    valA   = alpha * A.unsafe_get(k, i);
                    end    = indexB + B.numCols;
                    indexC = indexC_start;
                    // this is the loop for j
                    while (indexB < end)
                    {
                        C.data[indexC++] += valA * B.data[indexB++];
                    }
                }
            }
            //CONCURRENT_ABOVE });
        }
예제 #9
0
        /**
         * <p>Sets the value of A to all zeros except along the diagonal.</p>
         *
         * @param A Block matrix.
         */
        public static void setIdentity(DMatrixRBlock A)
        {
            int minLength = Math.Min(A.numRows, A.numCols);

            CommonOps_DDRM.fill(A, 0);

            int blockLength = A.blockLength;

            for (int i = 0; i < minLength; i += blockLength)
            {
                int h = Math.Min(blockLength, A.numRows - i);
                int w = Math.Min(blockLength, A.numCols - i);

                int index = i * A.numCols + h * i;

                int m = Math.Min(h, w);
                for (int k = 0; k < m; k++)
                {
                    A.data[index + k * w + k] = 1;
                }
            }
        }
        //CONCURRENT_OMIT_BEGIN

        /**
         * @see CommonOps_DDRM#multTransAB(double, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row)
         */
        public static void multTransAB_aux(double alpha, DMatrix1Row A, DMatrix1Row B, DMatrix1Row C, double[] aux)
        {
            UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'");
            UtilEjml.assertShape(A.numRows, B.numCols, "The 'A' and 'B' matrices do not have compatible dimensions");
            C.reshape(A.numCols, B.numRows);

            if (aux == null)
            {
                aux = new double[A.numRows];
            }

            if (A.numCols == 0 || A.numRows == 0)
            {
                CommonOps_DDRM.fill(C, 0);
                return;
            }
            int indexC = 0;

            for (int i = 0; i < A.numCols; i++)
            {
                for (int k = 0; k < B.numCols; k++)
                {
                    aux[k] = A.unsafe_get(k, i);
                }

                for (int j = 0; j < B.numRows; j++)
                {
                    double total = 0;

                    for (int k = 0; k < B.numCols; k++)
                    {
                        total += aux[k] * B.unsafe_get(j, k);
                    }
                    C.set(indexC++, alpha * total);
                }
            }
        }
예제 #11
0
        public virtual void divide(DMatrixRMaj A, /**/ double val, DMatrixRMaj output)
        {
            CommonOps_DDRM.divide(A, (double)val, output);
        }

        public virtual bool invert(DMatrixRMaj A, DMatrixRMaj output)
        {
            return(CommonOps_DDRM.invert(A, output));
        }

        public virtual void pseudoInverse(DMatrixRMaj A, DMatrixRMaj output)
        {
            CommonOps_DDRM.pinv(A, output);
        }

        public virtual bool solve(DMatrixRMaj A, DMatrixRMaj X, DMatrixRMaj B)
        {
            return(CommonOps_DDRM.solve(A, B, X));
        }

        public virtual void set(DMatrixRMaj A, /**/ double val)
        {
            CommonOps_DDRM.fill(A, (double)val);
        }
예제 #12
0
 /// <summary>
 /// Sets all the elements in this matrix equal to the specified value.
 /// </summary>
 /// <see cref="CommonOps_DDRM.fill(DMatrixD1, double)"/>
 public override void set(double val)
 {
     CommonOps_DDRM.fill(mat, val);
 }
예제 #13
0
 /**
  * <p>
  * Sets every element in the matrix to the specified value.<br>
  * <br>
  * a<sub>ij</sub> = value
  * <p>
  *
  * @param A A matrix whose elements are about to be set. Modified.
  * @param value The value each element will have.
  */
 public static void set(DMatrixRBlock A, double value)
 {
     CommonOps_DDRM.fill(A, value);
 }
예제 #14
0
 public void fill(Matrix A, double value)
 {
     CommonOps_DDRM.fill((DMatrixRMaj)A, (double)value);
 }
예제 #15
0
        /**
         * <p>
         * Given an eigenvalue it computes an eigenvector using inverse iteration:
         * <br>
         * for i=1:MAX {<br>
         *   (A - &mu;I)z<sup>(i)</sup> = q<sup>(i-1)</sup><br>
         *   q<sup>(i)</sup> = z<sup>(i)</sup> / ||z<sup>(i)</sup>||<br>
         * &lambda;<sup>(i)</sup> =  q<sup>(i)</sup><sup>T</sup> A  q<sup>(i)</sup><br>
         * }<br>
         * </p>
         * <p>
         * NOTE: If there is another eigenvalue that is very similar to the provided one then there
         * is a chance of it converging towards that one instead.  The larger a matrix is the more
         * likely this is to happen.
         * </p>
         * @param A Matrix whose eigenvector is being computed.  Not modified.
         * @param eigenvalue The eigenvalue in the eigen pair.
         * @return The eigenvector or null if none could be found.
         */
        public static DEigenpair computeEigenVector(DMatrixRMaj A, double eigenvalue)
        {
            if (A.numRows != A.numCols)
            {
                throw new ArgumentException("Must be a square matrix.");
            }

            DMatrixRMaj M = new DMatrixRMaj(A.numRows, A.numCols);

            DMatrixRMaj x = new DMatrixRMaj(A.numRows, 1);
            DMatrixRMaj b = new DMatrixRMaj(A.numRows, 1);

            CommonOps_DDRM.fill(b, 1);

            // perturb the eigenvalue slightly so that its not an exact solution the first time
//        eigenvalue -= eigenvalue*UtilEjml.EPS*10;

            double origEigenvalue = eigenvalue;

            SpecializedOps_DDRM.addIdentity(A, M, -eigenvalue);

            double threshold = NormOps_DDRM.normPInf(A) * UtilEjml.EPS;

            double prevError = double.MaxValue;
            bool   hasWorked = false;

            LinearSolverDense <DMatrixRMaj> solver = LinearSolverFactory_DDRM.linear(M.numRows);

            double perp = 0.0001;

            for (int i = 0; i < 200; i++)
            {
                bool failed = false;
                // if the matrix is singular then the eigenvalue is within machine precision
                // of the true value, meaning that x must also be.
                if (!solver.setA(M))
                {
                    failed = true;
                }
                else
                {
                    solver.solve(b, x);
                }

                // see if solve silently failed
                if (MatrixFeatures_DDRM.hasUncountable(x))
                {
                    failed = true;
                }

                if (failed)
                {
                    if (!hasWorked)
                    {
                        // if it failed on the first trial try perturbing it some more
                        double val = i % 2 == 0 ? 1.0 - perp : 1.0 + perp;
                        // maybe this should be turn into a parameter allowing the user
                        // to configure the wise of each step

                        eigenvalue = origEigenvalue * Math.Pow(val, i / 2 + 1);
                        SpecializedOps_DDRM.addIdentity(A, M, -eigenvalue);
                    }
                    else
                    {
                        // otherwise assume that it was so accurate that the matrix was singular
                        // and return that result
                        return(new DEigenpair(eigenvalue, b));
                    }
                }
                else
                {
                    hasWorked = true;

                    b.set(x);
                    NormOps_DDRM.normalizeF(b);

                    // compute the residual
                    CommonOps_DDRM.mult(M, b, x);
                    double error = NormOps_DDRM.normPInf(x);

                    if (error - prevError > UtilEjml.EPS * 10)
                    {
                        // if the error increased it is probably converging towards a different
                        // eigenvalue
//                    CommonOps.set(b,1);
                        prevError = double.MaxValue;
                        hasWorked = false;
                        double val = i % 2 == 0 ? 1.0 - perp : 1.0 + perp;
                        eigenvalue = origEigenvalue * Math.Pow(val, 1);
                    }
                    else
                    {
                        // see if it has converged
                        if (error <= threshold || Math.Abs(prevError - error) <= UtilEjml.EPS)
                        {
                            return(new DEigenpair(eigenvalue, b));
                        }

                        // update everything
                        prevError  = error;
                        eigenvalue = VectorVectorMult_DDRM.innerProdA(b, A, b);
                    }

                    SpecializedOps_DDRM.addIdentity(A, M, -eigenvalue);
                }
            }

            return(null);
        }