2015-03-30 2 views
6

У меня есть два вектора x и y соответствующих длин n и p. Есть встроенный способ создания нп х 2 матрицы, которая будетДекартово произведение двух векторов в Юлии

x[1] y[1] 
x[1] y[2] 
... 
x[1] y[p] 
x[2] y[1] 
... 
x[n] y[p] 

я могу сделать это с вложенным для цикла, но я ищу для встроенной функции, если он существует.

ответ

6

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

Другой вариант будет использовать repmat (это один немного быстрее, чем с помощью повторения):

[repmat(x,1,length(y))'[:] repmat(y,length(x),1)[:]] 

ли некоторые быстрое тестирование обоих методов:

x=rand(1000) 
y=rand(1000) 

function withrepeat(x,y) 
    [repeat(x, inner=[size(y,1)]) repeat(y, outer=[size(x,1)])] 
end 

function withrepmat(x,y) 
    [repmat(x,1,length(y))'[:] repmat(y,length(x),1)[:]] 
end 

withrepeat(x,y) 
elapsed time: 0.21556302 seconds (95986112 bytes allocated) 

with repmat(x,y) 
elapsed time: 0.075604488 seconds (56000560 bytes allocated) 

Не знаю, почему такая большая разница и я думаю, что еще есть возможности для улучшения. Не пробовал функцию продукта внутри пакета Iterators.jl.

Также немного больше информации здесь: https://groups.google.com/forum/#!topic/julia-users/dtl--SyFgwY

Надеется, что это помогает.

Пробовал пару вложенных циклов и в самом деле быстрее:

function withloops (x,y) 
    leny=length(y) 
    lenx=length(x) 
    m=leny*lenx 
    OUT = zeros(Float64, m,2) 
    c=1 
    for i = 1:lenx 
     for j = 1:leny 
      OUT[c,1] = x[i] 
      OUT[c,2] = y[j] 
      c+=1 
     end 
    end 
    return OUT 
end 

И для того же rand(1000) для x и y.

withloops(x,y) 
elapsed time: 0.011350679 seconds (16000128 bytes allocated) 
+1

Помогает ли' @ inbounds' цикл 'for'? – rickhg12hs

+1

@ rickhg12hs Должно быть, я был немного поспешен, когда я разместил его, поэтому у меня не было времени проверить его правильно, но я сделаю это завтра и отредактирую сообщение соответственно. Спасибо за предложение. – Esteban

+0

Я попытался использовать '@ inbounds', но не получил заметного улучшения, может быть, это потому, что с массивами нет операций, и я просто назначаю значения? Кроме того, на моем компьютере, используя векторы длиной 10000 в качестве входных данных для 'x' и' y', возникали ошибки памяти при использовании 'repeat' или' repmat', но отлично работали с функцией вложенных циклов. – Esteban

4

Вот как я могу это сделать:

julia> x = [1, 2, 3, 4]; 

julia> y = [9, 8, 7]; 

julia> [repeat(x, inner=[size(y,1)]) repeat(y, outer=[size(x,1)])] 
12x2 Array{Int64,2}: 
1 9 
1 8 
1 7 
2 9 
2 8 
2 7 
3 9 
3 8 
3 7 
4 9 
4 8 
4 7 

вы также можете взглянуть на Iterators.j - в частности функцию product.

+0

Обратите внимание, что можно опустить скобки '' inner' и outer' аргументов, поэтому формула сводится к '[Повтор (х, внутренний размер = (у, 1)) repeat (y, outer = size (x, 1))] ' –

3

Это предусмотрено в модуле Iterators.

Взятые из https://github.com/JuliaLang/Iterators.jl

перебирать все комбинации в декартово произведении входов.

Пример:

for p in product(1:3,1:2) 
    @show p 
end yields 

p = (1,1) 
p = (2,1) 
p = (3,1) 
p = (1,2) 
p = (2,2) 
p = (3,2) 
Смежные вопросы