How to find the name of the path between two nodes - anylogic

I'm new to Anylogic and I apologize in advance if this is a beginner question. I have an agent that travel in a network between nodes along paths. In a function, I would like to get the name of the path between two nodes - the node that the agent is at and the node that it is going to. As an example, the variables containing the name of the two nodes are n1 and n2.
The network is set up such that there is only one path between two given nodes.
I am using the following to get the name of the node for the the current node:
Node n = (Node)agent.getNetworkNode();
String n1 = n.getName();
n2 is manually assigned. For example:
String n2 = "node2";
What is the best way to get the name of the path? Any help would be much appreciated. Thank you.

I don't think there is and easy way so I show you this way... Note that there can be many paths connecting both nodes, so this solution gives you the paths names for all the paths that connect n1 and n2
Node n1=findFirst(network.nodes(),n->n.getName().equals("n1"));
Node n2=findFirst(network.nodes(),n->n.getName().equals("n2"));
ArrayList <Path> conn1=new ArrayList();
ArrayList <Path> conn2=new ArrayList();
ArrayList <Path> paths=new ArrayList();
for(int i=0;i<n1.getConnectionsCount();i++){
if(n1.getConnection(i) instanceof Path)
conn1.add(n1.getConnection(i)); // add the path connected to n1
}
for(int i=0;i<n2.getConnectionsCount();i++){
if(n2.getConnection(i) instanceof Path)
conn2.add(n2.getConnection(i)); // add the path connected to n2
}
for(Path p1 : conn1){
if(conn2.contains(p1)){
paths.add(p1); // add the path matches
}
}
for(int i=0;i<paths.size();i++){
traceln(paths.get(i).getName()); // print the name of the paths
}

Related

How To Use kmedoids from pyclustering with set number of clusters

I am trying to use k-medoids to cluster some trajectory data I am working with (multiple points along the trajectory of an aircraft). I want to cluster these into a set number of clusters (as I know how many types of paths there should be).
I have found that k-medoids is implemented inside the pyclustering package, and am trying to use that. I am technically able to get it to cluster, but I do not know how to control the number of clusters. I originally thought it was directly tied to the number of elements inside what I called initial_medoids, but experimentation shows that it is more complicated than this. My relevant code snippet is below.
Note that D holds a list of lists. Each list corresponds to a single trajectory.
def hausdorff( u, v):
d = max(directed_hausdorff(u, v)[0], directed_hausdorff(v, u)[0])
return d
traj_count = len(traj_lst)
D = np.zeros((traj_count, traj_count))
for i in range(traj_count):
for j in range(i + 1, traj_count):
distance = hausdorff(traj_lst[i], traj_lst[j])
D[i, j] = distance
D[j, i] = distance
from pyclustering.cluster.kmedoids import kmedoids
initial_medoids = [104, 345, 123, 1]
kmedoids_instance = kmedoids(traj_lst, initial_medoids)
kmedoids_instance.process()
cluster_lst = kmedoids_instance.get_clusters()[0]
num_clusters = len(np.unique(cluster_lst))
print('There were %i clusters found' %num_clusters)
I have a total of 1900 trajectories, and the above-code finds 1424 clusters. I had expected that I could control the number of clusters through the length of initial_medoids, as I did not see any option to input the number of clusters into the program, but this seems unrelated. Could anyone guide me as to the mistake I am making? How do I choose the number of clusters?
In case of requirement to obtain clusters you need to call get_clusters():
cluster_lst = kmedoids_instance.get_clusters()
Not get_clusters()[0] (in this case it is a list of object indexes in the first cluster):
cluster_lst = kmedoids_instance.get_clusters()[0]
And that is correct, you can control amount of clusters by initial_medoids.
It is true you can control the number of cluster, which correspond to the length of initial_medoids.
The documentation is not clear about this. The get__clusters function "Returns list of medoids of allocated clusters represented by indexes from the input data". so, this function does not return the cluster labels. It returns the index of rows in your original (input) data.
Please check the shape of cluster_lst in your example, using .get_clusters() and not .get_clusters()[0] as annoviko suggested. In your case, this shape should be (4,). So, you have a list of four elements (clusters), each containing the index or rows in your original data.
To get, for example, data from the first cluster, use:
kmedoids_instance = kmedoids(traj_lst, initial_medoids)
kmedoids_instance.process()
cluster_lst = kmedoids_instance.get_clusters()
traj_lst_first_cluster = traj_lst[cluster_lst[0]]

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);
}

