public void testSVD() { //BOOST_MESSAGE("Testing singular value decomposition..."); setup(); double tol = 1.0e-12; Matrix[] testMatrices = { M1, M2, M3, M4 }; for (int j = 0; j < testMatrices.Length; j++) { // m >= n required (rows >= columns) Matrix A = testMatrices[j]; SVD svd = new SVD(A); // U is m x n Matrix U = svd.U(); // s is n long Vector s = svd.singularValues(); // S is n x n Matrix S = svd.S(); // V is n x n Matrix V = svd.V(); for (int i = 0; i < S.rows(); i++) { if (S[i, i] != s[i]) { QAssert.Fail("S not consistent with s"); } } // tests Matrix U_Utranspose = Matrix.transpose(U) * U; if (norm(U_Utranspose - I) > tol) { QAssert.Fail("U not orthogonal (norm of U^T*U-I = " + norm(U_Utranspose - I) + ")"); } Matrix V_Vtranspose = Matrix.transpose(V) * V; if (norm(V_Vtranspose - I) > tol) { QAssert.Fail("V not orthogonal (norm of V^T*V-I = " + norm(V_Vtranspose - I) + ")"); } Matrix A_reconstructed = U * S * Matrix.transpose(V); if (norm(A_reconstructed - A) > tol) { QAssert.Fail("Product does not recover A: (norm of U*S*V^T-A = " + norm(A_reconstructed - A) + ")"); } } }
public void testQRSolve() { // Testing QR solve... setup(); double tol = 1.0e-12; MersenneTwisterUniformRng rng = new MersenneTwisterUniformRng(1234); Matrix bigM = new Matrix(50, 100, 0.0); for (int i = 0; i < Math.Min(bigM.rows(), bigM.columns()); ++i) { bigM[i, i] = i + 1.0; } Matrix[] testMatrices = { M1, M2, M3, Matrix.transpose(M3), M4, Matrix.transpose(M4), M5, I, M7,bigM, Matrix.transpose(bigM) }; for (int j = 0; j < testMatrices.Length; j++) { Matrix A = testMatrices[j]; Vector b = new Vector(A.rows()); for (int k = 0; k < 10; ++k) { for (int i = 0; i < b.Count; ++i) { b[i] = rng.next().value; } Vector x = MatrixUtilities.qrSolve(A, b, true); if (A.columns() >= A.rows()) { if (norm(A * x - b) > tol) { QAssert.Fail("A*x does not match vector b (norm = " + norm(A * x - b) + ")"); } } else { // use the SVD to calculate the reference values int n = A.columns(); Vector xr = new Vector(n, 0.0); SVD svd = new SVD(A); Matrix V = svd.V(); Matrix U = svd.U(); Vector w = svd.singularValues(); double threshold = n * Const.QL_EPSILON; for (int i = 0; i < n; ++i) { if (w[i] > threshold) { double u = 0; int zero = 0; for (int kk = 0; kk < U.rows(); kk++) { u += (U[kk, i] * b[zero++]) / w[i]; } for (int jj = 0; jj < n; ++jj) { xr[jj] += u * V[jj, i]; } } } if (norm(xr - x) > tol) { QAssert.Fail("least square solution does not match (norm = " + norm(x - xr) + ")"); } } } } }