Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to decompose a 9x9 matrix to 3x3 matrices?

Tags:

matrix

matlab

I'm trying to decompose a 9x9 matrix into 9 3x3 matrices. I've already used the command reshape, but the matrices it returns are the ones as transforming the columns of the 9x9 matrix to 3x3 matrices, but that isn't what I need. This is 9x9 the matrix M

0   0   0   0   0   0   0   7   6
0   2   0   9   0   0   0   0   0
0   3   8   0   5   4   1   0   0
9   0   0   5   0   0   0   3   0
0   0   0   0   1   8   0   6   7
4   0   0   0   0   0   2   0   0
0   1   0   8   0   0   0   5   0
0   0   0   0   0   7   0   0   0
6   0   2   0   3   0   8   9   4

And I need it in form

0 0 0    0 0 0    0 7 6
0 2 0    9 0 0    0 0 0
0 3 8    0 5 4    1 0 0       etc...

This code generates the matrices exactly as I need them, but only saving the last one:

for i=[1 4 7]
    for j=[1 4 7]
        v(:,:)=M([i:i+2],[j:j+2])
    end
end
like image 634
David BG Avatar asked Dec 22 '22 17:12

David BG


2 Answers

You make a new v of size 3x3 every loop iteration, i.e. you overwrite it. What you can easily do is to add a third dimension, and store all your separate matrices along there:

n = 3;  % Amount of rows of the sub-matrices
m = 3;  % Amount of columns of the sub-matrices
v = zeros(size(M,1)./n,size(M,2)./m,(size(M,1)*size(M,2))./(n*m)); % Initialise v

kk = 1;  % Initialise page counter
for ii = 1:n:size(M,1)
    for jj = 1:m:size(M,2)
        v(:,:,kk) = M(ii:ii+2, jj:jj+2); % Save on page kk
        kk = kk+1;  % Increase page counter
    end
end

A few other notes:

  • In order to generalise the code I used size(M) everywhere, such that you can easily extend M to larger sizes.

  • Don't use i or j as indices/variables names, as they denote the imaginary unit. Using those can easily lead to hard to debug errors.

  • ii:ii+2 already is an array, adding square brackets is superfluous

  • Initialise v, i.e. tell MATLAB how large it will be before going into the loop. Otherwise, MATLAB will have to increase its size every iteration,which is very slow. This is called preallocation.

  • n and m obviously need to be integers, but not only that. You need an integer amount of sub-matrices to fill each dimension, i.e. size(M,1)/n and size(M,2)/m both need to be integers. If this is not the case, this code will error out on the initialisation of v.

like image 196
Adriaan Avatar answered Dec 29 '22 00:12

Adriaan


You can also use mat2cell function. You need to declare the input_size and the chunk_size. Then you need to declare the number of chunks in each dimension (sc variable).

For example:

M = [0   0   0   0   0   0   0   7   6
     0   2   0   9   0   0   0   0   0
     0   3   8   0   5   4   1   0   0
     9   0   0   5   0   0   0   3   0
     0   0   0   0   1   8   0   6   7
     4   0   0   0   0   0   2   0   0
     0   1   0   8   0   0   0   5   0
     0   0   0   0   0   7   0   0   0
     6   0   2   0   3   0   8   9   4];

% Z = zeros(size(M, 1), size(M, 2));
input_size = size(M);
chunk_size = [3 3];
sc = input_size ./ chunk_size;

C = mat2cell(M, chunk_size(1)*ones(sc(1), 1),...
                chunk_size(2)*ones(sc(2), 1));
celldisp(C')

Output:

 
ans{1,1} =
 
     0     0     0
     0     2     0
     0     3     8

 
 
ans{2,1} =
 
     0     0     0
     9     0     0
     0     5     4

 
 
ans{3,1} =
 
     0     7     6
     0     0     0
     1     0     0

 
 
ans{1,2} =
 
     9     0     0
     0     0     0
     4     0     0

 
 
ans{2,2} =
 
     5     0     0
     0     1     8
     0     0     0

 
 
ans{3,2} =
 
     0     3     0
     0     6     7
     2     0     0

 
 
ans{1,3} =
 
     0     1     0
     0     0     0
     6     0     2

 
 
ans{2,3} =
 
     8     0     0
     0     0     7
     0     3     0

 
 
ans{3,3} =
 
     0     5     0
     0     0     0
     8     9     4
like image 22
Ahx Avatar answered Dec 29 '22 01:12

Ahx