2015-03-30 14 views
6

Ho due vettori x e , delle rispettive lunghezze n e p. C'è un modo integrato per creare un np x 2 matrice che sarebbeProdotto cartesiano di due vettori in Julia

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

posso farlo con un nidificato ciclo for, ma sto cercando una funzione built-in, se esiste.

risposta

6

Julia è in genere molto veloce nei cicli nidificati, quindi se funzionano correttamente per te, dovresti controllare pro spettivamente le prestazioni, magari limitarti a seguirle.

altra opzione sarebbe utilizzando repmat (questo è un po 'più veloce rispetto all'utilizzo di ripetizione):

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

Ha fatto qualche rapido test di entrambi i metodi:

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) 

Non capisco perché tanta differenza e penso che ci sia ancora spazio per miglioramenti. Non ho provato la funzione del prodotto all'interno del pacchetto Iterators.jl.

anche un po 'più informazioni qui: https://groups.google.com/forum/#!topic/julia-users/dtl--SyFgwY

Spero che questo aiuti.

provato un paio di cicli nidificati e in effetti è più veloce:

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 

E, per lo stesso rand(1000) per x e y.

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

' 'inbounds' aiuta il ciclo' for'? – rickhg12hs

+1

@ rickhg12hs Dovrebbe sì, ho avuto un po 'di fretta quando l'ho pubblicato, quindi non ho avuto il tempo di testarlo correttamente, ma lo farò domani e modificherò il post di conseguenza. Grazie per il suggerimento. – Esteban

+0

Ho provato a usare '@ inbounds' ma non ho ottenuto alcun miglioramento evidente, forse perché non ci sono operazioni con gli array e sto solo assegnando valori? Inoltre, nel mio computer usando vettori di lunghezza 10000 come input per 'x' e' y', ho prodotto errori di memoria quando si utilizzava 'repeat' o' repmat', ma funzionava bene con la funzione di cicli annidati. – Esteban

4

Ecco come potrei farlo:

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 

si potrebbe anche voler dare un'occhiata a Iterators.j - in particolare la funzione product.

+0

noti che è possibile omettere le parentesi intorno al '' inner' e argomenti outer', quindi la formula riduce a '[repeat (x, interno = dimensione (y, 1)) repeat (y, outer = size (x, 1))] ' –

3

Questo è fornito nel modulo Iterators.

Tratto da https://github.com/JuliaLang/Iterators.jl

iterare su tutte le combinazioni nel prodotto cartesiano degli ingressi.

Esempio:

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) 
Problemi correlati