예제 #1
0
 /**
  * Computes the p=∞ norm.  If A is a matrix then the induced norm is computed.
  *
  * @param A Matrix or vector.
  * @return The norm.
  */
 public static double normPInf(DMatrixRMaj A)
 {
     if (MatrixFeatures_DDRM.isVector(A))
     {
         return(CommonOps_DDRM.elementMaxAbs(A));
     }
     else
     {
         return(inducedPInf(A));
     }
 }
예제 #2
0
 /**
  * Computes the p=2 norm.  If A is a matrix then the induced norm is computed. This
  * implementation is faster, but more prone to buffer overflow or underflow problems.
  *
  * @param A Matrix or vector.
  * @return The norm.
  */
 public static double fastNormP2(DMatrixRMaj A)
 {
     if (MatrixFeatures_DDRM.isVector(A))
     {
         return(fastNormF(A));
     }
     else
     {
         return(inducedP2(A));
     }
 }
예제 #3
0
        /**
         * <p>
         * Creates a reflector from the provided vector and gamma.<br>
         * <br>
         * Q = I - &gamma; u u<sup>T</sup><br>
         * </p>
         *
         * <p>
         * In practice {@link VectorVectorMult_DDRM#householder(double, DMatrixD1, DMatrixD1, DMatrixD1)}  multHouseholder}
         * should be used for performance reasons since there is no need to calculate Q explicitly.
         * </p>
         *
         * @param u A vector.  Not modified.
         * @param gamma To produce a reflector gamma needs to be equal to 2/||u||.
         * @return An orthogonal reflector.
         */
        public static DMatrixRMaj createReflector(DMatrixRMaj u, double gamma)
        {
            if (!MatrixFeatures_DDRM.isVector(u))
            {
                throw new ArgumentException("u must be a vector");
            }

            DMatrixRMaj Q = CommonOps_DDRM.identity(u.getNumElements());

            CommonOps_DDRM.multAddTransB(-gamma, u, u, Q);

            return(Q);
        }
예제 #4
0
        /**
         * <p>
         * Creates a reflector from the provided vector.<br>
         * <br>
         * Q = I - &gamma; u u<sup>T</sup><br>
         * &gamma; = 2/||u||<sup>2</sup>
         * </p>
         *
         * <p>
         * In practice {@link VectorVectorMult_DDRM#householder(double, DMatrixD1, DMatrixD1, DMatrixD1)}  multHouseholder}
         * should be used for performance reasons since there is no need to calculate Q explicitly.
         * </p>
         *
         * @param u A vector. Not modified.
         * @return An orthogonal reflector.
         */
        public static DMatrixRMaj createReflector(DMatrix1Row u)
        {
            if (!MatrixFeatures_DDRM.isVector(u))
            {
                throw new ArgumentException("u must be a vector");
            }

            double norm  = NormOps_DDRM.fastNormF(u);
            double gamma = -2.0 / (norm * norm);

            DMatrixRMaj Q = CommonOps_DDRM.identity(u.getNumElements());

            CommonOps_DDRM.multAddTransB(gamma, u, u, Q);

            return(Q);
        }
예제 #5
0
        /**
         * Performs a variety of tests to see if the provided matrix is a valid
         * covariance matrix.
         *
         * @return  0 = is valid 1 = failed positive diagonal, 2 = failed on symmetry, 2 = failed on positive definite
         */
        public static int isValid(DMatrixRMaj cov)
        {
            if (!MatrixFeatures_DDRM.isDiagonalPositive(cov))
            {
                return(1);
            }

            if (!MatrixFeatures_DDRM.isSymmetric(cov, TOL))
            {
                return(2);
            }

            if (!MatrixFeatures_DDRM.isPositiveSemidefinite(cov))
            {
                return(3);
            }

            return(0);
        }
예제 #6
0
 /**
  * An unsafe but faster version of {@link #normP} that calls routines which are faster
  * but more prone to overflow/underflow problems.
  *
  * @param A Vector or matrix whose norm is to be computed.
  * @param p The p value of the p-norm.
  * @return The computed norm.
  */
 public static double fastNormP(DMatrixRMaj A, double p)
 {
     if (p == 1)
     {
         return(normP1(A));
     }
     else if (p == 2)
     {
         return(fastNormP2(A));
     }
     else if (double.IsInfinity(p))
     {
         return(normPInf(A));
     }
     if (MatrixFeatures_DDRM.isVector(A))
     {
         return(fastElementP(A, p));
     }
     else
     {
         throw new ArgumentException("Doesn't support induced norms yet.");
     }
 }
예제 #7
0
 /**
  * This is a fairly light weight check to see of a covariance matrix is valid.
  * It checks to see if the diagonal elements are all positive, which they should be
  * if it is valid.  Not all invalid covariance matrices will be caught by this method.
  *
  * @return true if valid and false if invalid
  */
 public static bool isValidFast(DMatrixRMaj cov)
 {
     return(MatrixFeatures_DDRM.isDiagonalPositive(cov));
 }
예제 #8
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);
        }