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()
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).
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.
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.
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").
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With