Task: Cholesky decomposition



C#: using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Cholesky
{
    class Program
    {
        
        
        
        
        static void Main(string[] args)
        {
            double[,] test1 = new double[,]
            {
                {25, 15, -5},
                {15, 18, 0},
                {-5, 0, 11},
            };

            double[,] test2 = new double[,]
            {
                {18, 22, 54, 42},
                {22, 70, 86, 62},
                {54, 86, 174, 134},
                {42, 62, 134, 106},
            };

            double[,] chol1 = Cholesky(test1);
            double[,] chol2 = Cholesky(test2);

            Console.WriteLine("Test 1: ");
            Print(test1);
            Console.WriteLine("");
            Console.WriteLine("Lower Cholesky 1: ");
            Print(chol1);
            Console.WriteLine("");
            Console.WriteLine("Test 2: ");
            Print(test2);
            Console.WriteLine("");
            Console.WriteLine("Lower Cholesky 2: ");
            Print(chol2);

        }

        public static void Print(double[,] a)
        {
            int n = (int)Math.Sqrt(a.Length);

            StringBuilder sb = new StringBuilder();
            for (int r = 0; r < n; r++)
            {
                string s = "";
                for (int c = 0; c < n; c++)
                {
                    s += a[r, c].ToString("f5").PadLeft(9) + ",";
                }
                sb.AppendLine(s);
            }

            Console.WriteLine(sb.ToString());
        }

        
        
        
        
        
        
        
        
        public static double[,] Cholesky(double[,] a)
        {
            int n = (int)Math.Sqrt(a.Length);

            double[,] ret = new double[n, n];
            for (int r = 0; r < n; r++)
                for (int c = 0; c <= r; c++)
                {
                    if (c == r)
                    {
                        double sum = 0;
                        for (int j = 0; j < c; j++)
                        {
                            sum += ret[c, j] * ret[c, j];
                        }
                        ret[c, c] = Math.Sqrt(a[c, c] - sum);
                    }
                    else
                    {
                        double sum = 0;
                        for (int j = 0; j < c; j++)
                            sum += ret[r, j] * ret[c, j];
                        ret[r, c] = 1.0 / ret[c, c] * (a[r, c] - sum);
                    }
                }

            return ret;
        }
    }
}






VB: Function Cholesky(Mat As Range) As Variant

Dim A() As Double, L() As Double, sum As Double, sum2 As Double
Dim m As Byte, i As Byte, j As Byte, k As Byte


    If Mat.Rows.Count <> Mat.Columns.Count Then
        MsgBox ("Correlation matrix is not square")
        Exit Function
    End If
    
    m = Mat.Rows.Count


    ReDim A(0 To m - 1, 0 To m - 1)
    ReDim L(0 To m - 1, 0 To m - 1)
    For i = 0 To m - 1
        For j = 0 To m - 1
            A(i, j) = Mat(i + 1, j + 1).Value2
            L(i, j) = 0
        Next j
    Next i


    Select Case m
        Case Is = 1
            L(0, 0) = Sqr(A(0, 0))
        
        Case Is = 2
            L(0, 0) = Sqr(A(0, 0))
            L(1, 0) = A(1, 0) / L(0, 0)
            L(1, 1) = Sqr(A(1, 1) - L(1, 0) * L(1, 0))
        
        Case Else
            L(0, 0) = Sqr(A(0, 0))
            L(1, 0) = A(1, 0) / L(0, 0)
            L(1, 1) = Sqr(A(1, 1) - L(1, 0) * L(1, 0))
            For i = 2 To m - 1
                sum2 = 0
                For k = 0 To i - 1
                    sum = 0
                    For j = 0 To k
                        sum = sum + L(i, j) * L(k, j)
                    Next j
                    L(i, k) = (A(i, k) - sum) / L(k, k)
                    sum2 = sum2 + L(i, k) * L(i, k)
                Next k
                L(i, i) = Sqr(A(i, i) - sum2)
            Next i
    End Select
    Cholesky = L
End Function