Union of disjoint sets

I am looking at disjoint sets that support the function of the Union.
The technique of height reduction of a tree:
We always merge the smaller tree to the greater one, i.e. we make the root of the smaller tree to point to the root of the greater tree.
A tree is greater than an other if it has more nodes.
Each node is a struct with fields: some information for the element, the pointer "parent" to the parent node, and a counter "count", that is used only if the node is the root and contains the number of the nodes at the up-tree.
The following algorithm merges two up trees:
pointer UpTreeUnion(pointer S,T) {
if (S == NULL OR P == NULL) return;
if (S->count >= T->count) {
S->count = S->count + T->count;
T->parent = S;
return S;
}
else {
T->count = T->count + S->count;
S->parent = T;
return T;
}
}
Consider an implementation of disjoint sets with union, where there can be at most k disjoint sets.
The implementation uses a hash table A[0.. max-1] at which there are stored keys based on the method ordered double hashing.
Let h1 and h2 be the primary and the secondary hash function, respectively. A contains the keys of the nodes of all of the above trees and also a pointer to the corresponding node for each of them.
I want to write an algorithm that takes as parameters the keys of two nodes and merges the up-trees to which the nodes belong (the nodes can belong to any up-trees, even at the same in which case it appears an appropriate message). At merging, we should apply techniques of path compression and height reduction.
Could you give me a hint how we could do this?
Suppose that we have this array:
At the beginning the nodes will be like that:
Then if k1=100, k2=5, after applying the algorithm, will we get this?
Then if we have k1=59, k2=5, we will get the following:
Right? Then applying the path compression we start doing this:
tmp=B
while (B->parent!=B)
parent=B->parent;
tmp->parent=B;
tmp=parent;
}
So we will have parent=F, tmp->parent=B, tmp=F.
How do we continue?
Having then k1=14, k2=59 we get this:
First, when you get keys, you need to find them in the hash table.
Hash table contains entries: (key, pointer-to-node).
Let's say you want to find key k. You check:
A[h1(k) + 0*h2(k) mod size(A)] - if it contains key k, you read corresponding pointer-to-node.
If there is something other than k, you check:
A[h1(k) + 1*h2(k) mod size(A)],
A[h1(k) + 2*h2(k) mod size(A)],
A[h1(k) + i*h2(k) mod size(A)]... until you find key k.
Now that you have pointers to 2 nodes, you need to find roots of the trees those nodes belong to. To find the root, you go up the tree until you reach root node. You use parent pointer of each node for it and you can assume that root's parent pointer points to itself for example.
Now that you have 2 roots, you can merge them using upTreeUnion.
Path compression works like this:
After you have found root of a tree for node s, you follow the path from s to root one more time and set parent pointer of every node on the path to the root.
Update:
Algorithm(k1,k2){
int i=0,j=0;
int i1,i2;
while (i<max and A[i1 = h1(k1)+i*h2(k1) mod size(A)]->key!=k1){
i++;
}
while (j<max and A[i2 = h1(k2)+j*h2(k2) mod size(A)]->key!=k2){
j++;
}
if (A[i1]->key!=k1) return;
if (A[i2]->key!=k2) return;
pointer node1,node2,root1,root2;
node1=A[i1]->node;
node2=A[i2]->node;
root1=UpTreeFind(node1);
root2=UpTreeFind(node2);
if (root1==root2){
printf("The nodes belong to the same up tree");
return;
}
// path compression
pointer tmp,tmpParent;
tmp = node1;
while (tmp->parent!=root1) {
tmpParent=tmp->parent;
tmp->parent=root1;
tmp=tmpParent;
}
tmp = node2;
while (tmp->parent!=root2) {
tmpParent=tmp->parent;
tmp->parent=root2;
tmp=tmpParent;
}
UpTreeUnion(root1,root2);
}

What is the query to access the nodes in reverse to a relationship in neo4j

