社區(community)定義:同一社區內的節點與節點之間關系緊密,而社區與社區之間的關系稀疏。
設圖G=G(V,E),所謂社區發現是指在圖G中確定nc(>=1)個社區C={C1,C2,...,Cnv},使得各社區的頂點集合構成V的一個覆蓋。
若任意兩個社區的頂點集合的交際均為空,則稱C為非重疊社區(disjoint communities);否則稱為重疊社區(overlapping communities)。
SLPA(Speaker-listener Label Propagation Algorithm)算法是一種社區發現算法,它是對LPA算法(標簽傳播算法)的拓展。
算法思想如下:
輸入參數:迭代次數T,滿足社區次數要求的閾值r
輸出參數:每一個節點的社區分布
(1)首先,每一個節點的存儲器中初始化一個唯一的標簽。
(2)然后,重復進行以下步驟,直到達到最大迭代T:
a. 選擇一個節點作為監聽器;
b. 所選節點的每個鄰居隨機選擇概率正比於該標簽在其存儲器中的出現頻率的標簽,把所選擇的標簽(speakervote)發送到聽眾(listener);
c. 監聽器增加接收到的最流行的標簽到內存。
(3)最后,根據在存儲器里的標簽和閾值r,后處理被用於輸出社區。

1 public int speakerVote() { 2 //Run through each element in the map to create a cumulative distribution 3 Set<Integer> communityIds = communityDistribution.keySet(); 4 ArrayList<Integer> communities = new ArrayList<Integer>(); 5 ArrayList<Integer> cumulativeCounts = new ArrayList<Integer>(); 6 7 int sum=-1; 8 for (Integer comm: communityIds) { 9 sum += communityDistribution.get(comm); 10 communities.add(comm); 11 cumulativeCounts.add(sum); 12 } 13 14 //Generate a random integer in the range [0,sum) 15 int rand = RandomNumGenerator.getRandomInt(sum+1); 16 17 //Find the index of first value greater than rand in cumulativeCounts 18 int i=0; 19 for (i=0; i<cumulativeCounts.size(); i++) { 20 if (cumulativeCounts.get(i)>=rand) 21 break; 22 } 23 24 //Return the corresponding community 25 return communities.get(i); 26 }

1 public void updateLabels(Integer userId){ 2 Set<DefaultWeightedEdge> incomingEdges = userNodegraph.getGraph().incomingEdgesOf(userId);//獲取所有該頂點的入度頂點 3 Map<Integer, Integer> incomingVotes = new HashMap<Integer, Integer>();//所有speaker頂點投票情況 4 5 //For each vertex V with an incoming edge to the current node 6 for ( DefaultWeightedEdge edge: incomingEdges ) { 7 int speakerId = userNodegraph.getGraph().getEdgeSource(edge); 8 UserNode speakerNode = userNodegraph.getNodeMap().get(speakerId); 9 10 int votedCommunity = speakerNode.speakerVote(); 11 int votedCommunitycount = 1; 12 if ( incomingVotes.containsKey(votedCommunity)){ 13 votedCommunitycount += incomingVotes.get(votedCommunity); 14 } 15 incomingVotes.put(votedCommunity, votedCommunitycount); 16 } 17 18 //Find the most popular vote 19 Iterator<Entry<Integer, Integer>> it = incomingVotes.entrySet().iterator(); 20 int popularCommunity=-1; 21 int popularCommunityCount=0; 22 while ( it.hasNext()) { 23 Entry<Integer, Integer> entry = it.next(); 24 if ( entry.getValue() > popularCommunityCount ) { 25 popularCommunity = entry.getKey(); 26 popularCommunityCount = entry.getValue(); 27 } 28 } 29 //Update community distribution of the current node by 1 30 UserNode currentNode = userNodegraph.getNodeMap().get(userId); 31 currentNode.updateCommunityDistribution(popularCommunity, 1); 32 }
注:源代碼請聯系limin12891@163.com.