# C# SV Decomp Example

← All NMath Code Examples

```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" );