@graphty/algorithms
Version:
Graph algorithms library for browser environments implemented in TypeScript
85 lines • 3.21 kB
JavaScript
/**
* Calculate Katz centrality for all nodes in the graph
* Uses iterative method to compute centrality scores
*/
export function katzCentrality(graph, options = {}) {
const { alpha = 0.1, beta = 1.0, maxIterations = 100, tolerance = 1e-6, normalized = true, } = options;
const centrality = {};
const nodes = Array.from(graph.nodes());
const nodeIds = nodes.map((node) => node.id);
if (nodeIds.length === 0) {
return centrality;
}
// Check if alpha is valid (should be less than 1/lambda_max)
// For simplicity, we'll trust the user's choice or use conservative default
// Initialize centrality scores
let currentScores = new Map();
let previousScores = new Map();
// Start with beta for all nodes
for (const nodeId of nodeIds) {
currentScores.set(nodeId.toString(), beta);
}
// Iterative computation
for (let iteration = 0; iteration < maxIterations; iteration++) {
previousScores = new Map(currentScores);
currentScores = new Map();
// Update each node's centrality
for (const nodeId of nodeIds) {
let sum = 0;
// For directed graphs, use in-neighbors
// For undirected graphs, use all neighbors
const neighbors = graph.isDirected ?
Array.from(graph.inNeighbors(nodeId)) :
graph.neighbors(nodeId);
for (const neighbor of neighbors) {
const neighborKey = neighbor.toString();
sum += previousScores.get(neighborKey) ?? 0;
}
currentScores.set(nodeId.toString(), (alpha * sum) + beta);
}
// Check for convergence
let maxDiff = 0;
for (const [nodeId, value] of Array.from(currentScores)) {
const prevValue = previousScores.get(nodeId) ?? 0;
const diff = Math.abs(value - prevValue);
maxDiff = Math.max(maxDiff, diff);
}
if (maxDiff < tolerance) {
break;
}
}
// Prepare results
for (const [nodeId, value] of Array.from(currentScores)) {
centrality[nodeId] = value;
}
// Normalize if requested
if (normalized) {
let maxValue = 0;
let minValue = Number.POSITIVE_INFINITY;
for (const value of Object.values(centrality)) {
maxValue = Math.max(maxValue, value);
minValue = Math.min(minValue, value);
}
const range = maxValue - minValue;
if (range > 0) {
for (const nodeId of Object.keys(centrality)) {
const centralityValue = centrality[nodeId];
if (centralityValue !== undefined) {
centrality[nodeId] = (centralityValue - minValue) / range;
}
}
}
}
return centrality;
}
/**
* Calculate Katz centrality for a specific node
*/
export function nodeKatzCentrality(graph, nodeId, options = {}) {
if (!graph.hasNode(nodeId)) {
throw new Error(`Node ${String(nodeId)} not found in graph`);
}
const centrality = katzCentrality(graph, options);
return centrality[nodeId.toString()] ?? 0;
}
//# sourceMappingURL=katz.js.map