Stop at point on Path closest to given (x, y) point while staying on Network - anylogic

In my model, I require my agents to go through a layout and stop adjacent to a given object. For now, I have used a series of moveTo blocks alongside code that returns the relative (x, y) coordinates that are adjacent of my objective object.
Given that I will be working to simulate an irregular layout, I want to use a Network - I am however running into issues.
According to AnyLogic's "Agents movement inside and outside network" page, in order to use Network paths, either the start or the end point of the agent's movement must be within the Network.
I have created a Rectangular Node, where my moving agents are first initiated. Then, I have them go though a moveTo block with an (x, y, z) destination. For the (x, y) coordinates, I am using Network.getNearestPath(objectiveObjectX, objectiveObjectY, 0.0, pointOnNearestPath).
The desired result would be the agent going through:
Initial Position > objectiveObject 1 > objectiveObject 2 > objectiveObject 3 > Initial Position
With all movement staying on the Network.
However, the actual result is that my agents simply ignore the existence of the Network. My agent populations exist within the Main alongside my Network, so that isn't the issue.
I can somewhat understand why going from objectiveObject to another objectiveObject doesn't follow the path, as neither the start or end destination are nodes, but even the initial movement does not function, and I do not understand why - as it begins in a node and ends in an (x, y, z) position, which is one of the scenarios covered in AnyLogic's aforementioned agent movement page.
How would I achieve my desired results? Would I have to go through the tedious exercise of creating Nodes at every single one of my destination points?
Thank you.

Related

breadth-first search in coordinate based system

