MATLAB - Count if for loop conditions are true - matlab

I have this problem about counting how many times the condition is true in for loop while using a timer object. so I set my timer object calling this function every 60 secs and it will check my condition in the database if X and Z are equal to 1, then it will do something. The problem is that I want it to count every time X and Z are both equal to 1 because I have another program changing values of X and Z every sec. If the count is equal to 1, 2, and 3 it will do differently. When I run it, it doesnt go more than 1 even though X and Z are equal to 1 for many times. Below are my code
a = timer('ExecutionMode', 'fixedRate','TimerFcn', 'func(1)', 'Period', 60);
start(a);
function [x] = func(y)
count = 0;
if x == y && z == y
count = count +1;
if count == 1
disp('1')
elseif count == 2
disp('2')
elseif count == 3
disp('3')
end
else
disp('same')
end

Your main problem is the count variable has function-local scope, so it's created every time the function is called and destroyed when the function ends. You need it to persist between calls the the function. One possibility is to make the count variable a global:
global count;
count = 0;
a = timer('ExecutionMode', 'fixedRate','TimerFcn', 'func(1)', 'Period', 60);
start(a);
function func(y)
global count;
if x == y && z == y
count = count + 1;
disp(num2str(count));
else
disp('same');
end
This code also replaces the if structure that made the various disp calls with a single call to disp. If your intention is to print out the count, this is a better method.

You are not closing the first if statement with an end. Therefore, if count == 1 and everything that follows is only executed when x== y && z == y
Close your first if statement and your code should work:
if x == y && z == y
count = count +1;
end
if count == 1
...
Note also that as you have written your code, you have count reset to 0 every time you enter the function, which means that count=count+1; will always be count = 0 + 1 = 1;

If you want to count how many times you get into a function, you must make the counter variable persistent, otherwise it will be set to zero in every call.

Related

Change while loops based on intervals defined by vector

Inside my code I currently have 2 while loops looking like this:
sequence = [15 35 50];
startStamp = GetSecs %GetSecs is a psychtoolbox function that returns the current time in seconds
while GetSecs - startStamp < sequence(1) || (GetSecs - startStamp >= sequence(2) && GetSecs - startStamp <= sequence(3))
cond1 %display stimulus 1
end
while GetSecs - startStamp >= sequence(1) && GetSecs - startStamp < sequence(2)
cond2 %display stimulus 2
end
Whenever the timer (GetSecs - startStamp) reaches one of the elements of sequence I want to go from one while loop into the other and then execute it until the next element of sequence is reached, switch loops and so forth...
The way I structured my conditional statements for entering the while loops is not very slim but it becomes exponentially worse as numel(sequence) increases.
Is there a way to do this more elegantly and to work with a variable length of seqeunce?
For variable length of array sequence, you can use one big while loop for looping through elements of the sequence array, and place flag inside the loop that will tell you which condition to use.
Translated to code:
counter = 1; flag = true;
while(counter <= length(sequence))
while(GetSecs - startStamp < sequence(counter))
if flag
cond1;
else
cond2;
end
end
flag = ~flag;
counter = counter + 1 ;
end
sequence = [15 35 50];
startStamp = GetSecs %GetSecs is a psychtoolbox function that returns the current time in seconds
while (Getsecs - startStamp) < sequence(end)
for i=1:length(sequence)
if (Getsecs-startStamp) < sequence(i)
break
end
end
if mod(i,2) == 1
cond1
else
cond2
end
end

Terminate recursion after reaching certain condition

I've been experimenting with a Sudoku solver using recursion. The problem I've encountered it that the recursive function after finding the right solution will not terminate, but goes on until every number is tested at every position.
How do I terminate such loop in Matlab? Error condition 'error('...') within the function can break the execution, but is by no means a good solution to my problem.
Here is a sample code for similar recursion, producing all possible 2 element vectors for numbers from 1 to 4. I would like it to stop when both numbers are equal to 2.
%possible moves at each position
moveMat = zeros([1,2])+3;
lineInput = zeros([1,2]);
%start recursion
recurNumbers(moveMat, 0, lineInput)
function recurNumbers(moveMat, position, lineVariable)
position = position + 1;
%if all numbers are equal to 2 then try to exit the function
if ~all(lineVariable == 2)
%if all numbers are not equal to 2, try other combination
if position < length(lineVariable)+1
for move = 0 : moveMat(position)
moveMat(position) = move;
lineVariable(position) = lineVariable(position) + 1;
recurNumbers(moveMat,position,lineVariable)
disp(lineVariable)
end
end
else
disp(lineVariable)
return
end
end
Now it will print the vector '[2 2]' twice, which indicates that it recognised the condition, but the 'return' will not do what I imagined it to do.
Although it is not very clear to me what you are trying to achieve, I assume that the following function meets your stopping criterion.
function exit_fl = recurNumbers(moveMat, position, lineVariable)
exit_fl = 0;
if (all(lineVariable == 2))
% Show the result and exit
disp(lineVariable)
exit_fl = 1;
else
position = position + 1;
%if all numbers are not equal to 2, try other combination
if position < length(lineVariable)+1
for move = 0 : moveMat(position)
moveMat(position) = move;
lineVariable(position) = lineVariable(position) + 1;
% Receive the exit status of your function
ex_fl = recurNumbers(moveMat,position,lineVariable);
if (ex_fl == 1)
% If the criterion was met, then stop
exit_fl = 1;
return
end
end
end
end
end

