diff --git a/pages/students/2016/jan_holp/pagerank.js b/pages/students/2016/jan_holp/pagerank.js new file mode 100644 index 000000000..056391efc --- /dev/null +++ b/pages/students/2016/jan_holp/pagerank.js @@ -0,0 +1,149 @@ +//"use strict"; +// pagerank.js 0.0.1 + +//Use a random surfer algorithm to determine the relative +//rank of nodes. The importance of each node is determined +//by the number of incoming links as well as the importance +//of those incoming links. + +// Expose +// ---------- + +//Expose our library to be called externally +module.exports = function (nodeMatrix, linkProb, tolerance, callback, debug) { + if (!nodeMatrix || !linkProb || !tolerance || !callback) { + throw new Error("Provide 4 arguments: "+ + "nodeMatrix, link probability, tolerance, callback"); + } + //If debug is unset set it to false + if (!debug) { + debug=false; + } + return new Pagerank(nodeMatrix, linkProb, tolerance, callback, debug); +}; + +// Initialize +// ---------- +function Pagerank(nodeMatrix, linkProb, tolerance, callback, debug) { + //**OutgoingNodes:** represents an array of nodes. Each node in this + //array contains an array of nodes to which the corresponding node has + //outgoing links. + this.outgoingNodes = nodeMatrix; + + //console.log(this.outgoingNodes); + //**LinkProb:** a value ?? + this.linkProb = linkProb; + //**Tolerance:** the point at which a solution is deemed optimal. + //Higher values are more accurate, lower values are faster to computer. + this.tolerance = tolerance; + this.callback = callback; + + //Number of outgoing nodes + this.pageCount = Object.keys(this.outgoingNodes).length; + //console.log(this.pageCount); + //**Coeff:** coefficient for the likelihood that a page will be visited. + this.coeff = (1-linkProb)/this.pageCount; + + this.probabilityNodes = !(nodeMatrix instanceof Array) ? {} : []; + this.incomingNodes = !(nodeMatrix instanceof Array) ? {} : []; + //console.log(this.incomingNodes); + this.debug=debug; + + this.startRanking(); +} + +//Start ranking +// ---------- +Pagerank.prototype.startRanking = function () { + + //we initialize all of our probabilities + var initialProbability = 1/this.pageCount, + outgoingNodes = this.outgoingNodes, i, a, index; + + //rearray the graph and generate initial probability + for (i in outgoingNodes) { + this.probabilityNodes[i]=initialProbability; + for (a in outgoingNodes[i]) { + index = outgoingNodes[i][a]; + if (!this.incomingNodes[index]) { + this.incomingNodes[index]=[]; + } + this.incomingNodes[index].push(i); + // console.log(this.incomingNodes); + + } + } + + //if debug is set, print each iteration + if (this.debug) this.reportDebug(1) + + this.iterate(1); +}; + +//Log iteration to console +// ---------- +Pagerank.prototype.reportDebug = function (count) { + //console.log("____ITERATION "+count+"____"); + //console.log("Pages: " + Object.keys(this.outgoingNodes).length); + //console.log("outgoing %j", this.outgoingNodes); + //console.log("incoming %j",this.incomingNodes); + //console.log("probability %j",this.probabilityNodes); +}; + + +//Calculate new weights +// ---------- +Pagerank.prototype.iterate = function(count) { + var result = []; + var resultHash={}; + var prob, ct, b, a, sum, res, max, min; + + //For each node, we look at the incoming edges and + //the weight of the node connected via each edge. + //This weight is divided by the total number of + //outgoing edges from each weighted node and summed to + //determine the new weight of the original node. + for (b in this.probabilityNodes) { + + sum = 0; + if( this.incomingNodes[b] ) { + for ( a=0; a