我想找出有向图中给定顶点的可到达顶点的数量(见下图),例如对于id = 0L,由于它连接到1L和2L,1L连接到3L,2L连接到4L,因此,输出应为4.以下是图形关系数据:
edgeid from to distance
0 0 1 10.0
1 0 2 5.0
2 1 2 2.0
3 1 3 1.0
4 2 1 3.0
5 2 3 9.0
6 2 4 2.0
7 3 4 4.0
8 4 0 7.0
9 4 3 5.0
我能够设置图表,但我不知道如何使用graph.edges.filter获取输出
val vertexRDD: RDD[(Long, (Double))] = sc.parallelize(vertexArray)
val edgeRDD: RDD[Edge[Int]] = sc.parallelize(edgeArray)
val graph: Graph[(Double), Int] = Graph(vertexRDD, edgeRDD)
答案 0 :(得分:0)
在您的示例中,所有顶点都与有向路径连接,因此每个顶点的值应为4.
但如果您要删除4> 0 (id = 8)连接,那么会有不同的数量。
由于你的问题依赖于(递归)并行遍历图形,Graphx Pregel API可能是最好的方法。
pregel调用需要3个函数
vprog
使用消息初始化每个顶点(在您的情况下为空List[VertexId]
)sendMsg
一个更新步骤,适用于每次迭代(在您的情况下累积相邻的VertexId
并返回Iterator
并发送消息以发送到下一次迭代mergeMsg
合并两条消息(2 List[VertexId]
s为1)在代码中它看起来像:
def vprog(id: VertexId, orig: List[VertexId], newly: List[VertexId]) : List[VertexId] = newly
def mergeMsg(a: List[VertexId], b: List[VertexId]) : List[VertexId] = (a ++ b).distinct
def sendMsg(trip: EdgeTriplet[List[VertexId],Double]) : Iterator[(VertexId, List[VertexId])] = {
val recursivelyConnectedNeighbors = (trip.dstId :: trip.dstAttr).filterNot(_ == trip.srcId)
if (trip.srcAttr.intersect(recursivelyConnectedNeighbors).length != recursivelyConnectedNeighbors.length)
Iterator((trip.srcId, recursivelyConnectedNeighbors))
else
Iterator.empty
}
val initList = List.empty[VertexId]
val result = graph
.mapVertices((_,_) => initList)
.pregel(
initialMsg = initList,
activeDirection = EdgeDirection.Out
)(vprog, sendMsg, mergeMsg)
.mapVertices((_, neighbors) => neighbors.length)
result.vertices.toDF("vertex", "value").show()
输出:
+------+-----+
|vertex|value|
+------+-----+
| 0| 4|
| 1| 3|
| 2| 3|
| 3| 1|
| 4| 1|
+------+-----+
如果您要获取OoM的遍历大图(或在pregel init中配置spark.graphx.pregel.checkpointInterval
),请务必试用maxIterations