Перемещение маленькой матрицы внутри большей матрицы в MATLAB

Предположим, что A представляет собой матрицу нулей 5x5:

>> A = zeros(5)

A =

     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0

А B — небольшая матрица из единиц (2x2):

>> B = ones(2)

B =

     1     1
     1     1

Теперь я ищу 16 разных случаев, которые представляют матрицы C1, C2, C3, ..., C16

Которые:

C1 =                                

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

C2 =                                

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



C3 =                                

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

... и, наконец, C16 равно:

C16 =                                

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

Как видите, это похоже на меньшую матрицу (B), которая движется внутри большей (A).

Большое спасибо,


person Iman    schedule 16.07.2015    source источник
comment
в чем именно заключается ваш вопрос?   -  person shrey    schedule 16.07.2015
comment
@shrey Как переместить матрицу A внутрь матрицы B.   -  person Iman    schedule 18.07.2015


Ответы (3)


Вы можете добиться того, чего хотите, используя circshift(...) в соответствующих строках и столбцах, чтобы сместить значения примерно на Матрица. Упомянутый вами пример — это пример, показанный в части страницы «Перемещение элементов матрицы» с матрицей 4x4.

Возьмем, к примеру

A = [1 1 0 0; 1 1 0 0; 0 0 0 0; 0 0 0 0]
A =

     1     1     0     0
     1     1     0     0
     0     0     0     0
     0     0     0     0
Y = circshift(A,[1 1])
Y =

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

На веб-сайте Mathworks есть встроенная функция, которая, кажется, будет делать именно то, что вы хотите. Точный код для отображения 16 комбинаций на матрице 5x5, которые сохраняют иллюзию движения маленькой матрицы через большую, будет

EDITED: теперь у него есть матрица 5x5x16 с выходами, называемыми C

A=zeros(5,5);
A(1:2,1:2)=1
c=1;C=zeros(5,5,16);
for i=0:3
    for j=0:3
        C(:,:,c)=circshift(A,[i j])
        c=c+1;
    end
end

Что дает вывод (ПРИМЕЧАНИЕ вывод не редактируется)

A =

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


ans =

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


ans =

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


ans =

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


ans =

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


ans =

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


ans =

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


ans =

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


ans =

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


ans =

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


ans =

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


ans =

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


ans =

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


ans =

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


ans =

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


ans =

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


ans =

     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     1     1
     0     0     0     1     1
person Matt    schedule 16.07.2015
comment
Потому что в Matlab есть встроенная функция, которая решает проблему. Если вы внимательно посмотрите на вопрос, он просто утверждает, что кажется, что матрица 2x2 движется через большую матрицу 5x5, а не то, что фактическое движение меньшей матрицы через большую было необходимо для решения проблемы. - person Matt; 16.07.2015
comment
OP хочет получить 16 матриц (в примере). Мой код выводит это, и я не думаю, что это имеет значение, если нам обоим пришлось использовать циклы for независимо от того, используете ли вы индексирование или circshift. - person user1543042; 16.07.2015
comment
Использование встроенных функций Matlab обычно имеет лучшую производительность, чем пользовательские функции, которые делают то же самое, и я считаю, что использование массива ячеек в этом случае не требуется. Если вы отредактируете свой пост, я избавлюсь от отрицательного голоса, чтобы он мог вернуться к нейтральному. - person Matt; 16.07.2015
comment
Я согласен с тем, что вы используете circshift - лучший ответ, но я думаю, что, поскольку мы не знаем, чего хочет OP от этих матриц, массив ячеек - лучший вариант. - person user1543042; 16.07.2015
comment
Я признаю, что поначалу я немного поторопился со своим отрицательным голосом. Вы делаете несколько обоснованных замечаний, и лучшим решением, вероятно, является комбинация двух ответов и некоторых разъяснений по вопросу. Я считаю, что существует метод circshift, который можно обобщить для матриц произвольных размеров, чтобы он мог возвращать все непрерывные комбинации меньшей матрицы внутри большей матрицы; по крайней мере, для разреженных матриц, где большинство элементов равны 0. - person Matt; 16.07.2015

Один векторный подход с bsxfun -

%// Get sizes and form size parameters for creating output
[mA,nA] = size(A);
[mB,nB] = size(B);
mC = mA - mB + 1;
nC = nA - nB + 1;

%// Get linear indices
stage1 = bsxfun(@plus,[1:mB]',[0:nB-1]*mA);    %//'
stage2 = bsxfun(@plus,[1:mC]',[0:nC-1]*mA)-1;  %//'
idx = bsxfun(@plus,stage1(:),stage2(:).' + [0:mC*nC-1]*mA*nA);   %//'

%// Replicate A to setup output; index into it with idx & replace B
C = repmat(A,1,1,mC*nC);
C(idx) = repmat(B(:),1,mC*nC)

Пробный запуск -

A =
     1     1     8     4
     9     8     8     2
     7     9     5     1
     7     9     2     9
B =
     3     5
     3     6
     3     1
C(:,:,1) =
     3     5     8     4
     3     6     8     2
     3     1     5     1
     7     9     2     9
C(:,:,2) =
     1     1     8     4
     3     5     8     2
     3     6     5     1
     3     1     2     9
C(:,:,3) =
     1     3     5     4
     9     3     6     2
     7     3     1     1
     7     9     2     9
....

C(:,:,6) =
     1     1     8     4
     9     8     3     5
     7     9     3     6
     7     9     3     1
person Divakar    schedule 17.07.2015
comment
Спасибо за ваше время. Ваше решение тоже выглядит великолепно! - person Iman; 18.07.2015

Я думаю, хороший способ сделать что-то вроде этого

A = zeros(5);
B = ones(2);
C = cell(size(A,1)-size(B,1) + 1, size(A,2)-size(B,2) + 1);

for i = 1:size(A,1)-size(B,1) + 1
    for j = 1:size(A,2)-size(B,2) + 1
        C{i, j} = A;
        C{i, j}(i:i+size(B,1) - 1, j:j+size(B,2) - 1) = B;

        % Additional code here
    end
end

C = C(:);

% Additional code here
person user1543042    schedule 16.07.2015
comment
Спасибо за твое время, приятель. Тоже отлично выглядит! - person Iman; 18.07.2015