public bool setA(T A) { if (alg.modifiesA()) { this.A = (T)UtilEjml.reshapeOrDeclare(this.A, A); this.A.To = A; return(alg.setA(this.A)); } return(alg.setA(A)); }
public bool setA(DMatrixRMaj A) { blockA.reshape(A.numRows, A.numCols, false); MatrixOps_DDRB.convert(A, blockA); return(alg.setA(blockA)); }
//@Override public void update(DMatrixRMaj z, DMatrixRMaj R) { // y = z - H x CommonOps_DDRM.mult(H, x, y); CommonOps_DDRM.subtract(z, y, y); // S = H P H' + R CommonOps_DDRM.mult(H, P, c); CommonOps_DDRM.multTransB(c, H, S); CommonOps_DDRM.addEquals(S, R); // K = PH'S^(-1) if (!solver.setA(S)) { throw new InvalidOperationException("Invert failed"); } solver.invert(S_inv); CommonOps_DDRM.multTransA(H, S_inv, d); CommonOps_DDRM.mult(P, d, K); // x = x + Ky CommonOps_DDRM.mult(K, y, a); CommonOps_DDRM.addEquals(x, a); // P = (I-kH)P = P - (KH)P = P-K(HP) CommonOps_DDRM.mult(H, P, c); CommonOps_DDRM.mult(K, c, b); CommonOps_DDRM.subtractEquals(P, b); }
public virtual bool setA(T A) { if (alg.modifiesA()) { if (this.A == null) { this.A = (T)A.copy(); } else { if (this.A.getNumRows() != A.getNumRows() || this.A.getNumCols() != A.getNumCols()) { this.A.reshape(A.getNumRows(), A.getNumCols()); } this.A.set(A); } return(alg.setA(this.A)); } return(alg.setA(A)); }
/** * <p> * Performs a matrix inversion operation on the specified matrix and stores the results * in the same matrix.<br> * <br> * a = a<sup>-1</sup> * </p> * * <p> * If the algorithm could not invert the matrix then false is returned. If it returns true * that just means the algorithm finished. The results could still be bad * because the matrix is singular or nearly singular. * </p> * * @param A The matrix that is to be inverted. Results are stored here. Modified. * @return true if it could invert the matrix false if it could not. */ public static bool invert(CMatrixRMaj A) { LinearSolverDense <CMatrixRMaj> solver = LinearSolverFactory_CDRM.lu(A.numRows); if (solver.setA(A)) { solver.invert(A); } else { return(false); } return(true); }
/** * <p> * Performs a matrix inversion operation that does not modify the original * and stores the results in another matrix. The two matrices must have the * same dimension.<br> * <br> * b = a<sup>-1</sup> * </p> * * <p> * If the algorithm could not invert the matrix then false is returned. If it returns true * that just means the algorithm finished. The results could still be bad * because the matrix is singular or nearly singular. * </p> * * <p> * For medium to large matrices there might be a slight performance boost to using * {@link LinearSolverFactory_CDRM} instead. * </p> * * @param input The matrix that is to be inverted. Not modified. * @param output Where the inverse matrix is stored. Modified. * @return true if it could invert the matrix false if it could not. */ public static bool invert(CMatrixRMaj input, CMatrixRMaj output) { LinearSolverDense <CMatrixRMaj> solver = LinearSolverFactory_CDRM.lu(input.numRows); if (solver.modifiesA()) { input = (CMatrixRMaj)input.copy(); } if (!solver.setA(input)) { return(false); } solver.invert(output); return(true); }
public override /**/ double quality() { return(SpecializedOps_FDRM.qualityTriangular(R)); } /** * <p> * Upgrades the basic solution to the optimal 2-norm solution. * </p> * * <pre> * First solves for 'z' * * || x_b - P*[ R_11^-1 * R_12 ] * z ||2 * min z || [ - I_{n-r} ] || * * </pre> * * @param X basic solution, also output solution */ protected void upgradeSolution(FMatrixRMaj X) { FMatrixRMaj z = Y; // recycle Y // compute the z which will minimize the 2-norm of X // because of the identity matrix tacked onto the end 'A' should never be singular if (!internalSolver.setA(W)) { throw new InvalidOperationException("This should never happen. Is input NaN?"); } z.reshape(numCols - rank, 1); internalSolver.solve(X, z); // compute X by tweaking the original CommonOps_FDRM.multAdd(-1, W, z, X); }
/** * 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(FMatrixRMaj A, float alpha) { initPower(A); LinearSolverDense <FMatrixRMaj> solver = LinearSolverFactory_FDRM.linear(A.numCols); SpecializedOps_FDRM.addIdentity(A, B, -alpha); solver.setA(B); bool converged = false; for (int i = 0; i < maxIterations && !converged; i++) { solver.solve(q0, q1); float s = NormOps_FDRM.normPInf(q1); CommonOps_FDRM.divide(q1, s, q2); converged = checkConverged(A); } return(converged); }
private void solveWithLU(float real, int index, FMatrixRMaj r) { FMatrixRMaj A = new FMatrixRMaj(index, index); CommonOps_FDRM.extract(_implicit.A, 0, index, 0, index, A, 0, 0); for (int i = 0; i < index; i++) { A.add(i, i, -real); } r.reshape(index, 1, false); SpecializedOps_FDRM.subvector(_implicit.A, 0, index, index, false, 0, r); CommonOps_FDRM.changeSign(r); // TODO this must be very inefficient if (!solver.setA(A)) { throw new InvalidOperationException("Solve failed"); } solver.solve(r, r); }
/** * <p> * Given an eigenvalue it computes an eigenvector using inverse iteration: * <br> * for i=1:MAX {<br> * (A - μI)z<sup>(i)</sup> = q<sup>(i-1)</sup><br> * q<sup>(i)</sup> = z<sup>(i)</sup> / ||z<sup>(i)</sup>||<br> * λ<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 FEigenpair computeEigenVector(FMatrixRMaj A, float eigenvalue) { if (A.numRows != A.numCols) { throw new ArgumentException("Must be a square matrix."); } FMatrixRMaj M = new FMatrixRMaj(A.numRows, A.numCols); FMatrixRMaj x = new FMatrixRMaj(A.numRows, 1); FMatrixRMaj b = new FMatrixRMaj(A.numRows, 1); CommonOps_FDRM.fill(b, 1); // perturb the eigenvalue slightly so that its not an exact solution the first time // eigenvalue -= eigenvalue*UtilEjml.F_EPS*10; float origEigenvalue = eigenvalue; SpecializedOps_FDRM.addIdentity(A, M, -eigenvalue); float threshold = NormOps_FDRM.normPInf(A) * UtilEjml.F_EPS; float prevError = float.MaxValue; bool hasWorked = false; LinearSolverDense <FMatrixRMaj> solver = LinearSolverFactory_FDRM.linear(M.numRows); float perp = 0.0001f; 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_FDRM.hasUncountable(x)) { failed = true; } if (failed) { if (!hasWorked) { // if it failed on the first trial try perturbing it some more float val = i % 2 == 0 ? 1.0f - perp : 1.0f + perp; // maybe this should be turn into a parameter allowing the user // to configure the wise of each step eigenvalue = origEigenvalue * (float)Math.Pow(val, i / 2 + 1); SpecializedOps_FDRM.addIdentity(A, M, -eigenvalue); } else { // otherwise assume that it was so accurate that the matrix was singular // and return that result return(new FEigenpair(eigenvalue, b)); } } else { hasWorked = true; b.set(x); NormOps_FDRM.normalizeF(b); // compute the residual CommonOps_FDRM.mult(M, b, x); float error = NormOps_FDRM.normPInf(x); if (error - prevError > UtilEjml.F_EPS * 10) { // if the error increased it is probably converging towards a different // eigenvalue // CommonOps.set(b,1); prevError = float.MaxValue; hasWorked = false; float val = i % 2 == 0 ? 1.0f - perp : 1.0f + perp; eigenvalue = origEigenvalue * (float)Math.Pow(val, 1); } else { // see if it has converged if (error <= threshold || Math.Abs(prevError - error) <= UtilEjml.F_EPS) { return(new FEigenpair(eigenvalue, b)); } // update everything prevError = error; eigenvalue = VectorVectorMult_FDRM.innerProdA(b, A, b); } SpecializedOps_FDRM.addIdentity(A, M, -eigenvalue); } } return(null); }