我正在研究2D矩形包装。通过更改零件的放置顺序,最大限度地减少无限张的长度(宽度恒定)。例如,我们可以在11个中放置11个部分!方法。
我可以使用perms
函数标记这些部分并保存所有可能的排列并逐个运行,但即使是11个部分我也需要大量的内存。我希望能够为大约1000个零件做到这一点。
幸运的是,我并不需要所有可能的顺序。我想将每个排列索引到一个数字。测试随机序列,然后使用GA收敛结果以找到最佳序列。
因此,我需要一个函数,它在运行任意次数时提供特定的排列值,而不像randperm
函数。
例如,function(5,6)
应始终为6个部分返回说[1 4 3 2 5 6]
。我不需要特定顺序的序列,但该函数应该为相同的索引提供相同的序列。而对于其他一些索引,序列不应与此序列相同。
到目前为止,我已经使用randperm
函数生成大约2000次迭代的随机序列,并通过比较长度找到最佳序列,但这仅适用于少数部分。同样使用randperm
可能会导致重复序列而不是唯一序列。
这是我所做的一幅画。
我无法保存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
答案 0 :(得分:3)
下面是两个函数,它们将按照词法顺序生成排列并返回第n个排列
例如,我可以打电话
nth_permutation(5, [1 2 3 4])
输出将为[1 4 2 3]
直观地说,此方法在n
中所需的时间是线性的。集合的大小并不重要。我对nth_permutations(n, 1:1000)
进行了基准测试,平均超过100次迭代并获得了以下图表
所以时间似乎没关系。
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