2012-04-07 3 views
2

1 백만 개의 노드가있는 페이지 랭크 알고리즘을 입력으로 구현하려고합니다.pagerank : java.lang.StackOverflowError를 해결하는 방법?

그러나이 오류가 발생했습니다. 나는 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 126,645 320,349 144,068 635,538 141,327 37,354 53,842 121,180 285,466 526,963 31,658 4,786 9,097 93,938 32,341 ............. 2 ......

+0

많은 재귀 호출에 대해 재귀 함수가 큰 데이터에는 적합하지 않습니다. 이 경우 루프를 사용해야합니다. – LawfulHacker

+0

@SergioGarcia 감사합니다 sergio,하지만 더 구체적으로 말할 수 있을까요? 그렇다면 여기에서 어떻게 수정할 수 있을까요? "private void generateParamList (String pageId) {........ (int i = 0; i

답변

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]); 
     } 
    } 
}