Skip to content

Instantly share code, notes, and snippets.

@JadedBlueEyes
Created March 28, 2023 19:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JadedBlueEyes/6a7eecd637ce7f71a38b348e76f2158f to your computer and use it in GitHub Desktop.
Save JadedBlueEyes/6a7eecd637ce7f71a38b348e76f2158f to your computer and use it in GitHub Desktop.
Pagerank implemented in plain JS and with graphology.js
import Graph from "graphology";
const defaultDampening = 0.85;
const defaultIterations = 40
// graph, or page map: the pages that exist, and that each page links to
/**
*
* @param {Graph} graph
* @param {number} iterations
* @param {number} dampening
* @param {*} initialScores
* @returns scores
*/
export function pageRank (graph, iterations, dampening, initialScores) {
// dampening factor - how likely the user is to continue clicking
dampening = dampening ?? defaultDampening
iterations = iterations ?? defaultIterations
let scores = {}
// set the initial score of each page
if (initialScores) {
graph.nodes().forEach((node) => {
scores[node] = initialScores[node] ?? 1.0;
})
} else {
graph.nodes().forEach((node) => {
scores[node] = 1.0;
})
}
let i = iterations;
while (i >= 0) {
// We want to calculate in stages, so store the new values until all values have been calculated
let iterationScores = {}
// Calculate the new score for each page according to the pagerank formula
graph.nodes().forEach((node) => {
let score = 1 - dampening
graph.inboundEdges(node).forEach((edge) => {
let neighbor = graph.source(edge)
let count = graph.outEdges(neighbor).length
let edgeScore = scores[neighbor] / count
score = score + dampening * edgeScore
})
iterationScores[node] = score
})
// update the stored final values and continue the loop
scores = iterationScores
i = i - 1;
}
return scores
}
const defaultDampening = 0.85;
const defaultIterations = 40
// graph, or page map: the pages that exist, and that each page links to
export function pageRank (graph, iterations, dampening, initialScores) {
// dampening factor - how likely the user is to continue clicking
dampening = dampening ?? defaultDampening
iterations = iterations ?? defaultIterations
let scores = {}
// set the initial score of each page
for (let node in graph) {
scores[node] = initialScores[node] || 1.0;
}
// invert the graph. eg. page a is linked to by pages e and f
let invertedGraph = {}
for (let node in graph) {
invertedGraph[node] = [];
}
for (let node in graph) {
graph[node].forEach((edge) => {
invertedGraph[edge].push(node)
})
}
let i = iterations;
while (i >= 0) {
// We want to calculate in stages, so store the new values until all values have been calculated
let iterationScores = {}
// Calculate the new score for each page according to the pagerank formula
for (let node in graph) {
let score = 1 - dampening
invertedGraph[node].forEach((edge) => {
let count = graph[edge].length
let edgeScore = scores[edge] / count
score = score + dampening * edgeScore
})
iterationScores[node] = score
}
// update the stored final values and continue the loop
scores = iterationScores
i = i - 1;
}
return scores
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment