using System; using CenterSpace.NMath.Core; namespace CenterSpace.NMath.Examples.CSharp { /// <summary> /// A .NET example in C# demonstrating the features of the singular value decomposition (SVD) classes. /// </summary> class SVDecompExample { static void Main( string[] args ) { // A general m x n system with random entries. var rng = new RandGenUniform( -1, 1 ); rng.Reset( 0x124 ); int rows = 6; int cols = 3; var A = new DoubleComplexMatrix( rows, cols, rng ); // Construct a SV decomposition of A. var decomp = new DoubleComplexSVDecomp( A ); Console.WriteLine(); // Look at the components of the factorization A = USV. Console.WriteLine( "U = " ); Console.WriteLine( decomp.LeftVectors.ToTabDelimited( "G3" ) ); Console.WriteLine( "B = " ); Console.WriteLine( decomp.RightVectors.ToTabDelimited( "G3" ) ); Console.WriteLine( "s = {0}", decomp.SingularValues ); // U = // (-0.177,0.467) (-0.204,0.0897) (0.0996,-0.151) // (0.102,0.0811) (0.211,0.12) (0.0504,-0.243) // (0.0774,-0.56) (-0.261,0.0474) (0.133,0.382) // (0.247,-0.152) (0.026,0.287) (-0.449,-0.173) // (0.13,-0.513) (0.165,-0.241) (0.287,-0.644) // (-0.147,-0.168) (0.298,0.751) (-0.0955,-0.0581) // B = // (0.556,0) (0.674,0) (-0.486,0) // (-0.644,-0.174) (0.512,-0.214) (-0.0265,-0.496) // (-0.454,0.199) (0.336,0.353) (-0.0537,0.717) // s = [ 2.30473458507626 1.59555281597513 1.05912909184625 ] // // Note that the singular values, elements on the main diagonal of // the diagonal matrix S, are returned as a vector. // The class DoubleComplexSVDecompServer allows more control over the // computation. Suppose that you are only interested in the singular values, // not the vectors. You can configure a DoubleComplexSVDecompServer object // to compute just the singular values. var decompServer = new DoubleComplexSVDecompServer(); decompServer.ComputeLeftVectors = false; decompServer.ComputeRightVectors = false; decomp = decompServer.GetDecomp( A ); Console.WriteLine(); Console.WriteLine( "Number of left vectors computed: {0}", decomp.NumberLeftVectors ); // 0 Console.WriteLine(); Console.WriteLine( "Number of right vectors computed: {0}", decomp.NumberRightVectors ); // 0 // By default, the "reduced" SVD is computed; that is, if A is m x n, then U // is m x n. The "full" SVD is obtained by adjoining an additional m-n // (assuming m > n) orthonormal columns to U making it a m x m unitary matrix. // The singular value decomposition server object can be configured to // compute the full SVD as follows: decompServer.ComputeLeftVectors = true; decompServer.ComputeFull = true; decomp = decompServer.GetDecomp( A ); Console.WriteLine(); Console.WriteLine( "Full SVD, U = " ); Console.WriteLine( decomp.LeftVectors.ToTabDelimited( "G5" ) ); // Full SVD, U = // (-0.17729,0.46733) (-0.20351,0.089678) (0.099576,-0.15138) (0.15718,-0.15252) (0.62805,0.4364) (-0.052634,-0.17958) // (0.10202,0.081075) (0.21072,0.11971) (0.0504,-0.2434) (-0.1824,0.22817) (-0.081697,0.34255) (-0.60561,0.53516) // (0.077361,-0.55956) (-0.26138,0.047439) (0.13273,0.38226) (0.038401,0.41859) (0.431,0.038413) (-0.2681,-0.10388) // (0.24748,-0.15212) (0.026012,0.28707) (-0.44923,-0.17313) (0.70087,-0.030787) (-0.1625,0.13184) (-0.17238,-0.1873) // (0.12984,-0.51288) (0.16486,-0.24073) (0.28688,-0.64427) (-0.073218,-0.25794) (0.1492,0.089866) (0.038802,-0.18397) // (-0.14678,-0.16813) (0.29846,0.75096) (-0.095458,-0.058056) (-0.33519,0.11664) (0.071816,0.15674) (0.33872,-0.11948) // You can also set a tolerance for the singular values. Singular values // whose value is less than the tolerance are set to zero. The number of // singular vectors are adjusted accordingly. // // Make A rank deficient. A.Col( 0 )[Slice.All] = A.Col( 1 ); // Two equal columns. decompServer.ComputeFull = false; decompServer.ComputeLeftVectors = true; decompServer.ComputeRightVectors = true; decomp = decompServer.GetDecomp( A ); Console.WriteLine( "Rank of A = {0}", decomp.Rank ); // 3 // Apparently A has full rank. Lets look at the smallest // singular value. Singular values are arranged in descending // order, so the smallest value is the last value. Console.WriteLine(); Console.WriteLine( "Smallest singular value = {0}", decomp.SingularValue( 2 ) ); // 5.48294957152069E-17 // This singular value is equal to 0, which is within machine precision. Truncating // the SVD will set this value to 0. double tolerance = 1e-16; decompServer.Tolerance = 1e-16; decomp = decompServer.GetDecomp( A ); // Now look at the rank. Console.WriteLine( "Rank of A = {0}", decomp.Rank ); // 2 // You can also truncate an existing decomp by calling its // truncate method with a specified tolerance. tolerance = 1e-12; decomp.Truncate( tolerance ); Console.WriteLine(); Console.WriteLine( "Press Enter Key" ); Console.Read(); } } }← All NMath Code Examples