2016-08-09 6 views
3

У меня есть следующий код. Мне нужно переписать его без циклов. Как я должен это делать?Настройка векторизации - MATLAB

l1 = [1 2 3 2 1]; 
l2 = [3 4 4 5 4]; 
A = zeros(5,5); 
for i=1:5 
    A(i, l1(i):l2(i)) = 1; 
end 

A 
+0

Зачем вам его переписывать? Это слишком медленно? –

+0

: D вы знаете, если вы правильно говорите, это на самом деле хороший вопрос. – GameOfThrows

+0

@ Jørgen Да, это медленно. Фактически размер матрицы огромен, и у меня есть несколько операций, аналогичных описанным выше. Это всего лишь пример, и он упрощен, насколько это возможно. – LNK

ответ

2

Вы можете использовать bsxfun -

I = 1:5 % Array corresponding to iterator : "for i=1:5" 
out = bsxfun(@le,l1(:),I) & bsxfun(@ge,l2(:),I) 

Если вам нужен двойной массив типа данных, конвертировать в два раза, как так -

out_double = double(out) 
+0

Приятно видеть, что вам не нужна полная координатная сетка, так как bsxfun автоматически расширит 1: 5. Обратите внимание, что этот ответ возвращает логический (что может быть хорошо, но не идентично циклу). –

+0

@DennisJaheruddin Отредактированное решение для покрытия этого требования. – Divakar

0

Вот как вы могли бы построить матрицу без использования цикла.

% Our starting values 
l1 = [1 2 3 2 1]; 
l2 = [3 4 4 5 4]; 

% Coordinate grid of the right size (we don't need r, but I keep it there for illustration) 
[r,c] = ndgrid(1:5); 

% Build the logical index based on our lower and upper bounds on the column indices 
idx_l1=bsxfun(@ge,c,l1'); 
idx_l2=bsxfun(@le,c,l2'); 

% The result 
A = zeros(size(idx_l1)); 
A(idx_l1&idx_l2)=1 

Возможно, вам понадобится что-то вроде [r,c] = ndgrid(1:numel(l1),1:10).

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

1

Добавить еще один в смесь затем! Это один просто использует cumsum, чтобы генерировать все 1s - так это не использовать оператор : вообще - это также полностью параллельно: D

l1 = [1 2 3 2 1]; 
l2 = [3 4 4 5 4]; 
A = zeros(5,5); 

L1 = l1+(1:5)*5-5; %Convert to matrix location index 
L2 = l2+(1:5)*5-5; %Convert to matrix location index 
A(L1) = 1;   %Place 1 in that location 
A(L2) = 1;   %Place 1 in that location 

B = cumsum(A,1) ==1 ; %So fast 
Answer = (A|B)';  %Lightning fast 

Answer = 

1  1  1  0  0 
0  1  1  1  0 
0  0  1  1  0 
0  1  1  1  1 
1  1  1  1  0 
0

Там должен быть некоторый скептицизм в каждом векторизации. Если вы измеряете время на самом деле, ваш цикл быстрее, чем заданные ответы, в основном потому, что вы выполняете только запись.

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

tic 
myind = []; 
for i = 1:5 
    myind = [myind (5*(i-1))+[l1(i):l2(i)]]; 
end 
A(myind) = 1; 
toc 

дает транспонированная A из линейного порядка индексации.

Смежные вопросы