Referize

An OCR based academic reference application

Android, Tesseract OCR, BoxPDF, PDF.js
Launch website
Use credentials [Email:omkar.patil@ves.ac.in,Password:omkar123]
Download Android application
Download Project Report

Introduction

Whenever we read newspaper articles, novels or journal articles there are several words beyond our current vocabulary and looking up these words on the internet or in a dictionary takes additional effort and time. Such a hiatus might disrupt the continuity essential for natural grasping and the reader's mood. The project attempts to overcome this problem by proposing a system which makes use of Optical Character Recognition (OCR) to scan, process and overlay the meaning of words based on their rarity or those the user intends to look up in real time and will also have provisions for applying the recognition process on an image file on the device’s storage such as a screenshot. By making use of various OCR techniques the words could be recognised, with minimal errors and its meaning can be searched from a local or online dictionary.

Another use case of this general character recognition framework could be extending it to Text Summarisation. The user can summarise the paragraphs of concerned from the Ebooks available for various subjects and create his own summary based on Extraction Summarization.

Problem Statement

As students and academicians we desire reliable sources of explanations on technical topics when we come across them in technical papers, magazines, articles or sources of technical information that are brief and need elaboration.The application that is the subject of this project aims to capture a word or group of technical words through the Android smartphone’s camera and searches for occurrences of the topic in reference books .

The links to the pages of electronic books in which the topic is mentioned is fetched and displayed on the screen in the form of cards. The user can go to that particular page of the electronic book to learn more about that topic.

The user can summarise text about the topics from reference books(which in most cases are generally verbose) and prepare his own summaries using the automatic summarization tool for future reference.

Technology Stack Used

