Preallocating in MATLAB when a loop has the "Union" function - matlab

Assume there is a loop which should be preallocated. It can be done either by "zeros", "eye" or "NAN" matrices. The problem is when one of these 3 matrices are being used, after using union function, an extra line of zeros (or one or NAN) will be remain which should delete at the end.
For example:
Q=[0 0];
for i=1:10
q= [rand(1) 2*rand(1)];
Q= union(Q,q,'rows');
end
Consequently, there is a [0 0] array remain at the beginning of our matrix which should be deleted.
Q(1,:)=[];
I was wondering if you could help with a code which can do reallocating without needing erasing the first line.
P.S. just image there is a reason for keep the union and loop.
Thanks

Don't ask for a union that you don't want:
Q = [];
for i=1:10
q = [rand(1) 2*rand(1)];
if(isempty(Q))
Q = q;
else
Q = union(Q,q,'rows');
end
end
Or, instead of initializing Q with values that you don't want, initialize it with a value you DO want:
Q = [rand(1) 2*rand(1)];
for i=1:9
q = [rand(1) 2*rand(1)];
Q = union(Q,q,'rows');
end
This really has nothing to do with preallocation. The way union works forces it to return a new value for Q each time, which means you overwrite the previous value. preallocation is when you insert data into the correct location of an appropriately-sized output matrix, in order to avoid extra memory allocations due to resizing your output.

Related

Double for loop, how to set non-continuous index?

