narnia649
narnia649

Reputation: 381

Is there a way in AnyLogic to assign resources to a population of agents in use rather than individual agents?

I have a simple example of dish washers at a restaurant to illustrate the issue I am having.

Question

How can I ensure that the correct number of dish washers are seized & released when it's depended on the number of agents being used?

Problem

Using a function to assign the resources, the number of dish washers are not always correct due to different times in which sinks are used and not used.

Example

Main:

enter image description here

Generates dishes and randomly assigns them to one of three sinks in the exit block. Sinks is a population of agents. dish_washers is a ResourcePool with a capacity of 10.

Sink:

enter image description here

Dishes enter a queue and are entered one at a time using a hold block. Once the dish is cleaned, the hold is unblocked to grab the next dish.

Details:

I have a shared ResourcePool of dish_washers at a restaurant. There are 3 sinks at the restaurant. Dishes are generated and randomly assigned to each sink.

If only 1 sink is being used, then two dish washers are needed. However, if 2 or more sinks are being used then the number of dish washers becomes:

numberOfDishWashers = 2 + numberOfSinksInUse;

In order to change the numberOfDishWashers as more sinks are being used, I created a function that defines the numberOfDishWashers to be seized from the dish_washer ResourcePool.

int numberOfSinksUsed = 0;
int numberOfWorkersToSeize = 0;
int numberOfWorkersAlreadySeized = 0;
int numberOfWorkersToAssign = 0;

ResourcePool[][] dish_washers;

for(Sink curSink : main.sinks){
    if(curSink.queue.size() > 0){
        numberOfSinksUsed += 1;
    }
}

numberOfWorkersAlreadySeized = main.dish_washers.busy();
numberOfWorkersToSeize = 2 + numberOfSinksUsed;
numberOfWorkersToAssign = numberOfWorkersToSeize - numberOfWorkersAlreadySeized;

dish_washers = new ResourcePool[1][numberOfWorkersToAssign];

for(int i = 0; i < numberOfWorkersToAssign; i++){
    dish_washers[0][i] = main.dish_washers;
}

return dish_washers;

Error Description:

However, depending on which sink completes first & releases, the number of dish washer assigned will be incorrect. A traceln at the end of the sink process illustrates this where the numberOfDishWashers seized on the exit block doesn't match "2 + numberOfSinksInUse". There is an instance where 3 sinks are in used but only 4 workers were seized.

Exit, Sink: C Workers Currently Seized: 4
Sinks in Use: 2
Exit, Sink: C Workers Currently Seized: 4
Sinks in Use: 3
Exit, Sink: C Workers Currently Seized: 5
Sinks in Use: 2
Exit, Sink: C Workers Currently Seized: 4
Sinks in Use: 2

Another way to look at the issue, is this Excel table outlining the current logic. The number of busy workers doesn't match the number of busy workers there should be based on the number of active sinks.

enter image description here

Methods I have Tried

  1. Custom function to release only the necessary workers to keep the correct total. Generates an error because the resource gets assigned to the 'agent' or dish. When the dish gets destroyed it has unreleased resources attached to it.
  2. Passing the "sink" agent through an "enter", "seize", and "exit" block to assign the resource to the agent "sink" instead of the dish that is generated. Error regarding the "dish" agent being in the flowchart of the "sink" agent while the "sink" agent is seizing the workers.

How can I ensure the correct number of dish washers are always grabbed?

Upvotes: 1

Views: 111

Answers (1)

Jaco-Ben Vosloo
Jaco-Ben Vosloo

Reputation: 3975

So your fundamental problem here is that inside the sink you will seize a dishwasher, then the dish goes into the delay (With the number of dishwashers seized) and once out of the delay it will release what ever dishwashers it seized... But during the time it is in the delay the situation might have changed and you actually wanted to seize a different number of dishwashers for that specific sink...

Your options are to either

  1. Remove dishes from the delay, release the correct amount of dishwashers, return back into the delay and delay for the remainder of the time...

  2. Implement your own logic.

I would go for option 2 as option 1 means that you develop a workaround for the block created by AnyLogic and you will end up not using the blocks the way they were designed, this is unfortunately the issue with blockification

So I would have a collection inside of a sink that shows the number of dishwashers currently assigned to this sink. Then whenever a new dish enters a sink we recalculate the number of dishwashers to assign (perhaps at every sink? ) and then make the correct assignment.

Here is an example with some sample code - I did not test it but you will have something similar

enter image description here

Upvotes: 0

Related Questions