1.Android Studio
2. Gradle
3. Netbeans IDE
4. Apache Web Server
5. Mosquitto MQTT server(for notifications)
6. BoxPDF (Java library for reading and manipulating .pdf files
7. Tesseract OCR (Open source library for optical character recognotion.)
8. PDF.js
9. Glose Word API
10. Volley HTTP Request Pooling Library

Objectives of Referize:

➔ To provide for a real time text processing framework for processing text under the current frame to fetch relevant references to electronic books based on the technical words selected by user.
➔ To provide easy and intuitive touch gestures such as taps to pick the words.
➔ To provide a structured navigation tree which follows the hierarchy of courses, modules and submodules(which is aligned with the syllabus of the university) to allow the student to make quick references to content in electronic books about topics.
➔ To allow users to search topics in the electronic books by searching using keywords which are provided as an input to a natural language search based on a full text index on the topics in the electronic books.
➔ To allow user to enter his course details so that relevant electronic books are recommended to him for study.
➔ To allow the user to create a concise summary of the paragraphs on various topics of interest from those electronic books.
➔ Provide an administrative panel for system administrators to allow them to add universites,fields,branches,courses, modules and submodules(academic hierarchy).
➔ To automate the process of extracting topics from electronic books by parsing the index provided in the electronic book and creating an online index to match search terms.
➔ When same topic is found in multiple books user can summarize the given topic so that is is beneficial for him in future.

Demonstration Videos

1. Using the Android Application and the User Dashboard

2. Using the Administrator Panel


Architectural Overview


Video Explanation



Download the Architectural Overview in .pdf format

If we consider the bare minimum set of components to describe the application functionally, we will have the following:

A. Android Application
Under the mobile device we have the following main components:

A.1 Camera : The application layer camera software which will provide the video frames.

A.2 Local OCR Engine : The local OCR engine is capable of identifying, processing and detecting words bounded by bounding boxes.

A.3 HTTP web request : It represents the HTTP request object in Java which will encapsulate the data to be sent to the server.

B. Summarization Module

C. Server side scripts for data retrieval, parsing of electronic books and their storage

Extractive Summarization Algorithm

This algorithm is based on the page rank algorithm which is used to rank web pages by the popular search engine Google.

The vertices in this case are the sentences in the paragraph and each of the words in these vertices is assigned a weight according to the vector space model and the TF-IDF weighting system.

An index of words is formed from the document and if wi is the ith word in the index then

The weight of wi is computed as follows:

The inverse sentence frequency of wi is computed as follows:

Where N is the total number of sentences in the document and ni is the number of sentences in which the word wi occurs.

The term frequency of the ith index term wi is calculated as follows:

Where freqi,j is the frequency of occurrence of the ith index term in the jth sentence. And maxl (freql,j) gives us the maximum frequency of occurrence of an index term in the jth sentence and is used to normalize the value of the term frequency of each word.Here the value of l loops through all of the index terms.

Summarizer Algorithm

1. Read the input document as a string using org.apache.commons.io.FileUtils

2.   Declare a Set of words to store the index

3.   Break the input string into sentences using java.text.BreakIterator;

4.   Store all sentences in a list.

5.   Declare a list of Nodes with length equal to the length of the input string

6.   Initialize each of the Node in the list with the list of sentences obtained in step 4.

7.   Find inverseTermCounts for each word in the each sentence.

8.   Populate the index of words declared      in step 2.

9.   Declare a map of nodes and their associated weight matrices.(A weight matrix for a node is computed using the product of the term frequency and the inverse sentence frequency of each word in a sentence.)

10.  Declare a graph to store all node to node associations. (In this case every node will have one association with every other node.)

11.  Initialize the graph with all the nodes.

12.  For each node (node_1) in the graph  
        12.1  To every other node (node_2)   in the graph which is not equal to node_1
             12.1.1 Edge weight of edge between these nodes= getDotProduct(Weight matrix of node_1, Weight matrix of node_2)/(getRootOfSumOfSquares(Weight matrix of node_1)*getRootOfSumOfSquares(Weight matrix of node_2));

13.  Run the Page Rank algorithm with the graph obtained, the damping factor and the number of top ranked sentences needed as a parameter.

Page Rank Algorithm

PAGE RANK ALGORITHM
1. Declare a rank map<Node,Rank(double)> 
2. Initialize the rank of each node to 1.
3. Set converged to false
4. While (! Converged)
             4.1 Create a temporary rank map 
              4.2 for( node_i in nodes in graph)
    4.2.1 Initialize sum =0.0
                4.2.2 for( node_j in nodes in graph)
      4.2.2.1 if(! node_j.equals(node_i))
       4.2.2.1.1 If an edge exists between node_i and node_j
        4.2.2.1.1.1weightIJ= Get the edge weight of that edge
        4.2.2.1.1.2 Page rank of node_j = get the rank of node_j from the rank map.
        4.2.2.1.1.3 sum_of_denominator=0.0
        4.2.2.1.1.4 for(node_k in nodes in graph)
         4.2.2.1.1.4.1 if(!node_k.equals(node_j))
          4.2.2.1.1.4.1.1 If an edge exists between node_j and node_k
           4.2.2.1.1.4.1.1.1 weightJK=get the edge weight of that edge
           4.2.2.1.1.4.1.1.2 sum_of_denominator+=weightJK
          4.2.2.1.1.4.1.2 End if
         4.2.2.1.1.4.2 End if
        4.2.2.1.1.5 End for
       4.2.2.1.1.6 sum+=(weightIJ* Page rank of node_j)/sum_of_denominator)
      4.2.2.1.2 End if
     4.2.2.2 End if
    4.2.3 End for
    4.2.4 rank of node_i= (1-damping factor)+damping factor*sum
    4.2.5 Put in temporary rank map (node_i, rank of node_i)
   4.3 End for
  5.End while
  6. Return top ‘n’ ranked sentences arranged by chronological order using the rank map.

Source Code(Java)

1. Class App

The main class that implements the summarizer algorithm

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
package com.omkar.summarization.GraphBasedSummarizer;

