Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to find a shortest path between two nodes in Tinkerpop 3.1

I know this was asked several time but I haven't found any reference regarding the last version of Tinkerpop (3.1), featuring many new useful functions we can use in our traversals.

Let's say I have to find a shortest path between nodes 3 and 4. Is this traversal sound?

g.V(3).repeat(out()).until(id().is(4).and().simplePath()).path().limit(1)

Here I'm assuming that when I'm looping a BFS search is executed (thus, the first result is the shortest path) as it seems that this was the case with the loop() function.

Additionally, is there any way to include a previously bound variable (by using an as step) in the until step? More precisely, I'm trying to select two nodes during the traversal, and then finding the shortest path between them, for example,

g.V().match(
__as('e0').out('Feedbacks').as('e1'),
__as('e0').repeat(out('Meets')).until(<I reach e1>).path().<get_length>.as('len')
).select('e0', 'e1', 'len')

Finally, as can be seen from the previous traversal, it's not clear to me how I can get the length of the shortest path. Using something like

g.V(3).repeat(out()).until(id().is(4).and().simplePath()).path().size()

returns the size of the result (number of rows returned), while

g.V(3).repeat(out()).until(id().is(4).and().simplePath()).path().by(__size())

returns an error.

Here is the graph I'm experimenting with, should anybody want to play a bit.

graph = TinkerGraph.open()
e0 = graph.addVertex(T.id, 0, label, "User", "name", "e0")
e1 = graph.addVertex(T.id, 1, label, "User", "name", "e1")
e2 = graph.addVertex(T.id, 2, label, "User", "name", "e2")
e3 = graph.addVertex(T.id, 3, label, "User", "name", "e3")
e4 = graph.addVertex(T.id, 4, label, "User", "name", "e4")
e0.addEdge("Feedbacks", e2)
e0.addEdge("Meets", e1)
e2.addEdge("Feedbacks", e4)
e2.addEdge("Meets", e4)
e3.addEdge("Feedbacks", e0)
e3.addEdge("Meets", e2)
e4.addEdge("Feedbacks", e0)
g = graph.traversal()
like image 232
Alberto Avatar asked Dec 02 '15 10:12

Alberto


People also ask

How do you determine the number of shortest paths between two nodes?

Use BFS to determine the length of the shortest v-w-path. Then use DFS to find the number of the v-w-shortest paths such that two nodes are connected and the length of path equals to the output of BFS. But the running time of this plan is O(m+n)+O(m+n).

How do you find the path between two nodes?

Approach: Either Breadth First Search (BFS) or Depth First Search (DFS) can be used to find path between two vertices. Take the first vertex as a source in BFS (or DFS), follow the standard BFS (or DFS). If the second vertex is found in our traversal, then return true else return false.

How do you get edges in Gremlins?

Create an edge To create a new edge between two vertices, use the addEdge(v1, v2, label) method. The edge will be created with the label specified. In the example below two vertices are created and assigned to a variable (Gremlin is based on Groovy), then an edge is created between them.


1 Answers

There's a slightly shorter variant for your shortest path query:

g.V(3).repeat(out().simplePath()).until(hasId(4)).path().limit(1)

Your assumption, that the first path is always the shortest path, is correct. To get the path lengths, you can use count(local):

g.V(3).repeat(out().simplePath()).until(hasId(4)).path().count(local)

UPDATE

Regarding your updated query, this one should solve the problem:

g.V().as("e0").out("Feedbacks").as("e1").select("e0").
      repeat(out("Meets")).until(where(eq("e1"))).path().
      map(union(count(local), constant(-2)).sum()).as("len").
      select("e0","e1","len")

I subtract 2 from the overall path length, because I think that you're only interested in the length of the path traversed by the repeat() block and the out().select() in the beginning should not be included. If that's not the case, then you can simply replace the 3rd line with count(local).as("len")..

like image 191
Daniel Kuppitz Avatar answered Oct 12 '22 23:10

Daniel Kuppitz