Algorithm 具有分组约束的前n个整数的置换

Algorithm 具有分组约束的前n个整数的置换,algorithm,matlab,constraints,permutation,Algorithm,Matlab,Constraints,Permutation,我想生成前n个整数的所有排列,这样指定的整数组仍然保留在它们的组中,并且这些组保持相同的顺序。例如,如果我们有n=5和分组[[1]、[2,3]、[4,5]],那么我想要输出 [1]、[2,3]、[4,5]] [1]、[2,3]、[5,4]] [1],[3,2],[4,5]] [1],[3,2],[5,4] 每个排列应该在矩阵中显示为一行,为了便于查看分组,我刚刚加入了括号符号。在我的例子中,数字1始终是每个排列的第一个元素。我尝试生成每个组的所有排列,然后将它们粘贴到矩阵中适当的次数,但无法计算

我想生成前n个整数的所有排列,这样指定的整数组仍然保留在它们的组中,并且这些组保持相同的顺序。例如,如果我们有n=5和分组[[1]、[2,3]、[4,5]],那么我想要输出

[1]、[2,3]、[4,5]]

[1]、[2,3]、[5,4]]

[1],[3,2],[4,5]]

[1],[3,2],[5,4]

每个排列应该在矩阵中显示为一行,为了便于查看分组,我刚刚加入了括号符号。在我的例子中,数字1始终是每个排列的第一个元素。我尝试生成每个组的所有排列,然后将它们粘贴到矩阵中适当的次数,但无法计算这里是我的代码:f是一个向量,其中f(i)是i组的起始索引,r是一个向量,r(i)是i组中元素的数量

function AP=allPerms(f,r)
%Construct all possible permutations of integers consistent with their
%grouping
n=length(r);                   %Number of groups
num_parts=f(n)+r(n)-1;         %Number of integers
num_perms=factorial(r(1)-1);   %Initialize num of perms
for i=2:n
    num_perms=num_perms*factorial(r(i));    %Formula for num_perms
end
AP=zeros(num_perms,num_parts); %Initialize matrix to store perms
AP(:,1)=ones(num_perms,1);     %First column is all 1's

%handle case where there is only 1 group
if n==1
    AP(:,2:num_parts)=perms(2:num_parts);
    return
end

%Construct all the sublist perms
v{1}=perms(2:f(2)-1); v{n}=perms(f(n):f(n)+r(n)-1);
for i=2:n-1
    v{i}=perms(f(i):f(i+1)-1);
end

%Insert into perm array appropriate number of times. consider i=1,n
%seperately
if r(1)~=1
    for j=1:num_perms/factorial(r(1)-1)
        AP((j-1)*factorial(r(1)-1)+1:j*factorial(r(1)-1),2:f(1)+r(1)-1)=v{1}; 
    end
end
for i=2:n-1
    for j=1:num_perms/factorial(r(i))
        AP((j-1)*factorial(r(i))+1:j*factorial(r(i)),f(i):f(i)+r(i)-1)=v{i};
    end
end 
for j=1:num_perms/factorial(r(n))
    AP((j-1)*factorial(r(n))+1:j*factorial(r(n)),f(n):f(n)+r(n)-1)=v{n};
end
结束

我已经尝试在j上的循环中使用circshift来获得不同的排列,并且可以使它在特定情况下工作,但不是一般情况下。有没有系统的方法来做到这一点?我不想生成所有排列,然后过滤它们

我还发现了这篇论文:


在我尝试实现之前,我想知道我的解决方案是否有一个变体可以工作。

这里是一个基于
cellfun
perms
ndgrid

grouping={1,[2 3],[4 5]};
perm = cellfun(@(x){perms(x)},grouping);      %for each group generate all permutations
cart = cell(1,numel(grouping));               
perm_size = cellfun(@(x){1:size(x,1)},perm);  % [1 : size_of_permutation] to be used in ndgrid
[cart{:}]=ndgrid(perm_size{:});               % Cartesian product of indexes of permutations
result = cell(1,numel(grouping));
for k = 1:numel(cart)
    result(k) = perm{k}(cart{k},:);           % In the loop index permutations with the cartesian product of their indexes
end
结果如下:

result =
{
  [1,1] =

     1
     1
     1
     1

  [1,2] =

     2   3
     3   2
     2   3
     3   2

  [1,3] =

     4   5
     4   5
     5   4
     5   4

}

谢谢!这很有效!唯一的一件事是在第4行中定义排列大小,它应该是阶乘(大小(x,2))来获得排列的大小。它仍然有效,因为我的示例案例有两个或更少的元素组。@onehalfatsquared好的,它应该是
size(x,1)
。或者它可以是
perm\u size=cellfun(@(x){1:factorial)(numel(x))},分组)
。答案已更新。