/** * Returns a copy of the found homography matrix. * @return Homography matrix. */ public DMatrixRMaj getHomography() { return found.copy(); } }
@Override public DMatrixRMaj getL(DMatrixRMaj L) { if( L == null ) { L = this.L.copy(); } else { L.set(this.L); } return L; }
/** * Computes the SVD of A and extracts the homography matrix from its null space */ protected boolean computeH(DMatrixRMaj A, DMatrixRMaj H) { if( !solverNullspace.process(A.copy(),1,H) ) return true; H.numRows = 3; H.numCols = 3; return false; }
@Override public DMatrixRMaj convertB(DMatrixRMaj A) { return A.copy(); }
@Override public DMatrixRMaj convertA(DMatrixRMaj A) { return A.copy(); }
/** * Computes the rank of a matrix using the specified tolerance. * * @param A Matrix whose rank is to be calculated. Not modified. * @param threshold The numerical threshold used to determine a singular value. * @return The matrix's rank. */ public static int rank(DMatrixRMaj A , double threshold ) { SingularValueDecomposition_F64<DMatrixRMaj> svd = DecompositionFactory_DDRM.svd(A.numRows,A.numCols,false,false,true); if( svd.inputModified() ) A = A.copy(); if( !svd.decompose(A) ) throw new RuntimeException("Decomposition failed"); return SingularOps_DDRM.rank(svd, threshold); }
/** * Computes the nullity of a matrix using the specified tolerance. * * @param A Matrix whose rank is to be calculated. Not modified. * @param threshold The numerical threshold used to determine a singular value. * @return The matrix's nullity. */ public static int nullity(DMatrixRMaj A , double threshold ) { SingularValueDecomposition_F64<DMatrixRMaj> svd = DecompositionFactory_DDRM.svd(A.numRows,A.numCols,false,false,true); if( svd.inputModified() ) A = A.copy(); if( !svd.decompose(A) ) throw new RuntimeException("Decomposition failed"); return SingularOps_DDRM.nullity(svd,threshold); }
/** * Checks to see if the rows of the provided matrix are linearly independent. * * @param A Matrix whose rows are being tested for linear independence. * @return true if linearly independent and false otherwise. */ public static boolean isRowsLinearIndependent( DMatrixRMaj A ) { // LU decomposition LUDecomposition<DMatrixRMaj> lu = DecompositionFactory_DDRM.lu(A.numRows,A.numCols); if( lu.inputModified() ) A = A.copy(); if( !lu.decompose(A)) throw new RuntimeException("Decompositon failed?"); // if they are linearly independent it should not be singular return !lu.isSingular(); }
/** * Returns an array of all the singular values in A sorted in ascending order * * @param A Matrix. Not modified. * @return singular values */ public static double[] singularValues( DMatrixRMaj A ) { SingularValueDecomposition_F64<DMatrixRMaj> svd = DecompositionFactory_DDRM.svd(A.numRows,A.numCols,false,true,true); if( svd.inputModified() ) { A = A.copy(); } if( !svd.decompose(A)) { throw new RuntimeException("SVD Failed!"); } double sv[] = svd.getSingularValues(); Arrays.sort(sv,0,svd.numberOfSingularValues()); // change the ordering to ascending for (int i = 0; i < sv.length/2; i++) { double tmp = sv[i]; sv[i] = sv[sv.length-i-1]; sv[sv.length-i-1] = tmp; } return sv; }
/** * <p> * Computes the Moore-Penrose pseudo-inverse:<br> * <br> * pinv(A) = (A<sup>T</sup>A)<sup>-1</sup> A<sup>T</sup><br> * or<br> * pinv(A) = A<sup>T</sup>(AA<sup>T</sup>)<sup>-1</sup><br> * </p> * <p> * Internally it uses {@link SolvePseudoInverseSvd_DDRM} to compute the inverse. For performance reasons, this should only * be used when a matrix is singular or nearly singular. * </p> * @param A A m by n Matrix. Not modified. * @param invA Where the computed pseudo inverse is stored. n by m. Modified. */ public static void pinv(DMatrixRMaj A , DMatrixRMaj invA ) { LinearSolverDense<DMatrixRMaj> solver = LinearSolverFactory_DDRM.pseudoInverse(true); if( solver.modifiesA()) A = A.copy(); if( !solver.setA(A) ) throw new IllegalArgumentException("Invert failed, maybe a bug?"); solver.invert(invA); }
/** * Creates a random distribution with the specified mean and covariance. The references * to the variables are not saved, their value are copied. * * @param rand Used to create the random numbers for the draw. Reference is saved. * @param cov The covariance of the distribution. Not modified. */ public CovarianceRandomDraw_DDRM(Random rand , DMatrixRMaj cov ) { r = new DMatrixRMaj(cov.numRows,1); CholeskyDecompositionInner_DDRM cholesky = new CholeskyDecompositionInner_DDRM( true); if( cholesky.inputModified() ) cov = cov.copy(); if( !cholesky.decompose(cov) ) throw new RuntimeException("Decomposition failed!"); A = cholesky.getT(); this.rand = rand; }
/** * <p> * Checks to see if the matrix is positive definite. * </p> * <p> * x<sup>T</sup> A x > 0<br> * for all x where x is a non-zero vector and A is a symmetric matrix. * </p> * * @param A square symmetric matrix. Not modified. * * @return True if it is positive definite and false if it is not. */ public static boolean isPositiveDefinite( DMatrixRMaj A ) { if( !isSquare(A)) return false; CholeskyDecompositionInner_DDRM chol = new CholeskyDecompositionInner_DDRM(true); if( chol.inputModified() ) A = A.copy(); return chol.decompose(A); }
public void setup( DMatrixRMaj A ) { if( A.numRows != A.numCols ) throw new RuntimeException("Must be square") ; if( N != A.numRows ) { N = A.numRows; this.A = A.copy(); u = new DMatrixRMaj(A.numRows,1); _temp = new DMatrixRMaj(A.numRows,1); numStepsFind = new int[ A.numRows ]; } else { this.A.set(A); UtilEjml.memset(numStepsFind,0,numStepsFind.length); } // zero all the off numbers that should be zero for a hessenberg matrix for( int i = 2; i < N; i++ ) { for( int j = 0; j < i-1; j++ ) { this.A.set(i,j,0); } } eigenvalues = new Complex_F64[ A.numRows ]; for( int i = 0; i < eigenvalues.length; i++ ) { eigenvalues[i] = new Complex_F64(); } numEigen = 0; lastExceptional = 0; numExceptional = 0; steps = 0; }
/** * Returns the matrix's rank. Automatic selection of threshold * * @param A Matrix. Not modified. * @return The rank of the decomposed matrix. */ public static int rank( DMatrixRMaj A ) { SingularValueDecomposition_F64<DMatrixRMaj> svd = DecompositionFactory_DDRM.svd(A.numRows,A.numCols,false,true,true); if( svd.inputModified() ) { A = A.copy(); } if( !svd.decompose(A)) { throw new RuntimeException("SVD Failed!"); } int N = svd.numberOfSingularValues(); double sv[] = svd.getSingularValues(); double threshold = singularThreshold(sv,N); int count = 0; for (int i = 0; i < sv.length; i++) { if( sv[i] >= threshold ) { count++; } } return count; }
@Test public void inverseUpdate() { int N = 6; DMatrixRMaj H = RandomMatrices_DDRM.symmetric(N,-1,1,rand); DMatrixRMaj s = RandomMatrices_DDRM.rectangle(N,1,-1,1,rand); DMatrixRMaj y = RandomMatrices_DDRM.rectangle(N,1,-1,1,rand); DMatrixRMaj tempV0 = new DMatrixRMaj(N,1); DMatrixRMaj tempV1 = new DMatrixRMaj(N,1); DMatrixRMaj expected = H.copy(); DMatrixRMaj found = H.copy(); naiveInverseUpdate(expected, s, y); EquationsBFGS.inverseUpdate(found,s,y.copy(),tempV0,tempV1); assertTrue(MatrixFeatures_DDRM.isIdentical(expected, found, 1e-8)); }
@Test public void undoHessianScalingOnParameters() { MockGaussNewtonBase_F64 alg = new MockGaussNewtonBase_F64(); alg.hessianScaling = new DMatrixRMaj(new double[][]{{1},{0.1},{2},{0.6}}); DMatrixRMaj p = RandomMatrices_DDRM.rectangle(4,1,-1,2,rand); DMatrixRMaj o = p.copy(); alg.undoHessianScalingOnParameters(p); for (int row = 0; row < 4; row++) { double expected = o.get(row, 0) / alg.hessianScaling.get(row); assertEquals(expected, p.get(row), UtilEjml.TEST_F64); } }
@Test public void applyHessianScaling() { MockGaussNewtonBase_F64 alg = new MockGaussNewtonBase_F64(); DMatrixRMaj H = ((HessianMath_DDRM)alg.hessian).getHessian(); H.reshape(4,4); alg.gradient = RandomMatrices_DDRM.rectangle(4,1,-1,2,rand); RandomMatrices_DDRM.fillUniform(H,rand); DMatrixRMaj _g = alg.gradient.copy(); DMatrixRMaj _H = H.copy(); alg.hessianScaling = new DMatrixRMaj(new double[][]{{1},{0.1},{2},{0.6}}); alg.applyHessianScaling(); for (int row = 0; row < 4; row++) { double expected = _g.get(row,0)/alg.hessianScaling.get(row); assertEquals(expected, alg.gradient.get(row), UtilEjml.TEST_F64); for (int col = 0; col < 4; col++) { expected = _H.get(row,col)/(alg.hessianScaling.get(row)*alg.hessianScaling.get(col)); assertEquals(expected, H.get(row,col), UtilEjml.TEST_F64); } } }
@Test public void divideRowsCols() { DMatrixRMaj M = RandomMatrices_DDRM.symmetricPosDef(10,rand); DMatrixRMaj scale = RandomMatrices_DDRM.rectangle(10,1,0,1,rand); DMatrixRMaj expected = M.copy(); CommonOps_DDRM.divideRows(scale.data,expected); CommonOps_DDRM.divideCols(expected,scale.data); setHessian(alg,M); alg.divideRowsCols(scale); // Not a great unit test since it doesn't check the off diagonal elements DMatrixRMaj found = RandomMatrices_DDRM.rectangle(10,1,rand); alg.extractDiagonals(found); for (int i = 0; i < M.numRows; i++) { assertEquals(expected.get(i,i),found.get(i), UtilEjml.TEST_F64); } }
@Test public void update() { Equation eq = new Equation(); eq.process("H=rand(5,5)"); eq.process("y=rand(5,1)"); eq.process("s=rand(5,1)"); eq.process("tmp=y'*s"); eq.process("p=1.0/tmp(0,0)"); eq.process("I=eye(5)"); eq.process("H_k= (I - p*y*s')*H*(I - p*s*y') + p*y*y'"); DMatrixRMaj H = eq.lookupDDRM("H"); DMatrixRMaj y = eq.lookupDDRM("y"); DMatrixRMaj s = eq.lookupDDRM("s"); DMatrixRMaj H_k = eq.lookupDDRM("H_k"); DMatrixRMaj found = H.copy(); EquationsBFGS.update(found,s,y, new DMatrixRMaj(1,1),new DMatrixRMaj(1,1)); assertTrue(MatrixFeatures_DDRM.isIdentical(H_k,found, UtilEjml.TEST_F64)); }
@Test public void solve() { DMatrixRMaj M = RandomMatrices_DDRM.symmetricPosDef(10,rand); DMatrixRMaj v = RandomMatrices_DDRM.rectangle(10,1,rand); DMatrixRMaj origv = v.copy(); DMatrixRMaj expected = v.createLike(); CommonOps_DDRM.solve(M,v,expected); DMatrixRMaj found = v.createLike(); alg.init(M.numCols); setHessian(alg,M); assertTrue(alg.initializeSolver()); assertTrue(alg.solve(v,found)); // make sure it didn't modify the input assertTrue(MatrixFeatures_DDRM.isIdentical(origv,origv,UtilEjml.TEST_F64)); // check the solution assertTrue(MatrixFeatures_DDRM.isIdentical(expected,found,UtilEjml.TEST_F64)); // run it again, if nothing was modified it should produce the same solution assertTrue(alg.initializeSolver()); assertTrue(alg.solve(v,found)); assertTrue(MatrixFeatures_DDRM.isIdentical(expected,found,UtilEjml.TEST_F64)); }