anylogic selectblock on 'true' returns same agent - anylogic

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++;

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!

How can I inject agents in a source block from an uploaded database table?

I am trying to inject agents from a database into a specific source block. The database consists of 2 columns of "OrderType" & "OrderAmount". I wish to inject "OrderAmount" of agents of their corresponding "OrderType" into this source, while retaining the differentiation (I.E. by storing a parameter attribute ID of each entry/agent in the corresponding agenttype of the source block).
I have saved the entries from the database in collections and constructed a table as such (For both arrays; type = double):
double [][] ArrayCustomerOrders = new double [coll_CustomerOrderType.size()][2];
for (int i = 0; i < coll_CustomerOrderType.size(); i++) {
ArrayCustomerOrders[i][0] = coll_CustomerOrderType.get(i);
ArrayCustomerOrders[i][1] = coll_CustomerOrderAmount.get(i);
}
I tried playing around with the source block calls of inject() function in the same event as I constructed the order table in, but was unable to inject eligible arguments.
Does anyone have a suggestion on how to go about this?
In your case, you can simply replace the Source block with an Enter block (named "myEnterBlock"):
Create an empty agent population pop_Orders with an agent type that has 2 parameters p_Type and p_Amount.
In your for-loop code, when you have the current order type and amount, create such an agent and push it into the Enter block directly:
myEnterBlock.take(add_pop_Orders(currentType, currentAmount))

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.

How do each agent specify different parameters?

I am modeling the type of Customer agents. They are given parameters: they work (true / false) and have education (true / false).
There is a condition that agents in the block service fall where works == true and education == true. And all the others go to the exit.
enter image description here
How do each agent specify different parameters?
So the first thing to notice here is that your queue block does nothing and you could just remove it.
And to change the parameters of your agent, in your source, in the "on at exit" action you can write the values you want, for instance:
agent.works=false;
agent.education==true;
you can also create random values...
agent.works=randomTrue(0.5);
agent.education==randomTrue(0.5);
also, if you go to your agent's variable "works", in the default value, you can make it also random writing randomTrue(0.5)
where randomTrue defines how likely it is for your variable to be true (0.5 means 50% chance)

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