My code has one condition:
if ticks = 10^7 [ do-something ]
Now this condition is checked on every ticks though I know exactly when I have to execute the command. This might be slowing my code. The time extension does exactly this by time:go command. My command using time extension is:
time:schedule-event patches task do-something 1000000
But this throwing an error:
Extension exception: Attempted to schedule an event for tick 999999.0 which is before the present 'moment' of 1000000.0
error while observer running TIME:SCHEDULE-EVENT
called by procedure GO
called by Button 'go'
Is there something I am missing? Or any other efficient way to schedule some event at specific tick without checking the ticks condition every tick?
If this looks like a bug in the time extension, please post it at https://github.com/colinsheppard/time/issues
and tell us where we can find your code. (Or email it to me.)
Related
The "Assembler" should stop working for 2 hours after 10 assemblies are done.
How can I achieve that?
There are so many ways to do this depending on what it means to stop working and what the implications are for the incoming parts.. but here's one option
create a resourcePool called Machine, this will be used along with the technicians:
on the "on exit" action of the assembler do this (I use 9 instead of 10 because the out.count() doesn't count until the agent is completely out, so when it counts 9, it means that you have produced 10)
if(self.out.count()==9){
machine.set_capacity(0);
create_MyDynamicEvent(2, HOUR);
}
In your dynamice event (that you have to create) you will add the following code:
machine.set_capacity(1);
A second option is to have a variable countAssembler count the number of items produced... then
on exit you write countAssembler++;
on enter delay you write the following:
if(countAssembler==10){
self.suspend(agent);
create_MyDynamicEvent(2, HOUR,agent);
}
on the dynamic event you write:
assembler.resume(agent);
Don't forget to add the parameter needed in the dynamic event:
Create a variable called countAssembler of type int. Increment this as agents pass through the assembler. Also create a variable called assemblerStopTime. You also record the assembler stop time with assemblerStopTime=time()
Place a selectOutputOut block before the and let them in if countAssembler value is less than 10. Otherwise send to a Wait block.
Now, to maintain the FIFO rule, in the first selectOutputOut condition, you need to check also if there is any agent in the wait block and if the current time - assemblerStopTime is greater than 2. If there is, you free it and send to the assembler with wait.free(0) function. And send the current agent to wait. You also need to reset the countAssembler to zero.
I would like to give the user a button that allows them to skip ahead 1 hour in the simulation and then continue running the model if play is clicked. The code below allows the user to skip ahead an hour, however they are unable to resume the simulation when play is clicked.
double nextHour = time() + 60;
pauseSimulation();
getEngine().runFast(nextHour); //Runs the model to the next hour when button is clicked
Any help much appreciated.
Try adding runSimulation() after the last line. But probably, that does not work. In that case:
Create a dynamic event (not the normal event) with the line runSimulation() in its action code.
In the button code, before the runFast... line, write create_MyDynamicEvent(1, HOUR). This will trigger the even 1 hour later and unpause the model.
AnyLogic Support suggested the following solution, which I have used:
Unfortunately, Ben's suggestion didn't didn't work; it seems to cause an issue when pauseSimulation() is used.
I'm trying to create an agent statechart where a transition should happen every day at 4 pm (except weekends).
I have already tried:
1. a conditional transition (condition: getHourOfDay() == 16)
2: A timeout transition that will "reinsert" my agent into the chart every 1 s and check if time = 16.
My code is still not running, does anyone have any idea how to solve it?
This is my statechart view. Customer is a single resource that is supposed to "get" the products out of my stock everyday at 4pm. It is supposed to happen in the "Active" state.
I have set a timeout transition (from Active-Active) that runs every 1s.
Inside my "Active" state in the "entrance action" i wrote my code to check if it is 4 pm and run my action if so.
I thought since i set a timeout transition it would check my condition every 1s, but apparently it is not working.
Your agent does not enter the Active state via an internal transition.
Redraw the transition to actually go out of the Active state and then enter it again as below:
Don't use condition-based transitions, for performance reasons. In your case, it also never triggers because it is only evaluated when something happens in the model. Incidentally, that is not the case at 4pm.
re your timeout approach: Why would you "reinsert" your agent into its own statechart? Not sure I understand...
Why not set up a schedule or event with your recurrence requirement and make it send a message to the statechart: stateChart.fireEvent("trigger!");. In your statechart, add a message-based transition that waits for this message. This will work.
Be careful to understand the difference between the Statechart.fireEvent() and the Statechart.receiveMessage() functions, though.
PS: and agree with Felipe: please start using SOF the way it is meant, i.e. also mark replies as solved. It helps us but also future users to quickly find solutions :-) cheers
I'm trying out some code that is supposed to block until moving to a new simulation time step (similar to waiting for sys.tick_start in e).
I tried writing a function that does this:
task wait_triggered();
event e;
`uvm_info("DBG", "Waiting trig", UVM_NONE)
-> e;
$display("e.triggered = ", e.triggered);
wait (!e.triggered);
`uvm_info("DBG", "Wait trig done", UVM_NONE)
endtask
The idea behind it is that I trigger some event, meaning that its triggered field is going to be 1 when control reaches the line with wait(!e.triggered). This line should unblock in the next time slot, when triggered is going to be cleared.
To test this out I added some other thread that consumes simulation time:
fork
wait_triggered();
begin
`uvm_info("DBG", "Doing stuff", UVM_NONE)
#1;
`uvm_info("DBG", "Did stuff", UVM_NONE)
end
join
#1;
$finish(1);
I see the messages Doing stuff and Did stuff, but Wait trig done never comes. The simulation also stops before reaching the finish(1). One simulator told me that this is because no further events have been scheduled.
All simulators exhibit the same behavior, so there must be something I'm missing. Could anyone explain what's going on?
The problem is with wait (!e.triggered); when e.triggered is changing from 1 to zero. It has to change in a region where nothing can be scheduled, so whether it changes at the end of the current time slot, or the beginning of the next time slot is unobservable. So the wait will hang waiting for the end of the current time slot, which never comes.
I think the closest thing to what you are looking for is #1step. This blocks for the smallest simulation precision time step. But I've got to believe there is a better way to code what you want without having to know if time is advancing.
I want to execute a function or a procedure or a block in regular intervals of 60seconds.
Do i have to use PS timer for that?
let this be my block
MyString = myEditor.Screen-Value.
Message MyString.
//myEditor is my Editor widget in the frame.
//My String is a string which i will use to display
I want to repeat this in each 60 seconds.. So that everytime it should display whatever I typed
inside the editor.? How can I do this with using PSTimer or without using it?
You must generate a Tick trigger block.
In this block can you write your code.
PSTimer has a property "Interval", which means interval for Tick event in miliseconds.
It has also other property "Enabled", witch starts and stopts timer.
When you run some longer code from your Tick event, schould be better switch that property "Enabled" on FALSE and on end of the trigger over on TRUE. Otherwise you can become a conflict with your code and new Tick event resp. your program will making never other, only showing runing your trigger script.