I have the following closed loop process model consisting of trucks moving between three stations (the three service blocks):
The three resource pools have a capacity on 1 and...:
"shovel" is assigned to the "cLoad" service block
"loadingPersonnel" is assigned to the "bLoad_unload" service block
"dcPeronnel" is assigned to "dcUnload"
There will be generated 12 trucks and they operate in the closed loop until the simulation clock finishes. The truck agent class has a "loadingCap" parameter of value 17 (data type is double) and a "ballast" variable with an initial value of 0 (data type is double and access is public):
In the "on enter" action field of the "cornfieldBakery" moveTo-block from the first image, the following java code is inserted for incrementing the ballast variable with the loadingCap parameter:
agent.ballast += agent.loadingCap;
traceln("the current ballast of the leaving truck is: " + agent.ballast);
When I run the simulation I get the following in the console after the first truck enters the moveTo block:
"the current ballast of the leaving truck is: 17.0"
However, when I inspect the 1st agent instance during the simulation run, the variable ballast still remains at 0:
Are there any explanation to why the traceln() value and the "ballast" variable of the 1st instance differ from each other?
Related
I want to store process times in my model for each agent of type Box. For this purpose I have created a Java class ProcessData.
My problem is that I always get NullPointerExceptions. I don't know if it's because of my code or the functionality of the batch block.
When the wait block reaches a certain size, all agents of type Box are routed to the batch block. The batch agent then waits in the seize block for staff member. If the agent is then seized, each agent of type Box contained in the batch agent should then get a start processing time. This is my code at enter of the delay block: box.getProcessData().add(new ProcessData(date(), duration()));. Using a constructor, I add the start time and duration as new variables to a new ProcessData entry.
To determine the end time of each Box agent I have the following code at unbatch block entry: box.getProcessData().getLast().setEnd(date());
Since I have a NullPointerException I can't tell exactly where it came from. My guess is that I have a bug with addressing the code: should I use agent. (from batch) or box. (name of original agent before batch)? Or is it not possible to give the batch agent properties that are inherited by the box agent?
First error is at unbatch, so the second code from above and second error is the following public void onExit( Box batch, Box agent ) { _unbatch_onExit_xjal( this, batch, agent ); }.
Following the screenshot of my error:
The problem you have with this model first,is that you are seizing a resource for the batch without releasing that resource... you need to release before unbatch
your error nevertheless is related to some code that you wrote in the on exit action of the unbatch block that you are unfortunately not telling us
But to discover what is null, check with a traceln() the value of the variables that are present in the on exit section of the unbatch in order to print on the screen what is null
In the default settings it is possible to set a time in the queue after which an agent leaves the queue via outTimeOut. However, only a fixed time can be entered in the corresponding field, e.g. 12 hours. Is there a possibility to link these 12 hours with a condition? In my case, the agent should only leave the queue after 12 hours via outTimeOut if a certain condition is also met. In my case, if a variable varIN == 1.
Collect the time in queue statistics for each agent. Create a parameter called entryTime. When they enter the block, set agent.entryTime=time();
You can create an event that iterates through the queue every 1 second and removes the agents that meet your conditions from the queue (by using remove(Agent agent) function). That means if (time()-agent.entryTime>12)&&(agent.varIN==1), you will remove that agent.
Loop will look like this:
for (int i=0; i< yourQueue.size(); i++) {
YourAgentType currentAgent = ((YourAgentType)yourQueue.get(i));
if ((time()-currentAgent.entryTime>12)&&(currentAgent.varIN==1)){
yourQueue.remove(currentAgent);
}
}
You can use a function (returning a double) to define and calculate the most complex logic you like. If you provide an argument of type Agent (or the specific agent type flowing through the blocks), it can even account for your agent characteristics.
In the queue block timeout, simply call the function.
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 am learning Anylogic, at the moment I want to run a bus on a given route with certain bus stops. For this I am using the following logic:
carSource->carMoveTo1->selectOutput->carMoveTo2->carDispose. carSource is the place where the bus appears; carMoveTo1 is the stop the bus goes to; selectOutPut
is the condition under which the bus ends its route; carMoveTo2 is the road to which the bus follows when the route ends.
Also in carMoveTo1 I specify the destination: bus.stops[bus.stop_value++] (this is how I pass the stop count to the bus).
In selectOutPut I add a condition: bus.stops.length==bus.stop_value.
For the bus I set agent "bus" which has two parameters: stops(type "other" - BusStop[], control type "one-dimensional array") is an array of stops;
stop_value(int type) - stops counter.
This logic causes an error: the stop_value counter exceeds the limits of stops[] array. As far as I understand, it happens because in carMoveTo1 I'm incrementing
the stop_value counter within the bus class from each bus.stops[bus.stop_value++]. How can I make each bus have a separate counter?
P.S. I've tried to refer to this: bus.stops[this.stop_value++] pointer - another error occurs.
So I have a vehicle which is going to pick up exact quantity (Wait for) the first 50 minutes in the simulation. After those 50 minutes have gone by, I want the same vehicle to pick up quantity (if available). How do I go about this?
Alternative approach (avoiding complex Java coding) is to use 2 Pickup blocks, each with a different setup. Put a SelectOutput block before them and route agents into the respective block using time()>50*minute() in the SelectOutput condition
Set it up for the first setup by default.
Create an event to trigger after 50 mins and make it execute this code:
myPickupObject.set_pickupType(PickupType.QUANTITY);
Here is a way to allow container entity to wait in a Pickup for some time t and then leave with whatever entities have been picked up. The example model looks like this:
There are two key components:
ReleaseOnTimeout Dynamic event which has a parameter called '_agent' of type Agent and following code:
for (Object o : pickup.getEmbeddedObjects()) {
// find the Delay object inside Pickup
if (Delay.class == o.getClass().getSuperclass()) {
// remove the container from the Delay
Agent a = ((Delay)o).remove(_agent);
if (a != null) {
// send the removed container into Enter
enter.take(a);
}
}
}
In pickup on enter action contains following code: `create_ReleaseOnTimeout(10, container);
How this works:
pickup is configured to have Exact quantity (wait for) behaviour
a container object enters Pickup block pickup
on entry a dynamic event ReleaseOnTimeout is scheduled in 10 units to check up on container
if sufficient number of entities were available then container picks them up and leaves
alternatively to (4), if by the time 10 units elapsed the container is still stuck in pickup then it will be removed and put into enter