векторизация 4 вложенных циклов for в Matlab

Я пишу программу для школы, и у меня есть вложенные циклы 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 и y, поэтому мне нужно найти расстояние между 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-мерного массива, я бы также определенно хотел это знать.


person Ayca    schedule 16.06.2011    source источник
comment
Вы говорите, что вам нужно расстояние между двумя наборами координат. Разве это не должно дать вам двумерный массив, где элемент (i,j) — это расстояние между [x1i,y1i] и [x2i,y2i]?   -  person Jonas    schedule 16.06.2011
comment
Я второй комментарий Джонаса. Можете ли вы объяснить причину вычисления расстояния между [x1i,y2j] и [x1k,y2l]? Если вы укажете причину, может быть кратчайший путь к этому ответу без заполнения 4D-матрицы.   -  person BlessedKey    schedule 16.06.2011
comment
спасибо за ответы. Извините за плохую формулировку, я в основном хочу иметь совокупность осцилляторов, равномерно расположенных на плоскости x-y. Я хочу смоделировать их связь, а функция связи зависит от расстояния между каждым осциллятором. И каждый осциллятор имеет координаты x и y, поэтому мне нужно найти расстояние между osci(1,1) и osci(1,1),..osci(1,N),osci(2,1),.. osci(N,N).. и затем то же самое для osci(1,2) и osci(1,1)... osci(N,N) и т.д.. (по сути, расстояние между всеми осцилляторами и всеми другие осцилляторы плюс самосвязь) если есть советник   -  person    schedule 17.06.2011
comment
Я не читал ваш код, но подозреваю, что он похож на этот вопрос. Возможно, вы захотите попробовать посмотреть ответы там и посмотреть, поможет ли это.   -  person abcd    schedule 17.06.2011


Ответы (2)


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

введите здесь описание изображения

Затем вы хотите рассчитать расстояние между осциллятором 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);
person Jonas    schedule 17.06.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);
person Rasman    schedule 17.06.2011