【发布时间】:2014-06-30 00:14:18
【问题描述】:
我使用的是 neo4j-enterprise 版本 2.1.2,并且确实有一个包含 229626 个节点和 1667834 个关系的图表。图模型描述了在关系上具有给定时间戳的人认识另一个人(包括每个人的标识符)。
我尝试使用 Neo4j Java Core API(嵌入式模式)的现有 dijkstra 实现来定义最宽路径问题的算法。不幸的是,它执行得非常慢。但首先让我向您展示我当前实现的一些细节:
-
使用自定义 CostEvaluator 和 PathExpander 定义算法
PathFinder<WeightedPath> finder = GraphAlgoFactory .dijkstra(new TimestampPathExpander(RelationType.KNOWS, Direction.BOTH, 1401746400, depth), new RelationshipCostEvaluator());数字“1401746400”代表时间戳。应该检查每个小于或等于它的关系。我还引入了一个深度来最小化路径长度和搜索开销。
-
时间戳路径扩展器
@Override public Iterable<Relationship> expand(Path path, BranchState<String> state) { List<Relationship> results = new ArrayList<Relationship>(); if(path.length() >= depth) { return results; } for (Relationship r : path.endNode().getRelationships(relationshipType, direction)) { // Traverse only relations for the given timestamp long relationTime = (long) r.getProperty("timestamp"); if (relationTime <= timestamp) { results.add(r); } } return results; }扩展器非常简单。只需查看关系时间戳并将节点添加到结果列表中。如果生成的路径已达到最大深度,则不会向其中添加其他节点。
-
自定义成本评估器
@Override public Double getCost(Relationship relationship, Direction direction) { double measure = significance.edgeStrength(relationship); return measure > 0 ? Double.MAX_VALUE - measure : 0; }
度量值作为容量值,根据包括起始节点和结束节点以及两者关系的度量来计算。因为 dijkstra 无法处理负边权重,所以我只是从大量(Double.Max_value)中减去该度量,从而实现大值被解释为“更便宜”。返回零是不应触及的极端情况。
这就是我预热缓存的方式:
for ( Node n : GlobalGraphOperations.at(db).getAllNodes() ) {
n.getPropertyKeys();
for ( Relationship relationship : n.getRelationships() ) {
Node start = relationship.getStartNode();
}
}
我还使用了软缓存和以下 graph.db 属性,以及节点标识符和关系开始和结束的索引:
neostore.nodestore.db.mapped_memory=3G
neostore.relationshipstore.db.mapped_memory=2G
neostore.propertystore.db.mapped_memory=100M
neostore.propertystore.db.strings.mapped_memory=500M
neostore.propertystore.db.arrays.mapped_memory=100M
neostore.propertystore.db.index.keys.mapped_memory=500M
neostore.propertystore.db.index.mapped_memory=500M
use_memory_mapped_buffers=true
以下是一些始终使用预热缓存的性能指标:
Cache warmup... | Cache warmup...
1742 ms | 30056 ms
1106 ms | 22696 ms
970 ms | 24406 ms
849 ms | 22842 ms
Angela Merkel | Angela Merkel
0.3 | 0.3
CDU | Wladimir Putin
一跳大约需要 3 秒。差不多了。是否有一些我不知道的技巧来改善这些结果?也许我做错了什么?希望有人能帮忙。
问候。
【问题讨论】:
-
耶稣。 Dijkstra 算法的一个可接受的快速实现需要与您的“扩展器”一样多的代码。你有 20 万个节点和超过一百万条边;没有理由不卸载图表并直接做最短路径。
-
也许我不明白你的意思,但是如果这条路径小于或等于 4,我需要两个节点之间的最大容量路径。我对通过重要性表达的有趣路径感兴趣措施。数字表示节点关联的强度,我想检索有趣的路线。所以算法应该走那条显着性最大化的路径。但如果路线超过 4 跳,我可以选择最短路径。我认为 neo4j 可以处理这么大的图和遍历。
-
这甚至不是一个大图。显着性是加法还是您想最大化路径上的最小显着性还是什么? (如果它是乘法的,那么它的对数就是加法的。如果你在做 min-max,你正在寻找 Prim 的算法,它......基本上与 Dijkstra 相同。)
-
意义是附加的。它表示两个节点的连接强度。通过搜索累积重要性最大化的路径,我可以检索仅包含关于起始节点和结束节点的“有趣”节点的路径。显着性度量是这样的 [1]
标签: java algorithm neo4j graph-databases