0% found this document useful (0 votes)
510 views

Recursive LU Factorization of A Matrix in Python

LU Recursive method of factorization of a square matrix Backed up by all Python functions and tests necessary

Uploaded by

theodor_munteanu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
510 views

Recursive LU Factorization of A Matrix in Python

LU Recursive method of factorization of a square matrix Backed up by all Python functions and tests necessary

Uploaded by

theodor_munteanu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 4

Recursive LU factorization of a matrix

Contents
Methodology of LU recursive factorization .................................................................................................. 1
Python code .................................................................................................................................................. 2
Permutation matrices .................................................................................................................................. 3

Methodology of LU recursive factorization


𝑎 𝑤𝑡
If for 𝐴 = (𝑎𝑖𝑗 )1≤𝑖,𝑗≤𝑚 ∈ 𝑀𝑚 (𝑅) we consider 𝐴 = ( 11 ) where 𝑤 𝑡 = (𝑎12 , … , 𝑎1𝑚 ), 𝑣 =
𝑣 𝐴′
1 0𝑡𝑚−1 𝑎11 𝑤𝑡
𝑡
(𝑎21 , … , 𝑎𝑚1 ) .If 𝑎11 ≠ 0 then we can write 𝐴 = ( 𝑣 ′
)( ′ (𝑣𝑤 𝑡 )) where 𝐴1 = 𝐴 −
𝑎
𝐼𝑚−1 0 𝑚−1 𝐴 − 𝑎
11 11
𝑣𝑤 𝑡
𝑎11
is called Schur complement.

We repeat the same transformation for 𝐴1 until we reach to a matrix of the order one.

ALGORITHM

S1. We read 𝒎 ∈ 𝑵∗ , 𝒎 ≥ 𝟐 and 𝑨 = (𝒂𝒊𝒋 ) ∈ 𝑴𝒎 (𝑹).


𝒊,𝒋=𝟏,𝒎

S2. For 𝒌 = 𝟏, 𝒎 − 𝟏:

If 𝒂𝒌𝒌 = 𝟎 then we cannot proceed further to the decomposition.

Else, (if 𝒂𝒌𝒌 ≠ 𝟎) ,then :


𝒂𝒋𝒌
𝒂𝒋𝒌 = 𝒂 , 𝒋 = 𝒌 + 𝟏, 𝒎
𝒌𝒌

The elements (𝒂𝒊𝒋 ) , transform into 𝒂𝒊𝒋 = 𝒂𝒊𝒋 − 𝒂𝒊𝒌 𝒂𝒌𝒋 .


𝒊,𝒋=𝒌+𝟏,𝒎

S3. If (𝒂𝒎𝒎 = 𝟎) then we cannot make the LU decomposition, else we write 𝑳, 𝑼:

