zZShort_CircuitZz
zZShort_CircuitZz

Reputation: 185

Matlab - removing rows and columns from a matrix that contain 0's

I'm working on a problem involving beam deflections (it's not too fun :P)

I need to reduce the global stiffness matrix into the structure stiffness matrix, I do this by removing any rows and columns from the original matrix that contain a 0.

So if I have a matrix like so (let's call it K):

0   0   5   3   0   0
0   0   7   8   0   0
7   1   2   6   2   1
3   8   6   9   5   3
0   0   4   5   0   0
0   0   1   8   0   0 

The reduced matrix (let's call it S) would be just

2   6
6   9

Here's what I have written so far to reduce global matrix K to stiffness matrix S

S = K;

for i = 1:length(S(:,1))
    for j = 1:length(S(1,:))
        if  S(i,j) == 0
            S(i,:) = [];
            S(:,j) = [];
            break;
        end
    end
end

However I get "Index exceeds matrix dimensions" on the line containing the "if" statement, and I'm not sure my thinking is correct on the best way to remove all rows and columns. Appreciate any feedback!

Upvotes: 2

Views: 1599

Answers (4)

Divakar
Divakar

Reputation: 221564

For nxn matrix, alternatively you can try out matrix multiplication based approach -

K=[
    0   0   5   3   2   0
    0   0   7   8   7   0
    7   1   6   6   2   1
    3   8   6   8   5   3
    0   0   4   5   5   0
    5   3   7   8   1   6]  %// Slightly different than the one in question

K1 = double(K~=0)
K2 = K1*K1==size(K,1)
K3 = K(K2)
S = reshape(K3,max(sum(K2,1)),max(sum(K2,2)))

Output -

S =
     6     6     2
     6     8     5
     7     8     1

Upvotes: 2

rayryeng
rayryeng

Reputation: 104503

Another method I can suggest is by converting the matrix K into a logical matrix where anything that is non-zero is 1 and 0 otherwise. You would then do a column sum on this matrix then check to see if any columns don't sum to the number of rows you have. You remove these columns, then do a row sum on the intermediate matrix and check if any rows don't sum to the number of columns you have. You remove these rows to be left with your final matrix. As such:

Kbool = K ~= 0;
colsToRemove = sum(Kbool,1) ~= size(Kbool,1);
K(colsToRemove,:) = [];
rowsToRemove = sum(Kbool,2) ~= size(Kbool,2);
K(:,rowsToRemove) = []; 

Upvotes: 0

Mehmet Emre
Mehmet Emre

Reputation: 79

The problem is when you remove some row or column you should not increase i or j but MATLAB's for loop automatically updates them. Also your algorithm cannot handle the cases like:

0 1 0
1 1 1
1 1 1

It will only remove the first column due to break condition so you need to remove it but handle indexes properly somehow. Another approach may be firstly taking product of rows and columns then checking those products and removing the corresponding rows and columns when an element of a product is zero. An example implementation in MATLAB might be like:

function [S] = stiff(K)
S = K;
% product of each row, rows(k) == 0 if there is a 0 in row k
rows = prod(S,2);
% product of each column, cols(k) == 0 if there is a 0 in column k
cols = prod(S,1);

Here we compute the product of each row and each column

% firstly eliminate the rows
% row numbers in the new matrix
ii=1;
for i = 1:size(S,1),
    if rows(i) == 0,
        S(ii, :) = []; % delete the row
    else
        ii = ii + 1; % skip the row
    end
end

Here we remove rows that contain zeros by updating the index manually (notice ii).

% handle the columns now
ii = 1;
for i = 1:size(S,2),
    if cols(i) == 0,
        S(:, ii) = []; % delete the row
    else
        ii = ii + 1; % skip the row
    end
end
end

Here we apply same operation to remaining columns.

Upvotes: 0

Luis Mendo
Luis Mendo

Reputation: 112679

Easy:

S = K(all(K,2), all(K,1));

Upvotes: 3

Related Questions