0
votes

enter image description here

Let me describe the situation above:

  • 20 agents injected at each soruce block.
  • Wait block has max capacity.
  • Assembler uses 1 of each source and delay is 1s.
  • Queue has max capacity
  • QueueSize1 is a queue of size 1
  • Delay is 15s
  • ResourcePool has capacity of 1

Function startAssembly():

if(queue.size()==0 && wait.size()>=1 && resourcePool.idle()>=1){
  wait.free(wait.get(0));
}
System.out.println("Queue: " + queue.size());
System.out.println("Wait: " + wait.size());
System.out.println("Idle: " + resourcePool.idle());

Function startAssembly(); is called:

  • onEntry of wait
  • onExit of assembler
  • onExit of queue

What do I want to happen: Model an assembly line with two processes connected through a queue(FIFO). Process 1(assembler) is faster than process 2(delay). Therefore queueSize1 fills up and after process 1 finishes a second part it can't work any further. Usually the worker is then displayed as busy() since the agent can't leave the assembler. I want it to be displayed as idle() when this happens using the function, wait and queue.

What happens: One agent passes the assembler and after that no other agent is able to pass through the wait block. By collecting resourcePool.idle() I noticed that even after the agent exited the assembly block there are no free resources. I also tried a consturct like assembler.delaySize()==0 in the if part, but there's also some strange behaviour. Replacing the idle-part with the delaySize-part kinda works, but it also passes 2 or 3 agents into the assembler block. So the "production line" contains more workpieces than it should.

Question: Is this a normal behaviour of the assembler block? Is it possible to avoid this and get the correct idle()-amount? Is there any other possible way to model my "production line"?

2

2 Answers

1
votes

This solution is valid in case you are using LIFO for the selection mode on simultaneous events, in which case the agent moves from the assembler to the queue and then to the queueSize1 and then to the delay (all in zero time) and AFTER that the resource is released.... which is a bit counterintuitive but it's how things work in LIFO selection mode.

So what you have to do is to create a dynamic event called StartAssembly and inside the dynamic event you will call the function: startAssembly(); Then in the on exit of your assembler, you will call the dynamic event to run almost immediately:

create_StartAssembly(0.001);

This will assure that the resource is released ... and that all the conditions are fulfilled.

You don't need to do the same in the other places, only on the exit of the assembler

Also, I think you should add a queue between source1 and the assembler or you may get errors

4
votes

For this particular example, you can go into the simulation experiment properties and set "Selection mode for simultaneous events" to "FIFO (in the order of scheduling)". As Felipe points out, you will need a queue between your 2nd source and assembler. Once you do those 2 things, your model will run as expected.

The release of the resource was put on the event calendar, all at the same time as other events. When the default of LIFO is utilized, the last in (i.e., entering the queues) gets executed first. If you select FIFO, the release of the resource was first on the calendar, so it occurs before the other items.

I believe AnyLogic changed the default behavior from FIFO to LIFO in AnyLogic 7. FIFO seems to be the much more common approach in discrete event simulation packages.

screenshot