If I want to construct a double for loop, but for index k I don't want it to be continuous index but like [1,2,4,7]. I tried to do the following, and it did not work.
for i=1:100
for k=1:2:4:7;
b(i)=i*k;
end
end
Anyone could help me deal with that?
When you want to construct an array, you don't want to necessarily use the colon (:) operator unless you want to create a range of values (like you do when you want i to be all values between 1 and 100), instead you want to use square brackets ([]) with comma separators to explicitly create an array of discrete values.
k = [1,2,4,7];
Now that you do this you can specify your loop like you had it with this small substitution for the values of k
kvalues = [1,2,4,7];
for i = 1:100
for k = 1:numel(kvalues)
b(i) = i * kvalues(k);
end
end
Notice that I have defined kvalues once outside of the loop so that it is not created every iteration through the outer loop (thanks to #dfri for pointing this oversight out)
The way that you have your loop written, you're actually over-writing the value of b(i) every time through the inner loop. I'm not sure if that's what you intended to do. If it is, then you can reduce your loop to the following:
b = k(end) * (1:100);
Otherwise, if you meant to have it be b(i,k) = i * k, you could rewrite this with bsxfun.
b = bsxfun(#mtimes, [1,2,4,7], (1:100).');
The syntax k=1:2:4:7 will not work as you intend. Usually we make use of the "two colon" syntax to describe a non-default (1) step size from the given start to end values, k = start:stepSize:end. Using an additional colon here even yields a Matlab warning ("third colon probably not intended?").
One possible workaround is to let your "non-continuous" indices reside in a vector and extract members of this vector in the inner for loop as follows
nonContIndex = [1; 2; 4; 7];
numIndices = numel(nonContIndex);
b = zeros(100,numIndices);
for i=1:100
for k=1:numIndices
b(i,k)=i*nonContIndex(k);
end
end
As noted by comments and the other answer: if b is simply a vector, your original loop will overwrite the b(i):th entry for each run of the inner loop. The above assumes that you in fact want a 2D matrix as a result.

MATLAB Cycle through vector values sequentially in a large for Loop

I have a small vector that has values that need to be calculated in sequence while a large for loop executes. Each time the for loop executes, it sequentially moves from vector index 1 to end then reset until the for loop executes completely.
For example, if the vector is [4 2 1] and the for loop executes n times, the index value will be 4,2,1,4,2,1,4,2,1... etc.
I was wondering if there was a way to optimize or shrink some code I developed or even if there was another way to accomplish the task, simpler or not.
Here's my code:
cookie_jar = [prt/4 prt/2 prt];
...
for k = 1:reps;
if k <= length(cookie_jar);
cookie = cookie_jar(k);
elseif rem(k,length(cookie_jar)) == 0
cookie = cookie_jar(end);
else
cookie = cookie_jar(rem(k,length(cookie_jar)));
end
end
Thanks!
You have to fix the third case to match indexing which starts with 1, then the first two cases are no longer required:
for k = 1:reps
cookie=cookie_jar(rem(k-1,length(cookie_jar))+1)
%...
end

output iteration results from a loop in Matlab

I am trying to use a for loop to make some calculations in a cell array but at the end only the results for the last loop are displayed. I would like Matlab to display the results for all loops. Here there is the code:
slope=[];
time=[];
position= [];
for p=1:max(L) % max L gives the number of result{n}. so if max(L)=6 we have from result{1} to result{6} and therefore 6 final values that i want to get%
a=result{n}(:,1);
b=result{n}(:,2);
end
B = [ones(length(a),1) a] \ b % this is to obtain the slope and intercept of a lin. regresion
slope = B(2)
time = result{n}(end,1)-result{n}(1:1)
position = (slope.*result{n}(end,1)+intercept)-(slope.*result{n}(1:1)+intercept)
At the moment in the output that is what i get:
slope =
4.4089
time =
0.5794
position =
2.5546
This result is correct. However, these values are the ones obtained with result{6} and i need the values previous to this one.
Any help is much appreciated !
Thanks in advance!
You are making a mess with the indexes… It is a bit hard to understand what you did on your code, but it may be something like this (pseudocode since the code you gave does not have the result declared):
slope=zeros(1,max(L)); % Pre allocate zeros, one index for each interation
time=zeros(1,max(L));
position=zeros(1,max(L));
a=zeros(1,max(L));
b=zeros(1,max(L));
for p=1:max(L) % max L gives the number of result{n}. so if max(L)=6 we have from result{1} to result{6} and therefore 6 final values that i want to get%
a(p)=result{p}(:,1);
b(p)=result{p}(:,2);
B = [ones(length(a( p ),1) a( p )] \ b( p) % this is to obtain the slope and intercept of a lin. regresion
slope( p) = B(2)
time( p) = result{p}(end,1)-result{p}(1:1)
position( p) = (slope( p ).*result{p}(end,1)+intercept)-(slope ( p) .*result{p}(1)+intercept)
end
position(6) will get your value, position(5) the previous value.
The easiest way to do this is to remove the ";" for lines that you want printed to the command window. This will display all loop values you need.
for p=1:max(L)
a=result{n}(:,1)
b=result{n}(:,2)
end
Can you do all calculations inside the loop and don't block with ";" instead. If you get a result after coming out of a loop, you will only get the last one.

How do I know how many iterations are left in a parfor loop in Matlab?

I am running a parfor loop in Matlab that takes a lot of time and I would like to know how many iterations are left. How can I get that info?
I don't believe you can get that information directly from MATLAB, short of printing something with each iteration and counting these lines by hand.
To see why, recall that each parfor iteration executes in its own workspace: while incrementing a counter within the loop is legal, accessing its "current" value is not (because this value does not really exist until completion of the loop). Furthermore, the parfor construct does not guarantee any particular execution order, so printing the iterator value isn't helpful.
cnt = 0;
parfor i=1:n
cnt = cnt + 1; % legal
disp(cnt); % illegal
disp(i); % legal ofc. but out of order
end
Maybe someone does have a clever workaround, but I think that the independent nature of the parfor iterations belies taking a reliable count. The restrictions mentioned above, plus those on using evalin, etc. support this conclusion.
As #Jonas suggested, you could obtain the iteration count via side effects occurring outside of MATLAB, e.g. creating empty files in a certain directory and counting them. This you can do in MATLAB of course:
fid = fopen(['countingDir/f' num2str(i)],'w');
fclose(fid);
length(dir('countingDir'));
Try this FEX file: http://www.mathworks.com/matlabcentral/fileexchange/32101-progress-monitor--progress-bar--that-works-with-parfor
You can easily modify it to return the iteration number instead of displaying a progress bar.
Something like a progress bar could be done similar to this...
Before the parfor loop :
fprintf('Progress:\n');
fprintf(['\n' repmat('.',1,m) '\n\n']);
And during the loop:
fprintf('\b|\n');
Here we have m is the total number of iterations, the . shows the total number of iterations and | shows the number of iterations completed. The \n makes sure the characters are printed in the parfor loop.
With Matlab 2017a or later you can use a data queue or a pollable data queue to achieve this. Here's the MathWorks documentation example of how to do a progress bar from the first link :
function a = parforWaitbar
D = parallel.pool.DataQueue;
h = waitbar(0, 'Please wait ...');
afterEach(D, #nUpdateWaitbar);
N = 200;
p = 1;
parfor i = 1:N
a(i) = max(abs(eig(rand(400))));
send(D, i);
end
function nUpdateWaitbar(~)
waitbar(p/N, h);
p = p + 1;
end
end
End result :
If you just want to know how much time is left approximately, you can run the program once record the max time and then do this
tStart = tic;
parfor i=1:n
tElapsed = toc(tStart;)
disp(['Time left in min ~ ', num2str( ( tMax - tElapsed ) / 60 ) ]);
...
end
I created a utility to do this:
http://www.mathworks.com/matlabcentral/fileexchange/48705-drdan14-parforprogress

Mark values from loop for each iteration

I want to mark each value that comes out of my loop with a value.
Say I have a variable number of values that come out of each iteration. I want those values to be labeled by which iteration they came out of.
like
1-1,
2-1,
3-1,
1-2,
2-2,
3-2,
4-2,
etc.
where the first number is the value from the loop and the second is counting which iteration it came from.
I feel like there is a way I just cant find it.
ok so here is some code.
for c=1:1:npoints;
for i=1:1:NN;
if ((c-1)*spacepoints)<=PL(i+1) && ((c-1)*spacepoints)>=PL(i);
local(c)=((c)*spacepoints)-PL(i);
end
if ((c-1)*spacepoints)>=PL(NN);
local(c)=((c)*spacepoints)-PL(NN);
element(i)=NN;
end
end
I want to mark each local value with the iteration it came from for the i:NN. PL is a vector and the output is a set of vectors for each iteration.
For this sort of quick problem I like to create a cell array:
for k = 1:12
results{k} = complicated_function(...);
end
If the output is really complicated, then I return a struct with fields relating to the outputs:
for k = 1:12
results{k}.file = get_filename(...);
results{k}.result = ...;
end
Currently as it is right now, in your inner 1:NN loop, your local(c) variable is being updated or overwritten. You never apply the previous value of local, so it is not some iterative optimization algorithm(?)...
Perhaps an easy solution is to change the size/type of local from a vector to a matrix. Let's say that local is of size [npoints 1]. Instead you make it of size [npoints NN]. It is now a 2d-array (a matrix of npoints rows and NN columns). use the second dimension to store each (assumed column) vector from the inner loop:
local = zeros([npoints NN]);
%# ... code in bewteen ...
for c=1:1:npoints;
for i=1:1:NN;
if ((c-1)*spacepoints)<=PL(i+1) && ((c-1)*spacepoints)>=PL(i);
local(c, i)=((c)*spacepoints)-PL(i);
end
if ((c-1)*spacepoints)>=PL(NN);
local(c, i)=((c)*spacepoints)-PL(NN);
element(i)=NN;
end
end
end
The c'th row of your local matrix will then corresponds to the NN values from the inner loop. Please note that I have assumed your vector to be a column vector - if not, just change the order of the sizes.