I am not an experienced programmer (programming language MATLAB) and hence have barely any knowledge of advanced algorithms. One of these is the breadth-first search. The concept I understand but implementing it into my problem is difficult for me.
My problem:
I place disks, of equal sizes, randomly in a square and will place the coordinates of the disks into separate matrices when they are one connected network. I colorized them for clarity (see image). Now, I have to find the shortest path from left to right of the network which spans from left to right and want to do this based on the coordinates. The disks have to touch in order to be connected to each other. They cannot form a path if they are not touching.
So this is what I currently have:
I have a matrix with coordinates x and coordinates y in columns 1 and 2, every row representing one of the disks (for ease, let's just take the coordinates of all the connecting disks, excluding those which are not spanning from left to right when connected).
The diameter of the disks is known (0.2).
We can easily identify which disks are on the left boundary of the square and which disks are on the right boundary of the square. These represent the possible starting coordinates and the possible goal coordinates.
% Coordinates of group of disks, where the group connects from left to right.
0.0159 0.1385
0.0172 0.2194
0.0179 0.4246
0.0231 0.0486
0.0488 0.1392
0.0709 0.2109
0.0813 0.0595
0.0856 0.3530
0.1119 0.3756
0.1275 0.2530
0.1585 0.4751
0.1702 0.2926
0.1908 0.3828
0.1961 0.3277
0.2427 0.4001
0.2492 0.4799
0.2734 0.4788
0.3232 0.3547
0.3399 0.3275
0.3789 0.3716
0.4117 0.3474
0.4579 0.3961
0.4670 0.3394
0.4797 0.3279
0.4853 0.4786
0.3495 0.4455
0.4796 0.2736
0.0693 0.0746
0.1288 0.4204
0.1271 0.4071
0.1218 0.4646
0.1255 0.3080
0.4154 0.2926
Positions of disks and colored the connecting disks. Image is very schematic and many more disks should be expected in a much larger area (keeping same size disks).
My strategy was to set up a breadth-first search, taking the starting coordinates as one of the disks (can be any) on the left side of the square. The goal will be to find the shortest path to the right side of the square.
To my understanding, I want to pick a starting coordinate and check all disks if they are within a diameter distance (middle point to middle point of the disks) of my starting coordinate. If they are within range of my starting coordinate I want to place them in a 'queue' (natively not supported by MATLAB? but let's set one up ourselves). Then, the next step is to take the first disk which was close enough and do the same for this one. I can do this but once I have to do the second disk which was within my first disk, I am lost in how and/or what data structure I should take and how to save the 'path' which it is finding. This means I can find a path but not all paths and hence also not the shortest path.
I appreciate any help! Maybe some documentation which I have not seen yet or maybe an example which is very comparable.
Best regards,
If they are within range of my starting coordinate I want to place
them in a 'queue'
Before you add it to the queue you want to make sure this disk was not processed (put in the queue) before. Each disk should be processed only once, so you make sure the "neighbor" disk has not been processed before, then mark it as processed and add it to the queue.
the next step is to take the first disk which was close enough and do
the same for this one.
Actually the next disc to process is simply the one at the head of the queue.
Continue to do so until you hit the target / stop criteria.
how to save the 'path' which it is finding
There are several techniques to do so. An easy one would be to maintain a "come from" value to each disk. This value points to the "parent" of the disk.
Since each disk is processed once (at most) it will have one "come from" value or none.
When the target is reached the path can be reconstructed starting from the "come from" value of the target.
This question has now been solved!
The way I have solved this was close to what was already suggested in my question but also with help from some of the comments.
The distance between coordinates can be put into a matrix. Let us look at coordinate (disk) 1 and coordinate (disk 3). This means that we will be at elements (1,3) and (3,1). If the disks are within touching distance, these two elements will indicate a 1 and otherwise a 0. This is done for all disks and this creates the adjacency matrix.
I created a 'graph' with the built-in function G = Graph(adjacency matrix) we can create an undirected graph. Then with the built in function [path, distance of path] = shortestpath(G,s,t) where G is the graph and s and t are the starting disks (in this case, indicated by integers), the shortest path can be found from disk s to t.
There is however one thing that we must pay attention to and that is representing the actual distance between disks. If we look at G, we can actually see that it contains two objects. One representing the nodes and the other representing the edges. The edges is crucial for the coordinate based distances as we can set the 'weight' of the edge as the distance between two disks. This can simply be done by looping over the nodes and calculating the distance between the neighbouring nodes and inserting them into the weight (G.Edges.Weight(i) = distance between the respective nodes).
How do I find the optimal path from left to right? I loop over all starting disks (defined as touching the left side of the square) and find the shortest path to all disks that touch the right side of the square. Saving the distances of the paths the actual shortest path can be found.
To give you an example of what can be achieved, the following video shows what paths from every starting disk can be found and the final frame shows the shortest path. Video of path finding. The shortest path I have also attached here:
Shortest path left to right.
If there are any questions you would like to ask me about specifics, let me know.

Anylogic Network - Agent not following path

I have a layout defined for agents to move from one rectangular node to another, based on a list in a database. So for example, agent 1 will go to 'lane' 701, then on to 702, etc.
The layout looks like this:
example of layout
The agents move enter from the top left, along the x to the end of that row, then down to the bottom and out to the right, visiting the 'lanes' on their way.
However, I've noticed that one agent has its first lane in the bottom right so rather than following the path across and then down, it's using the shortest distance and moving on the diagonal straight to the lane in the corner:
movement behaviour
Is there something in the software that I can set to strictly follow the paths set? I cannot work out why the agent is breaking the path so I can only assume it's something I am missing.
in the first place, your agent is doing this diagonal probably because you have 2 different networks... if your destination is not in the current network, then the agent will use the shortest distance to the destination, which seems to be your case.
On the other hand, you can't control how the agents move on your network, and it will always take the shortest path or some optimized option... in order to make them follow the path you want, you need to generate intermediary destinations.

How to make pedestrians appear at AreaNode with attractors from a pedSource

I am working on an evacuation project for a floor and would like to create a distribution of pedestrians from the pedSource block. These pedestrians will already appear in an area when I run the simulation. I want to obtain a fixed number of pedestrians in one area while the rest is distributed to other areas.
I have made a collection of areas that pedestrians will appear using allLocations (area, area1, area2 and OfficeArea). The event is triggered by an event and using a delay block. The max amount of pedestrians at the given floor is 100
Image of block flowchart
Image of floor layout plan
This is the code I tried where pedestrians would appear in the areas:
allLocations.get(uniform_discr(0, allLocations.size()-1))
I expect a fixed 10 number of pedestrians in the office area and positioned where I set the attractors, but the actual result shows more than 10 number of pedestrians and do not appear at the set attractor.
Image of actual result
Setting an attractor as a target for pedestrians is according to the documentation only working for the blocks pedWait and pedGoTo (I could actually only get it to work with pedWait, not with pedGoTo). Therefore you cannot initialize agents directly onto attractors using the initial location or the jumpTo() function.
You have several options as a workaround:
Extract the x,y coordinates of the attractor, and use the type point(x,y) to define the initial location or the location for the jumpTo()
Instead of using (graphical) attractors consider just defining points by code directly
Use very small individual areas instead of one large area with attractors
Use a pedWait block in your process flow and let your pedestrians 'walk' to their initial positions. Give the model a short time until everybody is on the desired location before starting your evacuation. You can also run the model in super fast mode during this initial phase, so that it will barely be visible.

Anylogic - line of sight

Is there a way to check if there is a line of sight between two agents assuming some buildings and presentation markup?
(Meaning a function that would check if two agents can see each other assuming buildings and walls)
This is how I did it once in the past. The only problem is that it might be slow if you need to do that calculation thousands of times per second. And it's only in 2D. If you need 3D, the idea is not so different.
1) add all your building nodes and everything that might be an obstacle between the two agents to a collection. You may want to put a rectangular node around your buildings to keep everything in one collection (assuming you are using space markup with nodes)
2) generate a delta distance delta (equal to 1 for example) and find the angle of the line that passes through both agents.
3) Make a loop from the position of agent1 till the position of agent2. It will be something like this:
L=delta;
while(L<LThatReachesSecondAgent){
x1 = agent1.getX() + L*cos(angle);
y1 = agent1.getY() + L*sin(angle);
for(Node n : yourCollectionOfNodes){
If(n.contains(x1,y1))
return false
}
/*This can also work maybe faster
//int numNodesInTheWay=count(yourCollectionOfNodes,n->n.contains(x1,y1));
//if(numNodesInTheWay>0) return false
*/
L+=delta;
}
return true
welcome to SOF.
No, there is no build-in function, afaik. You would have to code something manually, which is possible but not straight forward. If you want help with that, you need to provide more details on the specifics.

