While Loop and Logical Operators - matlab

I want to use an OR statement in my while loop so that the loop terminates whenever either of the two conditions aren't satisfied.
The conditions: (1) i must be less or equal to nmax, and (2) absolute value of R(i,i)-R(i-1,i-1) is less than specified delta
Here's my code (everything seems to work fine except for the while condition as the function executes until nmax is reached every time):
function [R] = romberg(f,a,b,delta,nmax)
R=zeros(nmax,nmax);
R(1,1)=(f(a)+f(b))*(b-a)/2;
i=2;
while i<nmax || abs(R(i,i)-R(i-1,i-1))<delta
m=2^(i-1);
R(i,1)=trapez(f,a,b,m);
for j=2:i
R(i,j)=R(i,j-1)+(R(i,j-1)-R(i-1,j-1))/(4^j-1);
end
i=i+1;
end
R

Try this. There were a few issues with the abs(R(i,i)-R(i-1,i-1)) condition for the while loop.
function [R] = romberg(f,a,b,delta,nmax)
R=zeros(nmax,nmax);
R(1,1)=(f(a)+f(b))*(b-a)/2;
i=2;
E=2*delta;
while i<nmax && E>delta
m=2^(i-1);
R(i,1)=trapez(f,a,b,m);
for j=2:i
R(i,j)=R(i,j-1)+(R(i,j-1)-R(i-1,j-1))/(4^j-1);
end
E=abs(R(i,i)-R(i-1,i-1));
i=i+1;
end

Related

How to jump to a particular place in the for loop if the if condition is satisfied?

I have some image files. I'm trying to perform some calculations using each file and if a certain condition is met, I'd like to go back to a particular line in the code and run it from there once more. But only just once again. Regardless of whether the if condition is satisfied or not satisfied the second time, I want to go to the next iteration. But, MATLAB doesn't seem to have a goto function and also, using goto implies bad programming so I thought I'd just iterate the for loop twice for a particular 'i' value which satisfies the if condition.
file = dir('*.jpg');
n = length(file);
for i = 1:n
*perform some operations on the 'i'th file*
if 'condition'
*run the for loop again for the 'i'th file instead of going to the 'i+1'th file*
i=i-1;
else
*go to next iteration*
end
end
I have tried to code this by changing the loop variable 'i' inside the loop to 'i-1' so that on the next iteration, the 'i'th loop will be repeated again but doing so is giving the wrong output, though I don't know if there is some other error in my code or if the changing of the loop variable internally is the cause of the problem. Any help on this is appreciated.
Replace the for loop with a while loop to have a bit more flexibility. The only difference is that you have to manually increment i, hence this also allows you to not increment i.
Given your new requirement, you can keep track of the number of attempts, and easily change this if needed:
file = dir('*.jpg');
n = length(file);
i = 1;
attempts = 1;
while i <= n
% perform code on i'th file
success = doSomething(); % set success true or false;
if success
% increment to go to next file
i = i + 1;
elseif ~success && attempts <= 2 % failed, but gave it only one try
% increment number of attempts, to prevent performing
attempts = attempts + 1;
else % failed, and max attempts reached, increment to go to next file
i = i + 1;
% reset number of attempts
attempts = 1;
end
end
Given the new requirement, added after rinkert's answer, the simplest approach becomes separating out code from your loop in a separate function:
function main_function
file = dir('*.jpg');
n = length(file);
for i = 1:n
some_operations(i);
if 'condition'
some_operations(i);
end
end
function some_operations(i)
% Here you can access file(i), since this function has access to the variables defined in main_function
*perform some operations on the 'i'th file*
end
end % This one is important, it makes some_operations part of main_function

How to restart a for loop iteration in MATLAB?

