2014-09-26 138 views
2

我的工作涉及梁挠度问题(这不是太好玩:P)Matlab的 - 从包含一个矩阵删除行和列0的

我需要降低整体刚度矩阵到结构刚度矩阵我通过从包含0。

那么原始矩阵任何的行和列,如果我有像这样一个矩阵做到这一点(我们称之为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 

简化的矩阵(让我们称它S)将只是

2 6 
6 9 

这里是我迄今写入全球矩阵K减少刚度矩阵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 

但是我得到包含“if”语句行“指数超过矩阵尺寸”,和我我不确定我的想法是否是删除所有行和列的最佳方式。感谢任何反馈!

回答

3

简单:

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

圣灵魔像魔法!我将不得不看看“全部”功能.....非常感谢! – 2014-09-26 21:25:36

+0

哈哈哈我真的大声笑出你的评论。谢谢!看看[this](http://www.mathworks.es/es/help/matlab/math/matrix-indexing.html) – 2014-09-26 21:31:06

+0

@zZShort_CircuitZz我已经做了一个更正。请参阅更新回答 – 2014-09-26 21:36:46

2

对于nxn矩阵,或者你可以尝试基于矩阵相乘的方法 -

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))) 

输出 -

S = 
    6  6  2 
    6  8  5 
    7  8  1 
+0

非常好的方法!使用'K1 * K1'非常聪明。关于'+ 0',你认为它比'double()'更快,还是更容易输入? :-) – 2014-09-26 22:45:37

+0

@LuisMendo不知道哪一个会更快,但主要是一种直觉,说'+ 0'会是,而且它紧凑。另外最好避免函数调用,我认为。 – Divakar 2014-09-26 23:48:40

+0

@LuisMendo只需少量测试即可比较'double()'和'+ 0'。 'double()'看起来像是在1000x1000向上的数据大小上略微提高了4%-8%,否则我认为可以使用任何一种。 – Divakar 2014-09-27 16:26:28

0

是问题你的时候删除一些行或列你不应该增加i或j,但是MATLAB的for循环会自动更新它们。另外你的算法无法处理的情况下,像:

0 1 0 
1 1 1 
1 1 1 

它只会消除由于,所以你需要将其删除,但处理指标正常某种程度上打破条件的第一列。另一种方法可能首先采用行和列的乘积,然后检查这些产品并在产品的元素为零时移除相应的行和列。在MATLAB的示例实现可能是这样:

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); 

在这里,我们计算出各行的产品和每一列

% 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 

在这里,我们删除通过手动更新索引包含零行(注意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 

这里我们对其余列应用相同的操作。

0

我建议的另一种方法是将矩阵K转换成逻辑矩阵,其中非零的任何东西都是10。然后你会在这个矩阵上做一个列总和,然后检查是否有任何列不和你所拥有的行数相加。您删除这些列,然后对中间矩阵进行一次求和,并检查是否有任何行的总和不等于您拥有的列数。您将这些行删除并留下最终矩阵。因此:

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