Break nested loop - matlab

I have three nested loop in Matlab and in each loop, I have an "if" that check a flag. If it was OK, the the algorithm proceeds, otherwise, I want that the program should be terminated. Here is my codes, I think something is wrong!
[A] = finction (...,...,...)
for i = 1:100
for j = 1:100
for k = 1:30
some operation which its results is a flag
if flag==1 % its initial value is 0
break
end;
end;
end;
end;
Where is should put that break in order I break the rest of the computations?

BREAK terminates the execution of a loop, so if you have a nested loop, break will only quit the innermost loop, and the program will continue running.
If you want the entire function to be terminated, you need to use RETURN. Please note that at the moment return is called, all the requested output arguments must be assigned to some value, otherwise the code will throw an error.

Related

Break statement in Matlab

For a certain number n I have to find the next greater number than n which is prime.
I had to solve this problem in Matlab.
Below is my code:
Solution1
function k = next_prime(n)
while n<10000000000
n=n+1;
if isprime(n)==true
k=n;
break
end
end
end
In this way the problem is correctly solved, but my initial solution was:
Solution2
function k = next_prime(n)
while n<10000000000
n=n+1;
if isprime(n)==true
k=n;
end
break
end
end
The only difference between Solution1 vs Solution2 is the break statement place.
Why Solution1 is ok and Solution2 is not ok?
The break statement in MATLAB
terminates the execution of a for or while loop. Statements in the loop after the break statement do not execute.
In solution 2 you are guaranteed to break at every loop iteration, not only if it is prime. Thus it will always only run the loop once, set n to n+1 and then break without setting k (unless coincidentally n+1 was prime).
It might help you to see it if you fix your indentation:
function k = next_prime(n)
while n<10000000000
n=n+1;
if isprime(n)==true
k=n;
end
break
end
end
so the loop does 3 things, it increments n, it checks if n is prime and then it exits, always.
In solution 1, you only exit if n is prime, which is obviously what you want.

Check if only once

In a MATLAB-function the following code is used:
function stuff()
if a == 2
do1();
else
do2();
end
end
This code is placed inside a simulation-loop and gets called 1000 times or more per second. The if-statement does only matter in the first call of the function, after that either do1 or do2 are used, the variable a will not change any more.
How do I prevent to waste processing time with this if-statement? Basically, how do I tell Matlab, to not check the if-statement any more, and just call the one function, that gets selected in the first call to stuff?
Contrary to your beliefs this is not a problem, the compiler (should) automatically does this optimization for you. See e.g. Loop-invariant code motion.
What you can do to help the compiler is to move the calculation of the check outside as a flag, e.g.
flag = a==2;
for i = 1:100
stuff(flag)
end
Then you only have to do the calculation once and it is clear to the compiler that the value does not change.
NOTE: Obviously, if your check really is a==2, this would not make much of a difference.
EDIT: I have not been able to definitely verify that MATLAB does this automatically. However, this is only the first layer of optimization that is done for you. All modern processors use what is called a Branch predictor, see e.g. this brilliant answer Why is processing a sorted array faster than processing an unsorted array?, or this wiki page. In short, the processor guesses the result of the if-statement, if it is correct, everything goes faster. I think it is fair to say that the processor guesses correctly in all of your cases.
TLDR: Do not wory about it.
Given the comments above, it seems what you are actually looking for is a way to dynamically chose the function to be run in your simulation. This choice should be dynamic (you do not know which function to use at runtime) but the choice should only be done once. This is easily achievable using function handles: https://www.mathworks.com/help/matlab/function-handles.html
Here is an example:
function dynamicSimulation()
if ( rand() > 0.5 ) % determine which function should be called dynamically
sim=#func1;
else
sim=#func2;
end
other_params = [];
for k = 1:5 % run the simulation
sim( k, other_params );
end
end
function func1( index, other_params )
fprintf( 'Index=%d: Simulating using function 1\n', index );
end
function func2( index, other_params )
fprintf( 'Index=%d: Simulating using function 2\n', index );
end
If you run this several times you will notice that the (random) choice of func1 or func2 will mean you do not get the same function being run each time, although the same one is used for the entire simulation.
I reckon you don't waste much time on checking the validity that if statement. However, since you specifically mention it only checks for the first iteration: why not get that out? So instead of:
for ii = 1:10
if ii == 1
k = 1;
else
k = k + 1;
end
end
You could do
k = 1;
for ii = 2:10
k = k + 1;
end
Thus eliminating the check.
NB: this scales badly of course, but as it is only a single iteration here I consider it a good option.

Too many input arguments error

