Parallel Looping with nested recursive for loop in MATLAB - matlab

Parallel Looping.
Hi there, I am having trouble figuring out what kind of loop I should be using for a section of my code.
my issue it that I would like to run the program with multiple initial conditions.for example lets say I have a matrix q where its dimensions are 4 by 2. q(:,1) is the first set of initial conditions and q(:,2) is the second set of initial conditions.
what I want is the recursive for loop (lines 11-22) to take the independent initial conditions q(:,1) and q(:,2) and simultaneously run them through the for loop independently.
Here is some mock code (unfortunately I cannot use the actual code due to an NDA):
1 p=ones(3,2); %initial condition
2 q=2.*ones(4,2); %initial condition
3 r=3.*ones(3,2); %initial condition
4 k=1; %here i want it to iterate for k=1:2 in parallel (i think)
5 pp=p(:,k);
6 qq=q(:,k);
7 rr=r(:,k);
8 p=p(:,k);
9 q=q(:,k);
10 r=r(:,k); %for loop below requires vector form.
11 for t=0:.5:60
12 v=[p;q;r]; %initial conditions for ode45
13 tspan=[t,t+.25,t+.5];
14 [T,Y]=ode45('somefunc',tspan,v,...);
15 v=Y(3,:);
16 p=v(1:3);
17 q=v(4:7);
18 r=v(8:10);
%building up a matrix with all the data from the iterated/recursive ode45
19 pp=cat(2,pp,p);
20 qq=cat(2,qq,q);
21 rr=cat(2,rr,r);
22 end
The code above evaluates for only k=1 or k=2. it does not iterate k=1:2.
what I want is to end up with a multi-dimensional array for pp, qq and rr for the two (at some point n) possible initial conditions. ie pp(:,:,1) would be the matrix with the first initial conditions and pp(:,:,2) would be the second initial conditions. same goes for qq and rr.
This is why I think I need a parallel for loop instead? so that the initial conditions in lines 1 through 3 can be called again rather than the redefined values of my variables due to the for loop in lines 11-22.
I am also confused on how to satisfy parfor's requirement of independent iterations while having a nested for loop with dependent iterations within.
Please let me know if there is anything else you would like me to explain further or clarify.
Thank you for your time and help!

Related

Splitting Vector into Sub-vectors MATLAB

I am trying to figure out how to split a vector in matlab into subvectors.
I am solving a differential equation numerically using dde23. When You do this the length of the solution vector changes. Thus, I am finding it not so easy to use the mat2cell command that many people suggest.
All I am trying to do is split (as evenly as possible) a vector of length N into an arbitrary amount of sub-vectors whose length may vary depending on the length of the time vector. I am doing this so then I can find the maximum value of each vector on in each interval.
If I understand the question, maybe you can try to split it by using code below
dataset=[ 1 2 3 4 5 6 7 8 9 10]
splitpoint = randi[2 length(dataset)-1]
subset1 = dataset(1,1:splitpoint)
splitpoint = randi[length(subset1)+1 length(dataset)-1]
subset2 = dataset(1,length(subset1)+1:splitpoint)
After that you can choose where to finish and accept rest of it for last subset or you can define one list to hold each subset in the row of the list. So you can define while loop to handle it automatically by defining stop_criteria.

Double for loop in MATLAB, storing the information

