简体   繁体   中英

Gremlin find lightest path between vertices

I am pretty new to Gremlin and I am trying to find within my graph the lightest paths from source_id vertex to target_id vertex. (On some edges I have weights and on others I don't)

To get the shortest path I can with:

             g.V()
            .has("id", source_id)
            .repeat(outV().simplePath())
            .until(has("id", target_id))
            .path()
            .limit(3)
            .toList()
        )

I have read this reference book

and it suggested to use something like:

             g.V()
            .has("id", source_id)
            .repeat(out()).simplePath())
            .until(has("id", target_id))
            .path()
            .by(coalesce(values("weight"), constant(0.0)))
            .limit(limit)
            .toList()
        )

This is not working and returning the weights of the paths, how can I achieve this with Gremlin? should first get the paths, calculate their weights and then sort them by the weights? there must be an easier and intuitive way for this basic need. (if it were neo4j I could just run Dijkstra's algorithm)

Would appreciate some help here, thanks

I created the following example graph to help illustrate this answer.

gremlin> g.addV('A').as('a').
......1>   addV('B').as('b').
......2>   addV('C').as('c').
......3>   addV('D').as('d').
......4>   addV('E').as('e').
......5>   addV('F').as('f').
......6>   addV('G').as('g').
......7>   addV('H').as('h').
......8>   addV('Z').as('z').
......9>   addE('knows').from('a').to('b').property('weight',0.2).
.....10>   addE('knows').from('a').to('c').property('weight',0.5).
.....11>   addE('knows').from('a').to('f').property('weight',3.5).
.....12>   addE('knows').from('b').to('c').property('weight',0.1).
.....13>   addE('knows').from('c').to('d').property('weight',0.3).
.....14>   addE('knows').from('c').to('e').property('weight',0.2).
.....15>   addE('knows').from('c').to('f').
.....16>   addE('knows').from('d').to('f').property('weight',0.1).
.....17>   addE('knows').from('d').to('g').property('weight',2.0).
.....18>   addE('knows').from('f').to('g').property('weight',0.9).
.....19>   addE('knows').from('f').to('h').property('weight',0.3).
.....20>   addE('knows').from('f').to('z').property('weight',0.1).
.....21>   addE('knows').from('h').to('z').property('weight',0.2).iterate()

The following routes exist from A to Z (regardless of edge weight).

gremlin>  g.V().hasLabel('A').
......1>     repeat(outE().inV().simplePath()).until(hasLabel('Z')).path().by(label)
==>[A,knows,F,knows,Z]
==>[A,knows,F,knows,H,knows,Z]
==>[A,knows,C,knows,F,knows,Z]
==>[A,knows,B,knows,C,knows,F,knows,Z]
==>[A,knows,C,knows,D,knows,F,knows,Z]
==>[A,knows,C,knows,F,knows,H,knows,Z]
==>[A,knows,B,knows,C,knows,D,knows,F,knows,Z]
==>[A,knows,B,knows,C,knows,F,knows,H,knows,Z]
==>[A,knows,C,knows,D,knows,F,knows,H,knows,Z]
==>[A,knows,B,knows,C,knows,D,knows,F,knows,H,knows,Z]     

Note that one of the edges does not have a weight. We can find the paths with the lightest weights (where no weight is treated as a zero value) as follows:

gremlin> g.withSack(0).V().
......1>       hasLabel('A').
......2>       repeat(outE().sack(sum).by(coalesce(values('weight'),constant(0))).inV()).
......3>       until(hasLabel('Z')).
......4>       order().by(sack(),asc).
......5>       path().
......6>         by(label)
==>[A,knows,B,knows,C,knows,F,knows,Z]
==>[A,knows,C,knows,F,knows,Z]
==>[A,knows,B,knows,C,knows,D,knows,F,knows,Z]
==>[A,knows,B,knows,C,knows,F,knows,H,knows,Z]
==>[A,knows,C,knows,D,knows,F,knows,Z]
==>[A,knows,C,knows,F,knows,H,knows,Z]
==>[A,knows,B,knows,C,knows,D,knows,F,knows,H,knows,Z]
==>[A,knows,C,knows,D,knows,F,knows,H,knows,Z]
==>[A,knows,F,knows,Z]
==>[A,knows,F,knows,H,knows,Z]   

Just to prove that things are working as expected we can add the total weight value to each result.

gremlin> g.withSack(0).V().
......1>       hasLabel('A').
......2>       repeat(outE().sack(sum).by(coalesce(values('weight'),constant(0))).inV()).
......3>       until(hasLabel('Z')).
......4>       order().by(sack(),asc).
......5>       local(
......6>         union(
......7>           path().
......8>             by(label),
......9>           sack()).
.....10>         fold())
==>[[A,knows,B,knows,C,knows,F,knows,Z],0.4]
==>[[A,knows,C,knows,F,knows,Z],0.6]
==>[[A,knows,B,knows,C,knows,D,knows,F,knows,Z],0.8]
==>[[A,knows,B,knows,C,knows,F,knows,H,knows,Z],0.8]
==>[[A,knows,C,knows,D,knows,F,knows,Z],1.0]
==>[[A,knows,C,knows,F,knows,H,knows,Z],1.0]
==>[[A,knows,B,knows,C,knows,D,knows,F,knows,H,knows,Z],1.2]
==>[[A,knows,C,knows,D,knows,F,knows,H,knows,Z],1.4]
==>[[A,knows,F,knows,Z],3.6]
==>[[A,knows,F,knows,H,knows,Z],4.0]   

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM