【发布时间】:2016-01-20 04:10:16
【问题描述】:
我试图找到连接任意节点集合的最短路径。 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 子句结合起来。然后你会得到一个这样的构造,其中 {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 子句。所以要小心,并准备好在项目的开头回退到更暴力的方法。
【问题讨论】:
-
您是否有任何提示可以在此处应用,以了解航点可能出现的顺序?或者它们可以按任何顺序发生吗?
-
我认为“最短路径”概念仅适用于某些已确定的 A 到 B。您提出问题的方式是指任何/所有节点,只要路径通过航路点节点。这个问题公式的问题是,如果通过航点节点不是从 A 到 B 的最短路径怎么办?还是您只想要合法的 shortestPath 也具有包含航点节点的属性的 A/B 对?
-
@FrobberOfBits 您对我的问题的理解是正确的。事实上,它在 Noe4j 上下文中被称为谓词。我需要有通过所有航点的最短路径,顺序无关紧要。从 Neo4j 2.3.0 开始, shortestPath() 函数有一个包含 predicate 的机制,它被考虑在内,但还不完全准确。所以当你有 (a)-[]->(b) 作为直接相关的节点并且你有 (a),(b),(c),(d),(e) 作为航点时,它有时会返回 0 结果,其中较短的航点列表,如 (a),(b),(c),(d) 可能返回 (c),(d),(e),(b),(a)
标签: neo4j cypher shortest-path