How do you write MATLAB code for LU factorization when U is the unit matrix instead of L. The upper triangular matrix will have the diagonal of 1s instead of the lower triangular matrix.
You are looking for Crout's Method for LU decomposition.
The Wikipedia article has the following code
function [L, U] = LUdecompCrout(A)
[R, C] = size(A);
for i = 1:R
L(i, 1) = A(i, 1);
U(i, i) = 1;
end
for j = 2:R
U(1, j) = A(1, j) / L(1, 1);
end
for i = 2:R
for j = 2:i
L(i, j) = A(i, j) - L(i, 1:j - 1) * U(1:j - 1, j);
end
for j = i + 1:R
U(i, j) = (A(i, j) - L(i, 1:i - 1) * U(1:i - 1, j)) / L(i,i);
end
end
end
Here's one way to do this. If M is your matrix,
[P,Q] = lu(M');
L = Q'; U = P';
Alternatively, assuming that M has an LU decomposition, we could do the following:
[L,U,P,Q,D] = lu(M);
L = L*P'*D*Q';
This should yield a lower triangular L and upper triangular U where U has 1's on the diagonal whenever M has an LU decomposition.
Related
Construct an experiment to study the performance of the Cramer rule (with two implementations
determinants) in relation to Gauss's algorithm.
In each iteration 10 random arrays A (NxN), and vectors b (Nx1) will be created.
The 10 linear systems will be solved using the Cramer rule ("cramer.m") using
of rec_det (A) and using det (A), and the Gaussian algorithm
(“GaussianElimination.m”), and the time for each technique will be the average of 10 values.
Repeat the above for N = 2 to 10 and make a graph of the average time
in relation to the dimension N.
This is my task. I dont know if the way that I calculate the average time is correct and the graphic is not displayed.
T1=0;
T2=0;
T3=0;
for N=2:10
for i=1:10
A=rand(N,N);
b=rand(N,1);
t1=[1,i];
t2=[1,i];
t3=[1,i];
tic;
crammer(A,b);
t1(i)=toc;
tic
crammer_rec(A,b);
t2(i)=toc;
tic
gaussianElimination(A,b);
t3(i)=toc;
T1=T1+t1(i);
T2=T2+t2(i);
T3=T3+t3(i);
end
avT1=T1/10;
avT2=T2/10;
avT3=T3/10;
end
plot(2:10 , avT1 , 2:10 , avT2 , 2:10 , avT3);
function x = cramer(A, b)
n = length(b);
d = det(A);
% d = rec_det(A);
x = zeros(n, 1);
for j = 1:n
x(j) = det([A(:,1:j-1) b A(:,j+1:end)]) / d;
% x(j) = rec_det([A(:,1:j-1) b A(:,j+1:end)]) / d;
end
end
function x = cramer(A, b)
n = length(b);
d = rec_det(A);
x = zeros(n, 1);
for j = 1:n
x(j) = rec_det([A(:,1:j-1) b A(:,j+1:end)]) / d;
end
end
function deta = rec_det(R)
if size(R,1)~=size(R,2)
error('Error.Matrix must be square.')
else
n = size(R,1);
if ( n == 2 )
deta=(R(1,1)*R(2,2))-(R(1,2)*R(2,1));
else
for i=1:n
deta_temp=R;
deta_temp(1,:)=[ ];
deta_temp(:,i)=[ ];
if i==1
deta=(R(1,i)*((-1)^(i+1))*rec_det(deta_temp));
else
deta=deta+(R(1,i)*((-1)^(i+1))*rec_det(deta_temp));
end
end
end
end
end
function x = gaussianElimination(A, b)
[m, n] = size(A);
if m ~= n
error('Matrix A must be square!');
end
n1 = length(b);
if n1 ~= n
error('Vector b should be equal to the number of rows and columns of A!');
end
Aug = [A b]; % build the augmented matrix
C = zeros(1, n + 1);
% elimination phase
for k = 1:n - 1
% ensure that the pivoting point is the largest in its column
[pivot, j] = max(abs(Aug(k:n, k)));
C = Aug(k, :);
Aug(k, :) = Aug(j + k - 1, :);
Aug(j + k - 1, :) = C;
if Aug(k, k) == 0
error('Matrix A is singular');
end
for i = k + 1:n
r = Aug(i, k) / Aug(k, k);
Aug(i, k:n + 1) = Aug(i, k:n + 1) - r * Aug(k, k: n + 1);
end
end
% back substitution phase
x = zeros(n, 1);
x(n) = Aug(n, n + 1) / Aug(n, n);
for k = n - 1:-1:1
x(k) = (Aug(k, n + 1) - Aug(k, k + 1:n) * x(k + 1:n)) / Aug(k, k);
end
end
I think the easiest way to do this is by creating a 9 * 3 dimensional matrix to contain all the total times, and then take the average at the end.
allTimes = zeros(9, 3);
for N=2:10
for ii=1:10
A=rand(N,N);
b=rand(N,1);
tic;
crammer(A,b);
temp = toc;
allTimes(N-1,1) = allTimes(N-1,1) + temp;
tic
crammer_rec(A,b);
temp = toc;
allTimes(N-1,2) = allTimes(N-1,2) + temp;
tic
gaussianElimination(A,b);
temp = toc;
allTimes(N-1,3) = allTimes(N-1,3) + temp;
end
end
allTimes = allTimes/10;
figure; plot(2:10, allTimes);
You can use this approach because the numbers are quite straightforward and simple. If you had a more complicated setup, the way to store the times/calculate the averages would have to be tweaked.
If you had more functions you could also use function handles and create a third inner loop, but this is a little more advanced.
I have this code for LU decomposition but I want to include determinant of L and U so that the output will be determinant of LU or determinant of PLU.
function [ P, L, U ] = LUdecomposition(A)
A=input('matrix A =');
m = size(A);
n = m(1);
L = eye(n);
P = eye(n);
U = A;
for i=1:m(1)
if U(i,i)==0
maximum = max(abs(U(i:end,1)));
for k=1:n
if maximum == abs(U(k,i))
temp = U(1,:);
U(1,:) = U(k,:);
U(k,:) = temp;
temp = P(:,1);
P(1,:) = P(k,:);
P(k,:) = temp;
end
end
end
if U(i,i)~=1
temp = eye(n);
temp(i,i)=U(i,i);
L = L * temp;
U(i,:) = U(i,:)/U(i,i);
end
if i~=m(1)
for j=i+1:length(U)
temp = eye(n);
temp(j,i) = U(j,i);
L = L * temp;
U(j,:) = U(j,:)-U(j,i)*U(i,:);
end
end
end
P = P';
end
L and U are triangular matrices. So their determinants are the product of the diagonal elements. In a classical LU decomposition the diagonal elements of L are 1, therefore det(L) = 1. Because of A = L*U => det(A) = det(L)*det(U) you can easily compute the determinant of LU by computing the determinant of U. Therefore det(PLU) = + or - det(LU). I'm not sure how to figure it out :/
I have implemented a MATLAB function for Gramm-Schmidt QR factorisation. Q's inverse should be equal to it's inverse, but it's not, and I can't see why. I even tried with somebody else's function, which is identical, and the result was the same. This is my function:
function [Q R] = gramschmidt(A)
[n n] = size(A);
for i = 1:n
R(i,i) = norm( A(:, i) );
Q(:, i) = A(:, i) / R ( i, i);
for j = i + 1 : n
R(i, j) = Q(:, i)' * A(:, j);
A(:, j) = A(:, j) - Q(:, i) * R(i, j);
end
end
end
`
Firstly, I think what you meant to say is Q's conjugate transpose should be equal to it's inverse, i.e. that it is a unitary matrix.
Secondly, what makes you think that Q returned by your function is not unitary? Let's check.
A = randn(20,20);
[Q, R] = gramschmidt(A);
diff = #(X,Y) max(abs(X(:)-Y(:))); % element-wise max abs difference
diff(Q'*Q, eye(size(A)))
ans =
1.7764e-15
As you can see, it is unitary to a very good precision.
Also, just in case, Matlab has a built-in and efficient qr function that performs this decomposition, which also handles rectangular matrices, not just square ones like your implementation.
I am trying to implement my own LU decomposition with partial pivoting. My code is below and apparently is working fine, but for some matrices it gives different results when comparing with the built-in [L, U, P] = lu(A) function in matlab
Can anyone spot where is it wrong?
function [L, U, P] = lu_decomposition_pivot(A)
n = size(A,1);
Ak = A;
L = zeros(n);
U = zeros(n);
P = eye(n);
for k = 1:n-1
for i = k+1:n
[~,r] = max(abs(Ak(:,k)));
Ak([k r],:) = Ak([r k],:);
P([k r],:) = P([r k],:);
L(i,k) = Ak(i,k) / Ak(k,k);
for j = k+1:n
U(k,j-1) = Ak(k,j-1);
Ak(i,j) = Ak(i,j) - L(i,k)*Ak(k,j);
end
end
end
L(1:n+1:end) = 1;
U(:,end) = Ak(:,end);
return
Here are the two matrices I've tested with. The first one is correct, whereas the second has some elements inverted.
A = [1 2 0; 2 4 8; 3 -1 2];
A = [0.8443 0.1707 0.3111;
0.1948 0.2277 0.9234;
0.2259 0.4357 0.4302];
UPDATE
I have checked my code and corrected some bugs, but still there's something missing with the partial pivoting. In the first column the last two rows are always inverted (compared with the result of lu() in matlab)
function [L, U, P] = lu_decomposition_pivot(A)
n = size(A,1);
Ak = A;
L = eye(n);
U = zeros(n);
P = eye(n);
for k = 1:n-1
[~,r] = max(abs(Ak(k:end,k)));
r = n-(n-k+1)+r;
Ak([k r],:) = Ak([r k],:);
P([k r],:) = P([r k],:);
for i = k+1:n
L(i,k) = Ak(i,k) / Ak(k,k);
for j = 1:n
U(k,j) = Ak(k,j);
Ak(i,j) = Ak(i,j) - L(i,k)*Ak(k,j);
end
end
end
U(:,end) = Ak(:,end);
return
I forgot that If there was a swap in matrix P I had to swap also the matrix L. So just add the next line after after swapping P and everything will work excellent.
L([k r],:) = L([r k],:);
Both functions are not correct.
Here is the correct one.
function [L, U, P] = LU_pivot(A)
[m, n] = size(A); L=eye(n); P=eye(n); U=A;
for k=1:m-1
pivot=max(abs(U(k:m,k)))
for j=k:m
if(abs(U(j,k))==pivot)
ind=j
break;
end
end
U([k,ind],k:m)=U([ind,k],k:m)
L([k,ind],1:k-1)=L([ind,k],1:k-1)
P([k,ind],:)=P([ind,k],:)
for j=k+1:m
L(j,k)=U(j,k)/U(k,k)
U(j,k:m)=U(j,k:m)-L(j,k)*U(k,k:m)
end
pause;
end
end
My answer is here:
function [L, U, P] = LU_pivot(A)
[n, n1] = size(A); L=eye(n); P=eye(n); U=A;
for j = 1:n
[pivot m] = max(abs(U(j:n, j)));
m = m+j-1;
if m ~= j
U([m,j],:) = U([j,m], :); % interchange rows m and j in U
P([m,j],:) = P([j,m], :); % interchange rows m and j in P
if j >= 2; % very_important_point
L([m,j],1:j-1) = L([j,m], 1:j-1); % interchange rows m and j in columns 1:j-1 of L
end;
end
for i = j+1:n
L(i, j) = U(i, j) / U(j, j);
U(i, :) = U(i, :) - L(i, j)*U(j, :);
end
end
i did an exercise with LU decomposition in Matlab, my professor highlighted some problems, but i don't understand what i should correct.
This is for the lower triangular matrix:
function b = triI(A,b)
n = length(A);
for i=1:n
for j=1:i-1
b(i) = b(i) - A(i,j)*b(j);
end
if A(i,i) == 0
error(’the matrix is singular’)
end
b(i) = b(i)/A(i,i);
end
This is for the lower triangular matrix:
function b = triS(A,b)
n = length(A);
for i=n:-1:1
for j=i+1:n
b(i) = b(i) - A(i,j)*b(j);
end
if A(i,i) == 0
error(’the matrix is singular’)
end
b(i) = b(i)/A(i,i);
end
LU decomposition
function x = solveLU(A,x)
n = lenght(A);
M = tril(A,-1)+eye(n);
x = solvetril(M,x);
M = triu(A);
x = solvetriu(M,x);
How can i resolve this? He said that it isn't a correct algorithm...
Thanks in advance!