I am trying to model a production line where the workstation has only 1 max capacity. I used "Service" block to model seize-delay-release. However, since the resource is available to let more than one "agent" flow into this service block, it creates a mis-understanding. As shown below, the "Base 1" block has 2 agents - 1 at seize queue, 1 at delay which is wrong, should be just 1 at delay. How can I solve it as I can't put "zero" at Queue capacity.
enter image description here
Related
I have two variables in agent
handicap = RandonTrue(0.3)
priority.
The priority variable value set in source exit based on wither agent is handicap or not, as shown in the image below.
Now in the queue I set Queuing to priority base and set agent priority to agent.priority . Shown in image below.
Note: Queue capacity is set to 10.
Now when I run the model and 10 agents enter I the queue, according to the priority handicap agents should be on the top of the queue but that is not happening. shown in the image below.
When the agents enter the delay after the queue, I also print their priorities on the console. The result is still the same, no priority is followed.
In the above image it is clear that they are not sorted based on priority.
Why priority queue is not working?
Moreover, I also changed the Queuing to LIFO, queue showed the same result, showing zero effect on agents.
this happens because contrary to the intuitive idea that events happen in the order you see, they don't... Things occur in the following order:
agent is created with the default value for the priority value
on at exit action is executed
the queue priority value is checked for the queue
the on exit action is executed
So from the point of view of the queue, the priority for all agents is the same
Solution
Instead of setting the priority value "on exit" do it on the "on at exit" action of the source block
I currently have 2 different source blocks, 1 that sources agents for one half of the day, the other for the other half. Both converge into the same starting point of the model. I am only using 2 different sources to help simulate 2 different halves of the day.
I also have a resourcePool that increases in capacity from 1 to 2 at time() == 150. How can I ensure that the 1st resource unit that starts the day interacts only with those agents coming from source1, and the 2nd resource unit that arrives at time 150 only interacts with those agents coming from source2? Agents from both sources go through the same seize blocks that seize 1 unit each of 2 different resources at the same time.
There is a short overlap in which both resource units are working, so I want to ensure that one is not interacting with the other's agents.
You need to make use of the resource choice option inside a size block.
To do this start by having a new agent that will represent the resources inside your resource pool and give it a variable that you can use for assigning what source agents it will take. e.g. have an int variable sourceNumber
Now when you increase the number of resources in the resource pool from 1 to 2, you assign the source number of the second resource to 2.
resourcePool.set_capacity(2);
int counter = 0;
for (MyResource r:resourcePool) {
r.sourceNumber = counter;
}
If the agents that need to seize the resource all use the same seize blocks it is perhaps best to make a custom agent and send the seize block from which they came to the agent.
Then inside the source the resource choice field van be used to dictate the correct resource to use
If I have a condition where a resource pool reduces capacity from 2 to 1 at a certain time of the model OR when the unit interacts with a certain number of different agents, will the unit that is being removed from the model stop what it's doing and leave? Or will it finish all of it's queued tasks? I would like it to finish all of it's queued tasks.
My code for the condition is as follows where Surgeons is the resourcePool and seizedAgents is a collection inside the Surgeon agent type:
if( unit.seizedAgents.stream().distinct().count() >= 17 ) {
Surgeons.set_capacity(1);;
}
If the capacity is dynamically reduced by calling set_capacity(), and the number of currently seized units exceeds the new capacity, the extra units will only be disposed of after they are released. The rest immediately
Thus units busy with a task will be disposed of only after completing the current task
Check the help for more details.
In my AnyLogic simulation model, I have two sources and going through two service blocks in a closed loop. At starting time I inject 1 50T Truck and 2 20T Trucks.
Descriptive image here:
Image of Model
At the second service block, "crusher1", I want the queue to always prioritize the agent "truck50ts" over "truck20ts". How can this be done?
Replace your Service block with Seize, Queue, Delay and Release blocks (same as a Service but more options for you).
in the Queue properties, set the queue priority to "agent comparison".
In the conditional code, write agent1 instanceof Truck_50tons ? true : false as below:
This assumes your 50t truck is an agent of a custom agent type called Truck_50tons (create those at the sources)
I have a resource pool and a service block. The number of the operator in the resource pool is 5 which is linked to the service block. I would like to setup the service in a way that the more workers work on the service the delay time decreases. (ex: if 1 worker works the delay time is 10 min - if 2 workers work the delay time is 5 min. - if 3 workers work the delay time is 3.33 min). I would like up to 5 operators to be working at the same time in the service block based on their availability.
Service Block and Resource Pool
How can I achieve this?
So you're trying to do two things with your Service block:
Seize a dynamic number of units (in the simplest case, seize all available units).
Have the delay time dependent on the number of units seized (in the simplest case, just decreasing multiplicatively according to the number of resources).
For the former, assuming you're seizing from a single pool, just enter a dynamic expression in the "Number of units" property. In the simplest case (seize all available) it would just be pool.idle() (for a resource pool called pool) but that's problematic if the next agent arrives whilst the first is being processed (because it will be treated as needing zero resources) so, depending what you want, you might need to do something like put RestrictedAreaStart / End blocks around your Service block so only one agent can be in the Service block at once.
NB: AnyLogic currently has a bug/limitation that the resource pool's idle/busy counts (from its idle() and busy() functions) are not guaranteed to be correct unless you are at a later simulation time than when seizes/releases occurred. (This is due to how things are resolved in hidden events under-the-covers.) So, if you want to use them in your determination of the number of resources to seize you need to work round this; e.g., by
tracking the number of busy/idle units via your own counts;
using the isIdle() function on individual resources in the pool instead (which typically requires ensuring the resource pool agents are in a custom population, not the hidden default one, so you can explicitly reference/loop through them);
something horrible and hacky like adding a very-small-timeout Delay block before entering a Service block (possibly within RestrictedAreaStart / Ends to ensure that agents don't make it into the Delay, and hence the Service block's seize mechanism, until you want them to).
In general, it makes sense to put the resources-needed calculation in a function (which returns an int and takes the agent as an argument) which you call in the "Number of units" expression. That way you can make the calculation as complex as you like; it would seem you might need a more complex consideration than just "grab everyone" (e.g., perhaps depending on the stream of to-arrive agents if you have knowledge of them, etc.). Maybe, for example, you'd also want to hold your arriving agents in a Wait block beforehand and only release them when the number of resources you want are available. (You'd need to give more precise detail about your requirements to be any more definite here.)
For the variable delay time, have an appropriate dynamic expression for the delay time; you can use the resourceUnits() function to get a list of the resource units seized by your agent. So, in the simplest case (decreases multiplicatively according to the number of resources) it would be something like 10.0 / agent.resourceUnits().size() (for a base delay of 10 time units).