𝟎, 𝟏 ≤ 𝒊 ≤ 𝒋 ≤ 𝒎
𝟎, 𝟏 ≤ 𝒋 ≤ 𝒊 ≤ 𝒎
𝑳 = (𝒍𝒊𝒋 ) ={ 𝟏, 𝒊 = 𝒋 , 𝑼 = (𝒖𝒊𝒋 ) = { 𝒂 , 𝒐𝒕𝒉𝒆𝒓𝒘𝒊𝒔𝒆 .
𝒊,𝒋=𝟏,𝒎 𝒊,𝒋=𝟏,𝒎 𝒊𝒋
𝒂𝒊𝒋 , 𝒐𝒕𝒉𝒆𝒓𝒘𝒊𝒔𝒆

The steps S2 and S3 can be transformed into the call 𝑳𝑼(𝒎, 𝑨) where 𝑳𝑼(𝒑, 𝑨) makes the
transformations in A starting with the line 𝒎 − 𝒑 + 𝟏 and ends if 𝒑 = 𝟏.

We have: 𝑳𝑼(𝒑, 𝑨)
K<- m-p+1

If 𝒂𝒌𝒌 = 𝟎 then the decomposition is not made, otherwise divide elements from column 𝒌 with 𝒂𝒌𝒌
under 𝒂𝒌𝒌 .

The right-bottom corner elements 𝒂𝒊𝒋 are transformed as described as in S2.

We recall 𝑳𝑼(𝒑 − 𝟏, 𝑨).

Python code
I will write the code for the first step, the first decomposition of A, and the small functions to extract
blocks of matrices as follows:
import numpy as np
def LU_tests():
def rewrite_matrix(A):
"I will write from matrix nxn A, a (n-1)x(n-1) matrix A1 from the "
"bottom-right corner, along with the remnants, a (n-1) line, (n-
1)col"
"and top-left corner element"
return A[1:np.shape(A)[0],1:np.shape(A)[1]]
def lower_right_corner(A):
return A[1:np.shape(A)[0],1:np.shape(A)[1]]
def transform_L(A):
sz = np.shape(A)[0]
v = A[1:sz,0]
L = np.zeros((sz,sz))
L[0,0]=1
L[1:sz,0] = np.transpose(v)/A[0,0]
L[1:sz,1:sz]=np.identity(sz-1)
return L
def transform_U(A):
sz = np.shape(A)[0]
A1 = A[1:sz,1:sz]
U = np.zeros((sz,sz))
w = A[0,1:sz]
v = A[1:sz,0]
U[0,0],a=A[0,0],A[0,0]
U[0,1:sz] = w
U[1:sz,1:sz] = A1 - np.outer(np.transpose(v),w)/a
"The right side above is called Schur complement"
return U
def Schur(A):
L = transform_L(A)
"only L is inferior triangular, U is yet to be redecomposed"
U = transform_U(A)
return L,U
return Schur
Now I will write the code for the transforming the matrix A into a new matrix 𝐴, that will be written as
𝐴 = 𝐿 + 𝑈, where 𝐿𝑈 = 𝐴.
def LU_recursive(A,p):
m = np.shape(A)[0]
if A[m-p,m-p]!=0 and p!=1:
v,w = A[m-p+1:m,m-p],A[m-p,m-p+1:m]
A[m-p+1:m,m-p] = A[m-p+1:m,m-p]/A[m-p,m-p]
A[m-p+1:m,m-p+1:m] = A[m-p+1:m,m-p+1:m] - np.outer(np.transpose(v),w)
LU_recursive(A,p-1)
return A
Now the final step of the decomposition:
def final_Schur_decomposition(A):
sz = np.shape(A)[0]
A = LU_recursive(A,sz)
def simply_LU(A):
"THis will simply write L,U from the elements of A where L[i,i]=1 and
"
"U[i,i] = 0. In simpler words, the inferior and superior diagonal
parts"
sz = np.shape(A)[0]
L,U = np.zeros((sz,sz)),A
L = np.diag(np.ones(sz))
for i in range(1,sz):
for j in range(0,i):
L[i,j] = A[i,j]
U[i,j] = 0
return L,U
return simply_LU(A)
Tests are also being carried out:
def test_final_dec():
A = np.array([[2,3,1,5],[6,13,5,19],[2,19,10,23],[4,10,11,31]])
B = A
print(final_Schur_decomposition(A)[0])
print(final_Schur_decomposition(A)[1])
print(B -
np.dot(final_Schur_decomposition(A)[0],final_Schur_decomposition(A)[1]))
Remark: B is the null matrix.

Permutation matrices
A special matrix derived from the identity matrix where 2 rows / columns are permutated is called a
permutation matrix.
1, 𝑖𝑓 𝑗 = 𝜎(𝑖)
𝑃 = (𝑝𝑖𝑗 ) = { , 𝜎 ∈ 𝑃𝑒𝑟𝑚({1,2, … , 𝑚}).
0, 𝑜𝑡ℎ𝑒𝑟𝑤𝑖𝑠𝑒
Python code:
def permutation_matrix_tests():
def test1():
A = np.matrix([[0,1,0,0],[1,0,0,0],[0,0,1,0],[0,0,0,1]])
print(A)
b1,b2,b3,b4 =
np.array([[0,1],[1,0]]),np.zeros((2,2)),np.zeros((2,2)),\
np.array([[0,1],[1,0]])
print(np.block([[b1,b2],[b3,b4]]))
test1()
def perm_matrix(n,i,j):
A = np.identity(n)
A[i-1,j-1],A[j-1,i-1]=1,1
A[i-1,i-1],A[j-1,j-1]=0,0
return A
print(perm_matrix(4,2,3))
def test2():
A = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(np.dot(A,perm_matrix(3,1,2)))
print(np.dot(perm_matrix(3,1,2),A))
test2()
Remark:
By multiplying a matrix with a permutation matrix at right, we permute two columns.
By multiplying a matrix with a permutation matrix at left, we permute two rows.
See test2() above in Python.

You might also like