How to Nest a Loop so the Entire Thing Repeats 100X - matlab

I have a loop that I am trying to create another loop around, but I'm not sure what the syntax should be. Here is my code:
for (?)
for i=1:6
r(i)=normrnd(0,0.1*sy);
y_new=A+B*x+r;
end
% estimate new A and B
[mm,nn]=size(x); DoF=mm-2;
x_mean=mean(x);
y_mean=mean(y_new);
xp=(x-x_mean);
yp=(y_new-y_mean);
num=sum(xp.*yp);
dem=sum(xp.*xp);
B_new=num/dem;
A_new=y_mean-B_new*x_mean;
end
I'm not sure what to put in the for loop to make it repeat 100X. I assume I need "for i=1:100" but then I'm not sure where in the loop to put set my x(i) to get the intended result. I'm not even sure if I nested the first loop in there correctly. I am trying to create a set of 6 new y values using normrnd and then run a linear regression to generate a new A and B (slope and intercept), and then I want to repeat that entire process 100X.

Unless you have a specific reason not to vectorize your normrnd() calls, you only need one level of fors:
%sy,A,B,x initialized elsewhere
for i=1:100
r=normrnd(0,0.1*sy,[6 1]);
y_new=A+B*x+r;
clear r;
% estimate new A and B
[mm,nn]=size(x);
DoF=mm-2;
x_mean=mean(x);
y_mean=mean(y_new);
xp=(x-x_mean);
yp=(y_new-y_mean);
num=sum(xp.*yp);
dem=sum(xp.*xp);
B_new=num/dem;
A_new=y_mean-B_new*x_mean;
%set B=B_new and A=A_new for the next iteration maybe?
end
clear i;

Related

Using a for loop inside a parallel for loop in Matlab

