No BSD License  

Highlights from
Null space of a sparse matrix

from Null space of a sparse matrix by Pawel Kowal
calculates null space and range of a rectangular sparse matrix

luq(A,do_pivot,tol)
function [L,U,Q] = luq(A,do_pivot,tol)
%  PURPOSE: calculates the following decomposition
%             
%       A = L |Ubar  0 | Q
%             |0     0 |
%
%       where Ubar is a square invertible matrix
%       and matrices L, Q are invertible.
%
% ---------------------------------------------------
%  USAGE: [L,U,Q] = luq(A,do_pivot,tol)
%  INPUT: 
%         A             a sparse matrix
%         do_pivot      = 1 with column pivoting
%                       = 0 without column pivoting
%         tol           uses the tolerance tol in separating zero and
%                       nonzero values
%
%   OUTPUT:
%         L,U,Q          matrices
%
%   COMMENTS:
%         based on lu decomposition
%
% Copyright  (c) Pawel Kowal (2006)
% All rights reserved
% LREM_SOLVE toolbox is available free for noncommercial academic use only.
% pkowal3@sgh.waw.pl

[n,m]                   = size(A);

if ~issparse(A)
    A                   = sparse(A);
end

%--------------------------------------------------------------------------
%       SPECIAL CASES
%--------------------------------------------------------------------------
if size(A,1)==0
    L                   = speye(n);
    U                   = A;
    Q                   = speye(m);
    return;
end
if size(A,2)==0
    L                   = speye(n);
    U                   = A;    
    Q                   = speye(m);
    return;
end        

%--------------------------------------------------------------------------
%       LU DECOMPOSITION
%--------------------------------------------------------------------------
if do_pivot
    [L,U,P,Q]           = lu(A);   
    Q                   = Q';
else
    [L,U,P]             = lu(A);   
    Q                   = speye(m);
end
p                       = size(A,1)-size(L,2);
LL                      = [sparse(n-p,p);speye(p)];
L                       = [P'*L P(n-p+1:n,:)'];
U                       = [U;sparse(p,m)];

%--------------------------------------------------------------------------
%       FINDS ROWS WITH ZERO AND NONZERO ELEMENTS ON THE DIAGONAL
%--------------------------------------------------------------------------
if size(U,1)==1 || size(U,2)==1
    S                   = U(1,1);
else
    S                   = diag(U);
end
I                       = find(abs(S)>tol);
Jl                      = (1:n)';
Jl(I)                   = [];
Jq                      = (1:m)';
Jq(I)                   = [];

Ubar1                   = U(I,I);
Ubar2                   = U(Jl,Jq);
Qbar1                   = Q(I,:);
Lbar1                   = L(:,I);

%--------------------------------------------------------------------------
%       ELININATES NONZEZO ELEMENTS BELOW AND ON THE RIGHT OF THE
%       INVERTIBLE BLOCK OF THE MATRIX U
%
%       UPDATES MATRICES L, Q
%--------------------------------------------------------------------------
if ~isempty(I)
    Utmp                = U(I,Jq);
    X                   = Ubar1'\U(Jl,I)';
    Ubar2               = Ubar2-X'*Utmp;
    Lbar1               = Lbar1+L(:,Jl)*X';

    X                   = Ubar1\Utmp;
    Qbar1               = Qbar1+X*Q(Jq,:);    
    Utmp                = [];
    X                   = [];
end

%--------------------------------------------------------------------------
%       FINDS ROWS AND COLUMNS WITH ONLY ZERO ELEMENTS
%--------------------------------------------------------------------------
I2                      = find(max(abs(Ubar2),[],2)>tol);
I5                      = find(max(abs(Ubar2),[],1)>tol);

I3                      = Jl(I2);
I4                      = Jq(I5);
Jq(I5)                  = [];
Jl(I2)                  = [];
U                       = [];

%--------------------------------------------------------------------------
%       FINDS A PART OF THE MATRIX U WHICH IS NOT IN THE REQIRED FORM
%--------------------------------------------------------------------------
A                       = Ubar2(I2,I5);

%--------------------------------------------------------------------------
%       PERFORMS LUQ DECOMPOSITION OF THE MATRIX A
%--------------------------------------------------------------------------
[L1,U1,Q1]              = luq(A,do_pivot,tol);

%--------------------------------------------------------------------------
%       UPDATES MATRICES L, U, Q
%--------------------------------------------------------------------------
Lbar2                   = L(:,I3)*L1;
Qbar2                   = Q1*Q(I4,:);
L                       = [Lbar1 Lbar2 L(:,Jl)];
Q                       = [Qbar1; Qbar2; Q(Jq,:)];

n1                      = length(I);
n2                      = length(I3);
m2                      = length(I4);
U                       = [Ubar1 sparse(n1,m-n1);sparse(n2,n1) U1 sparse(n2,m-n1-m2);sparse(n-n1-n2,m)];

Contact us at files@mathworks.com