2016-07-28 78 views
3

我有一个二维矩阵A的尺寸mxnm>n在Matlab中。我想构建一个尺寸为cxn的矩阵B,列出A中包含行索引的笛卡尔乘积的每个元素。要更清楚地考虑下面的例子。在Matlab中的行索引的笛卡尔乘积

例子:

%m=4; 
    %n=3; 

    A=[1 0 1; 
    0 0 1; 
    1 1 0; 
    0 0 1]; 

    %column 1: "1" are at rows {1,3} 
    %column 2: "1" are at row {3} 
    %column 3: "1" are at rows {1,2,4} 

    %Hence, the Cartesian product {1,3}x{3}x{1,2,4} is 
    %{(1,3,1),(1,3,2),(1,3,4),(3,3,1),(3,3,2),(3,3,4)} 

    %I construct B by disposing row-wise each 3-tuple in the Cartesian product 

    %c=6 

B=[1 3 1; 
    1 3 2; 
    1 3 4; 
    3 3 1; 
    3 3 2; 
    3 3 4]; 

回答

4

你可以得到笛卡尔乘积与combvec命令,为您的示例:

A=[1 0 1;... 
    0 0 1;... 
    1 1 0;... 
    0 0 1]; 

[x y]=find(A); 

B=combvec(x(y==1).',x(y==2).',x(y==3).').'; 

% B = 
% 1 3 1 
% 3 3 1 
% 1 3 2 
% 3 3 2 
% 1 3 4 
% 3 3 4 

您可以通过使用扩展为一个未知的列数产品的关联性。

[x y]=find(A); 

u_y=unique(y); 

B=x(y==u_y(1)).'; 

for i=2:length(u_y) 
    B=combvec(B, x(y==u_y(i)).'); 
end 

B=B.'; 
+1

警告。 'combvec'属于神经网络工具箱。 – rayryeng

3

一种解决方案(没有工具箱):

A= [1 0 1; 
    0 0 1; 
    1 1 0; 
    0 0 1]; 



[ii,jj] = find(A) 

kk = unique(jj); 

for i = 1:length(kk) 
    v{i} = ii(jj==kk(i)); 
end 

t=cell(1,length(kk)); 
[t{:}]= ndgrid(v{:}); 

product = [] 
for i = 1:length(kk) 
    product = [product,t{i}(:)]; 
end 
+0

有趣的是,我发现除了索引和创建矩阵的细微差别外,我们还有类似的代码。 – edwinksl

2

总之,我会使用find以产生所需的笛卡尔乘积的索引,然后使用ndgrid执行这些指数的笛卡儿积。这样做的代码是:

clear 
close all 
clc 

A = [1 0 1; 
    0 0 1; 
    1 1 0; 
    0 0 1]; 

[row,col] = find(A); 
[~,ia,~] = unique(col); 
n_cols = size(A,2); 
indices = cell(n_cols,1); 

for ii = 1:n_cols-1 
    indices{ii} = row(ia(ii):ia(ii+1)-1); 
end 
indices{end} = row(ia(end):end); 

cp_temp = cell(n_cols,1); 
[cp_temp{:}] = ndgrid(indices{:}); 

cp = NaN(numel(cp_temp{1}),n_cols); 
for ii = 1:n_cols 
    cp(:,ii) = cp_temp{ii}(:); 
end 
cp = sortrows(cp); 
cp 
3

您可以根据accumarray获取与每列非零元素的行索引向量。这适用于列的任意号码:

[ii, jj] = find(A); 
vectors = accumarray(jj, ii, [], @(x){sort(x.')}); 

然后申请this answer有效计算的矢量的笛卡尔乘积:

n = numel(vectors); 
B = cell(1,n); 
[B{end:-1:1}] = ndgrid(vectors{end:-1:1}); 
B = cat(n+1, B{:}); 
B = reshape(B,[],n); 

在你的榜样,这给

B = 
    1  3  1 
    1  3  2 
    1  3  4 
    3  3  1 
    3  3  2 
    3  3  4