朱莉娅(Julia):有没有办法用离散集合中的项来枚举大小为m×n的所有矩阵?

时间:2019-05-08 12:03:36

标签: performance matrix julia permutation

我正在使用2D网格中具有两个变量f(x,y)的一组函数。网格中每个点的函数本身只能采用有限集合中的值。我需要列举我可以构造的所有可能的函数。

特别是,函数定义为矩阵,第ith个第j个元素告诉我在x_i,y_j处求值的函数的值。

我希望能够创建所有可能的矩阵。我知道这类矩阵的总数为nf ^(nx * ny),其中nf是函数可以在一个点中采用的值的数量,而nx,ny是x和y网格中的点的数量。因此,我的测试将使用少量的网格点。

谢谢

我试图通过枚举树中的所有分支并使用递归来表达问题,但是无法创建矩阵作为输出。

2 个答案:

答案 0 :(得分:1)

这是您想要的吗?

function funs(fs)
    nf = length(fs)
    @assert length(unique(size.(fs))) == 1
    nx,ny = size(fs[1])
    sigs = Iterators.product(ntuple(i -> 1:nf, nx*ny)...)
    ([fs[sig[i+(j-1)*nx]][nx,ny] for i in 1:nx, j in 1:ny] for sig in sigs)
end

我将返回一个生成器,您可以轻松地对其进行迭代而不会实现,因为收集它可能会占用过多的内存。当然,对于小型数据,您可以collect进行处理,其额外好处是它将成为nx*ny维数组,使您可以轻松地切片变化的维。

这里是一个例子:

julia> fs = [fill(1,2,2), fill(2,2,2), fill(3,2,2)]
3-element Array{Array{Int64,2},1}:
 [1 1; 1 1]
 [2 2; 2 2]
 [3 3; 3 3]

julia> funs(fs)
Base.Generator{Base.Iterators.ProductIterator{NTuple{4,UnitRange{Int64}}},getfield(Main, Symbol("##46#49")){Array{Array{Int64,2},1},Int64,Int64}}(getfield(Main, Symbol("##46#49")){Array{Array{Int64,2},1},Int64,Int64}(Array{Int64,2}[[1 1; 1 1], [2 2; 2 2], [3 3; 3 3]], 2, 2), Base.Iterators.ProductIterator{NTuple{4,UnitRange{Int64}}}((1:3, 1:3, 1:3, 1:3)))

julia> collect(funs(fs))
3×3×3×3 Array{Array{Int64,2},4}:
[:, :, 1, 1] =
 [1 1; 1 1]  [1 1; 2 1]  [1 1; 3 1]
 [2 1; 1 1]  [2 1; 2 1]  [2 1; 3 1]
 [3 1; 1 1]  [3 1; 2 1]  [3 1; 3 1]

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

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

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

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

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

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

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

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

答案 1 :(得分:0)

这是我对OP的了解:

function all_functions(finite_set, nx, ny)
  I = Iterators.product(fill(finite_set, nx*ny)...)
  (reshape(collect(i), (nx,ny)) for i in I)
end

并付诸行动:

julia>fs = (0,1,2,3)
julia>collect(Iterators.take(all_functions(fs, 2, 2), 8))
Array{Int64,2}[[0 0; 0 0], [1 0; 0 0], [2 0; 0 0], [3 0; 0 0], [0 0; 1 0], [1 0; 1 0], [2 0; 1 0], [3 0; 1 0]]