C# Least Squares 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 classes for solving ordinary least
  /// squares problems.
  /// </summary>
  class LeastSquaresExample
  {

    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 = 20;
      int cols = 4;
      var A = new DoubleMatrix( rows, cols, rng );

      // Construct a class to solve the least squares problem using a
      // Cholesky factorization of the normal equations.
      var cholLsq = new DoubleCholeskyLeastSq( A );

      Console.WriteLine();
      
      // Make sure the Cholesky factorization is good (for example, that matrix A
      // has full rank).
      Console.WriteLine( "Cholesky least squares is good = {0}", cholLsq.IsGood );

      // Create a random right-hand side to solve for.
      var b = new DoubleVector( A.Rows, rng );

      // Use Cholesky least squares method to solve.
      DoubleVector x = cholLsq.Solve( b );

      // Look at the norm squared of the residual Ax - b.
      double residualNorm = cholLsq.ResidualNormSqr( b );
      Console.WriteLine( "Cholesky: residual = {0}", residualNorm ); // 5.89829729588437
      Console.WriteLine();

      // Solve the same system with a QR decomposition and compare the results.
      var qrLsq = new DoubleQRLeastSq( A );
      Console.WriteLine( "Rank of A from QR = {0}", qrLsq.Rank );
      x = qrLsq.Solve( b );
      residualNorm = qrLsq.ResidualNormSqr( b );
      Console.WriteLine( "QR: residual = {0}", residualNorm ); // 5.89829729588437
      Console.WriteLine();

      // How about SVD?
      var svdLsq = new DoubleSVDLeastSq( A );
      Console.WriteLine( "Rank of A from SVD = {0}", svdLsq.Rank );
      x = svdLsq.Solve( b );
      residualNorm = svdLsq.ResidualNormSqr( b );
      Console.WriteLine( "SVD: residual = {0}", residualNorm ); // 5.89829729588438
      Console.WriteLine();

      // All methods give about the same residual. But what if A is nearly
      // rank deficient? Set the 2nd column of A to be almost equal to the 3rd.
      var normalRNG = new RandGenNormal( 0, 3e-23 );
      normalRNG.Reset( 0x131 );
      var smallNormalDeviates = new DoubleVector( A.Rows, normalRNG );
      A.Col( 1 )[Slice.All] = A.Col( 2 ) + smallNormalDeviates;

      // Use Cholesky least squares method to solve ill-conditioned.
      cholLsq.Factor( A );
      // Depending on your hardware, A could be so close to being rank
      // deficient that the Cholesky factorization fails. 
      if ( !cholLsq.IsGood )
      {
        Console.WriteLine( "Can not use Cholesky method on A. A is rank deficient." );
      }
      else
      {
        x = cholLsq.Solve( b );
        residualNorm = cholLsq.ResidualNormSqr( b );
        Console.WriteLine( "Cholesky ill conditioned: residual = {0}", residualNorm );
      }
      Console.WriteLine();

      // Solve the same system with a QR decomposition and compare the results.
      qrLsq.Factor( A );
      Console.WriteLine( "Rank of A from QR = {0}", qrLsq.Rank );
      x = qrLsq.Solve( b );
      residualNorm = qrLsq.ResidualNormSqr( b );
      Console.WriteLine( "QR  ill conditioned: residual = {0}", residualNorm );
      Console.WriteLine();

      // How about SVD?
      svdLsq.Factor( A );
      Console.WriteLine( "Rank of A from SVD = {0}", svdLsq.Rank );
      x = svdLsq.Solve( b );
      residualNorm = svdLsq.ResidualNormSqr( b );
      Console.WriteLine( "SVD  ill conditioned: residual = {0}", residualNorm );

      Console.WriteLine();
      Console.WriteLine( "Press Enter Key" );
      Console.Read();
    }
  }
}

← All NMath Code Examples
Top