I am trying to use a for loop inside of a parfor loop in Matlab.
The for loop is equivalent to the ballode example in here.
Inside the for loop a function ballBouncing is called which is a system of 6 differential equations.
So, what I am trying to do is to use 500 different sets of parameter values for the ODE system and run it, but for each parameter set, a sudden impulse is added, which is handled through the code in 'for' loop.
However, I don't understand how to implement this using a parfor and a for loop as below.
I could run this code by using two for loops but when the outer loop is made to be a parfor it gives the errors,
the PARFOR loop cannot run due to the way variable results is used,
the PARFOR loop cannot run due to the way variable y0 is used and
Valid indices for results are restricted in PARFOR loops
results=NaN(500,100);
x=rand(500,10);
parfor j=1:500
bouncingTimes=[10,50];%at time 10 a sudden impulse is added
refine=2;
tout=0;
yout=y0;%initial conditions of ODE system
paras=x(j,:);%parameter values for the ODE
for i=1:2
tfinal=bouncingTimes(i);
[t,y]=ode45(#(t,y)ballBouncing(t,y,paras),tstart:1:tfinal,y0,options);
nt=length(t);
tout=[tout;t(2:nt)];
yout=[yout;y(2:nt,:)];
y0(1:5)=y(nt,1:5);%updating initial conditions with the impulse
y0(6)=y(nt,6)+paras(j,10);
options = odeset(options,'InitialStep',t(nt)-t(nt-refine),...
'MaxStep',t(nt)-t(1));
tstart =t(nt);
end
numRows=length(yout(:,1));
results(1:numRows,j)=yout(:,1);
end
results;
Can someone help me to implement this using a parfor outer loop.
Fixing the assignment into results is relatively straightforward - what you need to do is ensure you always assign a whole column. Here's how I would do that:
% We will always need the full size of results in dimension 1
numRows = size(results, 1);
parfor j = ...
yout = ...; % variable size
yout(end:numRows, :) = NaN; % Expand if necessary
results(:, j) = yout(1:numRows, 1); % Shrink 'yout' if necessary
end
However, y0 is harder to deal with - the iterations of your parfor loop are not order-independent because of the way you're passing information from one iteration to the next. parfor can only handle loops where the iterations are order-independent.

How to create a vector of the results in a for loop

I have a problem with the following code. I want to store all the values I am creating in the for loop below so that I can make a plot of it. I have tried several things, but nothing works. Does anyone know a simple method to create a vector of the results and then plot them?
dx=0.1;
t=1;
e=1;
for x=-1:dx:1
lower_bound=-100;
upper_bound=x/(sqrt(4*t*e));
e=1;
u=(1/sqrt(pi))*quad(#integ,lower_bound,upper_bound);
plot(x,u)
hold on
end
hold off
I would like to use as much of this matlab code as possible.
dx=0.1;
t=1;
e=1;
xval=[-1:dx:1].';
upper_bound = zeros(numel(xval),1);
u = zeros(numel(xval),1);
for ii=1:numel(xval)
x = xval(ii)
lower_bound=-100;
upper_bound(ii,1)=x/(sqrt(4*t*e));
u(ii,1)=(1/sqrt(pi))*quad(#integ,lower_bound,upper_bound(ii));
end
figure;
plot(xval,u)
by adding the (ii) behind your statements it saves your variables in an array. I did not use that on your lower_bound since it is a constant.
Note that I first created an array xval and called that with integers in ii, since subscriptindices must be positive integers in MATLAB. I also initialised both upper_bound and u by creating a zero matrix before the loop executes. This is handy since extending an existing vector is very memory and time consuming in MATLAB and since you know how big they will get (same number of elements as xval) you might as well use that.
I also got the plot call outside the loop, to prevent you from plotting 21 blue lines in 1 plot.

parallel independent iteration of elements in an array

I want to iterate all the elements independently (same condition for all elements though). I want to stop the iteration when the value stops changing. I will post the part of my code. According to some research, I figured that it can also be done using parfor loop but i don't know how to implement it. Can anyone please correct my code? Thanks in Advance.
probability = (ones(1,2048) .* 1/2048);
Tij = sum(StateTransitionfwd); %gives us an array of 2048 elements.
probability = ((probability * StateTransitionbwd) - (Tij .* probability));
threshold = (ones(1,2048) .* 0.05);
old = zeros(1,2048);
new = zeros(1,2048);
while(1)
probability = ((probability * StateTransitionbwd) - (Tij .* probability));
new = probability;
if old-new <= threshold
break
end
old = probability;
end
So basically I want the steady state probability (where it is not changing anymore)
For one you cannot parallellise while loops.
To implement a parfor loop make sure of the following:
- All variables must be defined before the parfor loop. Thus define output variables before the loop.
- All iterations must be absolutely independent of one another.
The second condition is not fulfilled in your case, since you are constantly updating the variable new, making it not independent.
I'd not even parallellise this code, since it's designed to break up before it went through all elements, but for the sake of argument I'll try this:
parfor ii = 1:length(Tij)
probability{ii} = ((probability * StateTransitionbwd) - (Tij .* probability));
end
Either use a cell or a matrix, whichever is more useful for your work.
Now you can go ahead and use a simple if to find your threshold:
for ii = 1:length(probability)-1
if probability(ii+1)-probability(ii)<threshold
break
end
end
As for your while loop stop condition: it's dangerous to let a loop run uncontrolled to some condition, as you do. It's rather easy to get stuck in an infinite loop. Use an additional condition MaxIt for the maximum number of iterations to do before terminating, regardless of the other condition.
while probability<threshold && MaxIt<someNumber
your code
end
Also you are checking for the validity of a full array.
A = logical([1;0]);
while A
B=1;
end
C = logical([1;1]);
while C
D=1;
end
The first while loop will not run, since one of its entries is not true; the second loop is an infinite loop now. If you want to terminate each row as soon as the condition is met, put the while loop inside a for loop over each row instead. That forloop can be parallellised if you put the while loop into a function, see the parfor documentation for that.

Is it possible to use a "while" loop in parallel when using MATLAB?

I know that it seems like the straightforward answer is NO. Yet, I wonder if there is not a way to get it to work.
Basically, I would like to randomly draw from a distribution and only keep those who respect a certain condition and fill a pre-determined storage matrix and stop once the matrix is full.
Since these are draw, I suppose I can harness Matlab's parallel capabilities but since the completion of the storage matrix depends on the sequence of draws, I feel there is an issue there.
Alternatively, is there a way to use a time-check for the problem at hand. For instance, I would use a parfor with a limit absurdely large but include a way to check the size of the storage matrix at frequent interval.
In pseudo-code, it would give:
create size of the storage matrix: A=zeros(100,1); Naccepted=0;Ntried=0;
initiate the for loop: parfor i=1:100000000000
do the loop: x(i)=randn(1,1)
check whether it respects the condition: if x(i)>0, Naccepted=Naccepted+1; Ntried=Ntried+1; A(j,1)=x(i), else Ntried=Ntried+1
Check with a timer every 5 minutes (that I have no clue as to implement it in Matlab) if the size of A has reached 100 or not. If so, then stop and take the first 100 accepted draw. If not, continue.
I realize that my question is very messy but I fail to see properly which part could work in parallel or not.
Ok, figured it out:
matlabpool open 8
tic
clear;
j=1;
Naccepted=0;
A=[];
workers=8;
while size(A,1)<=100
spmd(workers)
x=zeros(10,1);
for i=1:10
x(i)=randn(1,1);
end
end
for k=1:workers
Z(:,k)=x(1,k);
end
for k=1:workers
V(1+(k-1)*10:10+(k-1)*10,1)=cell2mat(Z(1,k));
end
V=V(V>0);
A=[A;V];
Naccepted(j,1)=size(V,1);
j=j+1;
end
Ntried=j*workers*10;
rejection=1-sum(Naccepted)/Ntried;
A=A(1:100,1);
toc
matlabpool close
Using a while loop directly is not possible, however, there is a small trick that can be used.
A while loop can be decomposed into a for loop in combination with checking the same condition as the while loop.
If it is possible to use a for loop, it can be possible, given suitable use of the variables inside the loop (broadcast, slice, etc), to use a parfor loop.
To give you an example:
clear
nb_tests=1e8;
tic
i=1;
captured=zeros(1,nb_tests);
while i<nb_tests
tester=rand;
if tester>0.5
captured(i)=tester;
i=i+1;
end
end
toc
tic
captured=zeros(1,nb_tests);
for i=1:nb_tests
respect=0;
while respect<1
tester=rand;
if tester>0.5
captured(i)=tester;
respect=1;
end
end
end
toc
parpool
tic
captured=zeros(1,nb_tests);
parfor i=1:nb_tests
respect=0;
while respect<1
tester=rand;
if tester>0.5
captured(i)=tester;
respect=1;
end
end
end
toc
Be advised that the advantage of parallelization kicks in when you either have a lot of iterations or when the content of the loop is more complex.

Extract parts of a big matrix and allocate them in new variables with loop function

I am a total beginner in MATLAB and I hope to find some help here. I have some model prediction results for 80 individuals alltogether in one large matrix. I need to extract the data for each individual from the big matrix, assign them in a new variable/matrix, do some extra calculations and then plot certain information as needed.
To do so, I am trying to write a script with a loop function but in a complicated, or maybe more accurately: in a primitive way!
Simplified Example:
My matrix is called: All_Indi_Data .... its dimension is: 600 rows x 21 columns
%Column 1: grouping variable (e.g., code or ID with values 1,2,3,4,5, etc.);
%Column 2: independent var.;
%Column 3: t;
%Column 4: OBS;
%Column 5: PRED;
i= length (All_Indi_Data);
%% First Indi.
q=1; % indicating the ID of the indi for which I want to extract the data
j=1; % variable added to insure writing start from the first row
for r=1:i
if All_Indi_Data (r,1)==q
Indi_1 (j,1:21) = All_Indi_Data (r,1:21)
j=j+1
end
end
%% Second Indi.
q=q+1
j=1
for r=1:i
if All_Indi_Data (r,1)==q
Indi_2 (j,1:21) = All_Indi_Data (r,1:21)
j=j+1
end
end
.
.
.
1) My first question is: can I allocate these data in new variables (Indi_1, Indi_2, ect.) in a more simple way with or without the loop function?!!! I would appreciate your help a lot.
2) Is there any code or any way to plot these selected parts (according to the grouping variable, e.g. data for Indi_1) from the previously mentioned big matrix without wasting a lot of time and space (wto recopying the core part of the code again and again) for the script, and using the loop function?! in other words, I would like to detect - with loop function & the grouping variable- which values are of interest and then to plot them (e.g. data in colum 3 with data from column 4 for each individual, starting from the first to the last)?!
I hope that I described my problem clearly and hope to hear something from the expert guys :) ...
Thanks a lot in advance ..
Try the following code:
for idx=1:80
pos=find(All_Indi_Data(:,1)==idx);
eval(['Indi_' num2str(idx) '=All_Indi_Data(pos,:);']);
end
What I do is: in each iteration, I search for a value of the ID, indicated in the variable idx. Note that I do not use ´i´ as the name of a variable, because Matlab uses it and ´j´ and the imaginary unit for complex numbers and that could cause problems.
Then, using find I search for the position (or positions) of All_Indi_Data in which I can find the information of that individual. Now I have in the variable ´pos´ the indexes of the rows in which there is information for the individual of interest.
Finally, using eval I extract the data for each individual into a variable. Note that eval combined with a loop makes it easy to create lots of variables. I indicate the rows I want to extract with ´pos´ and, as I want all the columns, I use just ´:´ (you could use ´1:21´ too).
With another similar loop you can plot the information you want. For example:
for idx=1:80
eval(['x=Indi_' num2str(idx) ';']);
% Now I have in X the information for this individual
%Plot the columns of x I want
plot(x(:, 3), x(:,4));
pause; %stay here until a press a key
end