/** * Creates a new random symmetric matrix that will have the specified real eigenvalues. * * @param num Dimension of the resulting matrix. * @param rand Random number generator. * @param eigenvalues Set of real eigenvalues that the matrix will have. * @return A random matrix with the specified eigenvalues. */ public static FMatrixRMaj symmetricWithEigenvalues(int num, IMersenneTwister rand, float[] eigenvalues) { FMatrixRMaj V = RandomMatrices_FDRM.orthogonal(num, num, rand); FMatrixRMaj D = CommonOps_FDRM.diag(eigenvalues); FMatrixRMaj temp = new FMatrixRMaj(num, num); CommonOps_FDRM.mult(V, D, temp); CommonOps_FDRM.multTransB(temp, V, D); return(D); }
/** * <p> * Creates a randomly generated set of orthonormal vectors. At most it can generate the same * number of vectors as the dimension of the vectors. * </p> * * <p> * This is done by creating random vectors then ensuring that they are orthogonal * to all the ones previously created with reflectors. * </p> * * <p> * NOTE: This employs a brute force O(N<sup>3</sup>) algorithm. * </p> * * @param dimen dimension of the space which the vectors will span. * @param numVectors How many vectors it should generate. * @param rand Used to create random vectors. * @return Array of N random orthogonal vectors of unit length. */ // is there a faster algorithm out there? This one is a bit sluggish public static FMatrixRMaj[] span(int dimen, int numVectors, IMersenneTwister rand) { if (dimen < numVectors) { throw new ArgumentException("The number of vectors must be less than or equal to the dimension"); } FMatrixRMaj[] u = new FMatrixRMaj[numVectors]; u[0] = RandomMatrices_FDRM.rectangle(dimen, 1, -1, 1, rand); NormOps_FDRM.normalizeF(u[0]); for (int i = 1; i < numVectors; i++) { // Console.WriteLine(" i = "+i); FMatrixRMaj a = new FMatrixRMaj(dimen, 1); FMatrixRMaj r = null; for (int j = 0; j < i; j++) { // Console.WriteLine("j = "+j); if (j == 0) { r = RandomMatrices_FDRM.rectangle(dimen, 1, -1, 1, rand); } // find a vector that is normal to vector j // u[i] = (1/2)*(r + Q[j]*r) a.set(r); VectorVectorMult_FDRM.householder(-2.0f, u[j], r, a); CommonOps_FDRM.add(r, a, a); CommonOps_FDRM.scale(0.5f, a); // UtilEjml.print(a); FMatrixRMaj t = a; a = r; r = t; // normalize it so it doesn't get too small float val = NormOps_FDRM.normF(r); if (val == 0 || float.IsNaN(val) || float.IsInfinity(val)) { throw new InvalidOperationException("Failed sanity check"); } CommonOps_FDRM.divide(r, val); } u[i] = r; } return(u); }
/** * <p> * Creates a random matrix which will have the provided singular values. The length of sv * is assumed to be the rank of the matrix. This can be useful for testing purposes when one * needs to ensure that a matrix is not singular but randomly generated. * </p> * * @param numRows Number of rows in generated matrix. * @param numCols NUmber of columns in generated matrix. * @param rand Random number generator. * @param sv Singular values of the matrix. * @return A new matrix with the specified singular values. */ public static FMatrixRMaj singleValues(int numRows, int numCols, IMersenneTwister rand, float[] sv) { FMatrixRMaj U = RandomMatrices_FDRM.orthogonal(numRows, numRows, rand); FMatrixRMaj V = RandomMatrices_FDRM.orthogonal(numCols, numCols, rand); FMatrixRMaj S = new FMatrixRMaj(numRows, numCols); int min = Math.Min(numRows, numCols); min = Math.Min(min, sv.Length); for (int i = 0; i < min; i++) { S.set(i, i, sv[i]); } FMatrixRMaj tmp = new FMatrixRMaj(numRows, numCols); CommonOps_FDRM.mult(U, S, tmp); CommonOps_FDRM.multTransB(tmp, V, S); return(S); }