【问题标题】:Generating linear combination of a matrix生成矩阵的线性组合
【发布时间】:2011-06-20 22:02:05
【问题描述】:

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

矩阵 A 始终以 1 作为其对角线。 A11,A22,A33,A44 = 1

这个矩阵可以被认为是两半,前半部分是前 4 列,后半部分是后 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 的所有可能组合,并在每次迭代中创建一个矩阵。这看起来可行吗?

【问题讨论】:

  • 你已经尝试了什么? 具体你在用卢布做什么?
  • 我无法掌握如何执行此操作的逻辑。我还在想。 :(
  • 来吧。另一个问题也是我问的。我正在尝试对矩阵做同样的事情。
  • @Oli Charlesworth:这是一个类似的问题,但要困难得多。

标签: matlab matrix


【解决方案1】:

这是一种可能的解决方案。如果你暂时忽略对角线,你可以使用函数KRONREPMATPERMSUNIQUEEYEONES为其他7个值生成所有可能的模式:

>> 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 种可能的行模式(相当多)。您可以使用函数NDGRIDCATRESHAPE 生成所有可能的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 向行模式索引并使用函数 TRILTRIUEYEZEROS 生成矩阵 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

【讨论】:

    【解决方案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
    

    【讨论】:

    • 谢谢 Amro。完美运行。
    • +1 用于使用 NDGRID 创建索引。这比我使用的 DEC2BASE 算法更直接(也更快)。
    猜你喜欢
    • 1970-01-01
    • 2011-06-20
    • 2011-04-28
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    相关资源
    最近更新 更多