Partial batch sizes - anylogic

I'm trying to simulate pallet behavior by using batch and move to. This works fine except towards the end where the number of elements left is smaller than the batch size, and these never get picked up. Any way out of this situation?
Have tried messing with custom queues, pickup/dropoff pairs.
To elaborate, the batch object has a queue size of 15. However once the entire set has been processed a number of elements less than 15 remain which don't get picked up by the subsequent moveTo block. I need to send the agents to the subsequent block once the queue size falls below 15.

You can dynamically change the batch size of your Batch object towards "the end" (whatever you mean by that :-) ). You need to figure out when to change the batch size (as this depends on your model). But once it is time to adjust, you can call myBatchItem.set_batchSize(1) and it will now batch things together individually.
However, a better model design might be to have a cool-down period before the model end, i.e. stop taking model measurements before your batch objects run out of agents to batch.

You need to know what the last element is somehow for example using a boolean variable called isLast in your agent that is true for the last agent.
and in the batch you have to change the batch size programatically.. maybe like this in the on enter action of your batch:
if(agent.isLast)
self.set_batchSize(self.size());

To determine if the "end" or any lack of supply is reached, I suggest a timeout. I would save a timestamp in a variable lastBatchDate in the OnExit code of the batch block:
lastBatchDate = date();
A cyclically activated event checkForLeftovers will check every once in a while if there is objects waiting to be batched and the timeout (here: 10 minutes) is reached. In this case, the batch size will be reduced to exactly the number of waiting objects, in order for them to continue in a smaller batch:
if( lastBatchDate!=null //prevent a NullPointerError when date is not yet filled
&& ((date().getTime()-lastBatchDate.getTime())/1000)>600 //more than 600 seconds since last batch
&& batch.size()>0 //something is waiting
&& batch.size()<BATCH_SIZE //not more then a normal batch is waiting
){
batch.set_batchSize(batch.size()); // set the batch size to exactly the amount waiting
}
else{
batch.set_batchSize(BATCH_SIZE); // reset the batch size to the default value BATCH_SIZE
}
The model will look something like this:
However, as Benjamin already noted, you should be careful if this is what you really need to model. Take care for example on these aspects:
Is the timeout long enough to not accidentally push smaller batches during normal operations?
Is the timeout short enough to have any effect?
Is it ok to have a batch of a smaller size downstream in your process?
etc.
You might just want to make sure upstream that the number of objects reaches the batching station are always filling full batches, or you might to just stop your simulation before the line "runs dry".
You can see the model and download the source code here.

Related

Frame collector & Out of memory errors (large memory allocations)

Task: Tasks spawn with fixed time intervals (source), each has remaining processing time which is given by uniform random [0 .. x]. Each task is processed by the module (delay). Each module has a fixed processing time. Module substracts it's processing time from the task's remaining processing time. If a task's remaining processing time depleted (less than 0), that task becomes completed reaches (sink). Otherwise it goes to the next module, and the same process repeats. There are N modules, that are linked one after eachother. If the task's remaining processing time has not depleted after processing at the N'th module, it goes to the 1st module with the highest priority and is being processed there until remaining processing time depletes.
Model Image
The issue: I've created the model, the max amount of spawned/sinked agents i could get is 17 for -Xmx8G and 15 for -Xmx4G. Then CPU/RAM usage rises to max and nothing happens.
Task Manager + Simulation Image
Task Manager Image
I've also checked troubleshooting "I got “Out Of Memory” error message. How can I fix it?" page.
Case
Result
Large number of agents, or agents with considerable memory footprints
My agents have 2 parameters that are unique to each agent. One is double (remaining_processing_time), another one is integer (queue_priority). Also all 17 spawned agents reached sink.
System Dynamics delay structures under small numeric time step settings
Not using that function anywhere, besides delay block.
Datasets auto-created for dynamic variables
This option is turned off
Maybe i missing something, but i can't really analyze with such small amount of agents. I'll leave a model here.
This model really had me stumped. Could not figure out where the memory was going and why as you run the model visually it stops yet the memory keeps on increasing exponentially... Until I did a Java profiling and found that you have 100s of Main in the memory...
]
You create a new Main() for every agent that comes from the source - so every agent is a new Main and every Main is a completely new "simulation" if you will..
Simply change it back to the default or in your case create your own agent type, since you want to save the remaining time and queue priority
You will also need to change the agent type in all your other blocks
Now if you run. your app it uses a fraction of memory

Temporary adjustment of delay time

