UNPKG

@graphty/algorithms

Version:

Graph algorithms library for browser environments implemented in TypeScript

85 lines 3.21 kB
/** * 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