I have two for loops in MATLAB.
One of the for loops leads to different variables being inserted into the model, which are 43 and then I have 5 horizons.
So I estimate the model 215 times.
My problem is I want to store this in 215x5 matrix, the reason I have x5 is that I am estimating 5 variables, 4 are fixed and the other one comes from the for loop.
I have tried to do this in two ways,
Firstly, I create a variable called out,
out=zeros(215,5);
The first for loop is,
for i=[1,2,3,4,5];
The second for loop is,
for ii=18:60;
The 18:60 is how I define my variables using XLS read, e.g. they are inserted into the model as (data:,ii).
I have tried to store the data in two ways, I want to store OLS which contains the five estimates
First,
out(i,:)=OLS;
This method creates a 5 x 5 matrix, with the estimates for one of the (18:60), at each of the horizons.
Second,
out(ii,:)=OLS;
This stores the variables for each of the variables (18:60), at just one horizon.
I want to have a matrix which stores all of the estimates OLS, at each of the horizons, for each of my (18:60).
Minimal example
clear;
for i=[1,2,3,4,5];
K=i;
for ii=18:60
x=[1,2,3,i,ii];
out(i,:)=x;
end
end
So the variable out will store 1 2 3 5 60
I want the variable out to store all of the combinations
i.e.
1 2 3 1 1
1 2 3 1 2
...
1 2 3 5 60
Thanks
The simplest solution is to use a 3D matrix:
for jj=[1,2,3,4,5];
K=jj;
for ii=18:60
x=[1,2,3,jj,ii];
out(ii-17,jj,:)=x;
end
end
If you now reshape the out matrix you get the same result as the first block in etmuse's answer:
out = reshape(out,[],size(out,3));
(Note I replaced i by jj. i and ii are too similar to use both, it leads to confusion. It is better to use different letters for loop indices. Also, i is OK to use, but it also is the built-in imaginary number sqrt(-1). So I prefer to use ii over i.)
As you've discovered, using just one of your loop variables to index the output results in most of the results being overwritten, leaving only the results from the final iteration of the relevant loop.
There are 2 ways to create an indexing variable.
1- You can use an independent variable, initialised before the loops and incremented at the end of the internal loop.
kk=1;
for i=1:5
for ii=18:60
%calculate OLC
out(kk,:)=OLC;
kk = kk+1;
end
end
2- Use a calculation of i and ii
kk = i + 5*(ii-18)
(Use in loop as before, without increment)

(MATLAB) On drawing elements randomly from vectors and rows randomly from matrices without replacement in for loops

So, two related questions for code I'm writing for an experiment I'm building in MATLAB. Firstly, I have a 20 row column vector, called block1 (with a number in each of the 20 slots).
I want to draw a number randomly from the vector without replacement and repeat this until there are no numbers left in the vector (so 20 times total). I have the following line within a for loop (which is set to run for 20 iterations), which draws the random number from the vector and sets it equal to variable rand_num:
rand_num = randsample(block1,1,false)
It draws the random number just fine, but the problem is that the draw without replacement part doesn't work. Initially I thought this was because the vector was reset at the beginning of each iteration of the for loop. To make sure, I debugged and found that even when I stop the for loop before the first iteration finishes (and after the random number has been drawn), there are still 20 numbers in the vector (when there should be 19). Any ideas as to how I can fix this?
The second question is as follows. For the same experiment, I have a 20 by 6 matrix called pick_matrix. During each iteration of the same for loop as above, I want to pick one row at random from the matrix (including every element in that row; so 6 elements total for each row) without replacement and assign that row to variable random_row.
I figured out the code to pick a row at random and assign it to random_row, but I'm having the same problem as with the last question: the without replacement part isn't working.
randsample works fine, and exactly as expected. You just need to call it once before your loop rather than twenty times within the loop. Read the help carefully - randsample does not change anything about the input variable block1. Generally speaking (ignoring globals and such), input variables are not changed by Matlab functions, even if they are changed within a function, unless they are then explicitly output.
e.g. consider this:
function y = myfunc(x);
x = x*2;
y = x*3;
disp(x)
end
Within the function, x is doubled. Say I have a variable x in my workspace, value 10. If I call y = myfunc(2), I will see "4" displaced - and y will be output as 12, not 6. However, the x in my base workspace is never changed, which is exactly the expected behaviour.
If I want x to be changed, I have to set it explicitly as output to the function and deliberately call the function in such a way as to overwrite my variable x, e.g [x y] = myfunc(2);
As suggested in the comments, you could use randperm instead if you're taking every number, but a more generic example using randsample to take a random pick of 10 from 20:
% sampling without replacement is default
rand_nums = randsample(block1, 10);
rand_ind = randperm(20,10); % 10 numbers from 1:20
for n = 1:10
rand_num = rand_nums(n);
rand_row = pick_matrix(rand_ind(n),:);
% whatever you need to do with these things goes here
end