how to create several regions in a networkx graph based on a criterion

I have 02 questions:
1- From the graph2 below, I want to create several regions in a networkx based on a criterion (first zone starts at node X up to a given set of nodes). For example, region 1 starts from node 1 to nodes (4 and 16). Is there a way to do that?
create regions on the graph
2- I also want to determine the depth of each node in the attached graph
node_depth of a graph
Thank you for any hint that could help.
What do you mean by "regions"? Are you asking how to create subgraphs (https://en.wikipedia.org/wiki/Glossary_of_graph_theory_terms#subgraph)? That is, do you want to create separate, smaller graphs which contain only the nodes and edges existing in the regions you have drawn in your picture?
If so, you can do that using the subgraph() function of networkx.
In your example, to create the subgraph of region 1 you would do:
region1 = graph2.subgraph([1,2,3,4,11,12,13,14,15,16])
and an equivalent statement for regions 2 and 3.
Then for node depth, I am not sure what you mean but I think you might mean distance from some root node.
Let's assume your root node is 1.
Then to find the "depth" of each node, you want to find the distance(number of edges) between that node and 1.
To do that you could do something like:
for n in myGraph.nodes():
print n, networkx.shortest_path(graph, 1, n)
I'm not an expert in networkx so sorry for not using the right terms. Coming back to my 02 points: A region can effectively be considered as a subgraph. To note that the main criterion behind the construction of the region is to start from a reference node (node 1 for region 1) and include all the nodes and edges until a specific condition is met on a specific edge (in my case it is the presence of a electric device on an edge).
how to build a region