检索特定的排列而不在Matlab中存储所有可能的排列

时间:2015-03-16 12:46:48

标签: matlab optimization permutation genetic-algorithm nested

我正在研究2D矩形包装。通过更改零件的放置顺序,最大限度地减少无限张的长度(宽度恒定)。例如,我们可以在11个中放置11个部分!方法。

我可以使用perms函数标记这些部分并保存所有可能的排列并逐个运行,但即使是11个部分我也需要大量的内存。我希望能够为大约1000个零件做到这一点。

幸运的是,我并不需要所有可能的顺序。我想将每个排列索引到一个数字。测试随机序列,然后使用GA收敛结果以找到最佳序列。

因此,我需要一个函数,它在运行任意次数时提供特定的排列值,而不像randperm函数。

例如,function(5,6)应始终为6个部分返回说[1 4 3 2 5 6]。我不需要特定顺序的序列,但该函数应该为相同的索引提供相同的序列。而对于其他一些索引,序列不应与此序列相同。

到目前为止,我已经使用randperm函数生成大约2000次迭代的随机序列,并通过比较长度找到最佳序列,但这仅适用于少数部分。同样使用randperm可能会导致重复序列而不是唯一序列。

这是我所做的一幅画。 Packing example

我无法保存randperm的输出,因为我没有可搜索的功能空间。我不想找到所有序列的表格长度。我只需要通过遗传算法确定的某些指标识别某些序列。如果我使用randperm,我将无法获得所有索引的序列(即使我只需要其中一些索引)。

例如,取一些函数,'y = f(x)',在[0,10]范围内。对于x的每个值,我得到一个y。这是我的纸张长度。 x是排列的索引。对于任何x,我找到它的序列(特定的排列),然后找到它相应的纸张长度。根据x的一些随机值的结果,GA将生成一个新的x列表,以找到更优的y。

我需要一个复制perms的函数,(我猜perms每次运行时都遵循相同的排列顺序,因为perms(1:4)在运行任意数量时会产生相同的结果时间)没有实际存储值。

有没有办法写这个功能?如果没有,那么我该如何解决我的问题呢?

编辑(我是如何解决问题的):

Genetic Algorithm中,你需要交叉父母(排列),但是如果你交叉排列,你会得到重复的数字。例如: - 与1 2 3 4交叉3 2 1 4可能会产生类似3 2 3 4的内容。因此,为了避免重复,我想到将每个父项索引到一个数字,然后将数字转换为二进制形式,然后交叉二进制索引以获得新的二进制数,然后将其转换回十进制并找到其特定的排列。但后来,我发现我可以使用排列本身的ordered crossover而不是越过它们的索引。

有关Ordered Crossover的更多详细信息,请here

1 个答案:

答案 0 :(得分:3)

下面是两个函数,它们将按照词法顺序生成排列并返回第n个排列

例如,我可以打电话

nth_permutation(5, [1 2 3 4])

输出将为[1 4 2 3]

直观地说,此方法在n中所需的时间是线性的。集合的大小并不重要。我对nth_permutations(n, 1:1000)进行了基准测试,平均超过100次迭代并获得了以下图表

Benchmark graph of n vs time

所以时间似乎没关系。

function [permutation] = nth_permutation(n, set)
%%NTH_PERMUTATION Generates n permutations of set in lexographical order and
%%outputs the last one
%% set is a 1 by m matrix

set = sort(set);
permutation = set; %First permutation

for ii=2:n
   permutation = next_permute(permutation);    
end

end

function [p] = next_permute(p)
%Following algorithm from https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order

%Find the largest index k such that p[k] < p[k+1]
larger = p(1:end-1) < p(2:end);
k = max(find(larger));

%If no such index exists, the permutation is the last permutation.
if isempty(k)
    display('Last permutation reached');
    return
end

%Find the largest index l greater than k such that p[k] < p[l].
larger = [false(1, k) p(k+1:end) > p(k)];
l = max(find(larger));

%Swap the value of p[k] with that of p[l].
p([k, l]) = p([l, k]);

%Reverse the sequence from p[k + 1] up to and including the final element p[n].
p(k+1:end) = p(end:-1:k+1);

end