【问题标题】:Generating only unique permutations仅生成唯一排列
【发布时间】:2019-11-27 21:50:47
【问题描述】:

我正在使用来自Combinatorics 库的permutations,该列表具有许多重复值。我的问题是 permutations 正在创建 all 排列,导致溢出,即使 许多 排列是相同的。

julia> collect(permutations([1, 1, 2, 2], 4))
24-element Array{Array{Int64,1},1}:
 [1, 1, 2, 2]
 [1, 1, 2, 2]
 [1, 2, 1, 2]
 [1, 2, 2, 1]
 [1, 2, 1, 2]
 [1, 2, 2, 1]
 [1, 1, 2, 2]
 [1, 1, 2, 2]
 [1, 2, 1, 2]
 [1, 2, 2, 1]
 [1, 2, 1, 2]
 [1, 2, 2, 1]
 [2, 1, 1, 2]
 [2, 1, 2, 1]
 [2, 1, 1, 2]
 [2, 1, 2, 1]
 [2, 2, 1, 1]
 [2, 2, 1, 1]
 [2, 1, 1, 2]
 [2, 1, 2, 1]
 [2, 1, 1, 2]
 [2, 1, 2, 1]
 [2, 2, 1, 1]
 [2, 2, 1, 1]

许多相同的值。我真正想要的只是唯一的排列,而不需要首先生成所有排列:

julia> unique(collect(permutations([1, 1, 2, 2], 4)))
6-element Array{Array{Int64,1},1}:
 [1, 1, 2, 2]
 [1, 2, 1, 2]
 [1, 2, 2, 1]
 [2, 1, 1, 2]
 [2, 1, 2, 1]
 [2, 2, 1, 1]

我可以看到permutations 应该始终返回 all 排列的论点,无论是否唯一,但是有没有办法生成 only 唯一排列所以我不要内存不足?

【问题讨论】:

  • permutations返回一个迭代器,所以内存应该没有问题,除非你collect它。你真的需要这样做吗?你试过unique(permutations(
  • unique(permutations(...))?

标签: julia permutation combinatorics


【解决方案1】:

即使对于尺寸相对较小的向量(例如,我认为 14 已经有问题),通过 unique 也可能会令人望而却步。在这种情况下,您可以考虑这样的事情:

using Combinatorics, StatsBase

function trans(x, v::Dict{T, Int}, l) where T
    z = collect(1:l)
    idxs = Vector{Int}[]
    for k in x
        push!(idxs, z[k])
        deleteat!(z, k)
    end
    res = Vector{T}(undef, l)
    for (j, k) in enumerate(keys(v))
        for i in idxs[j]
            res[i] = k
        end
    end
    res
end

function myperms(x)
    v = countmap(x)
    s = Int[length(x)]
    for (k,y) in v
        l = s[end]-y
        l > 0 && push!(s, l)
    end
    iter = Iterators.product((combinations(1:s[i], vv) for (i, vv) in enumerate(values(v)))...)
    (trans(z, v, length(x)) for z in iter)
end

(这是一篇简短的文章,因此代码质量不是生产级的——就风格和最大限度地发挥性能而言,但我希望它能让您了解如何实现这一点)

这为您提供了一个考虑重复项的唯一排列生成器。它相当快:

julia> x = [fill(1, 7); fill(2, 7)]
14-element Array{Int64,1}:
 1
 1
 1
 1
 1
 1
 1
 2
 2
 2
 2
 2
 2
 2

julia> @time length(collect(myperms(x)))
  0.002902 seconds (48.08 k allocations: 4.166 MiB)
3432

虽然unique(permutations(x)) 的此操作不会以任何合理的大小终止。

【讨论】:

  • 我认为这确实可行,但我仍然内存不足。我可能只需要聪明地处理问题并避免排列...
  • 您不需要collect。我的解决方案可以在不实现的情况下进行迭代。我刚刚使用collect 向您展示 - 在小情况下 - 它可以正常工作。
【解决方案2】:

包里有multiset_permutationCombinatorics

julia> for p in multiset_permutations([1,1,2,2],4) p|>println end
[1, 1, 2, 2]
[1, 2, 1, 2]
[1, 2, 2, 1]
[2, 1, 1, 2]
[2, 1, 2, 1]
[2, 2, 1, 1]

【讨论】:

    【解决方案3】:

    我也遇到了这个问题,用IterToolsdistinct

    using IterTools, Combinatorics
    
    distinct(permutations([1, 1, 2, 2], 4))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-08
      • 2012-11-04
      相关资源
      最近更新 更多