/** * <p> * Computes a metric which measures the the quality of an eigen value decomposition. If a * value is returned that is close to or smaller than 1e-15 then it is within machine precision. * </p> * <p> * EVD quality is defined as:<br> * <br> * Quality = ||A*V - V*D|| / ||A*V||. * </p> * * @param orig The original matrix. Not modified. * @param eig EVD of the original matrix. Not modified. * @return The quality of the decomposition. */ public static double quality(DMatrixRMaj orig, EigenDecomposition_F64 <DMatrixRMaj> eig) { DMatrixRMaj A = orig; DMatrixRMaj V = EigenOps_DDRM.createMatrixV(eig); DMatrixRMaj D = EigenOps_DDRM.createMatrixD(eig); // L = A*V DMatrixRMaj L = new DMatrixRMaj(A.numRows, V.numCols); CommonOps_DDRM.mult(A, V, L); // R = V*D DMatrixRMaj R = new DMatrixRMaj(V.numRows, D.numCols); CommonOps_DDRM.mult(V, D, R); DMatrixRMaj diff = new DMatrixRMaj(L.numRows, L.numCols); CommonOps_DDRM.subtract(L, R, diff); double top = NormOps_DDRM.normF(diff); double bottom = NormOps_DDRM.normF(L); double error = top / bottom; return(error); }
/** * Computes the QR decomposition of the provided matrix. * * @param A Matrix which is to be decomposed. Not modified. */ public void decompose(DMatrixRMaj A) { Equation.Equation eq = new Equation.Equation(); this.QR = (DMatrixRMaj)A.copy(); int N = Math.Min(A.numCols, A.numRows); gammas = new double[A.numCols]; for (int i = 0; i < N; i++) { // update temporary variables eq.alias(QR.numRows - i, "Ni", QR, "QR", i, "i"); // Place the column that should be zeroed into v eq.process("v=QR(i:,i)"); eq.process("maxV=max(abs(v))"); // Note that v is lazily created above. Need direct access to it, which is done below. DMatrixRMaj v = eq.lookupMatrix("v"); double maxV = eq.lookupDouble("maxV"); if (maxV > 0 && v.getNumElements() > 1) { // normalize to reduce overflow issues eq.process("v=v/maxV"); // compute the magnitude of the vector double tau = NormOps_DDRM.normF(v); if (v.get(0) < 0) { tau *= -1.0; } eq.alias(tau, "tau"); eq.process("u_0 = v(0,0)+tau"); eq.process("gamma = u_0/tau"); eq.process("v=v/u_0"); eq.process("v(0,0)=1"); eq.process("QR(i:,i:) = (eye(Ni) - gamma*v*v')*QR(i:,i:)"); eq.process("QR(i:,i) = v"); eq.process("QR(i,i) = -1*tau*maxV"); // save gamma for recomputing Q later on gammas[i] = eq.lookupDouble("gamma"); } } }
/** * Computes the dot product of each basis vector against the sample. Can be used as a measure * for membership in the training sample set. High values correspond to a better fit. * * @param sample Sample of original data. * @return Higher value indicates it is more likely to be a member of input dataset. */ public double response(double[] sample) { if (sample.Length != A.numCols) { throw new ArgumentException("Expected input vector to be in sample space"); } DMatrixRMaj dots = new DMatrixRMaj(numComponents, 1); DMatrixRMaj s = DMatrixRMaj.wrap(A.numCols, 1, sample); CommonOps_DDRM.mult(V_t, s, dots); return(NormOps_DDRM.normF(dots)); }
public static double quality(DMatrixRMaj orig, DMatrixRMaj U, DMatrixRMaj W, DMatrixRMaj Vt) { // foundA = U*W*Vt DMatrixRMaj UW = new DMatrixRMaj(U.numRows, W.numCols); CommonOps_DDRM.mult(U, W, UW); DMatrixRMaj foundA = new DMatrixRMaj(UW.numRows, Vt.numCols); CommonOps_DDRM.mult(UW, Vt, foundA); double normA = NormOps_DDRM.normF(foundA); return(SpecializedOps_DDRM.diffNormF(orig, foundA) / normA); }
/** * This method computes the eigen vector with the largest eigen value by using the * direct power method. This technique is the easiest to implement, but the slowest to converge. * Works only if all the eigenvalues are real. * * @param A The matrix. Not modified. * @return If it converged or not. */ public bool computeDirect(DMatrixRMaj A) { initPower(A); bool converged = false; for (int i = 0; i < maxIterations && !converged; i++) { // q0.print(); CommonOps_DDRM.mult(A, q0, q1); double s = NormOps_DDRM.normPInf(q1); CommonOps_DDRM.divide(q1, s, q2); converged = checkConverged(A); } return(converged); }
private void solveEigenvectorDuplicateEigenvalue(double real, int first, bool isTriangle) { double scale = Math.Abs(real); if (scale == 0) { scale = 1; } eigenvectorTemp.reshape(N, 1, false); eigenvectorTemp.zero(); if (first > 0) { if (isTriangle) { solveUsingTriangle(real, first, eigenvectorTemp); } else { solveWithLU(real, first, eigenvectorTemp); } } eigenvectorTemp.reshape(N, 1, false); for (int i = first; i < N; i++) { Complex_F64 c = _implicit.eigenvalues[N - i - 1]; if (c.isReal() && Math.Abs(c.real - real) / scale < 100.0 * UtilEjml.EPS) { eigenvectorTemp.data[i] = 1; DMatrixRMaj v = new DMatrixRMaj(N, 1); CommonOps_DDRM.multTransA(Q, eigenvectorTemp, v); eigenvectors[N - i - 1] = v; NormOps_DDRM.normalizeF(v); eigenvectorTemp.data[i] = 0; } } }
/** * Computes the most dominant eigen vector of A using an inverted shifted matrix. * The inverted shifted matrix is defined as <b>B = (A - αI)<sup>-1</sup></b> and * can converge faster if α is chosen wisely. * * @param A An invertible square matrix matrix. * @param alpha Shifting factor. * @return If it converged or not. */ public bool computeShiftInvert(DMatrixRMaj A, double alpha) { initPower(A); LinearSolverDense <DMatrixRMaj> solver = LinearSolverFactory_DDRM.linear(A.numCols); SpecializedOps_DDRM.addIdentity(A, B, -alpha); solver.setA(B); bool converged = false; for (int i = 0; i < maxIterations && !converged; i++) { solver.solve(q0, q1); double s = NormOps_DDRM.normPInf(q1); CommonOps_DDRM.divide(q1, s, q2); converged = checkConverged(A); } return(converged); }
public virtual double conditionP2(DMatrixRMaj A) { return(NormOps_DDRM.conditionP2(A)); }
public virtual double normF(DMatrixRMaj A) { return(NormOps_DDRM.normF(A)); }
public static void main(String[] args) { IMersenneTwister rand = new MersenneTwisterFast(234); // easy to work with sparse format, but hard to do computations with DMatrixSparseTriplet work = new DMatrixSparseTriplet(5, 4, 5); work.addItem(0, 1, 1.2); work.addItem(3, 0, 3); work.addItem(1, 1, 22.21234); work.addItem(2, 3, 6); // convert into a format that's easier to perform math with DMatrixSparseCSC Z = ConvertDMatrixStruct.convert(work, (DMatrixSparseCSC)null); // print the matrix to standard out in two different formats Z.print(); Console.WriteLine(); Z.printNonZero(); Console.WriteLine(); // Create a large matrix that is 5% filled DMatrixSparseCSC A = RandomMatrices_DSCC.rectangle(ROWS, COLS, (int)(ROWS * COLS * 0.05), rand); // large vector that is 70% filled DMatrixSparseCSC x = RandomMatrices_DSCC.rectangle(COLS, XCOLS, (int)(XCOLS * COLS * 0.7), rand); Console.WriteLine("Done generating random matrices"); // storage for the initial solution DMatrixSparseCSC y = new DMatrixSparseCSC(ROWS, XCOLS, 0); DMatrixSparseCSC z = new DMatrixSparseCSC(ROWS, XCOLS, 0); // To demonstration how to perform sparse math let's multiply: // y=A*x // Optional storage is set to null so that it will declare it internally long before = DateTimeHelper.CurrentTimeMilliseconds; IGrowArray workA = new IGrowArray(A.numRows); DGrowArray workB = new DGrowArray(A.numRows); for (int i = 0; i < 100; i++) { CommonOps_DSCC.mult(A, x, y, workA, workB); CommonOps_DSCC.add(1.5, y, 0.75, y, z, workA, workB); } long after = DateTimeHelper.CurrentTimeMilliseconds; Console.WriteLine("norm = " + NormOps_DSCC.fastNormF(y) + " sparse time = " + (after - before) + " ms"); DMatrixRMaj Ad = ConvertDMatrixStruct.convert(A, (DMatrixRMaj)null); DMatrixRMaj xd = ConvertDMatrixStruct.convert(x, (DMatrixRMaj)null); DMatrixRMaj yd = new DMatrixRMaj(y.numRows, y.numCols); DMatrixRMaj zd = new DMatrixRMaj(y.numRows, y.numCols); before = DateTimeHelper.CurrentTimeMilliseconds; for (int i = 0; i < 100; i++) { CommonOps_DDRM.mult(Ad, xd, yd); CommonOps_DDRM.add(1.5, yd, 0.75, yd, zd); } after = DateTimeHelper.CurrentTimeMilliseconds; Console.WriteLine("norm = " + NormOps_DDRM.fastNormF(yd) + " dense time = " + (after - before) + " ms"); }
/** * Computes the QR decomposition of the provided matrix. * * @param A Matrix which is to be decomposed. Not modified. */ public void decompose(DMatrixRMaj A) { this.QR = (DMatrixRMaj)A.copy(); int N = Math.Min(A.numCols, A.numRows); gammas = new double[A.numCols]; DMatrixRMaj A_small = new DMatrixRMaj(A.numRows, A.numCols); DMatrixRMaj A_mod = new DMatrixRMaj(A.numRows, A.numCols); DMatrixRMaj v = new DMatrixRMaj(A.numRows, 1); DMatrixRMaj Q_k = new DMatrixRMaj(A.numRows, A.numRows); for (int i = 0; i < N; i++) { // reshape temporary variables A_small.reshape(QR.numRows - i, QR.numCols - i, false); A_mod.reshape(A_small.numRows, A_small.numCols, false); v.reshape(A_small.numRows, 1, false); Q_k.reshape(v.getNumElements(), v.getNumElements(), false); // use extract matrix to get the column that is to be zeroed CommonOps_DDRM.extract(QR, i, QR.numRows, i, i + 1, v, 0, 0); double max = CommonOps_DDRM.elementMaxAbs(v); if (max > 0 && v.getNumElements() > 1) { // normalize to reduce overflow issues CommonOps_DDRM.divide(v, max); // compute the magnitude of the vector double tau = NormOps_DDRM.normF(v); if (v.get(0) < 0) { tau *= -1.0; } double u_0 = v.get(0) + tau; double gamma = u_0 / tau; CommonOps_DDRM.divide(v, u_0); v.set(0, 1.0); // extract the submatrix of A which is being operated on CommonOps_DDRM.extract(QR, i, QR.numRows, i, QR.numCols, A_small, 0, 0); // A = (I - γ*u*u<sup>T</sup>)A CommonOps_DDRM.setIdentity(Q_k); CommonOps_DDRM.multAddTransB(-gamma, v, v, Q_k); CommonOps_DDRM.mult(Q_k, A_small, A_mod); // save the results CommonOps_DDRM.insert(A_mod, QR, i, i); CommonOps_DDRM.insert(v, QR, i, i); QR.unsafe_set(i, i, -tau * max); // save gamma for recomputing Q later on gammas[i] = gamma; } } }