PageRank算法及Java代碼實現(代碼有詳解)

PageRank算法及Java代碼實現

更改了一些參數的設置,以及加入阻尼係數變量,並且輸出時提示是第幾次的迭代輸出:


 *        相關參數獲取

   * 將鄰接矩陣放在文本文件中,規則如下:

   * 第一行:節點數;

   * 第二行:迭代的初始PR值,個數與節點數一致,以逗號分隔;

   * 第三行開始:每一行對應鄰接矩陣的一行,共N行N列,N同節點數目,其中:

   * 每個節點以逗號分隔,9代表節點自身,1代表有鏈接關係,0代表無鏈接關係。

初始PR值一般爲1,代碼如下:


package org.jazz;


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;


/**
 * 
 * PageRank代碼實現 支持從文件中讀取鄰接矩陣
 */


public class PageRank {


<span style="white-space:pre">	</span>public static void main(String[] args) throws IOException {


<span style="white-space:pre">		</span>int nodeNum = 100; // 節點數


<span style="white-space:pre">		</span>int TIMES = 20; // 迭代次數
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>float alpha = 0.85f; // 阻尼係數d或稱爲alpha 


<span style="white-space:pre">		</span>int[] outLink = new int[nodeNum]; // 存放節點的外鏈數A>>>>Z


<span style="white-space:pre">		</span>float rank = 0f; // 中間變量,保存rank值得中間值


<span style="white-space:pre">		</span>float value = 0f; // 計算後的pagerank值


<span style="white-space:pre">		</span>float[] copyPR = new float[nodeNum]; // 迭代完成後由新數組拷貝過來的副本


<span style="white-space:pre">		</span>boolean flag = true;


<span style="white-space:pre">		</span>/*
<span style="white-space:pre">		</span> * --------------------------------------------------------*
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 相關參數獲取
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 將鄰接矩陣放在文本文件中,規則如下:
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 第一行:節點數;
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 第二行:迭代的初始PR值,個數與節點數一致,以逗號分隔;
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 第三行開始:每一行對應鄰接矩陣的一行,共N行N列,N同節點數目,其中:
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 每個節點以逗號分隔,9代表節點自身,1代表有鏈接關係,0代表無鏈接關係。
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * --------------------------------------------------------
<span style="white-space:pre">		</span> */


<span style="white-space:pre">		</span>FileReader reader = new FileReader("D:\\PRinput-2.txt"); // 鄰接矩陣文件存放位置


<span style="white-space:pre">		</span>BufferedReader br = new BufferedReader(reader);


<span style="white-space:pre">		</span>String paramLine = br.readLine();


<span style="white-space:pre">		</span>String initPR = br.readLine();


<span style="white-space:pre">		</span>/*
<span style="white-space:pre">		</span> * -----------------------------*
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 獲取節點數
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * -----------------------------
<span style="white-space:pre">		</span> */


<span style="white-space:pre">		</span>nodeNum = new Integer(paramLine).intValue(); // 獲取節點數


<span style="white-space:pre">		</span>int[][] link = new int[nodeNum][nodeNum]; // 鄰接矩陣定義


<span style="white-space:pre">		</span>/*
<span style="white-space:pre">		</span> * -----------------------------*
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 獲取迭代初值
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * -----------------------------
<span style="white-space:pre">		</span> */


<span style="white-space:pre">		</span>float[] tempPR = new float[nodeNum];


<span style="white-space:pre">		</span>String[] strInit = initPR.split(",");


<span style="white-space:pre">		</span>for (int i = 0; i < strInit.length; i++) {


<span style="white-space:pre">			</span>tempPR[i] = new Float(strInit[i]).floatValue();


<span style="white-space:pre">			</span>System.out.print(tempPR[i] + "f, ");


<span style="white-space:pre">		</span>}


<span style="white-space:pre">		</span>System.out.println();


<span style="white-space:pre">		</span>/*
<span style="white-space:pre">		</span> * -----------------------------*
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 構造鄰接矩陣
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * -----------------------------
<span style="white-space:pre">		</span> */


<span style="white-space:pre">		</span>int tmp = 0;


<span style="white-space:pre">		</span>while (flag) {


<span style="white-space:pre">			</span>String lineText = br.readLine();


<span style="white-space:pre">			</span>if (null == lineText) {


<span style="white-space:pre">				</span>flag = false;


<span style="white-space:pre">				</span>continue;


<span style="white-space:pre">			</span>}


<span style="white-space:pre">			</span>String[] s = lineText.split(",");


<span style="white-space:pre">			</span>for (int j = 0; j < nodeNum; j++) {


<span style="white-space:pre">				</span>link[tmp][j] = new Integer(s[j]).intValue();


<span style="white-space:pre">			</span>}


<span style="white-space:pre">			</span>tmp++;


<span style="white-space:pre">		</span>}


<span style="white-space:pre">		</span>br.close(); // 關閉流


<span style="white-space:pre">		</span>reader.close(); // 關閉文件


<span style="white-space:pre">		</span>/*
<span style="white-space:pre">		</span> * ---------------------------------*
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 鄰接矩陣打印模塊
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * ---------------------------------
<span style="white-space:pre">		</span> */


<span style="white-space:pre">		</span>for (int i = 0; i < nodeNum; i++) {


<span style="white-space:pre">			</span>for (int j = 0; j < nodeNum; j++) {


<span style="white-space:pre">				</span>System.out.print(link[i][j] + ",");


<span style="white-space:pre">			</span>}


<span style="white-space:pre">			</span>System.out.println();


<span style="white-space:pre">		</span>}


<span style="white-space:pre">		</span>/*
<span style="white-space:pre">		</span> * ---------------------------------*
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 統計節點的外鏈接數
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * ---------------------------------
<span style="white-space:pre">		</span> */


<span style="white-space:pre">		</span>for (int i = 0; i < nodeNum; i++) {


<span style="white-space:pre">			</span>int links = 0;


<span style="white-space:pre">			</span>for (int j = 0; j < nodeNum; j++) {


<span style="white-space:pre">				</span>if (link[i][j] != 9) {


<span style="white-space:pre">					</span>links += link[i][j];


<span style="white-space:pre">				</span>}


<span style="white-space:pre">			</span>}


<span style="white-space:pre">			</span>outLink[i] = links; // 節點0到NODENUM的外鏈數 假設對應爲A B C D


<span style="white-space:pre">		</span>}


<span style="white-space:pre">		</span>System.out.println("");


<span style="white-space:pre">		</span>// 計算PR值


<span style="white-space:pre">		</span>/*
<span style="white-space:pre">		</span> * ----------------------------------------------------------------*
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 循環對每個節點的"入鏈"進行計算,得到該節點的PR值。 所謂入鏈接點,就是指鄰接矩陣
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 的縱向節點,其計算的方向爲縱向;
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 對於橫向的每個節點,有一個對應的縱向節點的數組。
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 爲0表示沒有鏈接,不用計算,
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 爲9表示節點自身,不用計算,
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * 爲1表示有鏈接,我們在前一個步驟中已經得到了該入鏈節點的外鏈接數。
<span style="white-space:pre">		</span> * 
<span style="white-space:pre">		</span> * ----------------------------------------------------------------
<span style="white-space:pre">		</span> */


<span style="white-space:pre">		</span>for (int m = 0; m < TIMES; m++) { // 迭代


<span style="white-space:pre">			</span>/*
<span style="white-space:pre">			</span> * ------------------------------------------------------------*
<span style="white-space:pre">			</span> * 
<span style="white-space:pre">			</span> * 每次迭代完成後,要把各個節點的PR值放到一個數組中,用於下一次迭代
<span style="white-space:pre">			</span> * 
<span style="white-space:pre">			</span> * 假設放到tempPR[]中;
<span style="white-space:pre">			</span> * 
<span style="white-space:pre">			</span> * 同時,還要保留一個計算用PR值的副本,假設爲copyPR[]
<span style="white-space:pre">			</span> * 
<span style="white-space:pre">			</span> * ------------------------------------------------------------
<span style="white-space:pre">			</span> */


<span style="white-space:pre">			</span>// 數組拷貝
<span style="white-space:pre">			</span>int t = m+1;
<span style="white-space:pre">			</span>System.out.println("經過" + t + "次迭代計算,PR值爲:");
<span style="white-space:pre">			</span>


<span style="white-space:pre">			</span>for (int x = 0; x < tempPR.length; x++) {


<span style="white-space:pre">				</span>copyPR[x] = tempPR[x];


<span style="white-space:pre">			</span>}


<span style="white-space:pre">			</span>float sum = 0f; // PageRank臨時求和變量


<span style="white-space:pre">			</span>// float[] fac = {2f,3f,4f,5f};


<span style="white-space:pre">			</span>for (int node = 0; node < nodeNum; node++) {


<span style="white-space:pre">				</span>/*
<span style="white-space:pre">				</span> * --------------------------------------------------------*
<span style="white-space:pre">				</span> * 
<span style="white-space:pre">				</span> * 這個循環是爲了得到本輪各個節點計算後的PR值,將得到一個新的PR值數組
<span style="white-space:pre">				</span> * 
<span style="white-space:pre">				</span> * --------------------------------------------------------
<span style="white-space:pre">				</span> */


<span style="white-space:pre">				</span>// 使用copyPR[]進行計算


<span style="white-space:pre">				</span>for (int j = 0; j < nodeNum; j++) {


<span style="white-space:pre">					</span>int var = link[j][node];


<span style="white-space:pre">					</span>/*
<span style="white-space:pre">					</span> * --------------------------------------------------------*
<span style="white-space:pre">					</span> * 
<span style="white-space:pre">					</span> * 比如要計算第0個節點,那麼對應的第0列:
<span style="white-space:pre">					</span> * 
<span style="white-space:pre">					</span> * link[0][0],link[1][0],link[2][0],link[3][0]
<span style="white-space:pre">					</span> * 
<span style="white-space:pre">					</span> * 爲其對應的縱向節點,
<span style="white-space:pre">					</span> * 
<span style="white-space:pre">					</span> * 其中值爲9代表節點本身,爲0不參與計算,爲1代表與節點有鏈接
<span style="white-space:pre">					</span> * 
<span style="white-space:pre">					</span> * -------------------------------------------------------
<span style="white-space:pre">					</span> */


<span style="white-space:pre">					</span>if (var == 0 | var == 9) {


<span style="white-space:pre">						</span>continue; // 沒有鏈接就跳過


<span style="white-space:pre">					</span>} else {


<span style="white-space:pre">						</span>rank = rank + copyPR[j] / (outLink[j]); // 計算


<span style="white-space:pre">					</span>}


<span style="white-space:pre">				</span>}


<span style="white-space:pre">				</span>
<span style="white-space:pre">				</span>value =(float) (rank * alpha + (1-alpha)); // 這個得到該節點在本輪迭代的最後值


<span style="white-space:pre">				</span>sum += value;


<span style="white-space:pre">				</span>System.out.println("PR[" + node + "]" + value); // 信息打印


<span style="white-space:pre">				</span>tempPR[node] = value;


<span style="white-space:pre">				</span>rank = 0f; // 本節點計算完成後,中間變量清零


<span style="white-space:pre">			</span>}


<span style="white-space:pre">			</span>System.out.println("AVG OF PR = " + sum / nodeNum);


<span style="white-space:pre">			</span>System.out.println("=====================================");

<span style="white-space:pre">		</span>}

<span style="white-space:pre">	</span>}

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章