Algorithm 计算julia中置换的最优方法
考虑一个列表Algorithm 计算julia中置换的最优方法,algorithm,julia,combinatorics,Algorithm,Julia,Combinatorics,考虑一个列表[1,1,1,…,1,0,0,…,0](一个由0和1组成的任意列表)。我们需要这个数组中所有可能的排列,将有二项式(l,k)排列(l表示列表的长度,k表示列表中的个数) 现在,我已经测试了三种不同的算法来生成整个可能的排列,一种使用递归函数,一种计算 通过计算区间数的排列[1,…,1,0,0,…,0] 到[0,0,…0,1,1,…,1](因为这可以看作是一个二进制数间隔),以及使用字典顺序计算排列的间隔 到目前为止,前两种方法在执行排列时失败 大约32。词典编纂技术仍然非常有效(只需
[1,1,1,…,1,0,0,…,0]
(一个由0和1组成的任意列表)。我们需要这个数组中所有可能的排列,将有二项式(l,k)
排列(l
表示列表的长度,k
表示列表中的个数)
现在,我已经测试了三种不同的算法来生成整个可能的排列,一种使用递归函数,一种计算
通过计算区间数的排列[1,…,1,0,0,…,0]
到[0,0,…0,1,1,…,1]
(因为这可以看作是一个二进制数间隔),以及使用字典顺序计算排列的间隔
到目前为止,前两种方法在执行排列时失败
大约32。词典编纂技术仍然非常有效(只需几毫秒即可完成)
我的问题是,特别是对于julia,哪种方法是计算的最佳方法
如我前面所述的排列?我对组合学知道的不多,但我认为下降基准应该是从总的
二项式(l,l/2)
中生成所有排列,正如您在评论中提到的,在这种情况下,l>>k
是绝对需要的。在这种情况下,我们可以通过不处理长度为l
的向量(直到我们真正需要它们),而是处理这些向量的索引列表来显著提高性能
在中,以下算法将允许您迭代空间O(k^2)
和时间O(k^2*binom(l,k))
但是,请注意,每次从索引组合生成位向量时,都会产生开销O(l)
,其中也会有下限(对于所有组合)为Omega(l*binom(l,k))
,并且内存使用量会增加到Omega(l+k^2)
算法
例子
然后,您可以按如下方式迭代所有组合:
for c in @task(combination_producer(l, k))
# do something with c
end
请注意此算法的可恢复性:您可以随时停止迭代,然后再次继续:
iter = @task(combination_producer(5, 3))
for c in iter
println(c)
if c[1] == 2
break
end
end
println("took a short break")
for c in iter
println(c)
end
这将产生以下输出:
[1,2,3]
[1,2,4]
[1,2,5]
[1,3,4]
[1,3,5]
[1,4,5]
[2,3,4]
took a short break
[2,3,5]
[2,4,5]
[3,4,5]
如果你想从c
中得到一个位向量,你可以这样做
function combination_to_bitvector(l, c)
result = zeros(l)
result[c] = 1
result
end
<> > <代码> L>代码>是位向量的期望长度。“最佳方式”将取决于问题的约束(列表的最大大小是什么?代码< > L<代码/代码>和<代码> k>代码>均匀分布)和您认为最好的值。(最简单、最快或最直接?针对使用的总内存或CPU时间进行了优化?)。听起来你已经有了一个很好的解决方案。你为什么不满意呢?实际上,
k
和l
的值是任意的。灵感来自于一个由费米子组成的物理系统。恰巧描述它的一个合适的数学基础是(Fock基)[,它具有维度二项式(l,k)
基础的一个成员是我给出的带有0和1的列表的一些排列。如果我没记错的话,一个好的例子是l>>k
,这个想法是有足够大的基础来模拟一个合适的物理系统(在fortran中,我或多或少地快速地执行了类似于~10^4
基本维度的操作).另一方面,我希望算法足够快,可以生成整个基础,如果可能的话,可以节省尽可能多的内存。最后的灵感是学习新的组合算法,并朝着这个方向深入研究,这是我想要真正探索的。这个实现似乎不再有效(在Julia 1.1中测试)。特别是,product
不久前已被弃用,我不知道它是如何被替换的。您能否将此答案至少更新为Julia 1.0?
function combination_to_bitvector(l, c)
result = zeros(l)
result[c] = 1
result
end