zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    js判断是移动端还是PC端
    如何删除mysql注释
    Javascript库的产生和解读
    zeptojs库解读3之ajax模块
    zeptojs库解读2之事件模块
    zeptojs库解读1之整体框架
    发起图片请求的几种可能性(webkit内核)
    让zend studio 支持 redis函数自动提示
    4种常见的MySQL日志类型
    redis 安装
  • 原文地址:https://www.cnblogs.com/aaronhoo/p/6187479.html
Copyright © 2011-2022 走看看