import java.io.File;
import java.io.IOException;
import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.io.FileUtils;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ) throws IOException
    {
        
        List<String> sentences;
        Set<String> wordsGlobal;
        List<Node> nodes;
        String inputDocument=FileUtils.readFileToString(new File("input.txt"));
        
        Locale locale = Locale.UK;
        BreakIterator breakIterator =
                BreakIterator.getSentenceInstance(locale);
        
        breakIterator.setText(inputDocument);
        
        sentences=new ArrayList<String>();
        
        int sentenceBoundaryIndex = breakIterator.first();
        int prevIndex         = 0;
        while(sentenceBoundaryIndex != BreakIterator.DONE){
            
            String sentence = inputDocument.substring(prevIndex, sentenceBoundaryIndex);
            if(sentence.compareTo("")!=0)
            {
                sentences.add(sentence);
            }
            prevIndex = sentenceBoundaryIndex;
            sentenceBoundaryIndex = breakIterator.next();
            
        }
        
        //for(String s:sentences)
       //System.out.println("\\"+s+"\\");
        
        //Create new nodes
        nodes=new ArrayList<Node>();
        for(String s:sentences)
        {
            nodes.add(new Node(s));
        }
        
       
        //Code to calculate inverse Sentence Counts for each word in each node.
        for(Node node:nodes)
        {
            Set<String>words=node.getWords();
            for(String word:words)
            {
                //Find inv t f of this word
                int inverseTermCount=0;
                 for(Node node2:nodes)
                    {
                        if(node2.getWords().contains(word))
                        {
                            inverseTermCount++;
                        }
                    }
                 
                 node.setInverseTermCountOfWord(word, Math.log10(inverseTermCount/(double)sentences.size()));
            }
        }
       
        for(Node node:nodes)
        {
            System.out.println(node.getSentence());
            Set<String> words=node.getWords();
            for(String word:words)
            {
                System.out.print(word+" ");
            }
            System.out.println(node.getMaxTermCount());
            System.out.println(node.getTermCounts());
            System.out.println(node.getInverseTermCounts());
            
        }
        
        
        //Create a global index set of words 
        Locale localeWords = Locale.UK;
        BreakIterator breakIteratorWords = BreakIterator.getWordInstance(localeWords) ;
        breakIteratorWords.setText(inputDocument);
        int wordBoundaryIndex = breakIteratorWords.first();
        int prevIndexWords         = 0;
        wordsGlobal= new HashSet<String>();
        
        while(wordBoundaryIndex != BreakIterator.DONE){
            String word = inputDocument.substring(prevIndexWords, wordBoundaryIndex).toLowerCase();
            if(isWord(word)) {
             wordsGlobal.add(word);
            }
              prevIndexWords = wordBoundaryIndex;
              wordBoundaryIndex = breakIteratorWords.next();
        }
        
        Object[] wordIndex=wordsGlobal.toArray();
       
        for(Object word:wordIndex)
        {
            System.out.println(word.toString());
        }
        
       
        
        
        //This index will then be used to create a the weight(tf-isf score) matrix for each sentence.
        Map<Node,double[]> nodeWeightMatrices= new HashMap<Node,double[]>();
        for(Node node:nodes)
        {
                nodeWeightMatrices.put(node, node.getWeightMatrix(wordIndex));
        }
        
        for(Entry entry:nodeWeightMatrices.entrySet())
        {
            double[] weightMatrix= (double[])entry.getValue();
            for(double d:weightMatrix)
            {
                System.out.print(d);
            }
            System.out.println();
        }
        
        Graph graph = new Graph(nodes);
        //Store edges from one to another
        for(Node node:nodes)
        {
            for(Node nodeIn:nodes)
            {
                if(!nodeIn.equals(node))
                {
                    if(!graph.checkIfEdgeExists(node, nodeIn))
                    {
                        double edgeWeight=getDotProduct(nodeWeightMatrices.get(node), nodeWeightMatrices.get(nodeIn))/(getRootOfSumOfSquares(nodeWeightMatrices.get(node))*getRootOfSumOfSquares(nodeWeightMatrices.get(nodeIn)));
                        System.out.println(edgeWeight);
                        graph.addEdge(node, nodeIn, edgeWeight);
                    }
                    
                }
            }
        }   
        
        System.out.println(graph.getEdges());
        
        PageRankAlgorithm pageRank = new PageRankAlgorithm(graph, 0.85);
        String[] rankedSentences=pageRank.startRanking(6);
        
        for(String sentence:sentences)
        {
            for(int i=0;i<rankedSentences.length;i++)
            {
                if(sentence.compareTo(rankedSentences[i])==0)
                {
                    System.out.println(rankedSentences[i]);
                }
            }
            
        }
        
    }
    
    public static double getDotProduct(double[] a,double b[])
    {
        double dotProduct=0.0;
        for(int i=0;i<a.length;i++)
        {
            dotProduct=dotProduct+a[i]*b[i];
        }
        return dotProduct;
    }
    
    public static double getRootOfSumOfSquares(double[] a)
    {
        double sumOfSquares=0.0;
        for(int i=0;i<a.length;i++)
        {
            sumOfSquares=sumOfSquares+a[i]*a[i];
        }
        return Math.sqrt(sumOfSquares);
    }
    
    public static boolean isWord(String word) {
        if(word.length() == 1){
            return Character.isLetterOrDigit(word.charAt(0));
        }
        return !"".equals(word.trim());
    }
}

2. Class Node

A node that represents a sentence in a document.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package com.omkar.summarization.GraphBasedSummarizer;

import java.text.BreakIterator;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class Node {

    String sentence;
    int maxTermCount;
    Set<String> words;
    Map<String,Integer> termCounts;
    Map<String,Double> termFrequency;
    Map<String,Double> inverseTermCounts;
    
    Node(String sentence)
    {
        this.sentence=sentence;
        Locale locale = Locale.UK;
        BreakIterator breakIterator = BreakIterator.getWordInstance(locale) ;
        breakIterator.setText(this.sentence);
        int wordBoundaryIndex = breakIterator.first();
        int prevIndex         = 0;
        
        this.termCounts = new HashMap<String,Integer>();
        this.words=new HashSet<String>();
        while(wordBoundaryIndex != BreakIterator.DONE){
            String word = this.sentence.substring(prevIndex, wordBoundaryIndex).toLowerCase();
            if(isWord(word)) {
                Integer wordCount = this.termCounts.get(word);
                if(wordCount == null) {
                    wordCount = 0;
                }
                wordCount++;
                termCounts.put(word, wordCount);
                this.words.add(word);
            }
            prevIndex = wordBoundaryIndex;
            wordBoundaryIndex = breakIterator.next();
        }
        
        
        this.maxTermCount=(Collections.max(this.termCounts.values()));
       
        this.termFrequency=new HashMap<String,Double>();
        for (Entry<String, Integer> entry : termCounts.entrySet())
        {
            termFrequency.put(entry.getKey(), entry.getValue()/(double)this.maxTermCount);
        }
        
        this.inverseTermCounts=new HashMap<String,Double>();
    }
    
    
    public void setInverseTermCountOfWord(String word, double inverseTermCount)
    {
        this.inverseTermCounts.put(word, new Double(inverseTermCount));
    }
    
    private  boolean isWord(String word) {
            if(word.length() == 1){
                return Character.isLetterOrDigit(word.charAt(0));
            }
            return !"".equals(word.trim());
        }


    public String getSentence() {
        return sentence;
    }


    public void setSentence(String sentence) {
        this.sentence = sentence;
    }


    public int getMaxTermCount() {
        return maxTermCount;
    }


    public void setMaxTermCount(int maxTermCount) {
        this.maxTermCount = maxTermCount;
    }


    public Set<String> getWords() {
        return words;
    }


    public void setWords(Set<String> words) {
        this.words = words;
    }


    public Map<String, Integer> getTermCounts() {
        return termCounts;
    }


    public void setTermCounts(Map<String, Integer> termCounts) {
        this.termCounts = termCounts;
    }


    public Map<String, Double> getTermFrequency() {
        return termFrequency;
    }


    public void setTermFrequency(Map<String, Double> termFrequency) {
        this.termFrequency = termFrequency;
    }


    public Map<String, Double> getInverseTermCounts() {
        return inverseTermCounts;
    }


    public void setInverseTermCounts(Map<String, Double> inverseTermCounts) {
        this.inverseTermCounts = inverseTermCounts;
    }
    
    public double[] getWeightMatrix(Object[] wordIndex)
    {
        double[] weightMatrix =new double[wordIndex.length];
        int weightMatrixCounter=0;
        for(Object word:wordIndex)
        {
            if(this.words.contains(word.toString()))
            {
                weightMatrix[weightMatrixCounter]=(double)(this.termFrequency.get(word.toString())*this.inverseTermCounts.get(word.toString()));
            }
            else
            {
                weightMatrix[weightMatrixCounter]=0.0;
            }
            weightMatrixCounter++;
        }
        
        return weightMatrix;
    }
}

