2014-12-13 66 views
2

我想(在這種情況下n=5)生成大小(n(n-1)/2, n),看起來像這樣的矩陣:如何生成此矩陣(僅包含0和±1)?

-1  1  0  0  0 
-1  0  1  0  0 
-1  0  0  1  0 
-1  0  0  0  1 
0 -1  1  0  0 
0 -1  0  1  0 
0 -1  0  0  1 
0  0 -1  1  0 
0  0 -1  0  1 
0  0  0 -1  1 

這就是我,很快,想出了:

G = []; 
for i = 1:n-1; 
    for j = i+1:n  
     v = sparse(1,i,-1,1,n); 
     w = sparse(1,j,1,1,n); 
     vw = v+w; 
     G = [G; vw];   
    end 
end 

G = full(G); 

它的工作原理,但是有沒有更快/更乾淨的方法呢?

回答

1

使用nchoosek生成的列,這將是非零的指標:

n = 5; %// number of columns 
ind = nchoosek(1:n,2); %// ind(:,1): columns with "-1". ind(:,2): with "1". 
m = size(ind,1); 
rows = (1:m).'; %'// row indices 
G = zeros(m,n); 
G(rows + m*(ind(:,1)-1)) = -1; 
G(rows + m*(ind(:,2)-1)) = 1; 
+0

解決。 Thx,這很好。 – lesspritfree 2014-12-14 09:58:35

+0

@lesspritfree很高興:-)在最後兩行中,您還可以使用['sub2ind'](http://es.mathworks.com/help/matlab/ref/sub2ind.html)而不是總和 – 2014-12-14 12:24:54

+0

哇。這是一個真正的matlab'ed思想!十分優雅。 – Mikhail 2014-12-15 15:05:57

0

您有兩個嵌套循環,這會導致非矢量化操作的複雜性,這對於此任務來說太多了。拿你的矩陣實際上有一個rectursive圖案一看:

G(n+1) = [ -1 I(n)] 
     [ 0 G(n)]; 

其中I(n)是大小n的身份矩陣。這就是你如何表達MATLAB這個模式:

function G = mat(n) 
    % Treat original call as G(n+1) 
    n = n - 1; 

    % Non-recursive branch for trivial case 
    if n == 1 
    G = [-1 1]; 
    return; 
    end 

    RT = eye(n);     % Right-top: I(n) 
    LT = repmat(-1, n, 1);  % Left-top: -1 
    RB = mat(n);     % Right-bottom: G(n), recursive 
    LB = zeros(size(RB, 1), 1); % Left-bottom: 0 

    G = [LT RT; LB RB]; 
end 

,它給我們O(N)非矢量化操作的複雜性。如果Matlab沒有足夠的智能來分解這些內容,它可能會在遞歸和矩陣組合中浪費一些內存。如果它很重要,你可以將遞歸展開到循環中並迭代地填充原始預分配矩陣中的相應位置。

+0

好主意使用遞歸! – 2014-12-15 15:21:31