I am using neo4j as my graph db. I am having some problem with the queries. Here is the scenario.
I have an neo4j index = users.
I have all the user nodes in users index.
I have another index called "comments"
Every comment is a node.
And Every comment has a relationship "HAS_COMMENT" with user node.
So I have, user_node ->HAS_COMMENT-> comment_node
I can get all the comments of a user by this query.
$ start n = node:users(username='user1') match n-[r:HAS_COMMENT] -> a return a;
Now, I want to get in reverse direction. I have to get username from comment.
This is I am trying but getting null result.
$ start n = node:comments(_id='c101') match n-[r:HAS_COMMENT] -> a return a;
c101 is my comment id(node id); and it is present in db.
How can I do this?
You can match arrows either way:
start n = node:comments(_id='c101') match n-[r:HAS_COMMENT] -> a return a;
start n = node:comments(_id='c101') match n<-[r:HAS_COMMENT] - a return a;

networkx: efficiently find absolute longest path in digraph

I want networkx to find the absolute longest path in my directed,
acyclic graph.
I know about Bellman-Ford, so I negated my graph lengths. The problem:
networkx's bellman_ford() requires a source node. I want to find the
absolute longest path (or the shortest path after negation), not the
longest path from a given node.
Of course, I could run bellman_ford() on each node in the graph and
sort, but is there a more efficient method?
From what I've read (eg,
http://en.wikipedia.org/wiki/Longest_path_problem) I realize there
actually may not be a more efficient method, but was wondering if
anyone had any ideas (and/or had proved P=NP (grin)).
EDIT: all the edge lengths in my graph are +1 (or -1 after negation), so a method that simply visits the most nodes would also work. In general, it won't be possible to visit ALL nodes of course.
EDIT: OK, I just realized I could add an additional node that simply connects to every other node in the graph, and then run bellman_ford from that node. Any other suggestions?
There is a linear-time algorithm mentioned at http://en.wikipedia.org/wiki/Longest_path_problem
Here is a (very lightly tested) implementation
EDIT, this is clearly wrong, see below. +1 for future testing more than lightly before posting
import networkx as nx
def longest_path(G):
dist = {} # stores [node, distance] pair
for node in nx.topological_sort(G):
pairs = [[dist[v][0]+1,v] for v in G.pred[node]] # incoming pairs
if pairs:
dist[node] = max(pairs)
else:
dist[node] = (0, node)
node, max_dist = max(dist.items())
path = [node]
while node in dist:
node, length = dist[node]
path.append(node)
return list(reversed(path))
if __name__=='__main__':
G = nx.DiGraph()
G.add_path([1,2,3,4])
print longest_path(G)
EDIT: Corrected version (use at your own risk and please report bugs)
def longest_path(G):
dist = {} # stores [node, distance] pair
for node in nx.topological_sort(G):
# pairs of dist,node for all incoming edges
pairs = [(dist[v][0]+1,v) for v in G.pred[node]]
if pairs:
dist[node] = max(pairs)
else:
dist[node] = (0, node)
node,(length,_) = max(dist.items(), key=lambda x:x[1])
path = []
while length > 0:
path.append(node)
length,node = dist[node]
return list(reversed(path))
if __name__=='__main__':
G = nx.DiGraph()
G.add_path([1,2,3,4])
G.add_path([1,20,30,31,32,4])
# G.add_path([20,2,200,31])
print longest_path(G)
Aric's revised answer is a good one and I found it had been adopted by the networkx library link
However, I found a little flaw in this method.
if pairs:
dist[node] = max(pairs)
else:
dist[node] = (0, node)
because pairs is a list of tuples of (int,nodetype). When comparing tuples, python compares the first element and if they are the same, will process to compare the second element, which is nodetype. However, in my case the nodetype is a custom class whos comparing method is not defined. Python therefore throw out an error like 'TypeError: unorderable types: xxx() > xxx()'
For a possible improving, I say the line
dist[node] = max(pairs)
can be replaced by
dist[node] = max(pairs,key=lambda x:x[0])
Sorry about the formatting since it's my first time posting. I wish I could just post below Aric's answer as a comment but the website forbids me to do so stating I don't have enough reputation (fine...)