How to vectorize for loops

Hello, I am quite new to Matlab but I have typed down the following piece of code. It works as desired, but I have noticed the following:
  • Matlab spends a lot of time on exprnd(.). Is there a way to improve this flaw?
  • As it is quite visible I am using three 'for' loops but I know that Matlab is much more efficient when loops are vectorized. Is there any way you could help me achieve this?
%Random Walk
RW=10;
nsteps = 10;
X = -99999:99999;
L = length(X);
m = ['x','d','*','s','o','.','h','^','v','>','<','p','h'];
S1 = zeros(nsteps,1);
MSD1 = zeros(nsteps,1);
nstepss1 = zeros(nsteps,1);
for k=1:nsteps+1
K1 = zeros(RW,1);
V1 = zeros(RW,1);
for j=1:RW+1
position = 0;
Xright = 0;
Xleft = 0;
u_left = 0;
u_right = 0;
for i=1:nsteps+1
u = exprnd( 1 );
z = rand;
p = 0.1*(u_right)./(0.3)./0.2*(u_right)./(0.3)+0.1*(u_left)./(0.3)).*(k<(1/20)*nsteps) + 0.1*(u_right)./(3.0)./0.2*(u_right)./(3.0)+0.1*(u_left)./(3.0)).*(k>=(1/20)*nsteps);
left_step = -1.*(z<p);
right_step = 1.*(z>p);
n = left_step+right_step;
%Boundary Conditions
if position+n > X(L)
position = X(1);
elseif position+n < X(1)
position = X(L);
else
position = position+n;
end
% Choice of Step
if n == 1
Xright = Xright+1;
if u_right>=u
u_right = u_right;
else
u_right=u;
end
else
Xleft = Xleft+1;
if u_left>=u
u_left = u_left;
else
u_left=u;
end
end
end
K1(j) = position; %Final position of each RW
V1(j) = ((Xright-Xleft)/nsteps); %Average velocity of each RW
end
S1(k) = std(V1);
MSD1(k)=sqrt(S1(k)^2+(mean(V1))^2);
nstepss1(k) = k;
hold all;
PLO1 = scatter(nstepss1.', MSD1, '+');
end
hold off;
drawnow
Sorry for the long piece of code provided and thank you for your answers.

3 Comments

foboo
foboo on 16 Jan 2018
Edited: foboo on 16 Jan 2018
It's not a vectorized version, but you can just draw the random numbers outside of the loop and then access the vector in the loop.
Hello, thanks for taking the time to answer. Would you mind elaborating a little bit on what exactly you are suggesting? Like I mentioned in the beginning of the post, I am not yet quite familiar with the vectorizing concept.
What foboo means is doing
myexprnd = exprnd(1,[nsteps+1, RW+1, nsteps+1]);
before the first for loop to get all the random numbers at once, since doing it that way is faster. Later, you can retrieve the number by calling
u = myexprnd(k,j,i);

Sign in to comment.

Answers (1)

@Evangelos: Omit useless code like: u_right = u_right; This is a waste of time only and confusing. Better replace
if u_left>=u
u_left = u_left;
else
u_left=u;
end
by
u_left = min(u_lect, u);
Your code contains a bug the line:
p = 0.1*(u_right)./(0.3)./0.2*(u_right)./(0.3)+0.1*(u_left)./(0.3)) ...
There is a right parenthesis too much. After fixing this, this line should be cleaned massively: No parentheses around scalar numbers, (0.3)./0.2 is 1.5, etc.
Replace:
left_step = -1.*(z<p);
right_step = 1.*(z>p);
by
left_step = -(z<p);
right_step = (z>p);
and
if position+n > X(L)
position = X(1);
elseif position+n < X(1)
position = X(L);
else
position = position+n;
end
by:
position = position + n;
if position > X(L)
position = X(1);
elseif position < X(1)
position = X(L);
end
You can improve the code and accelerate it, but I do not think that it is a candidate for a vectorization.

Products

Asked:

on 15 Jan 2018

Answered:

Jan
on 4 Feb 2018

Community Treasure Hunt

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

Start Hunting!