2016-07-28 79 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