我正在尝试优化force-directed graph。到目前为止,我已经使用天真的O(n 2 )方法实现了它。它只能处理大约1000个节点,这对我的需求来说太少了。
熟悉算法的人知道它有两个主要组成部分:使用胡克定律以库仑定律方式在节点之间排斥和沿边缘形成类似弹簧的吸引力,这两个组件都涉及节点之间的成对计算。
Barnes-Hut算法很好地适用于前者,它会将排斥成分带到O(n log n)。但是我还没能找到弹簧组件类似的东西。我考虑过以下几点:
将基于位置的节点划分为重叠的箱柜,并仅在同一箱柜中的节点之间执行成对计算。但是,这可能不适用于所有情况,特别是因为节点的初始配置是随机的,并且连接的节点可以在任何地方。我可以改变我生成节点的方式,但除非它们都在同一个bin中,否则仍然会产生不正确的结果。
分别存储边缘并迭代它们以计算弹簧力。现在这看起来对我来说是最有希望的方法。
有没有更好的方法我没考虑过?如果它很重要,我正在使用C#,如果投入并行循环是微不足道的话会很好。
答案 0 :(得分:0)
我觉得你给出的第二个选项应该是边缘数量的线性复杂度。只需遍历它们并不断更新相应2个节点上的合力。
编辑:对不起,我之前认为每个节点都通过弹簧连接到每个其他节点。
答案 1 :(得分:0)
如果我理解正确你的排斥成分有O(n log n)且吸引成分是稀疏的:对于你平均每个节点,k <&lt;&lt; n春天般的景点。如果是这样,你可以通过将吸引力存储在邻接列表而不是邻接矩阵中来处理O(n * k)中的吸引力分量。
答案 2 :(得分:0)
最后,我实施了我在第二个案例中所描述的内容并且效果很好。我维护并迭代了每个节点的邻居集合,这使得整个加速程序很容易并行化(与Barnes-Hut一起)。总时间复杂度为O(max(n log n,k))其中k是边的总数。我的C#实现以可接受的性能水平处理大约100000个节点和150000个边缘。