Replacing nested "for" loops

Asked by Amir Akb on 8 May 2012
Latest activity Commented on by Amir Akb on 10 May 2012

Hi all,

I have a set of "K" nested "for" loops, where "K" is variable. An example of my code for when K=4 is as follows:

    Spectral_eff_Points=(0):(1):(20);
    S=zeros(K,1);
    p=zeros(K,1);
    n = length(Spectral_eff_Points);
      for s1_index=1:n,
          S(1)=Spectral_eff_Points(s1_index);
          for s2_index=1:n,
              S(2)=Spectral_eff_Points(s2_index);
              for s3_index=1:n,
                  S(3)=Spectral_eff_Points(s3_index);
                  for s4_index=1:n,
                      S(4)=Spectral_eff_Points(s4_index);
                      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                      % MAIN CALCULATIONS DONE HERE
                      for user_index=1:K 
                          if user_index==1; 
                             p(user_index)=(2^(S(user_index))-1)*         (N/g(user_index)); 
                          else 
                             increment=1:(user_index-1); 
                             Sum_P_inc=sum(p(increment)); 
                             p(user_index)=(2^(S(user_index))-1)*  ((N/g(user_index))+Sum_P_inc); 
                          end 
                      end 
                      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                end 
            end 
        end 
    end 

As you can see, for large "K" and "n" values, the code will be very very slow :( Does anyone have any better way of conducting such loops, but in a much faster way?!

any help will be much appreciated.

Thanks

0 Comments

Amir Akb

Products

No products are associated with this question.

2 Answers

Answer by Jan Simon on 8 May 2012
Accepted answer

At first clean up the current code:

% MAIN CALCULATIONS DONE HERE
p(1) = (2^S(1) - 1) * (N/g(1));   % Avoid test for ==1 in each iteration!
tmp1 = cumsum(p);
for user_index = 2:K 
  Sum_P_inc     = tmp1(user_index - 1); 
  p(user_index) = (pow2(S(user_index))-1) * (N/g(user_index) + Sum_P_inc); 
end

Perhaps a vectorized version is faster:

p = (pow2(S) - 1) .* (N ./ g + [0; cumsum(p(1:end-1))]);

Please test this - I do neither have your data nor can I access Matlab currently.

In a further step you can convert the K "for" loops to 1 "while" loop by using a [1 x K] vector and increment the last element until the limit is reached. Then increment the next element and reset the last one until even the first element reaches the limit.

1 Comment

Amir Akb on 8 May 2012

Hi Jan,

Thank you very much for your time and effort to answer my question.
Just to let you know, the "clean-up" section works, and gives the same result, however, this doesn't speed the code up much.
About your second comment, would you be able to give me a bit more detail on how to convert the K for loops to a single while loop please.

Once again, many thanks for your time.

Jan Simon
Answer by Jan Simon on 9 May 2012

A code example for K "loops" represented by a [1 x K] vector:

n  = 3;
K  = 4;
V  = ones(1, K);
go = true;
while go
  % The action:
  disp(V);
    % Increment:
    V(K) = V(K) + 1;
    if V(K) > n
      V(K) = 1;
      go   = false;
      for i = K-1:-1:1
         V(i) = V(i) + 1;
         if V(i) <= n   % i.th counter not at limit
            go = true;
            break;      % Leave "for i" loop
         end
         V(i) = 1;      % Reset i.th counter 
      end
    end
  end

This is choosing K elements from the vector 1:n with repetition and order.

1 Comment

Amir Akb on 10 May 2012

Dear Jan,

You just made my day!
This is exactly what i was looking for. It is much faster than having "K" nested "for" loops, and i get the same result.

I really appreciate the time you have put into replying back to my question.

All the best

Jan Simon

Contact us