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 Comments

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.

Sign in to comment.

Answers (1)

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 Comments

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
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]
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.
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.

Sign in to comment.

Categories

Asked:

on 8 Feb 2017

Commented:

on 20 Feb 2017

Community Treasure Hunt

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

Start Hunting!