in vermeer/algorithms/louvain.go [284:379]
func (lw *LouvainWorker) Compute(vertexID uint32, pID int) {
//step 1:同步所有顶点的邻边
vertID := vertexID - lw.WContext.GraphData.VertIDStart
if len(lw.WContext.GraphData.Edges.GetInEdges(vertID))+len(lw.WContext.GraphData.Edges.GetOutEdges(vertID)) == 0 {
return
}
if lw.WContext.Step == 1 {
lw.neighborEdges[vertexID] = make([]serialize.SUint32, 0, len(lw.WContext.GraphData.Edges.GetInEdges(vertID)))
tempMap := make(map[serialize.SUint32]struct{})
tempMap[serialize.SUint32(vertexID)] = struct{}{}
for _, edge := range lw.WContext.GraphData.Edges.GetInEdges(vertID) {
if _, ok := tempMap[edge]; !ok {
lw.neighborEdges[vertexID] = append(lw.neighborEdges[vertexID], edge)
tempMap[edge] = struct{}{}
}
}
for _, edge := range lw.WContext.GraphData.Edges.GetOutEdges(vertID) {
if _, ok := tempMap[edge]; !ok {
lw.neighborEdges[vertexID] = append(lw.neighborEdges[vertexID], edge)
tempMap[edge] = struct{}{}
}
}
} else {
if lw.firstStep {
//以vertex为基本单元计算
currCommID := lw.firstStepCommID[vertexID]
kI := lw.firstStepKI[vertexID]
//neighborCommKIin 计算neighbor社区的KIin
neighborCommKVInInPID := make(map[serialize.SUint32]float64, len(lw.neighborEdges[vertexID]))
for _, neighbor := range lw.neighborEdges[vertexID] {
neighborCommID := lw.firstStepCommID[neighbor]
neighborCommKVInInPID[neighborCommID] += 1
}
var maxDeltaQ float64
targetCommID := currCommID
for neighborCommID, kVIn := range neighborCommKVInInPID {
sigmaTot := lw.communities[neighborCommID].sigmaTot
if currCommID == neighborCommID {
sigmaTot -= kI
}
commDeltaQ := lw.calDeltaQ(kVIn, sigmaTot, kI)
if commDeltaQ > maxDeltaQ {
targetCommID = neighborCommID
maxDeltaQ = commDeltaQ
}
}
if maxDeltaQ == 0 && len(lw.communities[currCommID].node) > 1 {
lw.node2comm[pID][serialize.SUint32(vertexID)] = lw.emptyComm
}
if targetCommID >= currCommID {
return
}
lw.node2comm[pID][serialize.SUint32(vertexID)] = targetCommID
} else {
nodeID := lw.nodeID[vertexID]
if lw.nodes[nodeID] == nil || atomic.LoadInt32(&lw.nodes[nodeID].once) > 0 {
return
}
atomic.AddInt32(&lw.nodes[nodeID].once, 1)
currCommID := lw.nodes[nodeID].commID
kI := lw.nodes[nodeID].kI
//neighborCommKIin 计算neighbor社区的KIin
neighborCommKVInInPID := make(map[serialize.SUint32]float64, len(lw.nodes[nodeID].neighbors))
for neighbor, weight := range lw.nodes[nodeID].neighbors {
neighborCommID := lw.nodes[neighbor].commID
neighborCommKVInInPID[neighborCommID] += weight
}
var maxDeltaQ float64
targetCommID := currCommID
for neighborCommID, kVIn := range neighborCommKVInInPID {
sigmaTot := lw.communities[neighborCommID].sigmaTot
if currCommID == neighborCommID {
sigmaTot -= kI
}
commDeltaQ := lw.calDeltaQ(kVIn, sigmaTot, kI)
if commDeltaQ > maxDeltaQ {
targetCommID = neighborCommID
maxDeltaQ = commDeltaQ
}
}
if maxDeltaQ == 0 && len(lw.communities[currCommID].node) > 1 {
lw.node2comm[pID][nodeID] = lw.emptyComm
}
if targetCommID >= currCommID {
return
}
lw.node2comm[pID][nodeID] = targetCommID
}
}
}