How to save matrices from for loop into another matrix

I have a 5-by-200 matrix where the i:50:200, i=1:50 are related to each other, so for example the matrix columns 1,51,101,151 are related to each other, and columns 49,99,149,199 are also related to each other.
I want to use a for-loop to create another matrix that re-sorts the previous matrix based on this relationship.
My code is
values=zeros(5,200);
for j=1:50
for m=1:4:200
a=factor_mat(:,j:50:200)
values(:,m)=a
end
end
However, the code does not work.
Here's what's happening. Let's say we're on the first iteration of the outer loop, so j == 1. This effectively gives you:
j = 1;
for m=1:4:200
a=factor_mat(:,j:50:200)
values(:,m)=a;
end
So you're creating the same submatrix for a (j doesn't change) 50 times and storing it at different places in the values matrix. This isn't really what you want to do.
To create each 4-column submatrix once and store them in 50 different places, you need to use j to tell you which of the 50 you're currently processing:
for j=1:50
a=factor_mat(:,j:50:200);
m=j*4; %// This gives us the **end** of the current range
values(:,m-3:m)=a;
end
I've used a little trick here, because the indices of Matlab arrays start at 1 rather than 0. I've calculated the index of the last column we want to insert. For the first group, this is column 4. Since j == 1, j * 4 == 4. Then I subtract 3 to find the first column index.
That will fix the problem you have with your loops. But loops aren't very Matlab-ish. They used to be very slow; now they're adequate. But they're still not the cool way to do things.
To do this without loops, you can use reshape and permute:
a=reshape(factor_mat,[],50,4);
b=permute(a,[1,3,2]);
values=reshape(b,[],200);

sortrows based on previous sort results

Here is the thing
I have a large matrix and I need to sort that based on some columns:
B is the large matrix
A=sortrows(B,[1 4 9 10]);%Just a sample input vector
Its OK so far.But then in next step (I'm iterating this function) I will need this:
A=sortrows(B,[1 4 9 10 16]);%Notice I just add a new column to input vector
And same story in next iterations
So my question is can I use previous sort results in each iteration?
Edit------------------------------------
for those who are familiar the main problem is a feature selection task.I have a matrix lets name it IS .You can find one in here .In IS rows are objects and columns are features.The task is evaluate a subset of features based on a fitness function .I'm not going in to fitness function because it is not related but as a black-box the input and output are:
function fitnessValue=fitness(inputMatrix,featureSubset)
end
inputMatrix must be sorted based on featureSubset but being sorted based on any permutation of feature set would do the thing
Now main algorithm
featureSubset=[];
iter=1;
while iter<iterMax and fitnessValue<1
j=chooseFeature(IS,featureSubset) %select a feature that has not been selected yet based on some parameters
featureSubset=union(featureSubset,j);%Add j to selected features
IS=sortrows(IS,featureSubset);%Here is the problem
fitnessValue=fitness(IS,featureSubset)
iter=iter+1;
end
That's it at each iteration I am adding features one by one and evaluating new feature subset but in order to do that I need to sort the IS matrix based on feature subset .As i said in previous iteration I also sort the entire matrix based on featureSubset(1:end-1) and I belive I can use previous sort result and somehow just sort IS based on current selected feature and get the same result .
P.S if someone can explain the algorithm of sortrows i would be really grateful
This is the function that I came up with might be useful for someone in future :
function [ndx]=sort2(x,cols,oldIndex)
x=x(:,cols);
[m,n] = size(x);
if nargin<3
ndx = (1:m)';
else
ndx=oldIndex;
end
for k = n:-1:1
[ignore,ind] = sort(x(ndx,k));
ndx = ndx(ind);
end
result--------
a=sort2(IS,[1 4 9 10]);
a=sort2(IS,16,a);
b=sort2(IS,[16 1 4 9 10]);
isequal(a,b)=1