векторизация 4 вложенных циклов for в Matlab - PullRequest
3 голосов
/ 16 июня 2011

Я пишу программу для школы, и у меня есть вложенные циклы for, которые создают 4-мерный массив (расстояний между двумя точками с координатами (x, y) и (x ', y')), как показано ниже :

pos_x=1:20;
pos_y=1:20;
Lx = length(pos_x);             
Ly = length(pos_y);
Lx2 = Lx/2;
Ly2 = Ly/2;

%Distance function, periodic boundary conditions
d_x=abs(repmat(1:Lx,Lx,1)-repmat((1:Lx)',1,Lx));
d_x(d_x>Lx2)=Lx-d_x(d_x>Lx2);
d_y=abs(repmat(1:Ly,Ly,1)-repmat((1:Ly)',1,Ly)); 
d_y(d_y>Ly2)=Ly-d_y(d_y>Ly2);

for l=1:Ly
    for k=1:Lx
        for j=1:Ly
            for i=1:Lx
            distance(l,k,j,i)=sqrt(d_x(k,i).^2+d_y(l,j).^2);
            end
        end
    end
end

d_x и d_y - это матрицы размером 20x20, а Lx = Ly для пробных целей. Это очень медленный и явно не очень элегантный способ сделать это. Я попытался векторизовать вложенные циклы и успешно избавился от двух внутренних циклов:

dx2=zeros(Ly,Lx,Ly,Lx);
dy2=zeros(Ly,Lx,Ly,Lx);
distance=zeros(Ly,Lx,Ly,Lx);

for l=1:Ly
    for k=1:Lx
        dy2(l,k,:,:)=repmat(d_y(l,:),Ly,1);
        dx2(l,k,:,:)=repmat(d_x(k,:)',1,Lx);
    end
end
distance=sqrt(dx2.^2+dy2.^2);

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

  1. возможно ли вообще избавиться от этих 2 петель
  2. Если это так, я буду признателен за любые советы и рекомендации для этого. До сих пор я пытался использовать repmat снова в 4 измерениях, но вы не можете транспонировать 4-мерную матрицу, поэтому я попытался использовать permute и repmat вместе во многих различных комбинациях, но безрезультатно.

Любой совет будет принята с благодарностью.


спасибо за ответы. Извините за плохую формулировку, я хочу, чтобы популяция осцилляторов была равномерно расположена на плоскости x-y. Я хочу смоделировать их связь, а функция связи - это функция расстояния между каждым генератором. И у каждого осциллятора есть координаты x и ay, поэтому мне нужно найти расстояние между osci(1,1) и osci(1,1),..osci(1,N),osci(2,1),..osci(N,N)..., а затем то же самое для osci(1,2) и osci(1,1)...osci(N,N) и т. Д. (Так что в основном расстояние между всеми осцилляторами и все остальные осцилляторы плюс самосоединение), если есть более простой способ сделать это, кроме использования 4-D массива, я также определенно хотел бы знать это.

Ответы [ 2 ]

1 голос
/ 17 июня 2011

Если я вас правильно понимаю, у вас повсюду осцилляторы, например:

enter image description here

Затем вы хотите вычислить расстояние между осциллятором 1 и осцилляторами 1-100, а затем между осциллятором 2 и осцилляторами 1-100 и т. Д. Я считаю, что это может быть представлено двумерной матрицей расстояний, если первое измерение идет от От 1 до 100, а второе измерение от 1 до 100.

Например

%# create 100 evenly spaced oscillators
[xOscillator,yOscillator] = ndgrid(1:10,1:10); 
oscillatorXY = [xOscillator(:),yOscillator(:)];

%# calculate the euclidean distance between the oscillators
xDistance = abs(bsxfun(@minus,oscillatorXY(:,1),oscillatorXY(:,1)')); %'# abs distance x
xDistance(xDistance>5) = 10-xDistance; %# add periodic boundary conditions
yDistance = abs(bsxfun(@minus,oscillatorXY(:,2),oscillatorXY(:,2)')); %'# abs distance y
yDistance(yDistance>5) = 10-yDistance; %# add periodic boundary conditions

%# and we get the Euclidean distance
euclideanDistance = sqrt(xDistance.^2 + yDistance.^2);
0 голосов
/ 17 июня 2011

Я считаю, что мнимые числа иногда могут достаточно хорошо передавать связанную информацию, уменьшая при этом беспорядок. Мой метод удвоит количество необходимых вычислений (то есть я найду расстояние X и Y, затем Y и X), и мне все еще нужен один цикл for

x = 1:20;
y = 1:20;
[X,Y] = meshgrid(x,y);
Z =X + Y*i;
z = Z(:);
leng = length(z);
store = zeros(leng);
for looper = 1:(leng-1) 
    dummyz = circshift(z,looper);
    store(:,looper+1) = z - dummyz;
end
final = abs(store);
...