生成矩阵的线性组合

时间:2011-02-03 19:34:07

标签: matlab matrix

我想创建一个矩阵A [4x8],如下所示。

矩阵A的对角线总是1A11,A22,A33,A44 = 1

这个矩阵可以被认为是两半,前半部分是前4列,后半部分是第二列,如下所示:

        1 -1 -1 -1   1 0 0 1
  A =  -1  1 -1  0   0 1 0 0
       -1 -1  1  0   1 0 0 0 
       -1 -1 -1  1   1 1 0 0

前半部分的每行可以有两个或三个-1:

  • 如果它有两个-1,那么下半年的相应行应该有一个1
  • 如果任何行有三个-1,则矩阵的后半部分应该有两个1

总体目标是使每行的总和为0。我需要生成像这样的矩阵的所有可能组合。

如果在每次迭代中创建具有新组合的矩阵将更好,以便在使用它之后我可以丢弃它或者存储所有组合是非常空间密集的。有谁能够帮我 ?

我能想到的一个可能的解决方案是生成row1,row2,row3和row4的所有可能组合,并在每次迭代中创建一个矩阵。这看起来可行吗?

2 个答案:

答案 0 :(得分:5)

这是一种可能的解决方案。如果您暂时忽略对角线,则可以使用函数KRONREPMATPERMSUNIQUE,{{为其他7个值生成所有可能的模式3}}和EYE

>> rowPatterns = [kron(eye(3)-1,ones(4,1)) ...      %# For 2 out of 3 as -1
                  repmat(eye(4),3,1); ...           %# For 1 out of 4 as 1
                  repmat([-1 -1 -1],6,1) ...        %# For 3 out of 3 as -1
                  unique(perms([1 1 0 0]),'rows')]  %# For 2 out of 4 as 1

rowPatterns =

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

请注意,对于任何给定的行,这是18种可能的模式,因此矩阵A可以有18 ^ 4 = 104,976种可能的行模式(相当多)。您可以使用函数ONESNDGRIDCAT生成每个可能的4行行模式索引:

[indexSets{1:4}] = ndgrid(1:18);
indexSets = reshape(cat(5,indexSets{:}),[],4);

indexSets将是一个104,976乘4的矩阵,每行包含1到18之间的4个值的一个组合(包括1和18),用作rowPatterns的索引以生成唯一矩阵A。现在,您可以循环遍历每组4个明确的行模式索引,并使用函数RESHAPETRILTRIUEYE生成矩阵A

for iPattern = 1:104976
  A = rowPatterns(indexSets(iPattern,:),:);  %# Get the selected row patterns
  A = [tril(A,-1) zeros(4,1)] + ...          %# Separate the 7-by-4 matrix into
      [zeros(4,1) triu(A)] + ...             %#   lower and upper parts so you
      [eye(4) zeros(4)];                     %#   can insert the diagonal ones
  %# Store A in a variable or perform some computation with it here
end

答案 1 :(得分:2)

这是另一种解决方案(最小化循环):

%# generate all possible variation of first/second halves
z = -[0 1 1; 1 0 1; 1 1 0; 1 1 1]; n = -sum(z,2);
h1 = {
    [         ones(4,1) z(:,1:3)] ;
    [z(:,1:1) ones(4,1) z(:,2:3)] ;
    [z(:,1:2) ones(4,1) z(:,3:3)] ;
    [z(:,1:3) ones(4,1)         ] ;
};
h2 = arrayfun(@(i) unique(perms([zeros(1,4-i) ones(1,i)]),'rows'), (1:2)', ...
    'UniformOutput',false);

%'# generate all possible variations of complete rows
rows = cell(4,1);
for r=1:4
    rows{r} = cell2mat( arrayfun( ...
        @(i) [ repmat(h1{r}(i,:),size(h2{n(i)-1},1),1) h2{n(i)-1} ], ...
        (1:size(h1{r},1))', 'UniformOutput',false) );
end

%'# generate all possible matrices (pick one row from each to form the matrix)
sz = cellfun(@(M)1:size(M,1), rows, 'UniformOutput',false);
[X1 X2 X3 X4] = ndgrid(sz{:});
matrices = cat(3, ...
    rows{1}(X1(:),:), ...
    rows{2}(X2(:),:), ...
    rows{3}(X3(:),:), ...
    rows{4}(X4(:),:) );
matrices = permute(matrices, [3 2 1]);              %# 4-by-8-by-104976

%#clear X1 X2 X3 X4 rows h1 h2 sz z n r

接下来,您可以访问4乘8的矩阵:

>> matrices(:,:,500)
ans =
     1    -1    -1    -1     0     1     0     1
    -1     1    -1     0     0     0     1     0
     0    -1     1    -1     0     0     1     0
     0    -1    -1     1     0     0     0     1

我们还可以确认所有矩阵中的所有行总和为零:

>> all(all( sum(matrices,2)==0 ))
ans =
     1