3. Class Edge

An edge between two nodes in a graph.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.omkar.summarization.GraphBasedSummarizer;

public class Edge {
Node firstNode;
Node secondNode;
double edgeWeight;

Edge(Node fNode, Node sNode, double edgeWeight)
{
    this.firstNode=fNode;
    this.secondNode=sNode;
    this.edgeWeight=edgeWeight;
}

public Node getFirstNode() {
    return firstNode;
}

public void setFirstNode(Node firstNode) {
    this.firstNode = firstNode;
}

public Node getSecondNode() {
    return secondNode;
}

public void setSecondNode(Node secondNode) {
    this.secondNode = secondNode;
}

public double getEdgeWeight() {
    return edgeWeight;
}

public void setEdgeWeight(double edgeWeight) {
    this.edgeWeight = edgeWeight;
}


}

4. Class Graph

A graph which is a set of nodes and edges between those nodes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.omkar.summarization.GraphBasedSummarizer;

import java.util.ArrayList;
import java.util.List;

public class Graph {
List<Edge> edges;
List<Node> nodes;

Graph(List<Node> nodes)
{
    this.nodes=nodes;
    this.edges=new ArrayList<Edge>();
}

public void addEdge(Node node1, Node node2, double edgeWeight)
{
    
    this.edges.add(new Edge(node1,node2,edgeWeight));
}

public boolean checkIfEdgeExists(Node node1, Node node2)
{
    for(Edge edge:edges)
    {
        if(edge.firstNode.equals(node1) && edge.secondNode.equals(node2) || edge.firstNode.equals(node2) && edge.secondNode.equals(node1))
        {
            //Edge already exists
            return true;
        }
        
    }
    return false;

}

public Edge getEdgeIfExists(Node node1, Node node2)
{
    for(Edge edge:edges)
    {
        if(edge.firstNode.equals(node1) && edge.secondNode.equals(node2) || edge.firstNode.equals(node2) && edge.secondNode.equals(node1))
        {
            //Edge already exists
            return edge;
        }
    }
    return null;

}

public List<Edge> getEdges() {
    return edges;
}

public void setEdges(List<Edge> edges) {
    this.edges = edges;
}

public List<Node> getNodes() {
    return nodes;
}

public void setNodes(List<Node> nodes) {
    this.nodes = nodes;
}


}

5. Class PageRankAlgorithm

A class that implements the Page Rank Algorithm as discussed above.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package com.omkar.summarization.GraphBasedSummarizer;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.swing.event.TreeExpansionEvent;

import java.util.Set;
import java.util.TreeMap;

import com.google.common.collect.MapDifference;
import com.google.common.collect.Maps;

