2008年9月12日星期五

PageRank算法代码实现


package org.jazz.pagerank;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/**
* PageRank代码实现
* 支持从文件中读取邻接矩阵
* @author zhengtanyun
* @version 0.1
*/
public class PageRank{

public static void main(String[] args) throws IOException{

int nodeNum = 4; //节点数
int TIMES = 10; //迭代次数
int[]outLink = new int[nodeNum]; //存放节点的外链数A>>>>Z

float rank = 0f; //中间变量,保存rank值得中间值
float value = 0f; //计算后的pagerank值
float[] copyPR = new float[nodeNum]; //迭代完成后由新数组拷贝过来的副本

boolean flag = true;


/* --------------------------------------------------------*
* 相关参数获取
* 将邻接矩阵放在文本文件中,规则如下:
* 第一行:节点数;
* 第二行:迭代的初始PR值,个数与节点数一致,以逗号分隔;
* 第三行开始:每一行对应邻接矩阵的一行,共N行N列,N同节点数目,其中:
* 每个节点以逗号分隔,9代表节点自身,1代表有链接关系,0代表无链接关系。
* --------------------------------------------------------*/
FileReader reader = new FileReader("E:\\a.txt"); //邻接矩阵文件存放位置
BufferedReader br = new BufferedReader(reader);

String paramLine = br.readLine();
String initPR = br.readLine();

/* -----------------------------*
* 获取节点数
* -----------------------------*/
nodeNum = new Integer(paramLine).intValue(); //获取节点数
int[][] link = new int [nodeNum][nodeNum]; //邻接矩阵定义

/* -----------------------------*
* 获取迭代初值
* -----------------------------*/
float[] tempPR = new float[nodeNum];
String[] strInit = initPR.split(",");
for(int i=0;i<strInit.length;i++){
tempPR[i] = new Float(strInit[i]).floatValue();
System.out.print(tempPR[i]+"f, ");
}
System.out.println();

/* -----------------------------*
* 构造邻接矩阵
* -----------------------------*/
int tmp=0;
while(flag){
String lineText = br.readLine();
if(null==lineText){
flag=false;
continue;
}
String[] s = lineText.split(",");

for(int j=0;j<nodeNum;j++){
link[tmp][j] = new Integer(s[j]).intValue();
}
tmp++;
}

br.close(); //关闭流
reader.close(); //关闭文件

/* ---------------------------------*
* 邻接矩阵打印模块
* ---------------------------------*/
for(int i=0;i<nodeNum;i++){
for(int j=0;j<nodeNum;j++){
System.out.print(link[i][j]+",");
}
System.out.println();
}


/* ---------------------------------*
* 统计节点的外链接数
* ---------------------------------*/
for(int i=0;i<nodeNum;i++){
int links = 0;
for(int j=0;j<nodeNum;j++){
if(link[i][j]!=9){
links += link[i][j];
}
}
outLink[i] = links; //节点0到NODENUM的外链数 假设对应为A B C D
}
System.out.println("");

//计算PR值
/* ----------------------------------------------------------------*
* 循环对每个节点的"入链"进行计算,得到该节点的PR值。 所谓入链接点,就是指邻接矩阵
* 的纵向节点,其计算的方向为纵向;
*
* 对于横向的每个节点,有一个对应的纵向节点的数组。
* 为0表示没有链接,不用计算,
* 为9表示节点自身,不用计算,
* 为1表示有链接,我们在前一个步骤中已经得到了该入链节点的外链接数。
* ----------------------------------------------------------------*/
for(int m=0;m<TIMES;m++){ //迭代
/* ------------------------------------------------------------*
* 每次迭代完成后,要把各个节点的PR值放到一个数组中,用于下一次迭代
* 假设放到tempPR[]中;
* 同时,还要保留一个计算用PR值的副本,假设为copyPR[]
* ------------------------------------------------------------*/
//数组拷贝
for(int x=0;x<tempPR.length;x++){
copyPR[x] = tempPR[x];
}
float sum = 0f; //PageRank临时求和变量
//float[] fac = {2f,3f,4f,5f};
for(int node=0;node<nodeNum;node++){
/* --------------------------------------------------------*
* 这个循环是为了得到本轮各个节点计算后的PR值,将得到一个新的PR值数组
* --------------------------------------------------------*/
//使用copyPR[]进行计算
for(int j=0;j<nodeNum;j++){

int var = link[j][node];
/* --------------------------------------------------------*
* 比如要计算第0个节点,那么对应的第0列:
* link[0][0],link[1][0],link[2][0],link[3][0]
* 为其对应的纵向节点,
* 其中值为9代表节点本身,为0不参与计算,为1代表与节点有链接
* -------------------------------------------------------*/
if(var==0var==9){
continue; //没有链接就跳过
}else{
rank = rank+copyPR[j]/(outLink[j]); //计算
}
}
value = rank*0.85f + 0.15f; //这个得到该节点在本轮迭代的最后值
sum += value;

System.out.println("PR["+node+"]"+value); //信息打印
tempPR[node] = value;
rank = 0f; //本节点计算完成后,中间变量清零
}
System.out.println("AVG OF PR = "+sum/nodeNum);
System.out.println("=====================================");
}
}
}

没有评论: