如何更有效地制作这个排列矩阵



我写了这样的代码:

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

但我根本不想使用置换,因为我想使用这个代码,制作更大维度的矩阵,而使用置换使其不可能。

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

来自C++,这是非常直观的,因为algorithm库提供了std::next_permutation,它可以生成向量的下一个字典排列。该算法非常简单,可以在这里找到: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

您正在生成在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

最新更新