Anylogic assign agent from population of agents to fluidsource batch - anylogic

I create a spreadsheet with some properties (columns); then in Anylogic create an agent (population of agents) and load it from DB. Run model. Works perfectly, it shows I have an Agent population "products" with 6 agents.. (model has FluidSource, Pipe, Tank, Valve, FluidDispose, all basic configuration)
So now I open the FluidSource, select Custom batch and for Batch: products.get[0].productName (productName is parameter of type string). I have also tried:
products[0];
products[0].productName;
products.get(0);
Now run again.. in model window it says "Error while drawing animation frame..." (orange block top right)
and in model.Console it says: Error during model creation:
Index: 0, Size: 0
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 ...
What am I doing wrong? How do I assign my FluidSource batch to one of my "Product" agents?

The problem is the order of initialization: your FluidSource object is trying to access the products population before that population is actually filled with agents.
Make your FluidSource account for this by using this conditional check:
products.size() == 0 ? "InitialBatch" : products[0].productName

Related

Count the sum of outputs

I have created an agent type named "Process" with a basic flow process inside (source-process-sink), in that agent i added a data output (named Treated) that counts the number of agents that went through the sink.
Now in my main i've put a population of that agent "Process" (lets say a population of 10)
my goal is to create a chart that shows the number counted by the data output of every agent of the "Process" population i tried to do a sum function { sum(Process.Treated, p ->p.count())} but it did not work
To know how many agent passes in the sink block of the "Process" Population, you do not have to count. It is enough for you to access the data in the sink block itself in the following way: process_population(index).sink.count()
You can use a bar chart to display for each member of your population the amount of agents that have left the sink block:
DataItem myDataItem = new DataItem();
for (int i = 0 ; i < process_population.size() ; i++)
{
myDataItem.setValue(process_population(i).sink.count());
MychartBar.addDataItem(myDataItem, "Titel" , Color);
}
MychartBar.updateData();
If you really want to invest and you want to add an X-axis with labels with the name or the index of each agent in your population, you can do the following instructions:
Put text labels below your chart bar in the lower left corner.
Define the Replication property for it as the population size: process_population.size().
For its X position property use the following code:
MychartBar.getX((MychartBar.getWidth()/(process_population.size()-1))*index
Under the Text property, you can put index + 1 to get the index of the agent or put any variable that is inside the agent, for example its name process_population(index).name
Good luck!

anylogic selectblock on 'true' returns same agent

I am simulating last-mile delivery and I want to iteratively evaluate the co2 emissions between stops. The numbers of the first route evaluation add up i.e. it correctly counts/removes each stop embedded within the route. The problem is that when the first route is finished, the model should consider the next route embedded in a new agent of type 'Order', in 'toConsumer' but it does not. From what I can see, is that the order agent is not updated after the condition in the select block has been met. I am not sure however, why it does this. When the condition is satisfied the agent does continue to the sink. Does anybody know how i can ensure this updating of the agent?
The anylogic model looks as follows:
In the source block I create agents following optimization results via:
int r = 0;
agent.routeVeh = (int) parVehicle.get(r);
agent.route = (List) parRoute.get(r);
agent.routeDep = (int) parDepot.get(r);
r++;
And in the select block i have:
The to consumer block:
If you are doing this operation in the Main agent, you need to define routeCount and consumerCount inside your Order agent (or if you have a Vehicle agent defined, inside that). Because they are defined for each order. Then in the routeFinished you need update the variable as agent.consumerCount++;

Netlogo : Using Levelspace for importing values from a child model to a parent model

Good day,
I am working with Levelspace since I want to create a model of Agents with brains. I have two files:
the master containing the environnement within which agents without brain can evolve with simple rules
the child containing the brain every agent will have after binding the two files.
I want to pass informations from the child models to the master so I am using this kind of code in the master:
print [vecteur_binaire] ls:of ls:models
with vecteur_binaire a function of the child model. But I noticed that the code above do work only for globals and that it doesn't work for functions. For example, with the code above, it will return :
" Extension exception: Model 0 (brain of (herbivore 0)) encountered an error: ITEM expected input to be a string or list but got the number 0 instead.
error while herbivore 1 running LS:OF
called by procedure CHOOSE_AND_MOVE_HERBIVORE
called by procedure MOVE
called by procedure GO
called by Button 'go'"
this error highlighting the "ls:of" of the code. I really do not understand what is happening and why I have this error message. Moreover, becuause of this, I can't run my child model and so make brains work well.
Do you know houw to solve it?
Thank you very much in advance for your reponse!
Juliette
More complete code:
In the master:
to choose_and_move_herbivore [in]
(ls:assign in visual_input [ vision ] of self )
print [vecteur_binaire] ls:of in
end
with "in" the id number of the child model.
In the child model:
to-report vecteur_binaire
go
report o_t
end
with "go" another function calling other functions in the programm to make brains work, and o_t the value that interests me.

Condition For Select Output based on distance between two different GIS Nodes

I am trying to find a condition to put in select output that is based on distance between two GIS points. My network includes a tram with people and I want my person to get off at tram stop nearest to its house. The tram moves in a counter loop and I want to place condition so that the person exits drops off at the right tram stop. Could you please help me with it?
I have already tried distanceByRoute but I don't know how to form a condition for it via statechart or in selectOutput.enter image description here
Assumptions
You have a population of Station-Agents named stations
You have a population of Passenger-Agents named passengers
You have a population of Tram-Agents named trams
You have a population of Home-Agents named homes
Step by step
Add toTram-Agent a variable nextStation of type Station in which the moveTo-Block always saves the current arrival station
Add to Passenger-Agent a parameter of type Home named home where at model startup a Home-Agent is filled in
Create a function named getNearestStation, with a input parameter of type Passenger and output of type Station:
//initialize with first station
Station nearestStation = stations.get(0);
double distanceToNearestStation = passenger.home.distanceByRoute(nearestStation);
double currentDistance;
for(Station station:stations){
currentDistance = passenger.home.distanceByRoute(station);
//save it if you find a closer station
if( currentDistance < distanceToNearestStation){
nearestStation = station;
distanceToNearestStation = passenger.home.distanceByRoute(station);
}
}
return nearestStation;
Instead of having a Station Agent, you could also use GISPoint for both your Variable nextStation inside tram and in the getNearestStation code.
Add a dropoff-Block to your flowchart and set the dropoff condition to the following:
getNearestStation(agent).equals(container.nextStation)
Additional note
In order to make the distance calculation less often, execute the getNearestStation only once at initialization of each passenger and save it in a variable, instead of calculating it each time it passes the dropoff block.
enter image description here
tramCollection here is my collection of tram stops (in GIS/INode) located on my map in Main.

Anylogic is assigning the value to all entities instead of only one

My source has the following code in "On at exit" field:
TRUCK.ID_number = parameter;
parameter = parameter + 1;
Then, each truck will receive an ID: 1, 2, 3, ...
The problem is that All the trucks are circulating at the same time and it looks like everytime a new truck is generated and the code runs it resets the ID for all trucks.
For example: When truck 4 (ID = 4) is created at the source all the other trucks receive ID 4 so I cannot know the correct ID of each truck.
What am I doing wrong?
a few things. First, you need to use the keyword agent in the onExit code box. So in your case, agent.ID_number=parameter. Please read up on these specific keywords that pop up everywhere in AnyLogic code boxes. I call it the "magic lightbulb", also see my blog on that topic:
The magic lightbulb
Second, newly created agents automatically get a unique index (if they belong to the same population). You can access that using the getIndex() method inside your truck agent.
The answer is: Use entity.ID_number=parameter