MATLAB Answers

Is there a way to remove the nested for loops from this segment of code? I'm trying to make the code generic so it can take in n-number of moment arrays.

13 views (last 30 days)
moment(:,:,1) = [1 0 0; 2 1 0];
moment(:,:,2) = [2 2 2; 3 0 1];
moment(:,:,3) = [3 1 2; 1 1 1];
moment(:,:,4) = [1 0 0; 0 0 1];
sum = [];
for i = 1:size(moment)
x = moment(i,:,1);
for j = 1:size(moment)
y = moment(j,:,2);
for k = 1:size(moment)
z = moment(k,:,3);
for ii = 1:size(moment)
xx = moment(ii,:,4);
sum = [sum;x+y+z+xx];
end
end
end
end

  2 Comments

Jan
Jan on 4 Apr 2017
Do not use "sum" as a name of a variable. This shadowing of built-in function causes unexpected behavior frequently, when the function sum() is used later.
Does for i = 1:size(moment) do, what you expect? size(moment) replies a vector. So better use: size(moment, 1) to avoid confusions.
What sould be flexible in the code? The number of dimension, the size of the array?
Zachary Bassett
Zachary Bassett on 4 Apr 2017
moment(:,:,1) = [1 0 0; 2 1 0];
moment(:,:,2) = [2 2 2; 3 0 1];
moment(:,:,3) = [3 1 2; 1 1 1];
moment(:,:,4) = [1 0 0; 0 0 1];
summation = [];
for i = 1:size(moment,1)
x = moment(i,:,1);
for j = 1:size(moment,1)
y = moment(j,:,2);
for k = 1:size(moment,1)
z = moment(k,:,3);
for ii = 1:size(moment,1)
xx = moment(ii,:,4);
summation = [summation;x+y+z+xx];
end
end
end
end
Here's an updated version of the code that fixes the "sum" and size(moment,1). Thanks for the suggestions!
What I would like to be flexible with the code is that the size of the array can be an n x 3. It will also always be a 3-dimensional array but the number of arrays in the 3rd dimension can also vary in size.

Sign in to comment.

Accepted Answer

David Goodmanson
David Goodmanson on 4 Apr 2017
Edited: David Goodmanson on 4 Apr 2017
Hello Joseph, I believe this does what you want. It assumes you have a 3d array called momentarray, containing an arbitrary number of moment matrices. It should work for any number of moment matrix rows and columns. I called each moment matrix a layer in the 3d array. S is the result.
The code does not preallocate any arrays so it is inefficient that way but it is still fast enough for reasonably sized S.
n = size(momentarray,3); % number of moment matrices
m = size(momentarray,1); % number of rows in each moment matrix
S = momentarray(:,:,n);
layr = n-1;
while layr >= 1
rowS = size(S,1);
temp = [];
for j = 1:m % loop over rows in a layer
a = repmat(momentarray(j,:,layr),rowS,1); % duplicate the row
temp = [temp;a+S]; % add to previous S and concatenate
end
S = temp;
layr = layr-1;
end

  3 Comments

Joseph Cheng
Joseph Cheng on 5 Apr 2017
Thanks but i didn't ask it :-p, but it is much more elegant. I didn't have much time to try to put an elegant solution of going through each permutation of all the sums or rows.
Zachary Bassett
Zachary Bassett on 5 Apr 2017
Joseph and David, thank you so much! Both of those methods work for what I'm trying to do. I'd been racking my brain for a day trying to figure out how to do this.
David Goodmanson
David Goodmanson on 5 Apr 2017
Hello Zachary and Joseph,
Oops, in my answer I should have said hello to Zachary, but thanks to each of you for your comments. As Joseph mentioned it does help a lot to have adequate time to work out an answer. This site can become habit forming, though.

Sign in to comment.

More Answers (2)

Spencer Chen
Spencer Chen on 4 Apr 2017
Not exactly sure if this is what you are looking for:
> sum(moment,3);
to sum the 3rd dimension of the matrix?

  0 Comments

Sign in to comment.


Joseph Cheng
Joseph Cheng on 4 Apr 2017
to make it more generic you could do something like
momentind = [1 1 1 1 1 1]
cind = 1;
while momentind(end)~=3;
%perform sum
% temp = 0;
% for ind = 1:numel(momentind)
% temp = temp+moment(momentind(end-ind+1),:,ind);
% end
%increment last index but check for carryovers
momentind(cind)=momentind(cind)+1;
for ind = 1:numel(momentind)-1
Covers = mod(momentind,3);
Coverinds = find(Covers==0);
momentind(Coverinds+1)=momentind(Coverinds+1)+1;
momentind(Coverinds)=1
end
end
where you can keep a index counter that increments by 1 for the last dimension and then look for carry overs which would increment the next. with this index list you can then just go through it with a loop

  0 Comments

Sign in to comment.