必须包含某些航路点的最短路径

时间:2015-10-21 08:40:32

标签: neo4j cypher shortest-path

我正在尝试找到连接任意节点集合的最短路径。 start和end都可以是集合中的任何节点,只要它们不相同即可。 标准密码函数shortestPath()或allShortestPaths()失败,因为它们找到从开始到结束的最短路径,并且不包括航点。 以下密码有效,但有更快的方法吗?

//some collection of nodeids, as waypoints the path has to include
match (n) where id(n) IN [24259,11,24647,28333,196] 
with collect(n) as wps

// create possible start en endpoints
unwind wps as wpstart
unwind wps as wpend
with wps,wpstart,wpend where id(wpstart)<id(wpend)

// find paths that include all nodes in wps
match p=((wpstart)-[*..6]-(wpend))
where ALL(n IN wps WHERE n IN nodes(p))

// return  paths, ordered by length
return id(wpstart),id(wpend),length(p) as lp,EXTRACT(n IN nodes(p) | id(n)) order by lp asc

2015年10月23日更新: 使用最新的Neo4j版本2.3.0,可以将shortestPath()与在评估过程中在某处拉出的WHERE clasue结合使用。然后你得到一个像这样的结构,其中{wps}是nodeIds的集合。

// unwind the collection to create combinations of all start-end points
UNWIND {wps} AS wpstartid
UNWIND {wps} AS wpendid
WITH wpstartid,wpendid WHERE wpstartid<wpendid

// for each start-end combi,calculate shortestPath() with a WHERE clasue
MATCH (wpstart) WHERE id(wpstart)=wpstartid
MATCH (wpend) WHERE id(wpend)=wpendid
MATCH p=shortestPath((wpstart)-[*..5]-(wpend))
WHERE ALL(id IN {wps}  WHERE id IN EXTRACT(n IN nodes(p) | id(n))   )

//return the shortest of the shortestPath()s
WITH p, size(nodes(p)) as length order by length limit 1
RETURN EXTRACT(n IN nodes(p) | id(n))

这种方法并不总是有效,因为有一个内部优化可以确定应用WHERE子句的阶段。所以要小心,并准备好回到项目开头的更强大的方法。

1 个答案:

答案 0 :(得分:0)

这将是一个非常令人不满意的答案,但这里有:

您强烈怀疑的问题可以归结为Hamiltonian Paths的问题。这是一个经典的图算法问题,结果证明是NP完全的。所以实际上,这意味着虽然有可能实现这一点,但性能可能会非常糟糕。

如果你真的必须实现这个,我可能建议不要使用cypher,而是使用neo4j遍历框架构建一些东西。您可以在线找到至少可以执行此操作的示例代码和算法。但更广泛地说,如果你的数据大小比平凡大,那么这个答案的不满意部分就是我可能根本就不会这样做。

更好的选择可能是将您的图形分解为可以独立工作的较小子问题,或者提出另一种启发式方法,使您接近所需,但不能通过此方法。