Джулия: создайте определенные индексные переменные в Base.Cartesian

Я впервые использую Base.Cartesian и считаю его очень мощным. Однако кажется, что он генерирует код, который использует все доступные индексы, тогда как у меня есть случай, когда я хотел бы использовать только некоторые из них.

Короче

Если я нахожусь внутри @nloops, но хочу использовать только подмножество переменных индексации, можно ли сгенерировать выражения для этих переменных индексации, используя скаляры, соответствующие индексам их индексов?

a,b -> i_{a}, i_{b} where we have i_{1:N}

Полная форма

В частности, у меня есть N объектов, каждый из которых может принимать некоторое количество значений:

Obj1: m11, m12, m13
Obj2: m21, m22, m23, m24
Obj3: m31, m32

что соответствует:

i_1 = 1 : 3
i_2 = 1 : 4
i_3 = 1 : 2

Я генерирую каждую комбинацию, используя @nloops:

{m11,m21,m31}{m12,m21,m31}{m13,m21,m31}{m11,m22,m31}{m12,m22,m31}...

Затем я запускаю попарные перечисления для каждой комбинации:

comb = {m11,m21,m31} -> pairs = {m11,m21}{m11,m31}{m21,m31}

Я хотел бы использовать эти пары для индексации в матрице. Вот где я спотыкаюсь, так как мне нужно сгенерировать изменяющееся выражение, используя только подмножество переменных индексации.

a,b = pair[1],pair[2]
foo = max(foo, mat[i_{a}, i_{b}]) # need to figure out appropriate syntax here

Вот подчищенный демонстрационный пример: (3 используется как N, позже я буду использовать @ngenerate)

@nloops 3 i d->1:lens[d] begin
    foo = 0
    for pair in combinations([1:3],2)
        a, b  = pair[1], pair[2]
        M_ind  = pair2ind(ia,ib)
        mat = M[M_ind]
        foo = max(foo, mat[i_{a}, i_{b}])  # need to figure this out
        if foo==1 # early exit
            break
        end
    end
    # do something with foo...
end

Возможно ли сделать то, что я пытаюсь сделать? Я пытался использовать @eval, но не смог его скомпилировать:

@eval(parse(@sprintf("foo = max(foo, mat[i_%d, i_%d])", a, b)))
Error: a not defined

Спасибо.


person Mageek    schedule 31.07.2014    source источник
comment
@eval(:(:foo = max(:foo :mat[symbol(@sprintf("i_%d", :a)), symbol(@sprintf("i_%d", :b))]))) запускается, но, похоже, foo не меняется должным образом.   -  person Mageek    schedule 31.07.2014
comment
Я не совсем понимаю, что вы пытаетесь сделать; Я не понимаю, почему вам нужно интерполировать переменные в первую очередь. Достаточно ли индексов? Вы можете получить их через @ntuple, например. @nloops 3 i d->1:3 begin x = @ntuple 3 i; println(x); end.   -  person DSM    schedule 31.07.2014
comment
Привет! Это работает. Вы правы, мне не нужны были сами символы, мне нужны были только их значения.   -  person Mageek    schedule 31.07.2014


Ответы (1)


Проблема решилась полным отказом от него. Использовалась отдельная версия с использованием рекурсии.

N = number of objects
M = array containing number of states

function next_combination!( comb )
    i = findfirst(i->comb[i] < M[i], 1:N)
    @assert(i != 0)
    comb[i] += 1
    comb[1:i-1] = 1
    return comb
end

ncombs = prod(M)
comb = int([0, ones(N-1)])
for ci = 1 : ncombs
    next_combination!(comb)

    foo = 0
    for pair in combinations([1:N],2)
        a, b = pair[1], pair[2]
        col_ind = pair2ind(a,b)
        foo = max(foo, mymat[col_ind][comb[a], comb[b]])
        if foo == 1 # early out
            break
        end
    end

    # do something with foo...
end

Изменение существующего метода

Как указывает DSM, работает следующее:

inds = @tuple 3 i
foo = max(foo, mymat[col_ind][inds[a], inds[b]])
person Mageek    schedule 31.07.2014