Anylogic: How to you make a random agent move to from state to another? - anylogic

I want to randomly select a person (agent) that is in state1 and instruct this random agent to move to state2. I also want to change the random agent's var1(variable) value to "true".
I think that I should use randomWhere(population,condition) to select the random agent, but I do not know how to code it.

Assume you have an Agent type MyAgentType with a state chart statechart and a msg-based transition between state1 and state2 that triggers upon the String "change", and the agents live in a population myPopulation, then you can do:
MyAgentType agentInState1 = randomWhere(myPopulation, p->p.statechart.isStateActive(MyAgentType.state1));
agentInState1.statechart.fireTransition("change");
agentInState1.var1 = true;

Related

Is it possible to dynamically update if functions in anylogic?

I'm using a state chart in combination with a schedule in Anylogic (see picture). The output of the schedule is equal to 1 during working hours and 0 otherwise. Now I want the transition from state1 to state2 to happen when the schedule is turning to 1 or is equal to 1(so otherwise wait until the working hours).
I have tried using an if statement
if( main.plannerSchedule()==1 )(<perform action>)
However, by this method, the state transition only happens if the statement is true but doesn't wait for it to become true. Is there a way to constantly update the state transition or is there a "wait until" function that can solve this problem?
Best let the schedule send a message to your statechart when it switches. This assumes that the statechart lives on the same agent type as the schedule. Write this code in the action code box of the schedule:
if (value==1) {
statechart.fireEvent("go to state 2");
}
Obviously, your message transition needs to await the "go to state 2" message.
Note the value keyword. See https://www.benjamin-schumann.com/blog/2016/2/4/the-magic-lightbulb-and-how-it-can-help-your-anylogic-modelling for more info on that

is it possible to copy the current state of the statechart from one agent to another?

I am trying to make a model to simulate the contagion of covid in public spaces using a mix between SEIR and pedestrian models.
In another question I asked to use a static population. They suggested that before deleting the agent a copy be saved in a list and after the first X agents have been generated I want the next agent generated by the pedSource to be one of the list.
Currently what I do is take a random agent from the list and if it is infected I send a message to the new agent so that it goes into the infected state. But by doing that I am resetting the timeout to recover every time an agent enters the zone that I am modeling.
this is the code that currently runs in the pedSource on exit:
if (personasEnCasa.size()+personasEnSuper.size() > poblacionMaxima){
Persona p = randomFrom(personasEnCasa);
if (p.statechart.getState() == Persona.Infeccioso){
send("Contagiado", ped);
};
personasEnCasa.remove(p);
};
personasEnSuper is my population of Persona, personasEnCasa is my list of agents outside the zone and and poblacionMaxima is the maximum number of agents in the lista and the population
I would like to be able to copy the current statechart of the agent in the list to the agent that generates my pedSource. Or use something similar to a pedSource.inject () but inserting an agent from the list instead of a new one. But I did not know how to do it.
is there any way to do this?
your ped already exists and you don't need to copy it you can just move it to the flow like this, with pedWait being any pedestrian block that you want, so instead of send("Contagiado", ped); you would do enter.take(ped);
but if you insist in using the send, then you can use branches on your statechart to define where this ped goes:
you will need in this case before the send, use ped.infectious=true; and the condition in the branch would be infectious==true to move to the infectious state.
As a side note, instead of p.statechart.getState() == Persona.Infeccioso you should use p.statechart.getState().equals(Persona.Infeccioso)
use == only with primitives such as boolean, int and double, otherwise you are susceptible to errors that are very difficult to discover

How do I choose both exact quanitity wait for and quanitity available in the same pick-up block?

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

difficult to find the current location of agents in Anylogic simulation

i built a simple model for pedestrian movement from start line towards target line, I want to find the number of moving agents in some area using the XY-coordinates (from X=150 to X=350, Y is the same )
The action for the event is to get the count of agents in that area and set the value for the variable crowd1:
crowd1=count(agents(), p-> p.getX()>150 && p.getX()<350)
the problem is that it's always 0 , even though the gents are moving in the simulation.
There are no agents in your environment because you haven't created any agent type... For your code to work you need to have a population of pedestrians registered in your environment (meaning that you have to create the agent type and add it to main as a populatin), and then you have to add to a custom population the agents created in pedSource...
Otherwise, you can use this code:
count(pedGoTo.getPeds(),p->p.getX()>150 && p.getX()<350)

How to add to agent to presentation

I am trying to simulate self-sustaining population of cows, but when i dinamicly add new agents to main agent's population newly created agent does not appear. How to fix it? I create agents from mother agent with
this.main.add_cows();
first generation population
pupulation without presentation
First go to the agent where the animation will exist (which is also where your agent is defined). In most cases this is the main agent, so you probably want to go to "main" and click on the cow agent to see the "initial location" in the properties of the cow agent.
When a new agent is created, the default position is at the agent animation location, which is probably somewhere out of the visible area since we generally position our defined agents out of the canvas, and in your case it's the same position for all cows.
Now you have other options: you can select for instance a random coordinate in the space (assuming you have a 600x600 pixels square):
Or you can select a node (as long as a node is defined in your animation canvas:
So, to summarize, when you create a new agent in your population, you have to tell AnyLogic where you want to locate it... Otherwise, how can the software know what you want?
ensure to set the initial location correct, otherwise it might appear at a default location you do not expect. Something like:
Cow myNewCow = this.main.add_cows();
myNewCow.setXY(uniform(0,600), uniform(0,400));