How to resolve the algorithm LU decomposition step by step in the Lobster programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm LU decomposition step by step in the Lobster programming language

Table of Contents

Problem Statement

Every square matrix

A

{\displaystyle A}

can be decomposed into a product of a lower triangular matrix

L

{\displaystyle L}

and a upper triangular matrix

U

{\displaystyle U}

, as described in LU decomposition. It is a modified form of Gaussian elimination. While the Cholesky decomposition only works for symmetric, positive definite matrices, the more general LU decomposition works for any square matrix. There are several algorithms for calculating L and U. To derive Crout's algorithm for a 3x3 example, we have to solve the following system: We now would have to solve 9 equations with 12 unknowns. To make the system uniquely solvable, usually the diagonal elements of

L

{\displaystyle L}

are set to 1 so we get a solvable system of 9 unknowns and 9 equations. Solving for the other

l

{\displaystyle l}

and

u

{\displaystyle u}

, we get the following equations: and for

l

{\displaystyle l}

: We see that there is a calculation pattern, which can be expressed as the following formulas, first for

U

{\displaystyle U}

and then for

L

{\displaystyle L}

We see in the second formula that to get the

l

i j

{\displaystyle l_{ij}}

below the diagonal, we have to divide by the diagonal element (pivot)

u

j j

{\displaystyle u_{jj}}

, so we get problems when

u

j j

{\displaystyle u_{jj}}

is either 0 or very small, which leads to numerical instability. The solution to this problem is pivoting

A

{\displaystyle A}

, which means rearranging the rows of

A

{\displaystyle A}

, prior to the

L U

{\displaystyle LU}

decomposition, in a way that the largest element of each column gets onto the diagonal of

A

{\displaystyle A}

. Rearranging the rows means to multiply

A

{\displaystyle A}

by a permutation matrix

P

{\displaystyle P}

: Example: The decomposition algorithm is then applied on the rearranged matrix so that

The task is to implement a routine which will take a square nxn matrix

A

{\displaystyle A}

and return a lower triangular matrix

L

{\displaystyle L}

, a upper triangular matrix

U

{\displaystyle U}

and a permutation matrix

P

{\displaystyle P}

, so that the above equation is fulfilled. You should then test it on the following two examples and include your output.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm LU decomposition step by step in the Lobster programming language

Source code in the lobster programming language

import std

// derived from JAMA v1.03

// rectangular input array A is transformed in place to LU form

def LUDecomposition(LU):
   // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
   let m = LU.length
   let n = LU[0].length
   let piv = map(m): _
   var pivsign = 1
   let LUcolj = map(m): 0.0
   // Outer loop.
   for(n) j:
      // Make a copy of the j-th column to localize references
      for(m) i:
         LUcolj[i] = LU[i][j]
      // Apply previous transformations
      for(m) i:
         let LUrowi = LU[i]
         // Most of the time is spent in the following dot product
         let kmax = min(i,j)
         var s = 0.0
         for(kmax) k:
            s += LUrowi[k] * LUcolj[k]
         s = LUcolj[i] - s
         LUcolj[i] = s
         LUrowi[j] = s
      // Find pivot and exchange if necessary.
      var p = j
      var i = j+1
      while i < m:
         if abs(LUcolj[i]) > abs(LUcolj[p]):
            p = i
         i += 1
      if p != j:
         for(n) k:
            let t = LU[p][k]
            LU[p][k] = LU[j][k]
            LU[j][k] = t
         let k = piv[p]
         piv[p] = piv[j]
         piv[j] = k
         pivsign = -pivsign
      // Compute multipliers.
      if j < m and LU[j][j] != 0.0:
         i = j+1
         while i < m:
            LU[i][j] /= LU[j][j]
            i += 1
   return piv

def print_A(A):
   print "A:"
   for(A) row:
      print row

def print_L(LU):
   print "L:"
   for(LU) lurow, i:
      let row = map(lurow.length): 0.0
      for(lurow) x, j:
         if i > j:
            row[j] = x
         else: if i == j:
            row[j] = 1.0
      print row

def print_U(LU):
   print "U:"
   for(LU) lurow, i:
      let row = map(lurow.length): 0.0
      for(lurow) x, j:
         if i <= j:
            row[j] = x
      print row

def print_P(piv):
   print "P:"
   for(piv) j:
      let row = map(piv.length): 0
      row[j] = 1
      print row

var A = [[1., 3., 5.],
         [2., 4., 7.],
         [1., 1., 0.]]

print_A A
var piv = LUDecomposition(A)
print_L A
print_U A
print_P piv

A = [[11.,  9., 24., 2.],
     [ 1.,  5.,  2., 6.],
     [ 3., 17., 18., 1.],
     [ 2.,  5.,  7., 1.]]

print_A A
piv = LUDecomposition(A)
print_L A
print_U A
print_P piv

  

You may also check:How to resolve the algorithm Draw a sphere step by step in the zkl programming language
You may also check:How to resolve the algorithm Smarandache prime-digital sequence step by step in the Pascal programming language
You may also check:How to resolve the algorithm Primorial numbers step by step in the Elixir programming language
You may also check:How to resolve the algorithm Enforced immutability step by step in the Erlang programming language
You may also check:How to resolve the algorithm P-Adic numbers, basic step by step in the Haskell programming language