如何生成此矩阵(仅包含0和±1)?

时间:2014-12-13 08:51:46

标签: arrays matlab matrix

我想生成大小为(n(n-1)/2, n)的矩阵,如下所示(在这种情况下为n=5):

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

它有效,但有更快/更清洁的方法吗?

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分:0)

您有两个嵌套循环,导致非O(N^2)非向量化操作的复杂性,这对于此任务来说太多了。看一下你的矩阵实际上有一个矩形模式:

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不聪明,它可能会在递归和矩阵组合期间浪费一些内存,从而将这些内容考虑在内。如果它很重要,您可以将递归展开为循环并迭代填充原始预分配矩阵中的相应位置。