【问题标题】:How can I make this matrix of permutations more efficiently?我怎样才能更有效地制作这个排列矩阵?
【发布时间】:2018-07-27 05:08:45
【问题描述】:

我已经写了这段代码:

a = repelem(ones(7,8)-2.*eye(7,8), 7:-1:1, 1);
for i=1:7
    a(i,i+1)=-1;
end
for i=8:13
    a(i,i-5)=-1;
end
for i=14:18
    a(i,i-10)=-1;
end
for i=19:22
    a(i,i-14)=-1;
end
for i=23:25
    a(i,i-17)=-1;
end
for i=26:27
    a(i,i-19)=-1;
end
for i=28:28
    a(i,i-20)=-1;
end

要产生这个矩阵:

-1  -1   1   1   1   1   1   1
-1   1  -1   1   1   1   1   1
-1   1   1  -1   1   1   1   1
-1   1   1   1  -1   1   1   1
-1   1   1   1   1  -1   1   1
-1   1   1   1   1   1  -1   1
-1   1   1   1   1   1   1  -1
 1  -1  -1   1   1   1   1   1
 1  -1   1  -1   1   1   1   1
 1  -1   1   1  -1   1   1   1
 1  -1   1   1   1  -1   1   1
 1  -1   1   1   1   1  -1   1
 1  -1   1   1   1   1   1  -1
 1   1  -1  -1   1   1   1   1
 1   1  -1   1  -1   1   1   1
 1   1  -1   1   1  -1   1   1
 1   1  -1   1   1   1  -1   1
 1   1  -1   1   1   1   1  -1
 1   1   1  -1  -1   1   1   1
 1   1   1  -1   1  -1   1   1
 1   1   1  -1   1   1  -1   1
 1   1   1  -1   1   1   1  -1
 1   1   1   1  -1  -1   1   1
 1   1   1   1  -1   1  -1   1
 1   1   1   1  -1   1   1  -1
 1   1   1   1   1  -1  -1   1
 1   1   1   1   1  -1   1  -1
 1   1   1   1   1   1  -1  -1

我正在寻找一种更有效的方法来生成这个矩阵。一种方法是:

S=[-1 -1 1 1 1 1 1 1];
P=unique(perms(S),'rows');

但我根本不想使用排列,因为我想使用这段代码并制作更大维度的矩阵,而使用排列则不可能。

【问题讨论】:

    标签: matlab matrix permutation


    【解决方案1】:

    @gnovice 的答案非常好,但是我想为教学目的添加一个替代答案。正如 gnovice 所说,“您正在生成将 2 个 -1 值定位在 1×8 向量中的每个排列”。我们可以通过思考如何生成[-1 -1 1 1 1 1 1 1] 的连续排列来将其应用于我们的问题。

    来自C++,这非常直观,因为algorithm 库提供std::next_permutation,它会生成向量的下一个lexicographical 排列。该算法非常简单,可以在这里找到:https://en.cppreference.com/w/cpp/algorithm/next_permutation。事实上,Jos 已经在matlab 中实现了这个算法的一个更通用的版本。我们将使用nextperm_local,它可以在nextperm的文件交换页面的“功能”选项卡的最底部找到。

    myP = [-1 -1 1 1 1 1 1 1];
    
    function P = nextperm_local(P)
        k1 = find(P(2:end) > P(1:end-1), 1, 'last');
        if isempty(k1)
            k1 = 0;
        else
            k2 = find(P(k1)<P, 1, 'last');
            P([k1 k2]) = P([k2 k1]);
        end
        P((k1+1):end) = P(end:-1:(k1+1));
    end
    
    total = nchoosek(8, 2);
    output = zeros(total, 8);
    
    for i = 1:total
        output(i,:) = myP ;
        myP = nextperm_local(myP) ;
    end
    

    并产生以下矩阵:

    output =
    
      -1  -1   1   1   1   1   1   1
      -1   1  -1   1   1   1   1   1
      -1   1   1  -1   1   1   1   1
      -1   1   1   1  -1   1   1   1
      -1   1   1   1   1  -1   1   1
      -1   1   1   1   1   1  -1   1
      -1   1   1   1   1   1   1  -1
       1  -1  -1   1   1   1   1   1
       1  -1   1  -1   1   1   1   1
       1  -1   1   1  -1   1   1   1
       1  -1   1   1   1  -1   1   1
       1  -1   1   1   1   1  -1   1
       1  -1   1   1   1   1   1  -1
       1   1  -1  -1   1   1   1   1
       1   1  -1   1  -1   1   1   1
       1   1  -1   1   1  -1   1   1
       1   1  -1   1   1   1  -1   1
       1   1  -1   1   1   1   1  -1
       1   1   1  -1  -1   1   1   1
       1   1   1  -1   1  -1   1   1
       1   1   1  -1   1   1  -1   1
       1   1   1  -1   1   1   1  -1
       1   1   1   1  -1  -1   1   1
       1   1   1   1  -1   1  -1   1
       1   1   1   1  -1   1   1  -1
       1   1   1   1   1  -1  -1   1
       1   1   1   1   1  -1   1  -1
       1   1   1   1   1   1  -1  -1
    

    【讨论】:

      【解决方案2】:

      您正在生成在 1×8 向量中定位 -1 的 2 个值的每个排列。因此,您可以使用nchoosek 生成-1 值的列索引,然后使用sub2ind 在单个索引步骤中修改矩阵a

      indices = nchoosek(1:8, 2);
      N = size(indices, 1);
      a = ones(N, 8);
      a(sub2ind([N 8], [1:N 1:N].', indices(:))) = -1;
      

      还有输出:

      a =
      
          -1    -1     1     1     1     1     1     1
          -1     1    -1     1     1     1     1     1
          -1     1     1    -1     1     1     1     1
          -1     1     1     1    -1     1     1     1
          -1     1     1     1     1    -1     1     1
          -1     1     1     1     1     1    -1     1
          -1     1     1     1     1     1     1    -1
           1    -1    -1     1     1     1     1     1
           1    -1     1    -1     1     1     1     1
           1    -1     1     1    -1     1     1     1
           1    -1     1     1     1    -1     1     1
           1    -1     1     1     1     1    -1     1
           1    -1     1     1     1     1     1    -1
           1     1    -1    -1     1     1     1     1
           1     1    -1     1    -1     1     1     1
           1     1    -1     1     1    -1     1     1
           1     1    -1     1     1     1    -1     1
           1     1    -1     1     1     1     1    -1
           1     1     1    -1    -1     1     1     1
           1     1     1    -1     1    -1     1     1
           1     1     1    -1     1     1    -1     1
           1     1     1    -1     1     1     1    -1
           1     1     1     1    -1    -1     1     1
           1     1     1     1    -1     1    -1     1
           1     1     1     1    -1     1     1    -1
           1     1     1     1     1    -1    -1     1
           1     1     1     1     1    -1     1    -1
           1     1     1     1     1     1    -1    -1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多