public class PageRankAlgorithm {
Map<Node,Double> rankMap;
boolean converged;
Graph graph;
double dampingFactor;

public PageRankAlgorithm(Graph graph, double dampingFactor) {
    // TODO Auto-generated constructor stub
    this.graph=graph;
    this.converged=false;
    this.rankMap= new HashMap<Node,Double>();
    for(Node node:graph.getNodes())
    {
        this.rankMap.put(node, 1.0);
    }
    this.dampingFactor=dampingFactor;
}

public String[] startRanking(int summaryLength)
{
    while(!converged)
    {
        Map<Node,Double> tempRankMap= new HashMap<Node, Double>();
        for(Node nodei:graph.getNodes())
        {
            double sum=0.0;
            for(Node nodej:graph.getNodes())
            {
                if(!nodej.equals(nodei))
                {
                    
                    if(graph.checkIfEdgeExists(nodei, nodej))
                    {
                    double wji= graph.getEdgeIfExists(nodei, nodej).getEdgeWeight();
                    //System.out.println(wji);
                    double pageRankj=this.rankMap.get(nodej);
                    double denSum=0.0;
                    for(Node nodek:graph.getNodes())
                    {
                        if(!nodek.equals(nodej))
                        {
                            if(graph.checkIfEdgeExists(nodej, nodek))
                            {
                            double wjk= graph.getEdgeIfExists(nodej, nodek).getEdgeWeight();
                            denSum=denSum+wjk;
                            }
                        }
                    }
                    
                    sum=sum+((wji*pageRankj)/denSum);
                    //System.out.println(sum);
                }       
                }
            }
            
            double rankOfnodei=(1-this.dampingFactor)+this.dampingFactor*sum;
            //System.out.println(rankOfnodei);
            tempRankMap.put(nodei, rankOfnodei);
        }
        System.out.println(tempRankMap);
        //Check for convergence
        boolean differenceFound=false;
        Collection<Double> newValues=tempRankMap.values();
        Collection<Double> oldValues=rankMap.values();
        
        Iterator targetIt = oldValues.iterator();
        for (Object obj:newValues)
        {
            if (!(Math.abs((Double)obj-(Double)targetIt.next())<0.000000001)){differenceFound=true;}
        }

       if(!differenceFound)
       {
           converged=true;
       }
       else
       {
           rankMap=tempRankMap;
           converged=false;
       }
}
    
    TreeMap<Double,String> rankedSentences = new TreeMap<Double, String>();
    
    for(Entry mapEntry:rankMap.entrySet())
    {
        Node tempNode =(Node) mapEntry.getKey();
        rankedSentences.put((Double)mapEntry.getValue(),tempNode.getSentence());
    }
    
    String rankedSentencesArray[]=new String[rankedSentences.size()];
    int sentenceIndex=0;
    for(Entry sentence: rankedSentences.entrySet())
    {
        System.out.println("Rank : "+sentence.getKey()+"Sentence :"+sentence.getValue());
        rankedSentencesArray[sentenceIndex]=sentence.getValue().toString();
        sentenceIndex++;
    }
    
    String[] reducedRankedSentenceArray = new String[summaryLength];
    int redIndex=0;
    for(int i=rankedSentencesArray.length-1;i>=(rankedSentencesArray.length-summaryLength-1);i--)
    {
        reducedRankedSentenceArray[redIndex]=rankedSentencesArray[i];
        redIndex++;
        if(redIndex==summaryLength)break;
    }
    return reducedRankedSentenceArray;
    
    
}

}

Output of the Summarizer

Given the following input paragraph:

