我已经阅读了许多文章以及Spark自己的文档,其中说Graphx Triangle Count要求Graph以Canonical Orientated为主。关于规范方向,描述为边缘source_id< DEST_ID。
在图表中有以下三条边
edges.add(new Edge<String>(1, 2, "Friend"));
edges.add(new Edge<String>(2, 3, "Advisor"));
edges.add(new Edge<String>(1, 3, "Friend"));
它表明节点1,2,3有一个与之相关的三角形,这是有意义的。但是,即使我按如下方式更改边缘的方向,结果仍然相同。
edges.add(new Edge<String>(2, 1, "Friend"));
edges.add(new Edge<String>(3, 2, "Advisor"));
edges.add(new Edge<String>(3, 1, "Friend"));
这令我感到困惑,因为在这种情况下,edge的source_id大于dest_id。有人可以解释这个概念吗?
答案 0 :(得分:1)
这取决于您如何在GraphX中执行三角计数算法。如果您只是致电TriangleCount.run
,那么GraphX会为您规划化图表,更具体地说,.run
方法如下所示:
def run[VD: ClassTag, ED: ClassTag](graph: Graph[VD, ED]): Graph[Int, ED] = {
// Transform the edge data something cheap to shuffle and then canonicalize
val canonicalGraph = graph.mapEdges(e => true).removeSelfEdges().convertToCanonicalEdges()
// Get the triangle counts
val counters = runPreCanonicalized(canonicalGraph).vertices
// Join them bath with the original graph
graph.outerJoinVertices(counters) { (vid, _, optCounter: Option[Int]) =>
optCounter.getOrElse(0)
}
}
请注意,run方法计算图形的规范方向然后运行。此外,即使您致电graph.triangleCount()
,此方法也只是从上方调用TriangleCount.run
:
def triangleCount(): Graph[Int, ED] = {
TriangleCount.run(graph)
}
我相信这就是为什么你的代码返回相同的值,无论你定位边缘的方式。至于为什么GraphX需要规范方向,我不太确定。我能想到两个原因:
edgeFunc
函数中的runPreCanonicalized
假设/要求边缘是规范的。您应该知道.run
方法可能很昂贵。文档明确指出&#34;规范化过程是昂贵的,因为它需要重新分区图。如果输入数据已经采用规范形式&#39;删除自行周期后,应使用TriangleCount.runPreCanonicalized
代替。&#34;
我希望这有用:)