我正在尝试实现一个包含100万个节点作为输入的pagerank算法。
但是,我有这个错误。我很确定这是因为一个开放的递归调用问题,来自generateParamList()。
我试图以不同的方式使这个方法不使用递归,但一次又一次失败。如果您让我知道如何修改“generateParamList()”,我将非常感谢!!!
Exception in thread "main" java.lang.StackOverflowError
at Ranking.getInboundLinks(Ranking.java:200)
at Ranking.generateParamList(Ranking.java:172)
import Jama.Matrix;
public class Ranking {
private final double DAMPING_FACTOR = 0.85;
private List params = new ArrayList();
private static Map<String, String[]> outlinkMap = new HashMap();
private static Map<String, String[]> inlinkMap = new HashMap();
public static void main(String[] args) throws IOException {
Ranking ranking = new Ranking();
FileInputStream in = new FileInputStream("linkgraph_test.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
String[] tempStringArray = null;
int iTemp = 0;
while ((strLine = br.readLine()) != null) {
tempStringArray = strLine.split(" ");
String[] tempValueArray = new String[tempStringArray.length-1];
for(iTemp=1;iTemp<tempStringArray.length;iTemp++){
tempValueArray[iTemp-1] = tempStringArray[iTemp];
}
outlinkMap.put(tempStringArray[0], tempValueArray);
}
in.close();
setInboundLinks();
for(int j=1;j<=outlinkMap.size();j++){
String keytoString = Integer.toString(j);
System.out.println(keytoString+" "+ranking.rank(keytoString));
}
}
/*
*
* Solve the equation of ax=b, which : a is the generated matrix based on the parameter constants. x is the page ranks matrix. b is a n*1 matrix which all the values are equal to the damping factor.
*
*/
public double rank(String pageId) {
generateParamList(pageId);
Matrix a = new Matrix(generateMatrix());
double[][] arrB = new double[params.size()][1];
for (int i = 0; i < params.size(); i++) {
arrB[i][0] = 1 - DAMPING_FACTOR;
}
Matrix b = new Matrix(arrB);
// Solve the equation and get the page ranks
Matrix x = a.solve(b);
int ind = 0;
int cnt = 0;
for (Iterator it = params.iterator(); it.hasNext();) {
String curPage = (String) it.next();
if (curPage.equals(pageId))
ind = cnt;
cnt++;
}
return x.getArray()[ind][0];
}
/*
*
* This method generates the matrix of the linear equations. The generated
*
* matrix is a n*n matrix where n is number of the related pages.
*
*/
private double[][] generateMatrix() {
double[][] arr = new double[params.size()][params.size()];
for (int i = 0; i < params.size(); i++) {
for (int j = 0; j < params.size(); j++) {
arr[i][j] = getMultiFactor((String) params.get(i),(String) params.get(j));
}
}
return arr;
}
/*
*
* This method returns the constant of the given variable in the linear equation.
*
*/
private double getMultiFactor(String sourceId, String linkId) {
if (sourceId.equals(linkId))
return 1;
if(!sourceId.equals(linkId) && getInboundLinks(sourceId)!=null ) {
//System.out.println("source"+sourceId+"\tlinkInd"+linkId);
String[] inc = getInboundLinks(sourceId);
for (int i = 0; i < inc.length; i++) {
if (inc[i].equals(linkId)) {
return -1*(DAMPING_FACTOR / getOutboundLinks(linkId).length);
}
}
}
return 0;
}
/*
*
* This method returns list of the related pages. This list is also the parameters in the linear equation.
*
*/
private void generateParamList(String pageId) {
System.out.println("start"+pageId);
if(getInboundLinks(pageId)!=null){
// Add the starting page.
if (!params.contains(pageId)) params.add(pageId);
// Get list of the inbound pages
String[] inc = getInboundLinks(pageId);
// Add the inbound links to the params list and do same for inbound links
for (int i = 0; i < inc.length; i++) {
if (!params.contains(inc[i])){
generateParamList(inc[i]);
}
}
}
}
/*
*
* Return list of the inbound links to a given page.
*
*/
private String[] getInboundLinks(String pageId) {
return (String[]) inlinkMap.get(pageId);
}
private static void setInboundLinks(){
int valueLength;
String keytoString;
String[] outlinkValueArray, inlinkValueArrayTemp, tempCopyArray, resultArray;
for(int i=1; i<=outlinkMap.size();i++){
keytoString = Integer.toString(i);
outlinkValueArray= outlinkMap.get(keytoString);
if(outlinkValueArray!=null){
valueLength = outlinkValueArray.length;
for(int j=0; j<valueLength;j++){
String[] tempValueArray = new String[1];
if(!inlinkMap.containsKey(outlinkValueArray[j])){
tempValueArray[0] = keytoString;
inlinkMap.put(outlinkValueArray[j],tempValueArray);
}
else{
tempCopyArray = inlinkMap.get(outlinkValueArray[j]);
tempValueArray[0] = keytoString;
resultArray = mergeArray(tempCopyArray, tempValueArray);
inlinkMap.put(outlinkValueArray[j],resultArray);
}
}
}
}
}
public static String[] mergeArray(String[] ar1, String[] ar2){
String[] ar3 = Arrays.copyOf(ar1, ar1.length+ar2.length);
System.arraycopy(ar2, 0, ar3, ar1.length, ar2.length);
return ar3;
}
/*
*
* Returns list of the outbound links from a page.
*
*/
private String[] getOutboundLinks(String pageId) {
// This simulates a simple page collection
return (String[]) outlinkMap.get(pageId);
}
}
输入格式: 1 126645 320349 144068 635538 37354 141327 53842 121180 4786 31658 285466 526963 93938 9097 32341 ............. 2 ......
答案 0 :(得分:0)
为此改变你的函数 generateParamList ,它是一个非递归版本。 我认为它做同样的工作,请测试。我提出了一些意见,以帮助您理解这个概念。
private void generateParamList(String pageId) {
// Don't process duplicates
if (params.contains(pageId)) return;
// Store links not processed
Stack<String> links = new Stack<String>();
// Store current pageId to be processed
links.push(pageId);
// Loop, processed the Stack link, not a recursive call
while (!links.empty()) {
pageId = links.pop();
// Link already processed
if (params.contains(pageId)) continue;
params.add(pageId);
// Get list of the inbound pages
String[] inc = getInboundLinks(pageId);
for (int i = 0; i < inc.length; i++) {
// Store link to be processed by the loop
links.push(inc[i]);
}
}
}