Number of iterations in a loop - matlab

Why does the following code
for a=1:5:100
a = a+ 1;
end
iterate 20 times?
a goes up by 5 every iteration, but also goes up by 1 in the actual loop. 99/6 = 16.5 or 17 iterations, so why does it do 20?
Thanks for any help understanding how the for loop function works.

In Matlab, whatever you do to the loop index variable (a) inside a for loop is thrown away, and a gets reset at the beginning of the next pass. So the a = a + 1 inside the loop has no effect. See Is there a foreach in MATLAB? If so, how does it behave if the underlying data changes?.

Unlike languages like C or C++, changing the loop index in MATLAB is not persistent across loop iterations.
In other words, if you increment a, it will remain incremented for the rest of that loop. However, upon reaching the top of the loop, MATLAB does not add 5 to a. Instead, it selects the next value of a from the list of values you provided. This effectively "overwrites" the change that you made to the loop index inside the loop.

The way to view a for loop in MATLAB like this one,
for a=1:5:100
Is to provide an array directly,
ai = [1:5:100];
for a = ai
The loop will iterate over the values in ai. Period. It doesn't matter what you do to a in the loop. At the beginning of each iteration, the value of a gets set according to the array given to the for statement.

Related

behavior of matlab's rng() function in loop

With rng() before for loop Matlab generate one array of random number, within for loop another one. Both results are repeatable, so rng() seeds work. But I want to know the reason of such behavior.I was expecting the results to be same. I think actually it is not because of rng but for loop
Code exapmle?
for i = 1:2
rng(1,'philox');
disp(randn(2,1)); % 1st number is 0.0906, 2nd one is -0.7327
end
rng(1,'philox');
for i = 1:2
disp(randn(2,1)); % 1st number is 0.7565, 2nd one is -0.7096
end
Shouldn't the results be same? Isn't rng(1,..) storing same array of numbers for seed 1
Your code works as you expect and would describe, I believe. You are definitely not showing in your code example all the outputs. This is what I get when running it.
>> test
First case:
0.0906
-0.7327
0.0906
-0.7327
Second case:
0.0906
-0.7327
0.7565
-0.7096
In the first case, you reset the random number generator inside the loop, and there fore you get twice the same results (two numbers). In the second case, you only set it once, and therefore you get the same numbers as before, and then the second loop you get the next 2 corresponding random numbers produced by the algorithm. These algorithms, once started, will produce an infinite amount of different numbers, and they won't produce the same unless you explicitly call the restart of the algorithm with the seed, like you do in the first example.
All this is way less confusing if you call disp(randn(1)) inside the loop, instead of generating 2 numbers each time.

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.

Change value inside a loop on Matlab

I have a question about how can I use different values in each iteration with a loop. I have an image with 145 bands. I calculate the size, the number of rows, columns and bands
size=size(HYP);
nrow= size(1);
ncolu= size(2);
nbands= size(3);
I have to do an operation for every band, and then obtain the result but I don't know how to change one of the values automatically for every iteration. I'm going to try to simplify the question. This is my loop. The value rad1 is defined before. I need that on every loop uses some value defined before (for example, band2 value rad2, band3 rad3...) and extract a result for each one (nd1 changes automatically to nd2, etc.)
output= zeros(nrow,ncolu,nbands);
for banda=1:nbands;
nd1= -((3.141592*rad1)/-HYP2(:,:,1));
output(banda,1)= (nd1);
end
end
So, for the first iteration:
nd1= -((3.141592*rad1)/-HYP2(:,:,1));
output(banda,1)= (nd1);
for the second...
nd2= -((3.141592*rad2)/-HYP2(:,:,2));
output(banda,2)= (nd2);
Rad1,rad 2... rad145 etc is defined before. And at the end, output would be a 145 band matrix.
Do you know how can I do it? Really thanks in advance,
Don't try using different variable names. Just use rad(1), rad(2) etc. and then
output= zeros(nrow, ncolu, nbands);
for banda=1:nbands;
output(:,:,banda) = -((3.141592*rad(banda))/-HYP2(:,:,1));
end
(Your initialization of output doesn't match the code in your loop, by the way.)

how to create a changing variable for fsolve

i want fsolve to calculate the output for different uc each time (increasing uc by 0.001 each time). each output from fsolve should be sent to a simulink model seperatly. so i set a loop to do so, but i believe that at the currenty constellation (if it will work)will just calculate 1000 different values? is there a way to send out the values seperately?
if not, how can i create a parameter uc. that goes from 0 to say 1000? i tried uc=0:0.001:1000, but again, the demension doen't seem to fit.
how do i create a function that takes the next element of a vector/matrix each time the function is called?
best regards
The general approach to iterating over an array of values and feeding them one-by-one into a series of evaluations of a function follows this form:
for ix = 0:0.1:10
func(arg1, arg2, ix)
end
See how each call to func includes the current value of ix ? On the first iteration ix==0, on the next ix==0.1 and so forth. You should be able to adapt this to your needs; in your code the loop index (which you call i) is not used inside the loop.
Now some un-asked-for criticism of your code. The lines
x0=[1,1,1];
y=x0(1);
u=x0(2);
yc=x0(3);
options=optimset('Display','off');
do not change as the loop iterations advance; they always return the same values whatever the value of the loop iterator (i in your code) may be. It is pointless including them inside the loop.
Leaving them inside the loop may even be a waste of a lot of time if Matlab decides to calculate them at every iteration. I'm not sure what Matlab does in this case, it may be smart enough to figure out that these values don't change at each iteration, but even if it does it is bad programming practice to write your code this way; lift constant expressions such as these out of loops.
It's not clear from the fragment you've posted why you have defined y, u and yc at all, they're not used anywhere; perhaps they're used in other parts of your program.

For loops in Matlab

I run through a for loop, each time extracting certain elements of an array, say element1, element2, etc. How do I then pool all of the elements I've extracted together so that I have a list of them?
John covered the basics of for loops, so...
Note that matlab code is often more efficient if you vectorize it instead of using loops (this is less true than it used to be). For example, if in your loop you're just grabbing the first value in every row of a matrix, instead of looping you can do:
yourValues = theMatrix(:,1)
Where the solo : operator indicates "every possible value for this index". If you're just starting out in matlab it is definitely worthwhile to read up on matrix indexing in matlab (among other topics).
Build the list as you go:
for i = 1:whatever
' pick out theValue
yourList(i) = theValue
end
I'm assuming that you pick out one element per loop iteration. If not, just maintain a counter and use that instead of i.
Also, I'm not assuming you're pulling out your elements from the same position in your array each time through the loop. If you're doing that, then look into Donnie's suggestion.
In MATLAB, you can always perform a loop operation. But the recommended "MATLAB" way is to avoid looping:
Suppose you want to get the subset of array items
destArray = [];
for k=1:numel(sourceArray)
if isGoodMatch(sourceArray(k))
destArray = [destArray, sourceArray(k)]; % This will create a warning about resizing
end
end
You perform the same task without looping:
matches = arrayfun(#(a) isGoodMatch(a), sourceArray); % returns a vector of bools
destArray = sourceArray(matches);