I am trying to force a for loop to restart if a condition is not stratified. I can do it with while since I want the loop to run for a certain number of iterations. I tried to set iter=iter-1 inside the if statement but it did not work. Any suggestions?
R=2*10^3;
lamda= 0.00001;
h=100;
a = 9.6117;
b = 0.1581;
for iter=1:10
M=poissrnd(lamda*R^2);
xx=R*rand(1,M);
yy=R*rand(1,M);
zz=ones(1,M)*h;
BS=[xx' yy' zz'];
user=[0,0, 0];
s=pdist2(BS(:,1:2),user(1,1:2));
anga=atand(h./s);
PL=1./(1+(a*exp(b*(a-anga))));
berRV=binornd(1,PL);
if berRV(1)==1
% do something
else
% repeat
end
end
You can accomplish this by using a while loop, with a comparison to whether the number of needed results have been identified. See the comment about saving your found values, as you hadn't specified what needs to be done when the condition you're searching for is satisfied.
R=2*10^3;
lamda= 0.00001;
h=100;
a = 9.6117;
b = 0.1581;
total_results_found = 0;
needed_results_found = 10;
while total_results_found < needed_results_found
M=poissrnd(lamda*R^2);
xx=R*rand(1,M);
yy=R*rand(1,M);
zz=ones(1,M)*h;
BS=[xx' yy' zz'];
user=[0,0, 0];
s=pdist2(BS(:,1:2),user(1,1:2));
anga=atand(h./s);
PL=1./(1+(a*exp(b*(a-anga))));
berRV=binornd(1,PL);
if berRV(1)==1
% save the result here
% iterate the counter
total_results_found = total_results_found + 1;
end
end
The simplest approach here would be with a while loop inside the for loop:
for iter=1:10
berRV(1) = 0
while berRV(1)~=1
% original loop code here
end
% do something
end
[Sadly, MATLAB does not have a do...while loop, it would make the above a little cleaner.]
While the other two solutions are perfectly valid, I wanted to give you another solution, which I think is the closest to the logic you provided in the question.
for iter=1:10
while 1
% loop code here
if berRV(1) == 1
break
end
end
end
The idea is similar to the one Cris presents, namely that you repeat the body of the for-loop until some condition is met. The difference lies solely in how you terminate the while loop,

Logical AND in a for loop

I want to add an additional condition in the for loop.
for(i=1; (i<100)&&(something>0.001) ; i++)
{
//do something
}
How can I implement this in MATLAB?
The following isn't working:
for (y = 1:pI_present_y) && (max_sim_value > threshold)
% do something
end
In a for loop, the number of iterations and the values that the loop variable will have in those iterations are selected as soon as it is executed the first time.
Since you want to check the condition on every iteration, you cannot use a for loop without introducing an if condition inside the loop. This is what already suggested by souty.
However, it would be better to use break once the condition is not satisfied. In this way it will be a true replica of the C code. Otherwise the loop will keep executing till y equals pI_present_y. The result will be same but there will be unnecessary iterations and the value of the loop variable will be different at the end of the loop. i.e.
for y = 1:pI_present_y-1 %Subtracting 1 because you have i<100 in the C code, not i<=100
if max_sim_value <= threshold
break;
end
%do something
end
If you want to use that condition in the loop statement, it is only possible with a while loop.
y=1;
while(y<pI_present_y && max_sim_value>threshold)
% do something
y=y+1;
end
Logical conditions are expressed in if statements
for (y = 1:pI_present_y)
if (max_sim_value > threshold)
% do something
end
end
If one of max_sim_value and threshold is a vector of length pI_present_y, index it with y in the if statement, i.e. max_sim_value(y) or threshold(y).

Smarter way to index loops in Matlab

I have written a function (call it F) that works "well" (i.e. gives me the result I want) and inside it I call the exact same function (call it G_i) four times (below one of them) except each time I change the way I index my loop to be able to cover all pairs of coefficients in a matrix. I think this method is poor and I would like to know if you have ideas to improve it please...
I do this to check sequentially conditions on the coefficients of a matrix (sometimes in the order (1,2) then (1,3) then (2,3). I go on checking in different orders).
function G_1=countbackward(a,,,)
n=a;
G_1=[];
N=1;
while N>0
for l=n:-1:1
for m=1:l
if some condition on generated matrices
...
elseif another condition on generated matrices
...
else
N=0 ;
end
G_1=[G_1,g_0] ;
end
end
end
(for n=3 I get with the above the entries: (3,1),(3,2),(2,1).)
Other indexing I use with the exact same body of the above function :
for l=n:-1:1
for m=(l-1):-1:1
Same for the following:
for l=1:n
for m=l+1:n
Same for the following:
for l=1:n
for m=n:-1:l
Thank you for your help.
APPENDIX:
below is a simplified example of my code:
function H=count2backward(a,g_0,s,e)
%matrix g_0 is the "start" matrix
%matrix g_K is the "end" matrix
n=a; % number of nodes in an undirected graph or size A
s=mypayoff(n,g_0);
e=mypayoff(n,g_K);
H=[];
N=1;
while N>0
for l=1:n
for m=n:-1:l
if l~=m && g_0(l,m)==0 && s(l)<=e(l) && s(m)<=e(m) && (s(l)<e(l) || s(m)<e(m) ) ;
g_0(l,m)=g_0(l,m)+1 ;
g_0(m,l)=g_0(m,l)+1 ;
g_0 ;
s=mypayoff(n,g_0);
elseif l~=m && g_0(l,m)==1 && (s(l)<e(l) || s(m)<e(m) ) ;
g_0(l,m)=g_0(l,m)-1 ;
g_0(m,l)=g_0(m,l)-1 ;
g_0 ;
s=mypayoff(n,g_0);
else
N=0;
end
H=[H,g_0] ;
end
end
end
You can generate the indexes and pass them as a parameter. That lets you abstract deciding how to loop into another function.
indexes = countbackwardpattern(a);
G_1=g_i(a, indexes);

continue statment not executing correctly within for loop+matlab

I have the following code:
for i=1:length(files)
for j=1:length(files(i,1).day)
if ((1:length(files(i,1).day(j).hour)) ~= 24)
continue
end
for h = 1:24
if ((1:length(files(i,1).day(j).hour(h).halfhour)) ~= 2)
continue
end
if isempty(1:length(files(i,1).day(j).hour))
continue
end
dayPSD = [];
for h2=1:2
dayPSD = [dayPSD; files(i,1).day(j).hour(h).halfhour(h2).data{8}'];
end
end
end
end
where
files=1x3 structure
files(i,1).day=1x335 structure that contains 1 field hour which is a 1x24 structure
files(i,1).day.hour=1x24 structure that contains 1 field halfhour which is a 1x2 structure
I am trying to loop through i and j, but when 1:length(files(i,1).day(j).hour) ~= 24 (so when the hours are less than 24) I would like to exit the loop and continue onto the next iteration of the for loop. I would also like it to exit the loop and continue onto the next iteration of the for loop if 1:length(files(i,1).day(j).hour(h).halfhour) ~= 2 (so when the half hours are less than 2) or if 1:length(files(i,1).day(j).hour is an empty cell (no data).
The current code I have written only seems to skip a loop index if 1:length(files(i,1).day(j).hour ~=24.
What am I doing wrong? Also how do I get it to continue onto the next iteration if any of those conditions are met? I've been banging my head on this for a while, and I know I'm probably making a simple mistake, but if anyone can point me in the right direction that would be great.
Thanks for your help in advance!
If I understand correctly, what you want is:
for i=1:length(files)
for j=1:length(files(i,1).day)
if ((1:length(files(i,1).day(j).hour)) ~= 24)
continue
end
for h = 1:24
if ((length(files(i,1).day(j).hour(h).halfhour)) ~= 2)
break
end
if isempty(files(i,1).day(j).hour)
break
end
dayPSD = [];
for h2=1:2
dayPSD = [dayPSD; files(i,1).day(j).hour(h).halfhour(h2).data{8}'];
end
end
end
end
so when either condition is met, the flow of execution will exit the for h=.. loop, and as there is no other statement in the for j=1... loop, the code will in effect skip that iteration.
Also note that if ((1:length(files(i,1).day(j).hour(h).halfhour)) ~= 2) is comparing a vector (1:length(..)) to a scalar 2 which results in a vector of booleans. The if part will only be executed if all its elements are true which is most likely never the case.