Юлия: Есть ли способ перечислить все матрицы размера m на n с записями из дискретного множества? - PullRequest
1 голос
/ 08 мая 2019

Я работаю с набором функций двух переменных f (x, y) в 2D-сетке.Сама функция в каждой точке сетки может принимать значения только из конечного множества.Мне нужно перечислить все возможные функции, которые я могу построить.

В частности, функция определяется как матрица, где i-й j-й элемент сообщает мне значение функции, оцененное в x_i, y_j.

Я хочу иметь возможность создавать все матрицывозможный.Я знаю, что общее число таких матриц равно nf ^ (nx * ny), где nf - количество значений, которые функция может принимать в точке, а nx, ny - количество точек в сетке x и y.Итак, мои тесты будут с небольшим количеством точек сетки.

Спасибо

Я пытался выразить проблему как перечисление всех ветвей в дереве и использование рекурсии, но не смог создать матрицу в качестве вывода.

Ответы [ 2 ]

1 голос
/ 08 мая 2019

Это то, что вы хотите?

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]
0 голосов
/ 26 июня 2019

Вот что я понимаю из ОП:

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]]
...