How can I execute two functions with a time delay between the two calls?
16 次查看(过去 30 天)
显示 更早的评论
I have the following script:
[G_d,G_o, isolated,active,phi] = Single_CF_initial(G,50,1,0.2);
for tt = 2:25
if isolated(tt-1)- isolated(tt)==0
break
end
[G_d, isolated,Needremove] = Single_CF_Stages(G_d,phi,isolated,active);
[G_r,isolated] = H(G_d, G_o,0.95,isolated);
G_d = G_r;
end
I want to call the function "H" after some time of calling both functions "Single_CF_initial" and "Single_CF_Stages". Let us say after 15 seconds.
Is it possible to accomplish this in MATLAB?
Thanks!
采纳的回答
Adam Danz
2021-6-8
If you want execution to stay "busy" during the 15 sec wait time, use a simple tic/toc evaluation. It's not clear which of the two functions are invoked second or if that's subject to change, but the second one should set the start time using ts=tic; and then enter a while-loop until toc(ts)>=15 after which the H function can be called (I'm hoping that's just a paceholder for the actual function name). Note that the wait period could be placed at the end of the second function or outside of the functions after the second one is called.
If you want Matlab's busy state to be 'ready' during the 15 sec wait time, a much more efficient method would be to use a timer. The timer can be created any time before the functions are called and will have a start delay of 15 sec. After the second function is called you can merely start the timer and it will execute its callback function after 15 sec. See Timer Callback Functions. See this answer for an example of using a timer that sets a variable value 3 minutes after an app is started.
If you get stuck, share your updated code and let us know where you are at and what the problem is.
21 个评论
Adam Danz
2021-6-8
编辑:Adam Danz
2021-6-8
Notes on precision of timing methods
All of Matlab's timing methods face precision limts but some are more variable than others (see documentation). For example, the pause() function is susceptible to variations due to your OS and concurrent system activity (see documentation). I explain limitations to tic/toc and the timeit functions in this answer. If you choose to use tic/toc you can optimize the method by following the advice in this answer.
To demonstrate, below is comparison of 11 iterations of pause(1) compared to 11 iterations of a while-loop waiting for 1-sec using tic/toc. The first iteration was removed for each comparison and I subtracted 1-second to display the error of each funciton (along with some unavoidable overhead). Variation between iterations has many sources incuding the JIT compiler method used in Matlab. tic/toc has less error than pause for this duration. However, pause is easier to implement and its error is still reasonable for most usecases.
clear
drawnow; pause(.5)
tt = zeros(1,11);
for i = 1:11
t = tic();
pause(1)
tt(i) = toc(t);
end
drawnow; pause(.5)
tt2 = zeros(1,11);
for i = 1:11
t = tic();
while toc(t)<1
% do nothing
end
tt2(i) = toc(t);
end
drawnow; pause(.5)
stem(2:11, tt(2:end)-1, 'b','DisplayName','pause')
hold on
stem(2:11, tt2(2:end)-1, 'r', 'DisplayName','TicTocLoop')
legend
xlabel('Iteration')
ylabel('error (sec)')
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/646550/image.png)
Waseem AL Aqqad
2021-6-10
Hi Adam,
I'm sorry for my late reply. I just needed some time to understand the timer object, and also to make sure that what I want to accomplish is something realistic. The two functions "Single_CF_initial" and "Single_CF_Stages" emulate the cascading failure of routers in a network, and then I plot the number of failed routers per unit of time as figure 1 'attached'. The function H (Healing) recovers the failed routers. One of the inputs of H depends on the output of first two functions. Figure 2 is what I got when I called H from out of the while loop. Figure 3 is what I got when I called H from inside the while loop.
When I used both pause and timer object I got exactly the same figures (2 and 3). Based on the hypothesis that I buit, I supposed that I will get something similar to figure 1 but the curve should maintain the steady state at a value much lower than 2000( maximum no. of routers).
This is what I did:
[G_dmg,G_orig, isolated,active,phi] = Single_CF_initial(G,3,0,0.2);
for tt = 2:30
if isolated(tt-1)- isolated(tt)==0
break
end
[G_dmg, isolated,Needremove] = Single_CF_Stages(G_dmg,phi,isolated,active);
t = timer('Name','t','ExecutionMode','singleShot', ...
'ObjectVisibility','off','StartDelay',15);
t.TimerFcn = @(t,Healing)disp('Hello World!');
[G_rec,isolated] = Healing(G_dmg, G_orig,.1,isolated);
G_dmg = G_rec;
end
figure
plot(1:length(isolated(1:end)),isolated(1:end)); hold on
title('Cascading Failure - Small World (Nodes=5000)');
xlabel('Time')
ylabel('No. of Isolated Nodes Per Unit Of Time')
I downloaded your demo "timerDemo.mlapp" but unfortunately, it didn't load when I opened it. So, I feel that I didn't fully understand timer object. To be honest with you, I got lost when I read the documentations.
Thanks.
Adam Danz
2021-6-10
编辑:Adam Danz
2021-6-10
I'm starting to have doubt that timers should be used for this problem. I think we're looking at an "xy problem" where we're solving problems caused by an inefficient solution rather than rethinking the solution.
Please explain the workflow and when H needs to be called.
Why is it time dependent?
Waseem AL Aqqad
2021-6-10
编辑:Waseem AL Aqqad
2021-6-12
Thanks for bringing my attention to this point. I debugged H again and I found that it is time independent. It recovered 60% of the entirly collapsed network in one step. Whereas for the CF (Cascading failure) functions, they have a domino effect, that is, I attack, say, two routers and then the failure propagates to other routers ( Time steps or stages).
Thank you so much for the time and effort you put in answering my question.
Adam Danz
2021-6-11
So does that mean the problem is solved?
I still wonder how Healing() is called after or during the attack propagation. Does there needs to be a time delay to start Healing() or a time delay within the Healing function?
Waseem AL Aqqad
2021-6-11
No it’s not solved. I just wanted to give you a more explanation of what Healing function is doing. I want to call it during the attack propagation and add a time delay to start Healing () and then a time delay within the Healing function and compare the two results.
Waseem AL Aqqad
2021-6-11
Great. G_orig is generated before the attack starts and G_dmg is continually updated during the attack.
Adam Danz
2021-6-11
编辑:Adam Danz
2021-6-11
Let's check if I got this right.
It starts by you simulating a network attack.
The router failures propagate to other routers in a domino effect
You want the Healing function to start 15 seconds after the start of the attack. The 2nd and 3rd inputs are available from the beginning of the simulation but the 1st input is continually updated during the simulation.
A timer function is almost perfect to solve this except that you need to access the current value of G_dmg. If you're doing this in an app or GUI or any type of figure, that problem can be solved by declaring G_dmg as a property of the app/figure; is that the case (we're avoiding global variables)?
But perhaps a timer could be avoided and the could be ever simpler. What controls the propagation? Is it done in a loop? If so, it would be easy and efficient to use tic/toc to control when healing begins by iteratively checking the time within the loop (assuming the loop iterates quickly). Is that the case? If propagation is not done in a loop, could you describe how that works?
Waseem AL Aqqad
2021-6-11
编辑:Waseem AL Aqqad
2021-6-11
Correct.
I'm not using an app or GUI. So, after generating the network, the propagation starts by choosing a no. of routers randomly, say two, and remove all their links (Stage 0) and this is done in function Single_CF_initial. The output of this function is passed as an input argument to function Single_CF_Stages, this function is composed of exactly 12 lines where it just compares the current no. of links of all other routers to a breakdown threshold and remove links of the routers that met the condition (gt the threshold) and this is Stage 1. After that I use a while loop in a script file as I showed earlier in my first comment to this answer. Please be noticed that the output of second function is passed as an input to it when it is called in the while loop to perform several stages.
[G_dmg,G_orig, isolated,active,phi] = Single_CF_initial(G,3,1,0.2);
t = 2;
while isolated(t-1)- isolated(t)~=0
[G_dmg, isolated,Needremove] = Single_CF_Stages(G_dmg,phi,isolated,active);
%[G_rec] = Healing(G_dmg, G_orig,.1);
%G_dmg = G_rec;
t = t+1;
end
EDIT: In my first comment I used a for loop cause I was trying to avoid an infinit loop when I call the healing funtion but the above script is the original one.
Adam Danz
2021-6-11
编辑:Adam Danz
2021-6-12
Ok, if I understand things correctly, here's how to start "Healing()" 15 sec after the entire process starts.
This assumes that the tt-loop runs fairly quickly and checks the run-time at the end of each loop. After the run-time meets or exceeds 15 sec, Healing() is called (on ever iteration thereafter).
DURATION = 15; % DELAY (sec) TO START HEALING()
START_TIME = tic(); % START TIME (PUT THIS WHERE THE 15-sec SHOULD START)
[G_dmg,G_orig, isolated,active,phi] = Single_CF_initial(G,3,0,0.2);
for tt = 2:30
if isolated(tt-1)- isolated(tt)==0
break
end
[G_dmg, isolated,Needremove] = Single_CF_Stages(G_dmg,phi,isolated,active);
% t = timer('Name','t','ExecutionMode','singleShot', ...
% 'ObjectVisibility','off','StartDelay',15);
if toc(START_TIME) >= DURATION % CHECK TIME
[G_rec,isolated] = Healing(G_dmg, G_orig,.1,isolated);
G_dmg = G_rec;
end
end
Waseem AL Aqqad
2021-6-11
Thank you so much, Adam. Much appreciated.
There is no use for the timer t here, correct? shall I comment it out?
I like to learn new things, so I would appreciate if you can send me a link to a useful documentation about app/GUI.
Waseem AL Aqqad
2021-6-11
编辑:Waseem AL Aqqad
2021-6-11
Can I consider the tt-loop iterations as time? As I'm plotting the number of damaged routers versus them. Or should the time axis (x-axis) be something else?
I think tt-loop iterations represent just the stages of the failure propagation, correct?
Adam Danz
2021-6-12
Oops, yes, comment-out the timer line (I'll fix it in my previous comment in a minute).
> Can I consider the tt-loop iterations as time
You can use the loop iterations instead of time if that's what you're asking. Just note that the speed of the iterations will always vary so if you want an actual temporal delay, don't use number of interations. If you want an interation-based delay, use the iterations.
> I think tt-loop iterations represent just the stages of the failure propagation, correct?
Yes. tt is just the number of times Single_CF_Stages has been called.
Waseem AL Aqqad
2021-6-12
Crystal clear.
But I wonder in case I want an actual time delay, what shall I use instead of no. of iterations?
Thank you again.
Adam Danz
2021-6-12
The tic/toc implementation in my previous comment is an actual time delay. Is there any part of it that isn't clear or not what you're looking for?
Waseem AL Aqqad
2021-6-12
Yes, I fully understand this implementation.
For plotting, I'm using the number of isolated or damaged routers vs. number of iterations:
plot(1:length(isolated(1:end)),isolated(1:end)); hold on
title('Cascading Failure - Small World (Nodes=2000)');
xlabel('Time')
ylabel('No. of Isolated Nodes')
But I want to use the real time calculated by tic/toc implementation as my x-axis based on what you told me earlier
"Just note that the speed of the iterations will always vary so if you want an actual temporal delay, don't use number of interations"
Adam Danz
2021-6-12
编辑:Adam Danz
2021-6-12
I understand now. Then you'll need to store the iteration time rather than just comparing the total time to 15 sec. This will affect the speed of the loop but not by much. Pre-allocating the storage variable will help to speed things up but if you're using a while-loop instead of a for-loop, you'll either need to guess the preallocation size or just avoid preallocation which will be slower.
Below are the changes to make (I removed other stuff)
CUMULATIVE_TIME = zeros(1,29); % since there are 29 loops
for tt = 2:30
% ...
% ...
% ...
CUMULATIVE_TIME(tt) = toc(START_TIME);
if CUMULATIVE_TIME(tt) >= DURATION % CHECK TIME
% ...
% ...
end
end
plot(CUMULATIVE_TIME, isolated) % no need for (1:end)
更多回答(1 个)
Gatech AE
2021-6-8
编辑:Gatech AE
2021-6-8
If you use the "pause" function, you can specify a time in seconds as the input. It does require integers and uses decimals as fractional seconds.
[G_d,G_o, isolated,active,phi] = Single_CF_initial(G,50,1,0.2);
waitTime = 15;
for tt = 2:25
if isolated(tt-1)- isolated(tt)==0
break
end
[G_d, isolated,Needremove] = Single_CF_Stages(G_d,phi,isolated,active);
pause(waitTime)
[G_r,isolated] = H(G_d, G_o,0.95,isolated);
G_d = G_r;
end
If you don't know how long you'll actually need to pause in advance, using "input" is another option that pauses execution until an input is provided.
1 个评论
Waseem AL Aqqad
2021-6-10
Hi Gatech,
Thanks for your reply.
The pause function didn't work out. I got the same exact plot.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Debugging and Analysis 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!发生错误
由于页面发生更改,无法完成操作。请重新加载页面以查看其更新后的状态。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
亚太
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)