在 Julia 中生成具有两个值的所有项目组合?

问题描述

我有 m 件商品。每个项目都是一对两个值。例如,对于 m=4我有矩阵:

julia> valid_pairs = [0 1;
                      1 2;
                      1 2;
                      2 3];

我想生成四个项目的所有组合,其中每个项目 i 只能采用 valid_pairs[i,:] 中的值。基于前面的例子,我想有:

julia> all_combs
4x16 Array{Int,2}
 0  0  0  0  0  0  0  0  1  1  1  1  1  1  1  1
 1  1  1  1  2  2  2  2  1  1  1  1  2  2  2  2
 1  1  2  2  1  1  2  2  1  1  2  2  1  1  2  2
 2  3  2  3  2  3  2  3  2  3  2  3  2  3  2  3

我觉得这可以使用 Combinatorics.jl 轻松完成。

虽然我使用了 Combinatorics.jl,但我做了以下事情:

using Combinatorics

m = 4
combs = combinations(1:m) |> collect
L = length(combs)
all_combs = zeros(Int,m,L+1)
for j in 1:L
    for i in 1:m
        if !in(i,combs[j])
             all_combs[i,j] = valid_pairs[i,1]
         else
             all_combs[i,2]
         end
    end
end
all_combs[:,end] = valid_pairs[:,1]
 

解决方法

顺序不同,但是

julia> [collect(x) for x in Iterators.product(eachrow(valid_pairs)...)]
2×2×2×2 Array{Array{Int64,1},4}:
[:,:,1,1] =
 [0,2]  [0,2,2]
 [1,2]  [1,2]

[:,2] =
 [0,3]  [0,3]
 [1,3]  [1,3]

[:,3]

应该可以。如果你真的想要一个矩阵(二维数组),那么你可以hcat上一个答案,或者直接做

julia> reduce(hcat,collect(x) for x in Iterators.product(eachrow(valid_pairs)...))
4×16 Array{Int64,2}:
 0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1
 1  1  2  2  1  1  2  2  1  1  2  2  1  1  2  2
 1  1  1  1  2  2  2  2  1  1  1  1  2  2  2  2
 2  2  2  2  2  2  2  2  3  3  3  3  3  3  3  3

编辑:旁注,我会将这些对定义为元组以澄清正在发生的事情,所以像

valid_pairs = [(0,1),(1,2),(2,3)]

我不会创建 2D(或 4D,或 m-D)数组,而是创建

comb_pairs = Iterators.product(valid_pairs...)

然后为您提供所有配对组合的 lazy 版本,以便您可以迭代它而无需先实际创建它,我认为这应该更有效(并且看起来更干净)。