Another way to determine what to look for is to find the most Martian-like places on Earth. The hyper-arid, high-altitude Atacama Desert, which, gets just 0.6 inches (15 millimeters) of rainfall a year but used to be much wetter, is exposed to punishing ultraviolet radiation and has active geothermal features such as hot springs. "If you want to find the microbe, you have to become the microbe. Very early on, you need to shelter — you need to adapt and you need to survive," Cabrol said. Microbes would also have to "organize around oases and organize a lot faster." These Martian oases could be similar, in some ways, to the evaporating lakes, salt flats and hot springs of the Atacama, Cabron said. Ancient creatures in these Martian environments would likely be extremophiles or superbugs that are highly adaptive, and are possibly very quick to form symbiotic communities, Cabrol said. While structures that could provide microbial habitats might be found on Mars, researchers will have to know where to look in the first place, Cabrol said. They won't get many opportunities to sample in many places, she said. Finding the tools with the resolution to identify those habitats will also be challenging, Cabrol added. However, drones that can fly up and down to image the area at different scales could reveal some of the fine detail that provides clues for ancient life, she said. And some tools already heading out on the Mars 2020 mission could reveal evidence of potential habitats. For instance, Cabrol showed images of Gusev Crater. Pictures of that feature initially lacked the resolution to reveal any evidence of habitat. But after looking at the light spectra reflected, "The spectra are telling us this is something that could be related to hydrothermal activity and constructs," Cabrol said. "There's only one way of knowing — it's to go back."

The summarizer produced the following output:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Rank : 0.43783834671158367Sentence :"There's only one way of knowing — it's to go back."
Rank : 0.5481579720600451Sentence :They won't get many opportunities to sample in many places, she said. 
Rank : 0.619597050307139Sentence :For instance, Cabrol showed images of Gusev Crater. 
Rank : 0.6988569438953812Sentence :Microbes would also have to "organize around oases and organize a lot faster."


Rank : 0.7582177019994549Sentence :The hyper-arid, high-altitude Atacama Desert, which, gets just 0.6 inches (15 millimeters) of rainfall a year but used to be much wetter, is exposed to punishing ultraviolet radiation and has active geothermal features such as hot springs.


Rank : 1.0039943770837287Sentence :Very early on, you need to shelter  you need to adapt and you need to survive," Cabrol said. 
Rank : 1.0072314462422134Sentence :Pictures of that feature initially lacked the resolution to reveal any evidence of habitat. 
Rank : 1.0179725658895435Sentence :"If you want to find the microbe, you have to become the microbe. 
Rank : 1.0301468179131923Sentence :But after looking at the light spectra reflected, "The spectra are telling us this is something that could be related to hydrothermal activity and constructs," Cabrol said. 
Rank : 1.096728114416393Sentence :Ancient creatures in these Martian environments would likely be extremophiles or superbugs that are highly adaptive, and are possibly very quick to form symbiotic communities, Cabrol said.


Rank : 1.1014702277489823Sentence :Finding the tools with the resolution to identify those habitats will also be challenging, Cabrol added.


Rank : 1.154489628552796Sentence : Another way to determine what to look for is to find the most Martian-like places on Earth. 
Rank : 1.2741403231012418Sentence :However, drones that can fly up and down to image the area at different scales could reveal some of the fine detail that provides clues for ancient life, she said.


Rank : 1.3989112787721734Sentence :And some tools already heading out on the Mars 2020 mission could reveal evidence of potential habitats. 
Rank : 1.419985023981618Sentence :These Martian oases could be similar, in some ways, to the evaporating lakes, salt flats and hot springs of the Atacama, Cabron said.


Rank : 1.4322621813245138Sentence :While structures that could provide microbial habitats might be found on Mars, researchers will have to know where to look in the first place, Cabrol said. 

Final Summary(6 sentences):
--------------------------------------------
 Another way to determine what to look for is to find the most Martian-like places on Earth. 
These Martian oases could be similar, in some ways, to the evaporating lakes, salt flats and hot springs of the Atacama, Cabron said.


While structures that could provide microbial habitats might be found on Mars, researchers will have to know where to look in the first place, Cabrol said. 
Finding the tools with the resolution to identify those habitats will also be challenging, Cabrol added.


However, drones that can fly up and down to image the area at different scales could reveal some of the fine detail that provides clues for ancient life, she said.


And some tools already heading out on the Mars 2020 mission could reveal evidence of potential habitats.