I want to make agents to not enter the queue if it's full (if it's full then go to sink) at the moment of arrival in selectOutput5.
I tried to put "if-else" into "Actions" section
But I don't really know which parameter to use (tried to use queue.size and queue.capacity but I don't know how to code this properly), please help. Not sure if I doing the right thing at all by trying to put if-else into actions of selectOutput5
The model look like this:
You need to code the conditions under which they should enter which queue and then if the conditions are not met it will assess the next out option.
See example below
It will only go to queue 1 if the queue size is less than 5, else it will assess the queue size of queue 2 and if both are full then go to the exit.
The Actions section is only for code you want to execute if they do exit one of the out options.
Put a selectOutputOut block, select conditions there. And type below your condition: yourQueue.size()>=yourQueue.capacity(). Send the ones to Sink block when this condition is true.
Related
is there any easy way to detect that agent stopped on a roller conveyor because there are other agents ahead? I tried to use dynamic variable and conditional event but it is consuming too much performence. I don´t want to go for dynamically checking condition (with cyclic event) because I have some bad experience with it.
Thanks!
Try this:
Create a LinkedList<YourAgentType> agentsOnConveyor.
Whenever an agent enters the conveyor, call agentsOnConveyor.addLast(agent). When it leaves, call agentsOnConveyor.removeFirst(agent).
Now you have a linked representation of the agents on the conveyor.
Last, you use the "on stopped" field in the conveyor and pass the message "upstream" through the linked list, i.e. use a for-loop from the first to the last entry and send them a msg "conveyor stopped".
You may still need to check if the individual agent is moving itself or has also stopped, but it might put you on a working path
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 have a queue,followed by selectoutput. the problem is that the agent does not go out from the queue.In this case the agent should choose the third exit of the selectoutput, so it is not possible (i presume) that the agent does not go out because the following block is full.What could be the reason? Thanks
the reason is that the condition that you think is true, is actually false, because anylogic calculates first the condition in the select output block, and then it runs the code on the "on exit" action of the queue7 block...
So my guess here, is that you are doing something on the on exit action, that changes the result for the condition.. but it's already too late..
use the "on at exit" action or sometimes you need to put a dummy delay of 1 milisecond or so between your last block before the selectoutput and the selectoutput to ensure your condition is met correctly
This is the order in which things happen:
on at exit queue
check condition
on exit queue
on enter select output
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 not sure if what I'm seeking is possible, but I'm just checking to make sure I'm not doing thing the hard way.
At the moment I have two sequences, which both run at the same time. Each sequence starts off by waiting 3 seconds and then one sequence scales a node, where the other adjusts that node's alpha. So the code looks something like this:
node.runAction(SKAction.sequence([animationWait, animationScale]))
node.runAction(SKAction.sequence([animationWait, animationAlpha]))
But is there a way of running both the animationScale and animationAlpha at the same time inside one sequence? So it will look something like this (this doesn't work, but I'm hoping you can see what I'm trying to do):
node.runAction(SKAction.sequence([animationWait, (animationScale, animationAlpha)]))
You can group actions together to a sequence:
var actions = Array<SKAction>()
actions.append(SKAction.sequence([animationWait, animationScale]))
actions.append(SKAction.sequence([animationWait, animationAlpha]))
let group = SKAction.group(actions)
node.runAction(group)
When the action executes, the actions that comprise the group all start immediately and run in parallel. The duration of the group action is the longest duration among the collection of actions. If an action in the group has a duration less than the group’s duration, the action completes, then idles until the group completes the remaining actions. This matters most when creating a repeating action that repeats a group.
I just tested something out, and it seemed to have worked. Instead of the below:
node.runAction(SKAction.sequence([animationWait, (animationScale, animationAlpha)]))
do:
node.runAction(SKAction.sequence([animationWait, [animationScale, animationAlpha]]))
I'm surprised it worked. I was going to delete the question, but someone might find this handy.
EDIT:
The below no longer works
node.runAction(SKAction.sequence([animationWait, [animationScale, animationAlpha]]))
As evilboxingdragonslayer suggested, you will need to use "group", see below:
node.runAction(SKAction.sequence([animationWait, group([animationScale, animationAlpha])]))