in a nested for loop, if statement: how to keep doing something until a condition is met

Dear all,
I have a 6x6 matrix of integers. In a for loop, for each entry in the matrix I grab a 3x3 submatrix and I randomly select an entry from the entire matrix. Then I want to see if the randomly selected entry is present in the submatrix as well. If it is, the original entry is replaced by the randomly selected entry. If not, I want to randomly select another entry and compare, keep doing this until I can find a randomly selected entry that is present in my submatrix and replace the original entry with it.
How would I write it so that if the first randomly selected entry is not present, I go back to randomly select another entry and repeat this process?
So far I have:
mat=[1 2 3 4 5 2; 3 4 5 1 1 1; 1 6 5 9 9 9; 1 3 4 1 3 1; 6 6 6 6 6 6; 1 9 9 2 3 4];
for ii=1:6 for jj=1:6 % going over each entry in the matrix
for x=-1:1; for y=-1:1; mat_sub(x+2,y+2) = mat(mod(ii+x,6)+1,mod(jj+y,6)+1); end end % grabbing a 3x3 submatrix with periodic boundaries
rand_idx = 1 + fix(rand(1,1)*6); rand_idy = 1 + fix(rand(1,1)*6); % generate a randomly selected indices
% check whether the randomly selected entry is present in the submatrix, % if it is then replace the old value with the new value.
if ismember(mat(rand_idx,rand_idy),mat_sub)==1 mat(ii,jj)=mat(rand_idx,rand_idy); else rand_idx = 1 + fix(rand(1,1)*6); rand_idy = 1 + fix(rand(1,1)*6); end end end
I'd need to write something after else, but I'm not sure how I'd do this. Any help is most appreciated.

 Accepted Answer

I am not sure that I really get what you want to do, but I guess that it is something around the following (which is dangerous, because you don't know how much time it will take to find this match that you are looking for):
Replace
rand_idx = 1 + fix(rand(1,1)*6);
rand_idy = 1 + fix(rand(1,1)*6);
if ismember(mat(rand_idx,rand_idy),mat_sub)==1
mat(ii,jj)= mat(rand_idx,rand_idy);
else
rand_idx = 1 + fix(rand(1,1)*6);
rand_idy = 1 + fix(rand(1,1)*6);
end
with
while true
rand_idx = 1 + fix(rand(1,1)*6) ;
rand_idy = 1 + fix(rand(1,1)*6) ;
if ismember(mat(rand_idx,rand_idy),mat_sub)
mat(ii,jj) = mat(rand_idx,rand_idy) ;
break ;
end
end
this way, the random indices generation and the test will go on until ISMEMBER return true, because in this case the BREAK breaks the loop.
Now if you really want to go for this kind of approach, you should implement some watchdog.. e.g.
wdog = 0 ;
while true
wdog = wdog + 1 ;
if wdog > 1000
error('Max iterations (1000) reached.') ;
end
... code given above ...
end

4 Comments

Thanks a lot for your help, but I don't really understand what you've done here. Can you help me understand it?
1) while true: is true just an arbitrary word or does this do something?
2) what does break do here? is it like if
ismember(mat(rand_idx,rand_idy),mat_sub) turns true, replace the old value and break the while loop, meaning now I'm on the next time iteration in my for loop?
I sort of understand what's going on, but I can't really see how this makes it so that the test and random indices generation go on until ismember turns true.
Your explanation for 2) is correct, and true and false are logicals (often noted 1 and 0). Type
doc true
in the command window to have more information. It is for example the class/type of the output of ISMEMBER (type doc ismember to see it). The statement:
while true
... do something.
end
is an infinite loop. There are two useful statements that we use in loops: break and continue. The first breaks the loop directly containing the statement when executed. We use it to escape loops before the upper bound is reached in FOR loops, and before the loop condition is false in WHILE loops.
One way to code "do something until a condition is true" is to implement an infinite loop and to break it when the condition is true. You might have understood better my example if I had built something like
flag_found = false ; % or 0.
while ~flag_found % or while flag_found == 0
...
if ismember(...)
mat(ii,jj) = ...
flag_found = true ; % or flag_found = 1
end
end
Now the solution based on the infinite loop and break allows us to avoid using the variable flag_found. The second statement is continue, which triggers the loop before the end statement at the end of the loop.
If it is still unclear, test this approach on a simpler case, e.g. for looping until a random number between 0 and 1 is above 0.9:
while true
x = rand()
if x > 0.9
break ;
end
end
Here you won't really see the interest, because the condition x > 0.9 could easily be implemented as a looping condition in the WHILE statement. Now when the condition has to be computed in several steps or when it is the outcome of a complicated computation, trying to implement it as a looping condition is sometimes cumbersome and and we prefer using an internal IF statement and a BREAK.
Thank you so much for your detailed explanations! It all makes sense now. :)

Sign in to comment.

More Answers (0)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!