How to perform tensor summation without using "for" loop

7 views (last 30 days)
Hi. I have a matrix A with n*4 dimentions, I want to sum each element of the first row with all the elements of the 2nd row to obtain a matrix B with 4.^2 elements and then, to sum each element of the 3rd row of matrix A with all the elements of matrix B to obtain a matrix C with 4.^3 elements. The process should continue until we have a matrix with 4.^n elements. I want to do this without for loop to increase the speed.
For example A=[1 2 3 4; 5 6 7 8; 9 10 11 12]
then B is:
B=[6 7 8 9; 7 8 9 10; 8 9 10 11; 9 10 11 12]
and C=C_0' is:
C_0=[15 16 17 18 16 17 18 19 17 18 19 20 18 19 20 21; 16 17 18 19 17 18 19 20 18 19 20 21 19 20 21 22; 17 18 19 20 18 19 20 21 19 20 21 22 20 21 22 23; 18 19 20 21 19 20 21 22 20 21 22 23 21 22 23 24]
Thank you in advance

Accepted Answer

Guillaume
Guillaume on 14 Jan 2019
A = [1 2 3 4; 5 6 7 8; 9 10 11 12];
rows = num2cell(A, 2); %split A, keeping columns together
[rows{:}] = ndgrid(rows{:}); %calculate cartesian product of all the rows
result = reshape(sum(cat(numel(rows) + 1, rows{:}), numel(rows) + 1), [], size(A, 2))' %sum the cartesian product and reshape into desired output format
Note that the above iterates over the elements of row1, then row2, ... then rown. If you want the reverse, then change the second line to:
[rows{:}] = ndgrid(rows{end:-1:1});
Your example is ambiguous in that respect.
  2 Comments
Davoud
Davoud on 15 Jan 2019
Thank you for your answer. I have checked the result of your code with that of a code written using "for" loops for
A = [0.1 0.2 0.4 0.6; 1 2 3 4; 0.4 0.6 0.8 1; 10 11 12 13]
It seems the results are not the same. The "for" loop code is :
B=zeros(4,4);
for i=1:4
B(i,1:4)=A(1,i)+A(2,:);
end
B=reshape(B, [],1);
C=zeros(4,16);
for i=1:4
C(i,1:16)=A(3,i)+B(1:16,1);
end
C=reshape(C, [],1);
D=zeros(4,64);
for i=1:4
D(i,1:64)=A(4,i)+C(1:64,1);
end
D
Would you please modify your code.
Thank you
Guillaume
Guillaume on 15 Jan 2019
Edited: Guillaume on 15 Jan 2019
It seems the results are not the same
That's because the order of iteration in your loop approah is not very logical. In your result,
D(1, 1) = A(1, 1) + A(2, 1) + A(3, 1) + A(4, 1)
D(1, 2) = A(1, 1) + A(2, 1) + A(3, 2) + A(4, 1) %notice that you're iterating over row 3 first
D(1, 3) = A(1, 1) + A(2, 1) + A(3, 3) + A(4, 1)
D(1, 4) = A(1, 1) + A(2, 1) + A(3, 4) + A(4, 1)
D(1, 5) = A(1, 2) + A(2, 1) + A(3, 1) + A(4, 1) %then over row 1
D(1, 6) = A(1, 2) + A(2, 1) + A(3, 2) + A(4, 1)
...
D(1, 17) = A(1, 1) + A(2, 2) + A(3, 1) + A(4, 1) %then over row 2
...
So the iteration order in your loop is row 3, 1, 2, 4. As I said, the iteration order in my solution is 1, 2, 3, 4 (with [rows{:}] = ndgrid(rows{:});) or 4, 3, 2, 1 (with [rows{:}] = ndgrid(rows{end:-1:1});) which is a lot more logical, and easily extends to inputs with more rows.
If you're bent on using that illogical order, then
[rows{:}] = ndgrid(rows{[3, 1, 2, 4]});
will give you the same output. However, the code is no longer generic so you'll have to decide what order you want to use for matrices with more rows.

Sign in to comment.

More Answers (0)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!