AnyLogic: how to get 2nd or 3rd nearest agents? - anylogic

In agent based model, let say I have 10 locations and in each location I have random number of people(10~20). Also, I have 5 facility locations. Now I can send all people from each people-location to nearest facility using getNearestAgent(). But I want to send 70% people to nearest one, 20% to second nearest one and 10% to 3rd nearest facility. How can I do that?
I put all locations in GIS map. And successfully send people to nearest facility.
Actual implementation

Make a function that takes as argument the person and returns a location:
Location nearest=person.getNearestAgent(locations);
if(randomTrue(0.7)){
return nearest;
}else{
List <Location> otherLocations=findAll(locations,l->!l.equals(nearest));
Location secondNearest=person.getNearestAgent(otherLocations);
if(randomTrue(2.0/3.0){
return secondNearest;
}else{
List <Location> otherLocations2=findAll(otherLocations,l->!l.equals(secondNearest));
return person.getNearestAgent(otherLocations2);
}
}

Related

Changing amount of resource sets in Seize-block programmatically

So the problem is:
How can I change the amount in "Resource Sets" programmatically? I'am planning on changing this value back and forth from 1 and 2 given some conditions during the simulation run.
Amount I want to change is marked in yellow below.
Emile answer is right, but if you insist in using what you are using, you can click on the equal sign and make it a function:
and in the function (which i made take a random number between 1 and 2, but you can do what you want), you use the following (the function returns a type ResourcePool[][])
ResourcePool[][] rp = new ResourcePool[1][num];
for(int i=0;i<num;i++){
rp[0][i]=resourcePool;
}
return rp;
In your case, it seems you are using one resource alternative only.
Why don't you choose units of the same pool, then the number of units to be seized becomes dynamic.

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

FleetApi - How to use legal rest times?

I'd like to know the position in which the driver would need to rest with given waypoints.
I am calling GET https://fleet.ls.hereapi.com/2/calculateroute.json with the following params:
{
mode: "fastest;car;traffic:enabled",
waypoint0: "19.286769, -99.652773",
waypoint1: "19.419185, -99.17755430000001",
waypoint2: "19.41530,-99.17844",
waypoint3: "31.29778, -110.93690",
restTimes: "MEX",
maxSpeed: 110,
departure: "2021-07-20T15:00:00.000Z"
}
This returns warnings with the info of rest times like this:
{
"message": "Taking the short driver rest time after 18036 sec for 1800 sec at routeLinkSeqNum 1485",
"code": 14,
"routeLinkSeqNum": 1485
}
I would like to know how to use/read this info. I don't know what routeLinkSeqNum is and how to utilize it.
Governments impose rules on how long a truck driver can drive before he needs to rest. Routing can consider these regulations w.r.t. short rests during a day and long (overnight) rests.
For example, in EU countries drivers have to rest after 4.5 hours of driving for at least 45 minutes, and must not exceed a total of 9 working hours per day before they have to rest for 11 hours.
Activate this feature in the router using the "&restTimes=local", in this case, it is the "MEX" in the request parameter. Routing will then consider each country's local regulations.
In the same parameter, you can specify whether the driver starts the route freshly or how long he is already driving / on duty since his last short or long rest period
routeLinkSeqNum is an index of the link array within a Leg. If you check the response, there will be response>route>[0]>leg[0]>[2]>link[1485].
So one route can have n-legs, 1 leg can have m-links
This will help you to plot the rest times.
Here is an example shown in the tool:
https://tcs.ext.here.com/examples/v3/fleet_telematics_api

HERE API:Swift. Wierd behaviour : Loops in a route - Creating a route based on GPS trace creates loops. / passthrough waypoints

im trying to create a route that follows a gps trace i provide.
The gps trace is cleaned up and it has no loops in it and is in correct order.
I checked it with other services.
It has 1920 points.
You can find the trace here GPX Files
Sadly if i create a route based on provided sdk example (github) i get loops in my path.
I was hoping you could help me to solve following problems:
how do i avoid loops while creating route by using HERE ios Swift SDK
how do i set route options is such way to follow provided point array and not create a fastest or balanced route.
Since i could not find those functions in Ios sdk i used additional REST API to filter the route a bit to remove all points that were not matched correctly according to here maps... before drawing the route.. ie everything with low probability, warnings, big distance to the road... yet the result is still not good. Here is a cleaned up file.. the file is being created after the original was maped / run once through HERE Maps. In this file all points that have low confidence or produce warnings or have big distance to original points .. are removed. This is the one i use to create a route and it still have the same issues like loops and weird turns.
Thank you very much in advance!
BR.
So far i have this code:
private lazy var router = NMACoreRouter()
#objc func do_routing_stuff( gps_trace :[NMAWaypoint]) {
var stops = [Any]()
stops = gps_trace
let routingMode = NMARoutingMode(routingType: .fastest,
transportMode: .car,
routingOptions: .avoidHighway)
// Trigger the route calculation
router.calculateRoute(withStops: stops ,
routingMode: routingMode)
{ [weak self] routeResult, error in
guard error == .none else {
self?.showMessage("Error:route calculation returned error code \(error.rawValue)")
return
}
guard let result = routeResult, let routes = result.routes, routes.count > 0 else {
self?.showMessage("Error:route result returned is not valid")
return
}
// Let's add the 1st result onto the map
self?.route = routes[0]
self?.updateMapRoute(with: self?.route)
// self?.startNavigation()
}
}
private func updateMapRoute(with route: NMARoute?) {
// remove previously created map route from map
if let previousMapRoute = mapRoute {
mapView.remove(mapObject:previousMapRoute)
}
guard let unwrappedRoute = route else {
return
}
mapRoute = NMAMapRoute(unwrappedRoute)
mapRoute?.traveledColor = .clear
_ = mapRoute.map{ mapView?.add(mapObject: $0) }
// In order to see the entire route, we orientate the
// map view accordingly
if let boundingBox = unwrappedRoute.boundingBox {
geoBoundingBox = boundingBox
mapView.set(boundingBox: boundingBox, animation: .linear)
}
}
in comparison same route presented with leaflet maps.
I believe the problem you have is that you are feeding the Routing API a large number of waypoints, all of which are in close proximity to each other.
You have almost 2000 waypoints in your GPX file (and ~1300 in your cleaned one). Each of these waypoints is less than 10 meters distance from their closest neighbors. This is not the type of data that the Routing API is really designed to work with.
I've experimented with your GPX Trace and I have come up with the following solution: simply skip a bunch of coordinates in your trace.
First, clean up your trace using the Route Matching API (which I believe you have been doing).
Second, pick the first trkpt in the GPX file as your first waypoint for the Routing call. Then skip the next 20 points. Pick the following trkpoint as the second waypoint. Repeat this until you are at the end of the file. Then add the last trkpt in the trace as the final waypoint.
Then call the Routing API and you should get a good match between your trace and your route, without any loops or other weird routing artefacts.
Some notes:
I have picked 20 as the number of traces to skip, because this would put about 200m in between each waypoint. That should be close enough to ensure that the Routing API does not deviate too much from the traced route. For larger traces you may wish to increase that number. For traces in urban environments with lots alternate routes, you may want to use a smaller number.
It's important to clean the data with the Route Matching API first, to avoid picking outliers as waypoints.
Also, you may not wish to use the "avoidHighways" option. Given your use case, there doesn't seem to be a benefit and I could see it causing additional problems.
By now you probably worked it out, but your waypoints are likely landing on bridges or tunnels that are along your route but not on the road you want. I.e. the waypoint is intended to be on the road under the bridge but the routing engine perceives that you want to drive on the bridge.
The routing engine is looping around those roads to drive you on that waypoint on the bridge or in the tunnel.
There is no simple solution to this that I have found.

Getting GPS locations and other attributes - BEGINNER

I am currently doing this tutorial to get the GPS coordinates of my present location. I need to know what these values means?
The first 2 values are the geo-coordinates, and i don't know what the other attributes are ?
From Apple's iOS Developer Library what you are seeing as a result of the description selector being sent to your CLLocation object (which represents your current location and other location-related info):
A string of the form <<latitude>, <longitude>> +/- <accuracy>m (speed
<speed> kph / heading <heading>) # <date-time>, where <latitude>,
<longitude>, <accuracy>, <speed>, and <heading> are formatted floating
point numbers and <date-time> is a formatted date string that includes
date, time, and time zone information.
What you probably want to do now is extract info from your CLLocation object by accessing its various properties (e.g. CLLocation.altitude will return the altitude only). Generally, aside from debugging purposes to the console, you would not want to print or display to the user the result of [CLLocation description] which is what you have there!