I am trying to run my function. it shows
[root, ni]=value1(xu,xl,acceptable)
Error using value1
Too many input arguments.
function[root, ni]=value1(xu,xl,acceptable)
fu=HW10B(xu);
fl=HW10B(xl);
Err=1;
N=0;
if fu*fl>=0
end
while Err>=acceptable;
m=(xu+xl)/2;
fm=HW10B(m)
if fm*fu<0;
fl=m;
else fu=m;
Err=abs(xu-xl)/xu*100;
end
N=N+1;
end
function [ y] = HW10B( x)
%equation of x
y=3*x^3-8*x^2-4*x+9;
end
root=m;
ni=N;
end
function[m, N]=value1(xu,xl,acceptable)
y=#(x)3*x.^3-8.*x.^2-4.*x+9;%//Used anonymous function instead of private
fu=y(xu);%//Used above definition
fl=y(xl);
Err=1;%//Initialise error
N=0;%//Initialise counter
while Err>=acceptable && N<1e4;%//check for convergence
m=(fu+fl)/2;%//Get new midpoint
fm=y(m);%//Get value at midpoint
if fm*fu<0;%//Get left or right value to move
fl=m;
else
fu=m;
Err=abs(fu-fl)/fu*100;%//Calculate the error
end
N=N+1;%//Update iteration counter
end
end
Call it from the command line:
xu=15;xl=2;acceptable=1e-3;
[root, ni]=value1(xu,xl,acceptable)
root =
2.7554
ni =
29
As you can see I cleaned up your code quite a bit. Using the two separate storage variables at the end of the code was just taking up more space than necessary. The if statement fu*fl>0 did not do anything, thus I chucked it out. Finally, you needed to update your values in your functions, thus using the fl, fx and fm, not the xu and xl.
If you call the function exactly as I showed you from the command line (with your own values of course), it should not throw any errors.
What happens in your original code is that you calculate everything once for the input variables, get an error which is larger than acceptable and therefore executes again, taking the same input arguments, returning the same error as before, which is still larger than acceptable. This is what we call an infinite loop. I suggest you check for it using a maximum number of iterations, i.e.
while Err>=acceptable && N<1e4
and change the 1e4 to whatever maximum number of iterations you want to have. If you accidentally end up going infinite, this counter will kill it without having to resort to crtl-c or equivalents.

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.

Assignment has more non-singleton rhs dimensions than non-singleton subscripts error in matlab

U can see a part of my code in MATLAB. when i run it, i receive this error:
Assignment has more non-singleton rhs dimensions than non-singleton
subscripts.
please help me to correct it and know it's reasons. tnx a lot.
while Time < t_stop
for i4 = 1:x
for j4 = 1:y
for k4 = 1:z
% t1 has been defined in another place and updates in every cycle
t2 = find(t1 ~= -1); %t2 is not empty because t1 has non-(-1) elements
t3 = zeros(1,numel(t2));
for i5 = 1:numel(t2)
t3(i5) = t1(t2(i5));
end;
var1 = min(t3(:));
min_time(i4,j4,k4) = var1;
if numel(find(t1 == var1)) == 1
min_IND (i4,j4,k4) = find(t1 == var1);
else
Temp_find = find(t1 == var1);
min_IND (i4,j4,k4) = Temp_find(randi(numel(find(t1 == var1))));
end;
t1 = zeros(1,41)-1;
end;
end;
end;
Time=Time+1;
end;
Why is your error happening?
This is due to the fact that your t2 = find(t1 ~= -1) statement returns an empty array. This means that your t1 array does not have any entries that are not equal to -1. As you start going down into your code, t3 = zeros(1,numel(t2)) will create an empty matrix as the number of elements in t2 are 0 due to the find call from earlier.
Next, when you get to this statement:
for i5 = 1:numel(t2)
t3(i5) = t1(t2(i5));
end
This for loop does not execute as the number of elements in t2 equals 0. When you get to this statement after:
var1 = min(t3(:));
var1 will also give you an empty matrix. Finally, when you get to this statement:
min_time(i4,j4,k4) = var1;
You are trying to assign an empty value into a location in min_time. Specifically, you are trying to assign one value to a location in min_time which should be stored in var1, but because it's empty, this is why you are getting this error. As such, you need to double check your t2 variable to ensure that this isn't empty before you proceed with your code.
So where is the error happening?
I can see why you are getting this error, and where this is happening. If you look towards the end of your code, you have this statement:
t1 = zeros(1,41)-1;
What you are doing is you are making t1 such that the entries are all -1. When you go back into the next iteration of your loop, the t2 = find(t1 ~= -1) statement will return an empty array as all values of t1 are equal to -1. Because find could not find any values that are not equal to -1, find returns an empty array stating that it could not find any locations in t1 that were not equal to -1. This is probably not what you intended to do.
Your comment states that t1 is being set outside of the for loops before your code is executed. Though that may be the case, you are changing t1 after the first iteration of your for loops, which will inevitably give you that error you are seeing.
As such, you probably need to correct this statement - either by removing it, or modifying it so that it is the definition that you are seeking.
Some tips for you
It really helps if you debug your code so that you can figure out what's going on. As such, MATLAB has some great facilities to help you debug your code so you can figure out why it isn't working. You need to set MATLAB to debug mode if you'd like to do this. If this is something you want, in your MATLAB editor, go to the line where you see the t2 = find(t1 ~= -1); statement, and click on the horizontal dash beside the line number. You'll see a red dot indicating that when the function runs, the function will pause at this point.
In debug mode, you are able to see what the current state of execution your code is in. You can also examine what the variables look like, as well as step through line by line after this point so you can see what each line is doing. You can either type in dbstep when you're in debug mode to go to the next line, or you can do this in your MATLAB editor by clicking on the Step buttons. There are also different buttons you can choose from:
Continue - Continue running your code until you reach the next breakpoint or the function exits
Step - Run the next line of code
Step In - Run the next line of code. If this line is a function, then you will go inside the function and be able to debug the statements within there. If you just do Step, it runs the function, but doesn't go inside. As such, this runs the entire function before pausing at the next line.
Step Out - If you are inside a function, doing this will run the code until the function leaves. The code will then pause right after the point where you leave the function and you continue from there.
For more information on MATLAB debugging, check out this great MathWorks link here: http://www.mathworks.com/help/matlab/matlab_prog/debugging-process-and-features.html#brqxeeu-178