Фильтрация диапазона в Юлии - PullRequest
0 голосов
/ 11 марта 2019

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

Например, если диапазон равен 1:100, я хочу иметь цикл for, каждый индекс которого будет в 4:6, взаимодействовать со всеми значениями 1:100 НО 4:6.

Я хочу сделать это, используя диапазоны / фильтры, чтобы избежать создания временных массивов.

В моем случае общий диапазон - это количество атомов в системе. Поддиапазон, это атомы в конкретной молекуле. Мне нужно сделать расчеты, где каждый атом в молекуле взаимодействует со всеми другими атомами, но не с атомами в той же молекуле.

Далее

Я стараюсь избегать использования операторов if, потому что это портит параллельные коды. Делать это с оператором if будет

for i=4:6
    for j = 1:100
        if j == 4 || j==5 || j==6
            continue
        end
        println(i, " ", j)
    end
end

У меня есть фактическая индексация в моем коде, я никогда не буду жестко кодировать значения, подобные приведенным выше ... Но я хочу избежать этого if утверждения.

Испытания

Следующее делает то, что я хочу, но теперь я понимаю, что использование filter плохо, когда речь идет о памяти, а используемое количество линейно масштабируется с b.

a = 4:6
b = 1:100
for  i in a
    for j in filter((b) -> !(b in a),b) 
        print(i, " ", j) 
    end
end

Есть ли способ получить двойной цикл for, который я хочу, когда внешний является поддиапазоном внутреннего, но внутренний не включает внешний поддиапазон и, что наиболее важно, является быстрым и не создает много памяти использование как фильтр делает?

Ответы [ 2 ]

3 голосов
/ 11 марта 2019

Если использование памяти действительно вызывает беспокойство, рассмотрим два цикла for, использующих компоненты диапазона:

systemrange = 1:50
moleculerange = 4:12
for i in systemrange[1]:moleculerange[1]-1
    println(i)
end
for i in moleculerange[end]+1:systemrange[end]
    println(i)
end

Возможно, вы сможете выполнить каждый цикл в отдельном потоке.

2 голосов
/ 11 марта 2019

А как насчет создания собственного итератора?Обратите внимание, что приведенный ниже пример нуждается в некоторых корректировках в зависимости от того, как вы определяете списки исключений (например, для длинного списка с индексами без продолжения вы должны использовать бинарный поиск).

struct RangeExcept
       start::Int
       stop::Int
       except::UnitRange{Int}
end

function Base.iterate(it::RangeExcept, (el, stop, except)=(it.except.start > 1 ? it.start : it.except.stop+1, it.stop, it.except))
    new_el = el+1
    if new_el in except
        new_el = except.stop+1
    end 
    el > stop && return nothing
    return (el, (new_el, stop,except))
end

Теперь давайте проверим код:

julia> for i in RangeExcept(1,10,3:7)
           println(i)
           end
1
2
8
9
10
...