PageRank的java實現


一個網絡(有向帶權圖)中節點u的PageRank的計算公式:

PR(u)表示節點u的PageRank值,d為衰減因子(damping factor)或阻尼系數,一般取d=0.85,N為網絡中的節點總數,nb(u)表示節點u的所有鄰居節點的集合,d(v)表示節點v的出度(如果是無向圖,就是度),w(u,v)表示節點v的邊<u,v>所占的權重(如果對於無權圖或者認為每條邊的權重都一樣,那么w(u,v)=1),PR(v)表示節點v的PageRank值。

由此可以看出要算出節點u的PR值需要先知道它的每個鄰居節點的PR值,似乎是個遞歸的過程。其實初始狀態下,可以給每個節點的PR值都賦值為一個任意正數,例如1,然后通過上述公式不斷迭代計算更新每個節點的PR值,數學證明,最終每個節點的PR值都會收斂到一個穩定的PR值(初值PR不同,最終的PR值也不同,但最后各節點之間PR的大小排名不因初值而改變)。編程時如何確定某個節點u的PR值已經收斂?如果這次的PR值與上次的PR值相差很小的時候就可以認為收斂了。很小是多小?越小越好,但不要太小,免得迭代次數太多浪費時間,可取10的-4或-5次方。

PageRank的數學原理的詳細說明,可參考:

深入淺出PageRank算法

PageRank on undirected and weighted graph

《集體智慧編程》上的例子:

 

Java實現代碼:

Program.java:

 1 package dd.lt;
 2 
 3 import dd.lt.entity.Node;
 4 
 5 public class Program
 6 {
 7     //計算每個節點的PageRank值
 8     public static void CalcPageRank(ArrayList<Node> graph)
 9     {
10         double distance = 0.00001;
11         double d = 0.85;// damping factor
12         double common = (1 - d) / graph.size();
13         while (true)
14         {
15             for (Node n : graph)
16             {
17                 double sum = 0.0;
18                 for (int nodeId : n.getNeighbors())
19                 {
20                     Node nb = getNodeById(nodeId,graph);
21                     sum += nb.getPR() / nb.getDegree();
22                 }
23                 double newPR = common + d * sum;
24                 //如果尚未收斂,賦新值,否則結束迭代
25                 if (Math.abs(n.getPR() - newPR) > distance)
26                     n.setPR(newPR);
27                 else
28                     return;
29             }
30         }
31     }
32 
33     public static Node getNodeById(int nodeId,ArrayList<Node> graph)
34     {
35         for(Node n:graph)
36         {
37             if (n.nodeId==nodeId)
38                 return n;
39         }
40         return null;
41     }
42     
43     
44     public static ArrayList<Node> buildGraph()
45     {
46         ArrayList<Node> graph = new ArrayList<Node>();//圖以節點集合形式來表示
47         //加載數據,組裝好圖結構
48         ....
49         return graph;
50     }
51     
52     public static void main(String[] args)
53     {
54         ArrayList<Node> graph = buildGraph();
55         CalcPageRank(graph);
56         for(Node n:graph)
57         {
58             System.out.println("PageRank of %d is %.2f",n.nodeId,n.getPR());
59         }
60     }
61 }

 

Node.java:

 1 package dd.lt.entity;
 2 
 3 import java.util.ArrayList;
 4 
 5 public class Node implements Comparable<Node>
 6 {
 7     public int nodeId;
 8     private ArrayList<Integer> neighbors = new ArrayList<Integer>();//以鄰接表的形式表示圖結構【無向圖】
 9     private double pr=1;
10     public Node(int nodeId)
11     {
12         this.nodeId = nodeId;
13     }
14 
15     public int getDegree()
16     {
17         return this.neighbors.size();
18     }
19     
20     public ArrayList<Integer> getNeighbors()
21     {
22         return this.neighbors;
23     }
24     public void setNeighbors(ArrayList<Integer> neighbors)
25     {
26         this.neighbors=neighbors;
27     }
28 
29     public double getPR()
30     {
31         return pr;
32     }
33     public void setPR(double val)
34     {
35         this.pr=val;
36     }
37     
38     // 按PageRank值排序
39     public int compareTo(Node anotherNode)
40     {
41         if (this.neighbors != null && anotherNode.neighbors != null)
42         {
43             // 降序排列
44             if (anotherNode.getPR() >this.getPR())
45                 return 1;
46             else if (anotherNode.getPR() <this.getPR())
47                 return -1;
48             else 
49                 return 0;
50             // 升序排列
51             // return this.getPR()-anotherNode.getPR();
52         }
53         return 0;
54     }
55 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM