C# Triangular Matrix Example

[TOC]

using System;

using CenterSpace.NMath.Core;
using CenterSpace.NMath.Matrix;

namespace CenterSpace.NMath.Matrix.Examples.CSharp
{
  /// <summary>
  /// A .NET example in C# demonstrating the features of the triangular matrix classes.
  /// </summary>
  class TriangularMatrixExample
  {

    static void Main(string[] args)
    {
      // Set up the parameters that describe the shape of a Hermitian banded matrix.
      int order = 5;

      // Create upper and lower triangular matrices.
      RandGenUniform rng = new RandGenUniform(-1, 1);
      rng.Reset(0x124);
      DoubleMatrix A = new DoubleMatrix(order, order, rng);
      DoubleLUFact lu = new DoubleLUFact(A);
      DoubleUpperTriMatrix U = new DoubleUpperTriMatrix(lu.U);
      DoubleLowerTriMatrix L = new DoubleLowerTriMatrix(lu.L);

      Console.WriteLine();
      Console.WriteLine("U = {0}", U.ToString("F4"));

      Console.WriteLine();
      Console.WriteLine("L = {0}", L.ToString("F4"));
      Console.WriteLine();

      // U = 5x5 [ 0.5764 -0.3249 -0.0770  0.7734  0.6222
      //           0.0000 -0.1691 -0.1416  0.0948 -0.9162  
      //           0.0000  0.0000  0.5759  0.3533  0.2067 
      //           0.0000  0.0000  0.0000 -1.4304 -1.0101 
      //           0.0000  0.0000  0.0000  0.0000 -0.5806 ]
      //
      // L = 5x5 [ 1.0000  0.0000 0.0000  0.0000 0.0000
      //           0.3403  1.0000 0.0000  0.0000 0.0000 
      //          -0.8630  0.5814 1.0000  0.0000 0.0000 
      //           0.5751 -0.8428 0.4012  1.0000 0.0000  
      //          -0.4343  0.3979 0.4225 -0.5379 1.0000 ]

      // Indexer accessor works just like it does for general matrices. 
      Console.WriteLine("U[2,2] = {0}", U[2, 2]);
      Console.WriteLine("L[0,3] = {0}", L[0, 3]);

      // You can set the values of elements in the upper triangular part
      // of a upper triangular matrix and the lower part of a lower
      // triangular matrix.
      double a = 99;
      L[2, 1] = a;
      Console.WriteLine("L[2,1] = {0}", L[2, 1]); // 99
      U[0, 2] = a + 1;
      Console.WriteLine("U[0,2] = {0}", U[0, 2]); // 100

      // But setting the values of elements in the lower triangular part
      // of a upper triangular matrix or the upper part of a lower
      // triangular matrix raises a NonModifiableElementException
      try
      {
        U[3, 0] = a;
      }
      catch (NonModifiableElementException e)
      {
        Console.WriteLine();
        Console.WriteLine("NonModifiableElementException: {0}", e.Message);
      }

      try
      {
        L[0, 3] = a;
      }
      catch (NonModifiableElementException e)
      {
        Console.WriteLine();
        Console.WriteLine("NonModifiableElementException: {0}", e.Message);
      }

      // Scalar multiplication and matrix addition/subtraction are supported.
      DoubleUpperTriMatrix C = a * U;
      DoubleUpperTriMatrix D = C + U;
      Console.WriteLine();
      Console.WriteLine("D = {0}", D.ToString("F4"));

      // Matrix/vector inner products too.
      DoubleVector x = new DoubleVector(L.Cols, rng);
      DoubleVector y = MatrixFunctions.Product(L, x);
      Console.WriteLine();
      Console.WriteLine("Lx = {0}", y.ToString());

      // You can transform the non-zero elements of a triangular matrix object
      // by using the Transform() method on its data vector.
      // Change every element of C to its absolute value.
      C.DataVector.Transform(NMathFunctions.AbsFunction);
      Console.WriteLine();
      Console.WriteLine("abs(C) = {0}", C.ToString("F4"));

      // You can also solve linear systems.
      DoubleVector x2 = MatrixFunctions.Solve(L, y);

      // x and x2 should be the same. Let's look at the l2 norm of
      // their difference.
      DoubleVector residual = x - x2;
      double residualL2Norm = Math.Sqrt(NMathFunctions.Dot(residual, residual));
      Console.WriteLine();
      Console.WriteLine("||x - x2|| = {0}", residualL2Norm);

      // You can calculate the determinant too.
      double det = MatrixFunctions.Determinant(U);
      Console.WriteLine();
      Console.WriteLine("Determinant of U = {0}", det);

      // You can use the Resize() method to change the bandwidths.
      D.Resize(6);
      Console.WriteLine();
      Console.WriteLine("D resized = {0}", D.ToString("F4"));

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

[TOC]