Matlab symbols used to terminate the loop

I am new to matlab and I have couple of questions about it. First one, "Your function should terminate the sequence when either the value of ... or..." I use || in the code but it does not work as expected while && gives me the correct answer. Second question, how could the code be to display only the final answer?
Problem: calculate X which is represented by the sequence below
X = 1 - 1/2^2 + 1/3^2 - 1/4^2 +....
Requirement: Your function should terminate the sequence when either the value of 1/k^2 is less than 0.0001 or k is equal to k_max.
input k
Initialize x = 0
for loop i from 1 to k
if 1/i^2<0.0001 && i >= 100
break
end
Calculate X = (-1)^(i+1)./i^2 + X
end
You can use the break function as follows, where END_CONDITION is the condition you want to end your loop in.
if END_CONDITION
disp(X);
break;
end
To display the final answer, you can use the disp function. Eg. if your variable you want to print is called A then you use the following code.
disp(A)
Collectively this is your code. Since k_max terminates at the end of the for loop, we don't have to add any conditions to break out of the loop.
X = 0;
for i = 1:k
if 1/i^2<0.0001 || i==100
break;
end
X = (-1)^(i+1)./i^2 + X;
end
disp(X);

Exit loop at the end of current iteration step if condition is fulfilled

A common problem I have is the following:
Within a loop (usually a for loop) some constraints are - and have to be - checked at the beginning. Now sometimes if a condition if fulfilled, the code within the loop should run to the end of the current iteration step and then quit.
Usually I'd do it somehow like so
a = 0;
quit = 0;
for i = 1:1:11
if (a == 5) % Condition to be checked *before* the calculation
quit = 1; % Stop loop after this iteration
end
a = a + 1; % Calculation
...
if (quit == 1)
break;
end
end
But in a tight loop already this extra condition checking if (quit == 1) might give a relevant slow down. Also one needs to introduce an extra variable so I wonder how this is usually done or if there is a better way to do it...
why not do this way.
for i = 1:1:11
if (a == 5) % Condition to be checked *before* the calculation
func() --> do all the calculations
break; % Stop loop after this iteration
else
func() --> do all calculations
end
end
function func()
a = a+1
//all other calculations
end
Normally you can detect when to stop iterating. But if I understand your question, you can only detect when it should be the last iteration. You could try this:
a = 0;
i = 1;
while (i<=11)
if (a == 5)
i = 12; % Make sure this is the last iteration
else
i = i + 1;
end
a = a + 1;
end
What about:
for i = 1:11
quit = (a==5); % Condition to be checked *before* the calculation
a = a+1
if quit
break; % Stop loop after this iteration
end
end
Makes any difference?
- Make an infinite loop with logical variable condition set to 1
- Within the loop when stopping loop criteria rises set the logical
variable condition to 0
- loop will no longer run
count = 0;
stop = 11;
condition = 1;
while condition
count = count + 1;
--> do all the calculations before checking
condition = ~(a == 5 || count == stop);
--> do all the remaining calculations then exit from the loop
end
The while loop is enough
a = 0;
quit = 0;
while (a <= 5)
a++; % Calculation
...
end

Identifying a flag set and printing a message in Matlab

Hi all I am working on checking for certain cases in a large loop, with in this large loop is this statement:
%Center Dialouge
timers_c = [start_dpc_sh_hi_timer_c, start_dpc_sh_lo_timer_c, start_ffm_sh_act_hi_timer_c,...
start_ffm_sh_act_lo_timer_c, start_hpot_eff_loss_timer_c, start_lfpt_dpsh_timer_c,...
start_pc_sh_time_c, start_post_tl_nl_c, start_pre_tl_nl_c, start_elec_lu_timer_c];
if perf_case_c ~= -1
for k = 1:10
if iscellstr(timers_c(k)) == 1
perf_case_timer_c = timers_c{k};
timer_set_c = 1;
end
end
end
To I identify the start time and the case type to be output in a dialogue message:
if timer_set_c == 1
pcase_c = msgbox([sprintf('%s'),perf_case_c,sprintf('\nMET:%s\n'),perf_case_timer_c],'PERFORMANCE CASE');
end
I can't get the if statement that determines which case has been determined to work. I am trying to use the change from -1 to a string somehow, but it doesn't quite work.
A minimal example would be
%Assume all timers initialized as zero
%Assume case ~= -1 (is a char array, string
timers_c = [timer1, timer2, timer3 ]
if case ~= -1
for k = 1:3
if iscellstr(timer_c(k)) ==1
case_time = timers(c{k});
time_set_flag = 1
end
end
end
...
and then outside of the loop would be the above msgbox