Matrix multiplication with three level loops

Hi everybody,
I have a problem with multiplying following two matrices. In first matrix (A), which is 62x2108 I have some coefficients in first row and columns 1:34 for country #1, all other column elements in 1st row are zeros, then in second row and column 35:68 for country #2, elsewhere in 2nd row are zeros etc. In matrix EXP, which is 2108x62 I have data for exports from 62 countries and 34 industries in rows, to 62 countries in columns. I would like to multiply matrix A as such with matrix EXP but with all entries equal to zero except the one corresponding to industry let's say k (for each country, this implies repetition of 34 multiplications). The result should be a matrix of size 2108x62.
My code is following, but I just can't get to include the third level of loop, which is that multiplication for each industry, zeros for all other industries.
B=zeros(2108,62);
help=zeros(34);
for i=1:62
for j=1:62
for k=1:34
B(((i-1)*34+1):(i*34),j)=A(i,((j-1)*34+1):(j*34))*((help(k,k)==1)*EXP(((i-1)*34+1):(i*34),j));
end
end
end
If enyone has an idea, let me know.
Best,
Miroslav

2 comentarios

Guillaume
Guillaume el 8 de Feb. de 2017
Editada: Guillaume el 8 de Feb. de 2017
It would help if you could produce a condensed example, with numbers, of what you want to obtain.
However, as I hinted in your previous question I'm not sure the way you're storing your data is a good idea. My feeling is that a better storage format would make all your calculations much easier.
Hi Guillaume,
I will try to be as clear as possible. So, I have a following matrix A (assuming its 9 x 9). Data 1,2 and 3 are 1x3 block of coefficients for country 1 for three different industries, 4,5 and 6 for country 2 and 7,8 and 9 for country 3.
A=[1 2 3 0 0 0 0 0 0;
0 0 0 4 5 6 0 0 0;
0 0 0 0 0 0 7 8 9]
I also have a matrix EXP, which is then 9x3, with each block being 3x1 (i.e. values 10,11 and 12)
EXP=[10 20 30;
11 21 31;
12 22 32;
13 23 33;
14 24 34;
15 25 35;
16 26 36;
17 27 37;
18 28 38]
My output should be a 9x3 matrix, M
M=[(1 2 3)*(10 0 0)' (1 2 3)*(20 0 0)' (1 2 3)*(30 0 0)'
(1 2 3)*(0 11 0)' (1 2 3)*(0 21 0)' (1 2 3)*(0 31 0)'
(1 2 3)*(0 0 12)' (1 2 3)*(0 0 22)' (1 2 3)*(0 0 32)'
(4 5 6)*(13 0 0)' (4 5 6)*(23 0 0)' (4 5 6)*(33 0 0)'
(4 5 6)*(0 14 0)' (4 5 6)*(0 24 0)' (4 5 6)*(0 34 0)'
(4 5 6)*(0 0 15)' (4 5 6)*(0 0 25)' (4 5 6)*(0 0 35)'
(7 8 9)*(16 0 0)' (7 8 9)*(26 0 0)' (7 8 9)*(36 0 0)'
(7 8 9)*(0 17 0)' (7 8 9)*(0 27 0)' (7 8 9)*(0 37 0)'
(7 8 9)*(0 0 18)' (7 8 9)*(0 0 28)' (7 8 9)*(0 0 38)']
As for the storage format, this is the way my database is organized, I am not sure at the moment how can I re-arrange it.

Iniciar sesión para comentar.

Respuestas (1)

Guillaume
Guillaume el 8 de Feb. de 2017
You do have a choice about the storage, it was your choice to rearrange your A matrix with all these 0.
The problem is at the moment you're conflating countries and industries in the same dimension (columns in A, rows in B), which makes it a lot more difficult to manipulate. If you separate this into different dimensions, it makes it all easier.
So, let's have A as a ncountries x nindustries matrix:
%to get there with your original 1x2108 vector:
%A = reshape(A, 34, 62)'
%example with 3 countries x 4 industries
A = [1 2 3 4
5 6 7 8
9 10 11 12];
Similarly, your EXP matrix should be an ncountries x nindustries x ncountries 3D matrix
EXP = [10 20 30
11 21 31
12 22 32
13 23 33
14 24 34
15 25 35
16 26 36
17 27 37
18 28 38
19 29 39
20 30 40
21 31 41]; %the not so useful (ncountries x nindustries) x ncountries matrix
EXP = permute(reshape(EXP, 4, 3, 3), [2 1 3]) %much more useful 3D matrix
Then to get the result you want, it's simply
M = A .* EXP %in R2016b, prior to that: M = bsxfun(@times, A, EXP)

5 comentarios

Miroslav Josic
Miroslav Josic el 10 de Feb. de 2017
Editada: Miroslav Josic el 10 de Feb. de 2017
Hi Guillaume,
I get your point. The problem is that my raw database is in such format and as I am not advanced user of Matlab, I still don't think in a way what can I do to make my job easier, by looking few steps in advance. Also, I never used so far 3D matrices. This is to be completely honest.
As for the code, to get the matrix A, I had to multiply two other similar matrices, which I managed to organize and got what we talked about.
So, in your example with 4 industries and 3 countries, now I have A as
A=[1 2 3 4
5 6 7 8
9 10 11 12]
EXP is still the same
EXP = [10 20 30
11 21 31
12 22 32
13 23 33
14 24 34
15 25 35
16 26 36
17 27 37
18 28 38
19 29 39
20 30 40
21 31 41];
I still have the same problem because I have to multiply first row vector from matrix A with first column block from matrix EXP (1:4,1) with industry #1 being the value, three other industries being 0, then with first column block from matrix EXP (1:4,1) but industry #2 being the value, three other industries being 0 etc. In these steps I'm calculating and collecting scalars which then need to be grouped in a matrix of form 2108x62.
This should be the output
M=[(1 2 3 4)*(10 0 0 0)' (1 2 3 4)*(20 0 0 0)' (1 2 3 4)*(30 0 0 0)'
(1 2 3 4)*(0 11 0 0)' (1 2 3 4)*(0 21 0 0)' (1 2 3 4)*(0 31 0 0)'
(1 2 3 4)*(0 0 12 0)' (1 2 3 4)*(0 0 22 0)' (1 2 3 4)*(0 0 32 0)'
(1 2 3 4)*(0 0 0 13)' (1 2 3 4)*(0 0 0 23)' (1 2 3 4)*(0 0 0 33)'
(4 5 6 7)*(14 0 0 0)' (4 5 6 7)*(24 0 0 0)' (4 5 6 7)*(34 0 0 0)'
(4 5 6 7)*(0 15 0 0)' (4 5 6 7)*(0 25 0 0)' (4 5 6 7)*(0 35 0 0)'
(4 5 6 7)*(0 0 16 0)' (4 5 6 7)*(0 0 26 0)' (4 5 6 7)*(0 0 36 0)'
(4 5 6 7)*(0 0 0 17)' (4 5 6 7)*(0 0 0 27)' (4 5 6 7)*(0 0 0 37)'
(7 8 9 10)*(18 0 0 0)' (7 8 9 10)*(28 0 0 0)' (7 8 9 10)*(38 0 0 0)'
(7 8 9 10)*(0 19 0 0)' (7 8 9 10)*(0 29 0 0)' (7 8 9 10)*(0 39 0 0)'
(7 8 9 10)*(0 0 20 0)' (7 8 9 10)*(0 0 30 0)' (7 8 9 10)*(0 0 40 0)'
(7 8 9 10)*(0 0 0 21)' (7 8 9 10)*(0 0 0 31)' (7 8 9 10)*(0 0 0 41)'];
By using your last two lines of codes, I get the result and matrix of size 2108x62 but it does not take into account those zeros that I have to be multiplying with for all other industries except the one I need in each step.
If the M matrix is really the one you written above, then I don't understand the logic. If it is, using valid matlab notation:
M=[[1 2 3 4]*[10 0 0 0]' [1 2 3 4]*[20 0 0 0]' [1 2 3 4]*[30 0 0 0]'
[1 2 3 4]*[0 11 0 0]' [1 2 3 4]*[0 21 0 0]' [1 2 3 4]*[0 31 0 0]'
[1 2 3 4]*[0 0 12 0]' [1 2 3 4]*[0 0 22 0]' [1 2 3 4]*[0 0 32 0]'
[1 2 3 4]*[0 0 0 13]' [1 2 3 4]*[0 0 0 23]' [1 2 3 4]*[0 0 0 33]'
[5 6 7 8]*[14 0 0 0]' [5 6 7 8]*[24 0 0 0]' [5 6 7 8]*[34 0 0 0]'
[5 6 7 8]*[0 15 0 0]' [5 6 7 8]*[0 25 0 0]' [5 6 7 8]*[0 35 0 0]'
[5 6 7 8]*[0 0 16 0]' [5 6 7 8]*[0 0 26 0]' [5 6 7 8]*[0 0 36 0]'
[5 6 7 8]*[0 0 0 17]' [5 6 7 8]*[0 0 0 27]' [5 6 7 8]*[0 0 0 37]'
[9 10 11 12]*[18 0 0 0]' [9 10 11 12]*[28 0 0 0]' [9 10 11 12]*[38 0 0 0]'
[9 10 11 12]*[0 19 0 0]' [9 10 11 12]*[0 29 0 0]' [9 10 11 12]*[0 39 0 0]'
[9 10 11 12]*[0 0 20 0]' [9 10 11 12]*[0 0 30 0]' [9 10 11 12]*[0 0 40 0]'
[9 10 11 12]*[0 0 0 21]' [9 10 11 12]*[0 0 0 31]' [9 10 11 12]*[0 0 0 41]'];
instead (that is rows 5-8 are [5 6 7 8]*... and rows 9-12 are [9 10 11 12]*...), then the code I've given does exactly what you want:
A=[1 2 3 4
5 6 7 8
9 10 11 12];
EXP = [10 20 30
11 21 31
12 22 32
13 23 33
14 24 34
15 25 35
16 26 36
17 27 37
18 28 38
19 29 39
20 30 40
21 31 41];
EXP = permute(reshape(EXP, 4, 3, 3), [2 1 3]); %4 industries x 3 countries x 3 countries
M2 = EXP .* A; %bsxfun(@times, EXP, A) prior to R2016b
The rows of M2 correspond to countries, the columns to industries, and the pages to the countries again. You can reshape / permute M2 to a form that makes it easier for you to visualise, maybe:
permute(M2, [2 3 1])
looks more similar to your M, or even
reshape(permute(M2, [2 1 3]), [], 3)
which I would not recommend since once again, you're mixing countries and industries in the rows but it does contain the exact same values as your M:
>>isequal(M, reshape(permute(M2, [2 1 3]), [], 3))
ans =
1
Miroslav Josic
Miroslav Josic el 17 de Feb. de 2017
Editada: Miroslav Josic el 17 de Feb. de 2017
Hi Guillaume,
Thanks again for your update and sorry for being late in reply, I postponed a bit my research project. And sorry for a typo in my previous post, you got that correctly.
I checked the code again and I did exactly the same as you said, however I know I don't get the result I should be getting.
EXP matrix is the matrix of exports from one country and respective industries to another (but I have let's say Italy in both rows and columns), so for example my values in 1st column and rows 1-4 are all zeros (because that's data for i.e. Italy >> country cannot export to itself), therefore in my output M matrix I should get all zeros on the same positions as in matrix EXP. So in our 4 industry, 3 countries example I should be getting:
M=[0 value value
0 value value
0 value value
0 value value
value 0 value
value 0 value
value 0 value
value 0 value
value value 0
value value 0
value value 0
value value 0]
instead of what I am getting now:
M=[ 0 value value
value 0 value
value value 0
value value value
0 value value
value 0 value
value value 0
value value value
0 value value
value 0 value
value value 0
value value value]
Guillaume
Guillaume el 20 de Feb. de 2017
I'm very confused. As shown above, the code gives the exact answer you asked for.
Please, give examples with numbers so I can actually test code. With your value example, it looks like a reshape or permute is not right. But as I said, I don't think this form of M is useful as it uses rows to store two orthogonal concepts.
Miroslav Josic
Miroslav Josic el 20 de Feb. de 2017
Hi Guillaume,
Attached you can find csv files containing data that should be my A[62,2108] and EXP[2108,62]. These are the initial ones before posting my question and without labels. I attached also the results for 3 countries in xls file Matrix M_Result because I did them manually. I put in sheet Belgium matrix multiplication that needs to be done.
What I should get is a new M matrix of a size 2108x62 with following elements:
A) for country #1 and its 34 industry to country #1 (basically itself, so it has zeros in all 34 industries)
M[1,1]=A[1,1:34] x EXP[1:34,1] such that it takes 1st row element from EXP as real value, all others ZEROS
M[2,1]=A[1,1:34] x EXP[1:34,1] such that it takes 2nd row element from EXP as real value, all others ZEROS
etc for all 34 industries and thus get first column block for M[1:34,1]
B) for country #1 and its 34 industry to country #2
M[1,2]=A[1,1:34] x EXP[1:34,2] such that it takes 1st row element from EXP as real value, all others ZEROS
M[2,2]=A[1,1:34] x EXP[1:34,2] such that it takes 2nd row element from EXP as real value, all others ZEROS
etc for all 34 industries and thus get second column block for M[1:34,2]
C) for country #2 and its 34 industry to country #1
M[35,1]=A[2,35:68] x EXP[35:68,1] such that it takes 35th row element from EXP as real value, all others ZEROS
M[36,1]=A[2,35:68] x EXP[35:68,1] such that it takes 36th row element from EXP as real value, all others ZEROS
etc for all 34 industries and thus get another column block, M[35:68,1]
D) for country #2 and its 34 industry to country #2
M[35,2]=A[2,35:68] x EXP[35:68,2] such that it takes 36th row element from EXP as real value, all others ZEROS
M[36,2]=A[2,35:68] x EXP[35:68,2] such that it takes 36th row element from EXP as real value, all others ZEROS
etc for all 34 industries and thus get another column block, M[35:68,2]
*Bottom line, each row and corresponding 34 columns from matrix A (so [1,1:34],[2,35:68],[3,69:102] etc.) represent one countries' coefficients, while each 34 rows and one column from matrix EXP (so [1:34,1],[35:68,1],[69:102,1],[1:34,2] etc.) represent export from one country to another.

Iniciar sesión para comentar.

Categorías

Más información sobre Matrices and Arrays en Centro de ayuda y File Exchange.

Preguntada:

el 8 de Feb. de 2017

Comentada:

el 20 de Feb. de 2017

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by