public void RandomRectangularSVD() { for (int c = 1; c < 64; c += 11) { Console.WriteLine(c); RectangularMatrix R = GenerateRandomMatrix(64, c); SingularValueDecomposition SVD = R.SingularValueDecomposition(); Assert.IsTrue(SVD.RowCount == R.RowCount); Assert.IsTrue(SVD.ColumnCount == SVD.ColumnCount); Assert.IsTrue(SVD.Dimension == SVD.ColumnCount); // U has right dimensions and is orthogonal SquareMatrix U = SVD.LeftTransformMatrix; Assert.IsTrue(U.Dimension == R.RowCount); Assert.IsTrue(TestUtilities.IsNearlyEqual(U.Transpose * U, UnitMatrix.OfDimension(U.Dimension))); // V has right dimensions and is orthogonal SquareMatrix V = SVD.RightTransformMatrix; Assert.IsTrue(V.Dimension == R.ColumnCount); Assert.IsTrue(TestUtilities.IsNearlyEqual(V.Transpose * V, UnitMatrix.OfDimension(V.Dimension))); // The transforms decompose the matrix with the claimed singular values RectangularMatrix S = U.Transpose * R * V; for (int i = 0; i < SVD.Contributors.Count; i++) { SingularValueContributor t = SVD.Contributors[i]; Assert.IsTrue(t.SingularValue >= 0.0); Assert.IsTrue(TestUtilities.IsNearlyEqual(S[i, i], t.SingularValue)); Assert.IsTrue(TestUtilities.IsNearlyEqual(R * t.RightSingularVector, t.SingularValue * t.LeftSingularVector)); } // We can reconstruct the original matrix from the claimed singular values RectangularMatrix R2 = new RectangularMatrix(SVD.RowCount, SVD.ColumnCount); foreach (SingularValueContributor t in SVD.Contributors) { R2 += t.SingularValue * t.LeftSingularVector * t.RightSingularVector.Transpose; } Assert.IsTrue(TestUtilities.IsNearlyEqual(R, R2)); } }
public void SquareMatrixSVD() { for (int d = 4; d < 64; d += 7) { SquareMatrix A = CreateSquareRandomMatrix(d, d); SingularValueDecomposition SVD = A.SingularValueDecomposition(); Assert.IsTrue(SVD.Dimension == A.Dimension); // U has right dimensions and is orthogonal SquareMatrix U = SVD.LeftTransformMatrix; Assert.IsTrue(U.Dimension == A.Dimension); Assert.IsTrue(TestUtilities.IsNearlyEqual(U.MultiplyTransposeBySelf(), UnitMatrix.OfDimension(U.Dimension))); // V has right dimensions and is orthogonal SquareMatrix V = SVD.RightTransformMatrix; Assert.IsTrue(V.Dimension == A.Dimension); Assert.IsTrue(TestUtilities.IsNearlyEqual(V.MultiplyTransposeBySelf(), UnitMatrix.OfDimension(V.Dimension))); Assert.IsTrue(SVD.Dimension == A.Dimension); // The transforms decompose the matrix with the claimed singular values SquareMatrix S = U.Transpose * A * V; for (int i = 0; i < SVD.Contributors.Count; i++) { SingularValueContributor t = SVD.Contributors[i]; Assert.IsTrue(t.SingularValue >= 0.0); Assert.IsTrue(TestUtilities.IsNearlyEqual(S[i, i], t.SingularValue)); } // We can solve a rhs using the SVD ColumnVector x = new ColumnVector(d); for (int i = 0; i < d; i++) { x[i] = i; } ColumnVector b = A * x; ColumnVector y = SVD.Solve(b); Assert.IsTrue(TestUtilities.IsNearlyEqual(x, y)); } }