I have the following problem which I am unable to solve:
I have a situation where a security point (added as delay) holds every half an hour a 15 min break. After the break, the security guards increase their speed till the queue is shorter than 10pp.
I wanted to model this as follows: a state chart with delay.set_capacity(0) after 30 minutes and delay.set_capacity(1) again after the 15 min break. For the increased speed after the break, I added an additional state with condition: queue.size()>10 and now I want to set the action such that the delay function changes the delay time from exponential (1/10) to exponential (1/5) as long as queue.size()>10.
Anyone experience with which function in the action box to use? Or would you suggest a different function?
Since you are using, or at least want to use a statechart I would suggest the following design, where you have composite states inside the working state to indicate if the security agent is working fast or normal and a message transition to let it move from one state to the next.
It is advised to use a message transition and trigger it as needed instead of a conditional state which gets chected for every change inside the agent since this can be a computational expensive exercise.
I assume you already implemented the correct capacity settings for the different on enter actions for working and breaking
Now you simply need to send the message every time an agent enters the queue and every time it exits the delay block, and of course, see the delay time based on the state of the statechart.
Aee screenshot below.

Is there a way to specify infinite allowed lateness in Apache Beam?

I'm using fixed windows to batch data by event time in order to send it to an external API efficiently (batches of 60 seconds), accumulation mode is set to DISCARDING because it doesn't matter if late data is sent to the external API without the previous data.
Is it possible to specify an infinite allowed lateness, so late data is never discarded?
It is definitely possible, you can set allowed lateness to a very high Duration (for instance, Duration.standardDays(36500)). On the other hand , doing so would result in your state growing indefinitely, which might not be what you want. Every open window (every window ever seen) will have at least a timer called a GC timer - a timer set for the end of the window + allowed lateness. Every timer has to be kept in state and therefore, the size of your state will grow over time.
If you do not need batching based on event-time, it might be a better option to use GroupIntoBatches, which should not suffer from this problem (you don't need to set allowed lateness and the size of your state will not grow).

Anylogic, how to change the size of production batches dynamically?

I have a production line where some resources create batches of pieces. The number of pieces created by the "source" block and the number of batches are parameters. For example, if you set 48 pieces created and 4 batches, each batch closes when resources complete 12 pieces. The problem arises when I have for example 51 pieces and 4 batches, in this case I should have batches of different sizes like 12, 12, 12 and the last one with 15 pieces. Is there any way to solve this problem?
Thanks for your advices
Following this Sample Model. Assuming all your parts arrive at the same time you just need to update the batchSize "On exit" at the source block with:
batchSize = numberOfParts/numberOfBatches;
batchparts.set_batchSize(batchSize);
And then, update it again "On exit" on the batch block:
if(queue.size()<2*batchSize){
batchSize=batchSize+(queue.size()%batchSize);
}
batchparts.set_batchSize(batchSize);
Note (queue.size()%batchSize) is the MOD function and gives you the additional number of parts needed to be batched in the last batch.
If the parts don't arrive at the same time, you can create a variable batchNumber that will let you know which number of batch you will do next (1 to numberOfBatches, initialized in 1).
Then, you just need to update it on the "On exit" of the batch block as follows:
//If the next batch is the last one, batch all the
//remaining quantity until completing the total number of parts
if(batchNumber+1=numberOfBatches){
batchSize=batchSize+(numberOfParts%batchSize);
batchparts.set_batchSize(batchSize);
batchNumber=1;
}
batchNumber=batchNumber+1;
I hope this helps.

Using ForkManager and Perl properly?

My developer recently disappeared and I need to make a small change to my website.
Here's the code I'll be referring to:
my $process = scalar(#rows);
$process = 500 if $process > 500;
my $pm = Parallel::ForkManager->new($process);
This is code from a Perl script that scrapes data from an API system through a cron job. Every time the cron job is run, it's opening a ton of processes for that file. For example, cron-job.pl will be running 100+ times.
The number of instances it opens is based on the amount of data that needs to be checked so it's different every time, but never seems to exceed 500. Is the code above what would be causing this to happen?
I'm not familiar with using ForkManager, but from the research I've done it looks like it runs the same file multiple times, that way it'll be extracting multiple streams of data from the API system all at the same time.
The problem is that the number of instances being run is significantly slowing down the server. To lower the amount of instances, is it really as simple as changing 500 to a lower number or am I missing something?
To lower the number of instances created, yes, just lower 500 (in both cases) to something else.
Parallel::ForkManager is a way of using fork (spawning new processes) to handle parallel processing. The parameter passed to new() specifies the maximum number of concurrent processes to create.
Your code simplifies to
my $pm = Parallel::ForkManager->new(500);
It means: Limit the the number of children to 500 at any given time.
If you have fewer than 500 jobs, only that many workers will be created.
If you have more than 500 jobs, the manager will start 500 jobs, wait for one to finish, then start the next job.
If you want fewer children executing any given time, lower that number.
my $pm = Parallel::ForkManager->new(50);