Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion algorithm/category.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"bellman_ford": "Bellman-Ford",
"floyd_warshall": "Floyd-Warshall",
"topological_sort": "Topological-Sort",
"bridges": "Find-Bridges"
"bridges": "Find-Bridges",
"page_rank": "PageRank Algorithm"
}
},
"cryptography": {
Expand Down
106 changes: 106 additions & 0 deletions algorithm/graph_search/page_rank/basic/code.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
PageRank Algorithm Version 1
Equation:
PR (X) = (1 - D) + D (Summation i->X (PR (I) / Out (i)))
NOTE: Algorithm uses the recommended damping factor (D). Number of iterations is small because only a small Web of 5 Pages is simulated
*/

function arraySum (array) {
return array.reduce (function (sum, curr) {
return sum + (curr ? 1 : 0); //if curr is 0 (no edge) or undefined (loop not allowed), sum remains unchanged
}, 0);
}

function showOutgoingEdges (i) {
G [i].forEach (function (edgeExists, j) {
edgeExists && graphTracer._visit (j, i)._wait () && graphTracer._leave (j, i)._wait ();
});
}

//PRECOMPUTATIONS

logger._print ('Calculate Outgoing Edge Count for each Node');
(function calculateOEC () {
var count = 0;
G.forEach (function (relations, i) {
outgoingEdgeCounts [i] = arraySum (relations);
showOutgoingEdges (i);

oecTracer._notify (i, outgoingEdgeCounts [i])._wait ();
oecTracer._denotify (i)._wait ();
});
}) ();

logger._print ('determine incoming nodes for each node');
(function determineIN () {
for (var i = 0; i < G.length; i++) {
for (var j = 0; j < G.length; j++) {
if (G [i] [j]) {
//there's an edge FROM i TO j
graphTracer._visit (j, i)._wait ();

var nextPos = incomingNodes [j].indexOf (-1);
incomingNodes [j] [nextPos] = i;
inTracer._notify (j, nextPos, i)._wait ();
inTracer._denotify (j, nextPos)._wait ();

graphTracer._leave (j, i)._wait ();
}
}
}

//logger._print ('All -1s will be removed from incoming node records, they are irrelevant');
incomingNodes.forEach (function (arr) {
arr.splice (arr.indexOf (-1));
});
}) ();

function updateRank (nodeIndex) {
var inNodeSummation = 0, result;

logger._print ('Updating rank of ' + nodeIndex);
logger._print ('The incoming Nodes of ' + nodeIndex + ' are being highlighted');

incomingNodes [nodeIndex].forEach (function (incoming, i) {
inTracer._select (nodeIndex, i)._wait ();
logger._print ('Outgoing edge count of ' + incoming + ' is ' + outgoingEdgeCounts [incoming]);
oecTracer._select (incoming)._wait ();

inNodeSummation += (ranks [incoming] / outgoingEdgeCounts [incoming]);

oecTracer._deselect (incoming)._wait ();
inTracer._deselect (nodeIndex, i)._wait ();
});
logger._print ('In-Node summation of ' + nodeIndex + ' = ' + inNodeSummation);

result = (1 - damping) + (damping * inNodeSummation);
logger._print ('Therefore, using Equation, new rank of ' + nodeIndex + ' = ' + result);
return result;
}

var damping = 0.85,
iterations = 7;
var initialRank = 1.0;

logger._print ('Initialized all Page ranks to ' + initialRank);
ranks = filledArray (G.length, initialRank);

rankTracer._setData (ranks);
logger._print ('Begin execution of PageRank Version #1');
logger._print ('Equation used: PR (X) = (1 - D) + D (In-Node-Summation i->X (PR (I) / Out (i)))');
logger._print ('D = Damping Factor, PR (X) = Page rank of Node X, i = the ith In-Node of X, Out (i) = outgoing Edge Count of i');
logger._print ('');

while (iterations--) {
for (var node = 0; node < ranks.length; node++) {
ranks [node] = updateRank (node);
rankTracer._notify (node, ranks [node])._wait ();
rankTracer._notify (node)._wait ();
}
}

logger._print ('Page Ranks have been converged to.')
ranks.forEach (function (rank, node) {
logger._print ('Rank of Node #' + node + ' = ' + rank);
});
logger._print ('Done');
21 changes: 21 additions & 0 deletions algorithm/graph_search/page_rank/basic/data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
function filledArray (length, value) {
return Array.apply (null, Array (length)).map (Number.prototype.valueOf, value);
}

var G = new DirectedGraph.random (5, 0.4),
ranks,
outgoingEdgeCounts = filledArray (G.length, 0),
incomingNodes;

var graphTracer = new DirectedGraphTracer ('Web Page inter-connections'),
rankTracer = new Array1DTracer ('Web Page Ranks'),
oecTracer = new Array1DTracer ('Outgoing Edge Counts'),
inTracer = new Array2DTracer ('Incoming Nodes');

var logger = new LogTracer ();

graphTracer._setData (G);
oecTracer._setData (outgoingEdgeCounts);

for (incomingNodes = []; incomingNodes.length < G.length; incomingNodes.push (filledArray (G.length, -1)));
inTracer._setData (incomingNodes);
17 changes: 17 additions & 0 deletions algorithm/graph_search/page_rank/desc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"PageRank-Algorithm": "PageRank is an algorithm used by Google Search to rank websites in their search engine results.",
"Applications": [
"Web Page Indexing for refining search results"
],
"Complexity": {
"time": "worst O(|V|+|E|)",
"space": "worst O(|V|)"
},
"References": [
"<a href='http://www.cs.princeton.edu/~chazelle/courses/BIB/pagerank.htm'>Princeton university</a>",
"<a href='http://pr.efactory.de/e-pagerank-algorithm.shtml'>E-Factory</a>"
],
"files": {
"basic": "Version #1 of PageRank Algorithm (does not take into account the total number of nodes in the graph, i.e., number of pages on web)."
}
}