/**
         * Checks to see if the provided matrix is within tolerance to an identity matrix.
         *
         * @param mat Matrix being examined.  Not modified.
         * @param tol Tolerance.
         * @return True if it is within tolerance to an identify matrix.
         */
        public static bool isIdentity(FMatrixRMaj mat, float tol)
        {
            // see if the result is an identity matrix
            int index = 0;

            for (int i = 0; i < mat.numRows; i++)
            {
                for (int j = 0; j < mat.numCols; j++)
                {
                    if (i == j)
                    {
                        if (!(Math.Abs(mat.get(index++) - 1) <= tol))
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        if (!(Math.Abs(mat.get(index++)) <= tol))
                        {
                            return(false);
                        }
                    }
                }
            }

            return(true);
        }
        /**
         * <p>
         * Returns true if the matrix is symmetric within the tolerance.  Only square matrices can be
         * symmetric.
         * </p>
         * <p>
         * A matrix is symmetric if:<br>
         * |a<sub>ij</sub> - a<sub>ji</sub>| &le; tol
         * </p>
         *
         * @param m A matrix. Not modified.
         * @param tol Tolerance for how similar two elements need to be.
         * @return true if it is symmetric and false if it is not.
         */
        public static bool isSymmetric(FMatrixRMaj m, float tol)
        {
            if (m.numCols != m.numRows)
            {
                return(false);
            }

            float max = CommonOps_FDRM.elementMaxAbs(m);

            for (int i = 0; i < m.numRows; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    float a = m.get(i, j) / max;
                    float b = m.get(j, i) / max;

                    float diff = Math.Abs(a - b);

                    if (!(diff <= tol))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
        private static void swapRowOrCol(FMatrixRMaj M, bool tran, int i, int bigIndex)
        {
            float tmp;

            if (tran)
            {
                // swap the rows
                for (int col = 0; col < M.numCols; col++)
                {
                    tmp = M.get(i, col);
                    M.set(i, col, M.get(bigIndex, col));
                    M.set(bigIndex, col, tmp);
                }
            }
            else
            {
                // swap the columns
                for (int row = 0; row < M.numRows; row++)
                {
                    tmp = M.get(row, i);
                    M.set(row, i, M.get(row, bigIndex));
                    M.set(row, bigIndex, tmp);
                }
            }
        }
        /**
         * <p>
         * Adjusts the matrices so that the singular values are in descending order.
         * </p>
         *
         * <p>
         * In most implementations of SVD the singular values are automatically arranged in in descending
         * order.  In EJML this is not the case since it is often not needed and some computations can
         * be saved by not doing that.
         * </p>
         *
         * @param U Matrix. Modified.
         * @param tranU is U transposed or not.
         * @param W Diagonal matrix with singular values. Modified.
         * @param V Matrix. Modified.
         * @param tranV is V transposed or not.
         */
        // TODO the number of copies can probably be reduced here
        public static void descendingOrder(FMatrixRMaj U, bool tranU,
                                           FMatrixRMaj W,
                                           FMatrixRMaj V, bool tranV)
        {
            int numSingular = Math.Min(W.numRows, W.numCols);

            checkSvdMatrixSize(U, tranU, W, V, tranV);

            for (int i = 0; i < numSingular; i++)
            {
                float bigValue = -1;
                int   bigIndex = -1;

                // find the smallest singular value in the submatrix
                for (int j = i; j < numSingular; j++)
                {
                    float v = W.get(j, j);

                    if (v > bigValue)
                    {
                        bigValue = v;
                        bigIndex = j;
                    }
                }

                // only swap if the current index is not the smallest
                if (bigIndex == i)
                {
                    continue;
                }

                if (bigIndex == -1)
                {
                    // there is at least one uncountable singular value.  just stop here
                    break;
                }

                float tmp = W.get(i, i);
                W.set(i, i, bigValue);
                W.set(bigIndex, bigIndex, tmp);

                if (V != null)
                {
                    swapRowOrCol(V, tranV, i, bigIndex);
                }

                if (U != null)
                {
                    swapRowOrCol(U, tranU, i, bigIndex);
                }
            }
        }
Exemple #5
0
        /**
         * <p>
         * Puts all the real eigenvectors into the columns of a matrix.  If an eigenvalue is imaginary
         * then the corresponding eigenvector will have zeros in its column.
         * </p>
         *
         * @param eig An eigenvalue decomposition which has already decomposed a matrix.
         * @return An m by m matrix containing eigenvectors in its columns.
         */
        public static FMatrixRMaj createMatrixV(EigenDecomposition_F32 <FMatrixRMaj> eig)
        {
            int N = eig.getNumberOfEigenvalues();

            FMatrixRMaj V = new FMatrixRMaj(N, N);

            for (int i = 0; i < N; i++)
            {
                Complex_F32 c = eig.getEigenvalue(i);

                if (c.isReal())
                {
                    FMatrixRMaj v = eig.getEigenVector(i);

                    if (v != null)
                    {
                        for (int j = 0; j < N; j++)
                        {
                            V.set(j, i, v.get(j, 0));
                        }
                    }
                }
            }

            return(V);
        }
Exemple #6
0
        private void replaceZeros(FSubmatrixD1 subU)
        {
            int N = Math.Min(A.blockLength, subU.col1 - subU.col0);

            for (int i = 0; i < N; i++)
            {
                // save the zeros
                for (int j = 0; j <= i; j++)
                {
                    subU.set(i, j, zerosM.get(i, j));
                }
                // save the one
                if (subU.col0 + i + 1 < subU.original.numCols)
                {
                    subU.set(i, i + 1, zerosM.get(i, i + 1));
                }
            }
        }
        /**
         * Extracts the tridiagonal matrix found in the decomposition.
         *
         * @param T If not null then the results will be stored here.  Otherwise a new matrix will be created.
         * @return The extracted T matrix.
         */
        public FMatrixRMaj getT(FMatrixRMaj T)
        {
            T = UtilDecompositons_FDRM.checkZeros(T, N, N);

            T.data[0] = QT.data[0];
            T.data[1] = QT.data[1];


            for (int i = 1; i < N - 1; i++)
            {
                T.set(i, i, QT.get(i, i));
                T.set(i, i + 1, QT.get(i, i + 1));
                T.set(i, i - 1, QT.get(i - 1, i));
            }

            T.data[(N - 1) * N + N - 1] = QT.data[(N - 1) * N + N - 1];
            T.data[(N - 1) * N + N - 2] = QT.data[(N - 2) * N + N - 1];

            return(T);
        }
 /**
  * Checks to see if all the diagonal elements in the matrix are positive.
  *
  * @param a A matrix. Not modified.
  * @return true if all the  diagonal elements are positive, false otherwise.
  */
 public static bool isDiagonalPositive(FMatrixRMaj a)
 {
     for (int i = 0; i < a.numRows; i++)
     {
         if (!(a.get(i, i) >= 0))
         {
             return(false);
         }
     }
     return(true);
 }
Exemple #9
0
        public override void solve(FMatrixRMaj B, FMatrixRMaj X)
        {
            if (X.numRows != numCols)
            {
                throw new ArgumentException("Unexpected dimensions for X");
            }
            else if (B.numRows != numRows || B.numCols != X.numCols)
            {
                throw new ArgumentException("Unexpected dimensions for B");
            }

            int BnumCols = B.numCols;

            // get the pivots and transpose them
            int[] pivots = decomposition.getColPivots();

            // solve each column one by one
            for (int colB = 0; colB < BnumCols; colB++)
            {
                x_basic.reshape(numRows, 1);
                Y.reshape(numRows, 1);

                // make a copy of this column in the vector
                for (int i = 0; i < numRows; i++)
                {
                    Y.data[i] = B.get(i, colB);
                }

                // Solve Q*a=b => a = Q'*b
                CommonOps_FDRM.multTransA(Q, Y, x_basic);

                // solve for Rx = b using the standard upper triangular solver
                TriangularSolver_FDRM.solveU(R11.data, x_basic.data, rank);

                // finish the basic solution by filling in zeros
                x_basic.reshape(numCols, 1, true);
                for (int i = rank; i < numCols; i++)
                {
                    x_basic.data[i] = 0;
                }

                if (norm2Solution && rank < numCols)
                {
                    upgradeSolution(x_basic);
                }

                // save the results
                for (int i = 0; i < numCols; i++)
                {
                    X.set(pivots[i], colB, x_basic.data[i]);
                }
            }
        }
        /**
         * Computes the likelihood of the random draw
         *
         * @return The likelihood.
         */
        public float computeLikelihoodP()
        {
            float ret = 1.0f;

            for (int i = 0; i < r.numRows; i++)
            {
                float a = r.get(i, 0);

                ret *= (float)Math.Exp(-a * a / 2.0f);
            }

            return(ret);
        }
Exemple #11
0
        /**
         * Multiplied a transpose orthogonal matrix Q by the specified rotator.  This is used
         * to update the U and V matrices.  Updating the transpose of the matrix is faster
         * since it only modifies the rows.
         *
         *
         * @param Q Orthogonal matrix
         * @param m Coordinate of rotator.
         * @param n Coordinate of rotator.
         * @param c cosine of rotator.
         * @param s sine of rotator.
         */
        protected void updateRotator(FMatrixRMaj Q, int m, int n, float c, float s)
        {
            int rowA = m * Q.numCols;
            int rowB = n * Q.numCols;

//        for( int i = 0; i < Q.numCols; i++ ) {
//            float a = Q.get(rowA+i);
//            float b = Q.get(rowB+i);
//            Q.set( rowA+i, c*a + s*b);
//            Q.set( rowB+i, -s*a + c*b);
//        }
//        Console.WriteLine("------ AFter Update Rotator "+m+" "+n);
//        Q.print();
//        Console.WriteLine();
            int endA = rowA + Q.numCols;

            for (; rowA != endA; rowA++, rowB++)
            {
                float a = Q.get(rowA);
                float b = Q.get(rowB);
                Q.set(rowA, c * a + s * b);
                Q.set(rowB, -s * a + c * b);
            }
        }
        /**
         * <p>
         * Checks to see if a matrix is skew symmetric with in tolerance:<br>
         * <br>
         * -A = A<sup>T</sup><br>
         * or<br>
         * |a<sub>ij</sub> + a<sub>ji</sub>| &le; tol
         * </p>
         *
         * @param A The matrix being tested.
         * @param tol Tolerance for being skew symmetric.
         * @return True if it is skew symmetric and false if it is not.
         */
        public static bool isSkewSymmetric(FMatrixRMaj A, float tol)
        {
            if (A.numCols != A.numRows)
            {
                return(false);
            }

            for (int i = 0; i < A.numRows; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    float a = A.get(i, j);
                    float b = A.get(j, i);

                    float diff = Math.Abs(a + b);

                    if (!(diff <= tol))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Exemple #13
0
        /**
         * <p>
         * Generates a bound for the largest eigen value of the provided matrix using Perron-Frobenius
         * theorem.   This function only applies to non-negative real matrices.
         * </p>
         *
         * <p>
         * For "stochastic" matrices (Markov process) this should return one for the upper and lower bound.
         * </p>
         *
         * @param A Square matrix with positive elements.  Not modified.
         * @param bound Where the results are stored.  If null then a matrix will be declared. Modified.
         * @return Lower and upper bound in the first and second elements respectively.
         */
        public static float[] boundLargestEigenValue(FMatrixRMaj A, float[] bound)
        {
            if (A.numRows != A.numCols)
            {
                throw new ArgumentException("A must be a square matrix.");
            }

            float min = float.MaxValue;
            float max = 0;

            int n = A.numRows;

            for (int i = 0; i < n; i++)
            {
                float total = 0;
                for (int j = 0; j < n; j++)
                {
                    float v = A.get(i, j);
                    if (v < 0)
                    {
                        throw new ArgumentException("Matrix must be positive");
                    }

                    total += v;
                }

                if (total < min)
                {
                    min = total;
                }

                if (total > max)
                {
                    max = total;
                }
            }

            if (bound == null)
            {
                bound = new float[2];
            }

            bound[0] = min;
            bound[1] = max;

            return(bound);
        }
Exemple #14
0
        /**
         * <p>
         * Induced matrix p = infinity norm.<br>
         * <br>
         * ||A||<sub>&#8734;</sub> = max(i=1 to m; sum(j=1 to n; |a<sub>ij</sub>|))
         * </p>
         *
         * @param A A matrix.
         * @return the norm.
         */
        public static float inducedPInf(FMatrixRMaj A)
        {
            float max = 0;

            int m = A.numRows;
            int n = A.numCols;

            for (int i = 0; i < m; i++)
            {
                float total = 0;
                for (int j = 0; j < n; j++)
                {
                    total += Math.Abs(A.get(i, j));
                }
                if (total > max)
                {
                    max = total;
                }
            }

            return(max);
        }
Exemple #15
0
        public override /**/ double quality()
        {
            return(SpecializedOps_FDRM.qualityTriangular(R));
        }

        /**
         * Solves for X using the QR decomposition.
         *
         * @param B A matrix that is n by m.  Not modified.
         * @param X An n by m matrix where the solution is written to.  Modified.
         */
        public override void solve(FMatrixRMaj B, FMatrixRMaj X)
        {
            if (X.numRows != numCols)
            {
                throw new ArgumentException("Unexpected dimensions for X");
            }
            else if (B.numRows != numRows || B.numCols != X.numCols)
            {
                throw new ArgumentException("Unexpected dimensions for B");
            }

            int BnumCols = B.numCols;

            Y.reshape(numRows, 1, false);
            Z.reshape(numRows, 1, false);

            // solve each column one by one
            for (int colB = 0; colB < BnumCols; colB++)
            {
                // make a copy of this column in the vector
                for (int i = 0; i < numRows; i++)
                {
                    Y.data[i] = B.get(i, colB);
                }

                // Solve Qa=b
                // a = Q'b
                CommonOps_FDRM.multTransA(Q, Y, Z);

                // solve for Rx = b using the standard upper triangular solver
                TriangularSolver_FDRM.solveU(R.data, Z.data, numCols);

                // save the results
                for (int i = 0; i < numCols; i++)
                {
                    X.set(i, colB, Z.data[i]);
                }
            }
        }
        /**
         * Checks to see if the two matrices are inverses of each other.
         *
         * @param a A matrix. Not modified.
         * @param b A matrix. Not modified.
         */
        public static bool isInverse(FMatrixRMaj a, FMatrixRMaj b, float tol)
        {
            if (a.numRows != b.numRows || a.numCols != b.numCols)
            {
                return(false);
            }

            int numRows = a.numRows;
            int numCols = a.numCols;

            for (int i = 0; i < numRows; i++)
            {
                for (int j = 0; j < numCols; j++)
                {
                    float total = 0;
                    for (int k = 0; k < numCols; k++)
                    {
                        total += a.get(i, k) * b.get(k, j);
                    }

                    if (i == j)
                    {
                        if (!(Math.Abs(total - 1) <= tol))
                        {
                            return(false);
                        }
                    }
                    else if (!(Math.Abs(total) <= tol))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
        public override void solve(FMatrixRMaj B, FMatrixRMaj X)
        {
            if (X.numRows != numCols)
            {
                throw new ArgumentException("Unexpected dimensions for X");
            }
            else if (B.numRows != numRows || B.numCols != X.numCols)
            {
                throw new ArgumentException("Unexpected dimensions for B");
            }

            int BnumCols = B.numCols;

            // get the pivots and transpose them
            int[] pivots = decomposition.getColPivots();

            float[][] qr     = decomposition.getQR();
            float[]   gammas = decomposition.getGammas();

            // solve each column one by one
            for (int colB = 0; colB < BnumCols; colB++)
            {
                x_basic.reshape(numRows, 1);
                Y.reshape(numRows, 1);

                // make a copy of this column in the vector
                for (int i = 0; i < numRows; i++)
                {
                    x_basic.data[i] = B.get(i, colB);
                }

                // Solve Q*x=b => x = Q'*b
                // Q_n*b = (I-gamma*u*u^T)*b = b - u*(gamma*U^T*b)
                for (int i = 0; i < rank; i++)
                {
                    float[] u = qr[i];

                    float vv = u[i];
                    u[i] = 1;
                    QrHelperFunctions_FDRM.rank1UpdateMultR(x_basic, u, gammas[i], 0, i, numRows, Y.data);
                    u[i] = vv;
                }

                // solve for Rx = b using the standard upper triangular solver
                TriangularSolver_FDRM.solveU(R11.data, x_basic.data, rank);

                // finish the basic solution by filling in zeros
                x_basic.reshape(numCols, 1, true);
                for (int i = rank; i < numCols; i++)
                {
                    x_basic.data[i] = 0;
                }

                if (norm2Solution && rank < numCols)
                {
                    upgradeSolution(x_basic);
                }

                // save the results
                for (int i = 0; i < numCols; i++)
                {
                    X.set(pivots[i], colB, x_basic.data[i]);
                }
            }
        }
Exemple #18
0
        public bool isZero(int x1, int x2)
        {
            // this provides a relative threshold for when dealing with very large/small numbers
            float target = Math.Abs(A.get(x1, x2));

            float above = Math.Abs(A.get(x1 - 1, x2));

            // according to Matrix Computations page 352 this is what is done in Eispack
            float right = Math.Abs(A.get(x1, x2 + 1));

            return(target <= 0.5f * UtilEjml.F_EPS * (above + right));
        }