go back to previous if condition from an elseif in for loop

32 views (last 30 days)
Kitt
Kitt on 2 Dec 2025 at 19:41
Edited: dpb on 2 Dec 2025 at 22:27
I have a big long state-dependent model that is essentially a nevering set of if elseif conditions within a for loop.
Essentially what I want to do is:
opt = [1 2 3 1];
for t = 1:4
if opt(t) == 1
disp('ABC')
elseif opt(t) == 2
disp('DEF')
elseif opt(t) == 3
if rand() < 0.5
opt(t) == 1
else
opt(t) == 2
end
end
end
ABC
DEF
ans = logical
0
ABC
where, if this opt variable is 3, then there's a 50/50 it "turns" into 1 or 2 in the same time step and runs through those outcomes; this way I don't have to rewrite ABC and DEF (because those are really really long)

Answers (3)

Walter Roberson
Walter Roberson on 2 Dec 2025 at 21:24
You have received some good answers already, but I wanted to show you how to do what you actually asked for.
opt = [1 2 3 1];
for t = 1:4
while true
if opt(t) == 1
disp('ABC')
break
elseif opt(t) == 2
disp('DEF')
break
elseif opt(t) == 3
if rand() < 0.5
opt(t) = 1;
else
opt(t) = 2;
end
end
end
end
ABC
DEF DEF
ABC
That is, to repeat previous tests, wrap a while around the tests, and break from the while when you no longer want to loop.

dpb
dpb on 2 Dec 2025 at 19:55
Edited: dpb on 2 Dec 2025 at 20:38
opt = [1 2 3 1];
for t = 1:4
if opt(t) == 3
opt(t) = (rand()>=0.5)+1; % set state from 3
end
if opt(t) == 1
disp('ABC')
elseif opt(t) == 2
disp('DEF')
end
If the decision is truly random within the above contstruct with the loop as given, then it would be just as valid to do
opt = [1 2 3 1];
ix3=(opt==3);
opt(ix3)=(rand(1,numel(ix3))>=0.5)+1; % set state(3) is 50:50
for t = 1:4
if opt(t) == 1
disp('ABC')
elseif opt(t) == 2
disp('DEF')
end
Somehow this must not be quite the actual construct?

Steven Lord
Steven Lord on 2 Dec 2025 at 20:36
I would probably turn your disp calls (which I'm assuming are placeholders for what you're actually doing in those cases) into functions that can be called both in the case where opt(t) is 1 and in half the cases where opt(t) is 3. In this case, since those placeholders are short, I can just use anonymous functions. But these could just as easily be "named" functions (implemented as "function outputs = name(inputs), blah blah, end").
option1 = @(t) fprintf("Hello world! Case %d\n", t);
option2 = @(t) fprintf("Goodbye world! Case %d\n", t);
for trials = 1:10
opt = randi(3);
switch opt
case 1
option1(1)
case 2
option2(2)
otherwise
if randi(2) == 1
option1(3)
else
option2(3)
end
end
end
Hello world! Case 1
Goodbye world! Case 2
Hello world! Case 3
Goodbye world! Case 2 Goodbye world! Case 2
Goodbye world! Case 3 Goodbye world! Case 3
Hello world! Case 1 Hello world! Case 1 Hello world! Case 1
In the "Hello world! Case 3" cases, opt was 3 and then the "coin flip" turned up heads (randi(2) == 1). In the "Goodbye world! Case 3" cases opt was 3 and the coin flip was tails.
  2 Comments
Kitt
Kitt on 2 Dec 2025 at 21:21
I don't know how well I can turn all of 'ABC' into a function because it's a bunch more nested if statements with coin tosses of over 900 lines of code. Can that be easily turned into a function?
dpb
dpb on 2 Dec 2025 at 21:33
Edited: dpb on 2 Dec 2025 at 22:27
"how well I can turn all of 'ABC' into a function because it's a bunch more nested if statements with coin tosses of over 900 lines of code. Can that be easily turned into a function?"
If you're trying do this alll in a script, it'll never work as intended until and unless you do factor it into separate pieces.
Yes, anything can be turned into a function including your top level script that should just return the desired results to the workplace, not keep everything in the world public.
Look at https://www.mathworks.com/help/matlab/matlab_prog/share-data-between-workspaces.html that discusses scope and passing variables. Using nested functions can also allow you to have acess to global variables inside the functions so you can control individual loop indices, etc., but still operate on one piece of data although note that MATLAB will not create extra copies of arguments but use memory access to the location of the passed-in array so there's really no need to not pass what is needed.
We can illustrate a trivial code that shows the ideas-- if the following is in an m-file, say testit.m,, it will error -- in fact, we can try to run it here to see...
x=rand(5);
func1
Unrecognized function or variable 'x'.
Error in testit>func1 (line 8)
x(1:3,:)
Error in testit (line 2)
func2
return
function func1
disp('Func1')
x(1:3,:)
x(1,1)=pi;
end
function func2
disp('Func2')
x(1:3,:)
end
because the two local functions each have their own private workspace and don't know anything about the base workspace where the variable x lives.
OTOH, if we took the same code but enclosed it all in a function like
testit
Func1
ans = 3×5
0.2388 0.1377 0.0880 0.5657 0.5398 0.4936 0.3527 0.6460 0.3572 0.2075 0.2880 0.7001 0.1960 0.5999 0.2250
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Func2
ans = 3×5
3.1416 0.1377 0.0880 0.5657 0.5398 0.4936 0.3527 0.6460 0.3572 0.2075 0.2880 0.7001 0.1960 0.5999 0.2250
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
function testit
x=rand(5);
func1
func2
return
function func1
disp('Func1')
x(1:3,:)
x(1,1)=pi;
end
function func2
disp('Func2')
x(1:3,:)
end
end
we in fact see that the first functioin did change the first element in the x array to the value of pi; these now are internal functions and by being fully contained inside |function testit|, everything visible in it is visible inside each.
OTOH, if it were like
test2
Func1
ans = 3×5
0.3766 0.8001 0.0680 0.2755 0.6627 0.5545 0.3377 0.0259 0.9714 0.0668 0.2262 0.6714 0.7218 0.5508 0.6005
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Func2
Unrecognized function or variable 'x'.

Error in solution>func2 (line 51)
x(1:3,:)
^^^^^^^^
Error in solution>test2 (line 39)
func2
^^^^^
function test2
x=rand(5);
func1
func2
return
function func1
disp('Func1')
x(1:3,:)
x(1,1)=pi;
end
end
function func2
disp('Func2')
x(1:3,:)
end
then func1 is internal and func2 is local and can't see x again. It would need to be called as
function test2
x=rand(5);
func1
func2(x)
return
Sight unseen, I'd probably opt to start with wrapping your entire code in a function and then make the lines of your standin code internal functions initially. Then I'd almost immediately move each of those outside the main function and pass into them what they need from the main function at the top.

Sign in to comment.

Categories

Find more on Structures 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!