2015-03-30 14 views
6

Tôi có hai vectơ xy, có độ dài tương ứng n và p. Có cách tích hợp để tạo ma trận np x 2 sẽ làSản phẩm Descartes của hai vectơ trong Julia

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

Tôi có thể làm điều đó với vòng lặp lồng nhau nhưng tôi đang tìm hàm tích hợp sẵn nếu có.

Trả lời

6

Julia thường rất nhanh trong các vòng lặp lồng nhau, vì vậy nếu chúng hoạt động chính xác cho bạn, bạn nên kiểm tra hiệu suất có thể chỉ gắn bó với nó.

tùy chọn khác sẽ được sử dụng repmat (cái này là nhanh hơn một chút so với sử dụng lặp lại):

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

Đã làm một số thử nghiệm nhanh của cả hai phương pháp:

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) 

Không chắc tại sao rất nhiều khác biệt và tôi nghĩ vẫn còn chỗ để cải thiện. Chưa thử chức năng sản phẩm bên trong gói Iterators.jl.

Cũng là một chút biết thêm thông tin ở đây: https://groups.google.com/forum/#!topic/julia-users/dtl--SyFgwY

Hope this helps.

Cố gắng một vài vòng lồng nhau và thực sự là nhanh hơn:

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 

Và, cho cùng rand(1000) cho xy.

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

' @ inbounds' có giúp vòng lặp 'for' không? – rickhg12hs

+1

@ rickhg12hs Nó phải có, tôi đã vội vàng một chút khi tôi đăng nó, vì vậy tôi không có thời gian để kiểm tra nó đúng cách, nhưng tôi sẽ làm điều đó vào ngày mai và chỉnh sửa bài viết cho phù hợp. Cám ơn vì sự gợi ý. – Esteban

+0

Tôi đã thử sử dụng '@ inbounds' nhưng không nhận được bất kỳ cải tiến đáng chú ý nào, có lẽ điều này là do không có hoạt động với mảng và tôi chỉ gán giá trị? Ngoài ra, trong máy tính của tôi sử dụng các vectơ có chiều dài 10000 làm đầu vào cho 'x' và' y', tạo ra lỗi bộ nhớ khi sử dụng 'repeat' hoặc' repmat' nhưng làm việc tốt với hàm lồng nhau. – Esteban

4

Đây là cách tôi có thể làm điều đó:

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 

bạn cũng có thể muốn có một cái nhìn tại Iterators.j - đặc biệt là product chức năng.

+0

Lưu ý rằng bạn có thể bỏ qua các dấu ngoặc xung quanh 'inner' và' đối số outer', vì vậy công thức giảm đến '[lặp lại (x, bên trong = kích thước (y, 1)) lặp lại (y, outer = size (x, 1))] ' –

3

Điều này được cung cấp trong mô-đun Iterators.

Taken từ https://github.com/JuliaLang/Iterators.jl

lặp qua tất cả các kết hợp trong sản phẩm Cartesian của các đầu vào.

Ví dụ:

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) 
Các vấn đề liên quan