Connect different agent type Anylogic - anylogic

I have 5 agents - bus, transformer , generator, load , line. I have a requirement where i need dynamically connect the above agents.
I have written the following code, where i am trying to connect for example bus [2] and generator[5]. The connections are not random but based on a circuit, which i am dynamically reading through a text file.
for (int l = 0; l < busList.size(); l++) {
for (int k = 0; k < generatorList.size(); k++) {
if (generatorList.get(k).getBusNumber()==busList.get(l).getBusNumber()) {
busList.get(l).getBusID().connectTo(generatorList.get(k).getGenID());
}
}
}
Can someone help with the connection part. I cannot have a generic list because I need the agent attributes for other functionalities as well.

Assuming that busList and generatorList are collections containing entries of type Bus and Generator respectively, which both are derived of type Agent, the following code should work for connecting:
busList.get(l).connectTo(generatorList.get(k));
I don't know why you used getBusID and getGenID which I assume return an integer. If they really return a Bus or a Generator object it should work as you already wrote. In this case you would need to provide us the error message or the exact problem that you have.

Related

Anylogic find agent in population and access one of its variables

I want to find the index my agent has in its population (named dullieses), which lives in my Main-agent.
I want to find one of my dullieses-agent via one of its variables (DullyID) which, in this example, shall be equal to my counter variable. Both are of type int.
I have tried the following to no avail:
int i = 0;
for ( i = 0; i < dullieses.size(); i++){
if (Main.dullieses(i).DullyID == counter){
traceln("I found myself! I have the index " + i);
break;
}
}
Error code: Cannot make a static reference to the non-static method dullies(int) from type Main.
How can I find my agent in my population and find its index?
I think you're probably already in main and don't need to add Main..
Anyway, I would recommend using:
Dully d = findFirst( dullieses, d -> d.ID == counter );
d.variable = 10;
I used variable and 10 as random examples, but this should give you the idea. Also replace Dully with whatever your agent type name is.
You don't need to use a custom ID parameter in your agents (at least not for what you're doing here).
All agents in a population have the getIndex function which returns their index in the population. Just be wary that, if you remove agents from a population, their indices will change (so you can't, for example, use their index as a unique ID for them in that case).

Same sequence to multiple sequencers in UVM

I have a DUT with 2 Interfaces of the same type. I have created 2 agents to drive the two interfaces. My idea is to drive the same signals on the interface ports to test a specific scenario. Hence, I thought of creating a sequence and driving it to the two sequencers of the agents. But I get an error. The code is something as follows:
my_sequencer m_seqr[2];
my_sequence m_seq;
for(int i=0; i<2; i++) begin
fork
int idx = i;
m_seq.start(p_sequencer.m_seqr[i];
join_none
end
I haven't shown the complete code for keeping the post short. I think my declarations and initializations are correct because I have a similar test with 2 sequences feeding into 2 sequencers working correctly.
My question is how can I achieve my objective of driving the same sequence into 2 or more sequencers?
Error is as follows(Haven't added the complete line of error):
uvm_test_top.m_env.m_my_agent_env.m_my_agent[1].m_seqr##m_in_seq%0d[SEQ_NOT_DONE] Sequuence .... already started
You need to construct a new object for each sequence you want to start. Also, you need to reference [idx] not [i].
my_sequencer m_seqr[2];
...
for(int i=0; i<2; i++)
fork
int idx = i;
my_sequence m_seq = my_sequence::type_id::create(...);
m_seq.start(p_sequencer.m_seqr[idx];
join_none

I want to convert from Point to Agent that gives me proper location

I am working on agent-based modelling where I have created a function that generates a random point inside a region and then converts that point to agent. However, when I use this function later, the points don't give me a proper location on the map for further computation. I want to know what I am doing wrong? Or how can this be improved.
The return type for the function is ArrayList
ArrayList<DeliveryHouse> House = new ArrayList<DeliveryHouse>();
int i;
Point p;
DeliveryHouse h;
for(i=0;i<packagesC2C;i++)
{
p = main.Region2.randomPointInside();
h = main.deliveryHouse.setLocation(p);
House.add(i, h);
};
return House;
The major problem I see with your code is that you are not initializing the agent "h" but pointing it to one agent you have at main which means you keep changing its location in the loop and it will only reflect the last location. The array list you created will have multiple references to same agent instead of one agent per location.
If you want to create an agent per location you need to create an agent population called "deliveryHouses" of the agent type "DeliveryHouse" and change your code to the following. Note that the population will have all the agents so you do not need any output from the function.
int i;
Point p;
for(i=0;i<packagesC2C;i++)
{
DeliveryHouse h = main.add_deliveryHouses();
p = main.Region2.randomPointInside();
h.setLocation(p);
}

Anylogic referencing columns in a collection

I am using a collection to represent available trucks in a system. I am using a 1 or 0 for a given index number, using a 1 to say that indexed truck is available. I am then trying to assign that index number to a customer ID. I am trying to randomly select an available truck from those listed as available. I am getting an error saying the left-hand side of an assignment must be a variable and highlighting the portion of the code reading Available_Trucks() = 1. This is the code:
agent.ID = randomWhere(Available_Trucks, Available_Trucks() = 1);
The way you are doing it won't work... randomWhere when applied to a collection of integers, will return the element of the collection (in this case 1 or 0).
So doing
randomWhere(Available_Trucks,at->at==1); //this is the right synthax
will return 1 always since that's the value of the number chosen in the collection. So what you need is to get the index of the number of the collection that is equal to 1. But you will have to create a function to do that yourself... something like this (probably not the best way but it works: agent.ID=getRandomAvailbleTruck(Available_Trucks);
And the function getRandomAvailbleTruck will take as an argument a collection (arrayList probably).. it will return -1 if there is no availble truck
int availableTrucks=count(collection,c->c==1);
if(availableTrucks==0) return -1;
int rand=uniform_discr(1,availableTrucks);
int i=0;
int j=0;
while(i<rand){
if(collection.get(j)==1){
i++;
if(i==rand){
return j;
}
}
j++;
}
return -1;
Now another idea is to instead of using 0 and 1 for the availability, you can use correlative numbers: 1,2,3,4,5 ... etc and use a 0 if it's not available. For instance if truck 3 is not availble, the array will be 1,2,0,4,5 and if it's available it will be 1,2,3,4,5.
In that case you can use
agent.ID=randomTrue(available_trucks,at->at>0);
But you will get an error if there is no available truck, so check that.
Nevertheless, what you are doing is horrible practice... And there is a much easier way to do it if you put the availability in your truck if your truck is an agent...
Then you can just do
Truck truck=randomWhere(trucks,t->t.available==1);
if(truck!=null)
agent.ID=truck.ID;

AnyLogic - custom network

I'm still having troubles with AnyLogic...I'm developing an epidemic SIRS model and I want to define my own network.
In particular, I have this matrix that defines the daily average number of contacts between age class
and therefore I want every agent to establish contact with other agents according to this matrix...it is driving me crazy :S
AgeClass is a parameter calculated with the following function
I thought to setup an event that occurs once at the beginning with the following code
Now I am saying "connect n times to a random agent"...what I want to say is "connect n times to a random agent with AgeClass k" is there a way to do so?
thanks for the support!
ps when I write int i = AgeClass i takes the value of the parameter AgeClass of the agent that is running the code, right? So i it will be different for different agents?
Probably, you have already found a solution. Here a way to do it:
Regarding age, you don't need that big if/else if sequence. Just do something like this:
int ageClass = 0; // a variable of agents
ageClass = (int) floor(age / 5.0);
if (age >= 70.0 ) ageClass == 14; // just to be sure that max class is 14
return ageClass;
Regarding the network. I would create a function named setup, so that you can put it in agent actions, on startup, e.g. setup();
You can create a link to agents object at the agent level (Person in my code, I use a connection object named contacts). The function would be something like:
// loop through age groups
for (int i = 0; i < network[0].length; i++) {
ArrayList<Person> ageGroupPeople = new ArrayList<Person>();
for (Person p : population ) {
if ( p.ageClass == i ) { ageGroupPeople.add(p) } \\ create pool of potential alters by age
}
\\ create network per agent
for (Person ego : population ) {
for (int k = 0; k < poisson(network[ego.ageClass][i]); k++) {
Person alter = randomFrom(ageGroupPeople);
if ( ego != alter ) { ego.contacts.connectTo(alter);}
}
}
I haven't checked the code and how slow might be, it is just one way to do it.
In AnyLogic, you can represent a matrix as two-dimensional Java array:
http://help.anylogic.com/topic/com.xj.anylogic.help/html/code/Arrays.html
After initializing the matrix, you may define custom contact network using the element 'Link to agents':
http://help.anylogic.com/topic/com.xj.anylogic.help/html/agentbased/Link.html