@graphty/algorithms 1.1.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +820 -235
- package/dist/algorithms.d.ts +42 -2
- package/dist/algorithms.js +11099 -2
- package/dist/algorithms.js.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.d.ts +4 -0
- package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.js +124 -170
- package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
- package/dist/src/algorithms/centrality/closeness.d.ts +26 -1
- package/dist/src/algorithms/centrality/closeness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/closeness.js +56 -149
- package/dist/src/algorithms/centrality/closeness.js.map +1 -1
- package/dist/src/algorithms/centrality/degree.js +3 -3
- package/dist/src/algorithms/centrality/degree.js.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts +39 -0
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js +286 -0
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js.map +1 -0
- package/dist/src/algorithms/centrality/delta-pagerank.d.ts +80 -0
- package/dist/src/algorithms/centrality/delta-pagerank.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/delta-pagerank.js +294 -0
- package/dist/src/algorithms/centrality/delta-pagerank.js.map +1 -0
- package/dist/src/algorithms/centrality/index.d.ts +2 -0
- package/dist/src/algorithms/centrality/index.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/index.js +1 -0
- package/dist/src/algorithms/centrality/index.js.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.d.ts +17 -0
- package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.js +45 -0
- package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
- package/dist/src/algorithms/community/girvan-newman.d.ts.map +1 -1
- package/dist/src/algorithms/community/girvan-newman.js +47 -54
- package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
- package/dist/src/algorithms/community/index.d.ts +2 -0
- package/dist/src/algorithms/community/index.d.ts.map +1 -1
- package/dist/src/algorithms/community/index.js.map +1 -1
- package/dist/src/algorithms/community/label-propagation.d.ts +13 -3
- package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -1
- package/dist/src/algorithms/community/label-propagation.js +50 -35
- package/dist/src/algorithms/community/label-propagation.js.map +1 -1
- package/dist/src/algorithms/community/leiden.d.ts +3 -2
- package/dist/src/algorithms/community/leiden.d.ts.map +1 -1
- package/dist/src/algorithms/community/leiden.js +34 -39
- package/dist/src/algorithms/community/leiden.js.map +1 -1
- package/dist/src/algorithms/community/louvain-optimized.d.ts +112 -0
- package/dist/src/algorithms/community/louvain-optimized.d.ts.map +1 -0
- package/dist/src/algorithms/community/louvain-optimized.js +303 -0
- package/dist/src/algorithms/community/louvain-optimized.js.map +1 -0
- package/dist/src/algorithms/community/louvain.d.ts.map +1 -1
- package/dist/src/algorithms/community/louvain.js +17 -76
- package/dist/src/algorithms/community/louvain.js.map +1 -1
- package/dist/src/algorithms/community/modularity-utils.d.ts +59 -0
- package/dist/src/algorithms/community/modularity-utils.d.ts.map +1 -0
- package/dist/src/algorithms/community/modularity-utils.js +112 -0
- package/dist/src/algorithms/community/modularity-utils.js.map +1 -0
- package/dist/src/algorithms/matching/bipartite.d.ts.map +1 -1
- package/dist/src/algorithms/matching/bipartite.js +8 -40
- package/dist/src/algorithms/matching/bipartite.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.js +1 -12
- package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts +37 -0
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts.map +1 -0
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +193 -0
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js.map +1 -0
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts +5 -2
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.js +15 -14
- package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs-unified.d.ts +29 -0
- package/dist/src/algorithms/traversal/bfs-unified.d.ts.map +1 -0
- package/dist/src/algorithms/traversal/bfs-unified.js +333 -0
- package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -0
- package/dist/src/algorithms/traversal/bfs-variants.d.ts +54 -0
- package/dist/src/algorithms/traversal/bfs-variants.d.ts.map +1 -0
- package/dist/src/algorithms/traversal/bfs-variants.js +368 -0
- package/dist/src/algorithms/traversal/bfs-variants.js.map +1 -0
- package/dist/src/algorithms/traversal/bfs.d.ts +4 -18
- package/dist/src/algorithms/traversal/bfs.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs.js +5 -182
- package/dist/src/algorithms/traversal/bfs.js.map +1 -1
- package/dist/src/benchmark-all-algorithms.d.ts +23 -0
- package/dist/src/benchmark-all-algorithms.d.ts.map +1 -0
- package/dist/src/benchmark-all-algorithms.js +462 -0
- package/dist/src/benchmark-all-algorithms.js.map +1 -0
- package/dist/src/clustering/hierarchical.d.ts +16 -15
- package/dist/src/clustering/hierarchical.d.ts.map +1 -1
- package/dist/src/clustering/hierarchical.js +209 -223
- package/dist/src/clustering/hierarchical.js.map +1 -1
- package/dist/src/clustering/index.d.ts +4 -2
- package/dist/src/clustering/index.d.ts.map +1 -1
- package/dist/src/clustering/index.js +2 -2
- package/dist/src/clustering/index.js.map +1 -1
- package/dist/src/clustering/k-core.d.ts +16 -15
- package/dist/src/clustering/k-core.d.ts.map +1 -1
- package/dist/src/clustering/k-core.js +57 -21
- package/dist/src/clustering/k-core.js.map +1 -1
- package/dist/src/clustering/spectral.d.ts +8 -0
- package/dist/src/clustering/spectral.d.ts.map +1 -1
- package/dist/src/clustering/spectral.js +158 -35
- package/dist/src/clustering/spectral.js.map +1 -1
- package/dist/src/core/graph.js +4 -4
- package/dist/src/core/graph.js.map +1 -1
- package/dist/src/flow/ford-fulkerson.d.ts +17 -11
- package/dist/src/flow/ford-fulkerson.d.ts.map +1 -1
- package/dist/src/flow/ford-fulkerson.js +141 -217
- package/dist/src/flow/ford-fulkerson.js.map +1 -1
- package/dist/src/flow/min-cut.d.ts +6 -5
- package/dist/src/flow/min-cut.d.ts.map +1 -1
- package/dist/src/flow/min-cut.js +17 -8
- package/dist/src/flow/min-cut.js.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/link-prediction/adamic-adar.d.ts.map +1 -1
- package/dist/src/link-prediction/adamic-adar.js +17 -26
- package/dist/src/link-prediction/adamic-adar.js.map +1 -1
- package/dist/src/link-prediction/common-neighbors.d.ts.map +1 -1
- package/dist/src/link-prediction/common-neighbors.js +7 -11
- package/dist/src/link-prediction/common-neighbors.js.map +1 -1
- package/dist/src/optimized/bit-packed.d.ts +143 -0
- package/dist/src/optimized/bit-packed.d.ts.map +1 -0
- package/dist/src/optimized/bit-packed.js +292 -0
- package/dist/src/optimized/bit-packed.js.map +1 -0
- package/dist/src/optimized/csr-graph.d.ts +86 -0
- package/dist/src/optimized/csr-graph.d.ts.map +1 -0
- package/dist/src/optimized/csr-graph.js +341 -0
- package/dist/src/optimized/csr-graph.js.map +1 -0
- package/dist/src/optimized/direction-optimized-bfs.d.ts +74 -0
- package/dist/src/optimized/direction-optimized-bfs.d.ts.map +1 -0
- package/dist/src/optimized/direction-optimized-bfs.js +223 -0
- package/dist/src/optimized/direction-optimized-bfs.js.map +1 -0
- package/dist/src/optimized/graph-adapter.d.ts +62 -0
- package/dist/src/optimized/graph-adapter.d.ts.map +1 -0
- package/dist/src/optimized/graph-adapter.js +146 -0
- package/dist/src/optimized/graph-adapter.js.map +1 -0
- package/dist/src/optimized/index.d.ts +14 -0
- package/dist/src/optimized/index.d.ts.map +1 -0
- package/dist/src/optimized/index.js +28 -0
- package/dist/src/optimized/index.js.map +1 -0
- package/dist/src/research/grsbm.d.ts +83 -0
- package/dist/src/research/grsbm.d.ts.map +1 -0
- package/dist/src/research/grsbm.js +403 -0
- package/dist/src/research/grsbm.js.map +1 -0
- package/dist/src/research/index.d.ts +12 -0
- package/dist/src/research/index.d.ts.map +1 -0
- package/dist/src/research/index.js +14 -0
- package/dist/src/research/index.js.map +1 -0
- package/dist/src/research/sync.d.ts +49 -0
- package/dist/src/research/sync.d.ts.map +1 -0
- package/dist/src/research/sync.js +316 -0
- package/dist/src/research/sync.js.map +1 -0
- package/dist/src/research/terahac.d.ts +65 -0
- package/dist/src/research/terahac.d.ts.map +1 -0
- package/dist/src/research/terahac.js +379 -0
- package/dist/src/research/terahac.js.map +1 -0
- package/dist/src/types/index.d.ts +8 -0
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/utils/algorithm-utilities.d.ts +2 -0
- package/dist/src/utils/algorithm-utilities.d.ts.map +1 -0
- package/dist/src/utils/algorithm-utilities.js +2 -0
- package/dist/src/utils/algorithm-utilities.js.map +1 -0
- package/dist/src/utils/graph-converters.d.ts +79 -0
- package/dist/src/utils/graph-converters.d.ts.map +1 -0
- package/dist/src/utils/graph-converters.js +196 -0
- package/dist/src/utils/graph-converters.js.map +1 -0
- package/dist/src/utils/graph-utilities.d.ts +62 -0
- package/dist/src/utils/graph-utilities.d.ts.map +1 -0
- package/dist/src/utils/graph-utilities.js +148 -0
- package/dist/src/utils/graph-utilities.js.map +1 -0
- package/dist/src/utils/index.d.ts +5 -0
- package/dist/src/utils/index.d.ts.map +1 -0
- package/dist/src/utils/index.js +5 -0
- package/dist/src/utils/index.js.map +1 -0
- package/dist/src/utils/math-utilities.d.ts +52 -0
- package/dist/src/utils/math-utilities.d.ts.map +1 -0
- package/dist/src/utils/math-utilities.js +123 -0
- package/dist/src/utils/math-utilities.js.map +1 -0
- package/dist/src/utils/matrix-utilities.d.ts +2 -0
- package/dist/src/utils/matrix-utilities.d.ts.map +1 -0
- package/dist/src/utils/matrix-utilities.js +2 -0
- package/dist/src/utils/matrix-utilities.js.map +1 -0
- package/dist/src/utils/optimization-helpers.d.ts +33 -0
- package/dist/src/utils/optimization-helpers.d.ts.map +1 -0
- package/dist/src/utils/optimization-helpers.js +47 -0
- package/dist/src/utils/optimization-helpers.js.map +1 -0
- package/package.json +28 -4
- package/src/algorithms/centrality/betweenness.ts +167 -199
- package/src/algorithms/centrality/closeness.ts +73 -191
- package/src/algorithms/centrality/degree.ts +3 -3
- package/src/algorithms/centrality/delta-pagerank-simple.ts +366 -0
- package/src/algorithms/centrality/delta-pagerank.ts +435 -0
- package/src/algorithms/centrality/index.ts +2 -0
- package/src/algorithms/centrality/pagerank.ts +66 -0
- package/src/algorithms/community/girvan-newman.ts +52 -59
- package/src/algorithms/community/index.ts +2 -0
- package/src/algorithms/community/label-propagation.ts +64 -35
- package/src/algorithms/community/leiden.ts +40 -41
- package/src/algorithms/community/louvain-optimized.ts +445 -0
- package/src/algorithms/community/louvain.ts +24 -104
- package/src/algorithms/community/modularity-utils.ts +146 -0
- package/src/algorithms/matching/bipartite.ts +8 -44
- package/src/algorithms/shortest-path/bellman-ford.ts +1 -14
- package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +248 -0
- package/src/algorithms/shortest-path/dijkstra.ts +17 -15
- package/src/algorithms/traversal/bfs-unified.ts +433 -0
- package/src/algorithms/traversal/bfs-variants.ts +496 -0
- package/src/algorithms/traversal/bfs.ts +10 -228
- package/src/benchmark-all-algorithms.ts +548 -0
- package/src/clustering/hierarchical.ts +241 -251
- package/src/clustering/index.ts +4 -2
- package/src/clustering/k-core.ts +87 -39
- package/src/clustering/spectral.ts +185 -34
- package/src/core/graph.ts +4 -4
- package/src/flow/ford-fulkerson.ts +186 -254
- package/src/flow/min-cut.ts +21 -11
- package/src/index.ts +9 -0
- package/src/link-prediction/adamic-adar.ts +17 -30
- package/src/link-prediction/common-neighbors.ts +7 -16
- package/src/optimized/bit-packed.ts +340 -0
- package/src/optimized/csr-graph.ts +455 -0
- package/src/optimized/direction-optimized-bfs.ts +291 -0
- package/src/optimized/graph-adapter.ts +200 -0
- package/src/optimized/index.ts +36 -0
- package/src/research/grsbm.ts +580 -0
- package/src/research/index.ts +17 -0
- package/src/research/sync.ts +440 -0
- package/src/research/terahac.ts +514 -0
- package/src/types/index.ts +8 -0
- package/src/utils/algorithm-utilities.ts +2 -0
- package/src/utils/graph-converters.ts +241 -0
- package/src/utils/graph-utilities.ts +199 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/math-utilities.ts +140 -0
- package/src/utils/matrix-utilities.ts +2 -0
- package/src/utils/optimization-helpers.ts +81 -0
package/dist/algorithms.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"algorithms.js","sourceRoot":"","sources":["../algorithms.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"algorithms.js","sources":["../src/core/graph.ts","../node_modules/typedfastbitset/lib/utils.js","../node_modules/typedfastbitset/lib/SparseTypedFastBitSet.js","../node_modules/typedfastbitset/lib/TypedFastBitSet.js","../node_modules/typedfastbitset/lib/index.js","../src/optimized/bit-packed.ts","../src/optimized/direction-optimized-bfs.ts","../src/optimized/csr-graph.ts","../src/optimized/graph-adapter.ts","../src/utils/graph-utilities.ts","../src/algorithms/traversal/bfs-unified.ts","../src/algorithms/traversal/dfs.ts","../src/algorithms/shortest-path/bellman-ford.ts","../src/data-structures/priority-queue.ts","../src/algorithms/shortest-path/bidirectional-dijkstra.ts","../src/algorithms/shortest-path/dijkstra.ts","../src/algorithms/shortest-path/floyd-warshall.ts","../src/algorithms/traversal/bfs-variants.ts","../src/algorithms/centrality/betweenness.ts","../src/algorithms/centrality/closeness.ts","../src/algorithms/centrality/degree.ts","../src/algorithms/centrality/delta-pagerank.ts","../src/algorithms/centrality/eigenvector.ts","../src/algorithms/centrality/hits.ts","../src/algorithms/centrality/katz.ts","../src/algorithms/centrality/delta-pagerank-simple.ts","../src/algorithms/centrality/pagerank.ts","../src/data-structures/union-find.ts","../src/algorithms/components/connected.ts","../src/algorithms/mst/kruskal.ts","../src/algorithms/mst/prim.ts","../src/algorithms/community/girvan-newman.ts","../src/utils/graph-converters.ts","../src/utils/math-utilities.ts","../src/algorithms/community/label-propagation.ts","../src/algorithms/community/leiden.ts","../src/algorithms/community/louvain-optimized.ts","../src/algorithms/community/modularity-utils.ts","../src/algorithms/community/louvain.ts","../src/utils/priorityQueue.ts","../src/pathfinding/utils.ts","../src/pathfinding/astar.ts","../src/flow/ford-fulkerson.ts","../src/flow/min-cut.ts","../src/clustering/hierarchical.ts","../src/clustering/k-core.ts","../src/clustering/mcl.ts","../src/clustering/spectral.ts","../src/algorithms/matching/bipartite.ts","../src/algorithms/matching/isomorphism.ts","../src/link-prediction/adamic-adar.ts","../src/link-prediction/common-neighbors.ts","../src/research/sync.ts","../src/research/terahac.ts","../src/research/grsbm.ts"],"sourcesContent":["import type {Edge, GraphConfig, Node, NodeId} from \"../types/index.js\";\n\n/**\n * Core Graph data structure for the Graphty Algorithms library\n *\n * Provides efficient graph representation with support for both directed and undirected graphs.\n * Uses adjacency lists for optimal performance with sparse graphs.\n */\nexport class Graph {\n private nodeMap: Map<NodeId, Node>;\n private adjacencyList: Map<NodeId, Map<NodeId, Edge>>;\n private incomingEdges: Map<NodeId, Map<NodeId, Edge>>; // For directed graphs\n private config: GraphConfig;\n private edgeCount: number;\n\n constructor(config: Partial<GraphConfig> = {}) {\n this.config = {\n directed: false,\n allowSelfLoops: true,\n allowParallelEdges: false,\n ... config,\n };\n this.nodeMap = new Map();\n this.adjacencyList = new Map();\n this.incomingEdges = new Map();\n this.edgeCount = 0;\n }\n\n /**\n * Add a node to the graph\n */\n addNode(id: NodeId, data?: Record<string, unknown>): void {\n if (!this.nodeMap.has(id)) {\n this.nodeMap.set(id, {id, data});\n this.adjacencyList.set(id, new Map());\n\n if (this.config.directed) {\n this.incomingEdges.set(id, new Map());\n }\n }\n }\n\n /**\n * Remove a node from the graph\n */\n removeNode(id: NodeId): boolean {\n if (!this.nodeMap.has(id)) {\n return false;\n }\n\n // Remove all edges connected to this node\n const outgoingEdges = this.adjacencyList.get(id);\n if (outgoingEdges) {\n for (const targetId of Array.from(outgoingEdges.keys())) {\n this.removeEdge(id, targetId);\n }\n }\n\n if (this.config.directed) {\n const incomingEdges = this.incomingEdges.get(id);\n if (incomingEdges) {\n for (const sourceId of Array.from(incomingEdges.keys())) {\n this.removeEdge(sourceId, id);\n }\n }\n } else {\n // For undirected graphs, also remove edges where this node is the target\n for (const [nodeId, edges] of Array.from(this.adjacencyList)) {\n if (edges.has(id)) {\n this.removeEdge(nodeId, id);\n }\n }\n }\n\n // Remove the node itself\n this.nodeMap.delete(id);\n this.adjacencyList.delete(id);\n\n if (this.config.directed) {\n this.incomingEdges.delete(id);\n }\n\n return true;\n }\n\n /**\n * Add an edge to the graph\n */\n addEdge(source: NodeId, target: NodeId, weight = 1, data?: Record<string, unknown>): void {\n // Ensure both nodes exist\n this.addNode(source);\n this.addNode(target);\n\n // Check self-loops\n if (!this.config.allowSelfLoops && source === target) {\n throw new Error(\"Self-loops are not allowed in this graph\");\n }\n\n // Check parallel edges\n if (!this.config.allowParallelEdges && this.hasEdge(source, target)) {\n throw new Error(\"Parallel edges are not allowed in this graph\");\n }\n\n const edge: Edge = {source, target, weight, data};\n\n // Add to adjacency list\n const sourceAdjacency = this.adjacencyList.get(source);\n\n if (sourceAdjacency) {\n sourceAdjacency.set(target, edge);\n }\n\n if (this.config.directed) {\n // For directed graphs, add to incoming edges list\n const targetIncoming = this.incomingEdges.get(target);\n\n if (targetIncoming) {\n targetIncoming.set(source, edge);\n }\n } else {\n // For undirected graphs, add the reverse edge\n if (source !== target) {\n const reverseEdge: Edge = {source: target, target: source, weight, data};\n const targetAdjacency = this.adjacencyList.get(target);\n\n if (targetAdjacency) {\n targetAdjacency.set(source, reverseEdge);\n }\n }\n }\n\n this.edgeCount++;\n }\n\n /**\n * Remove an edge from the graph\n */\n removeEdge(source: NodeId, target: NodeId): boolean {\n const sourceEdges = this.adjacencyList.get(source);\n if (!sourceEdges?.has(target)) {\n return false;\n }\n\n sourceEdges.delete(target);\n\n if (this.config.directed) {\n const targetIncoming = this.incomingEdges.get(target);\n if (targetIncoming) {\n targetIncoming.delete(source);\n }\n } else {\n // For undirected graphs, remove the reverse edge\n const targetEdges = this.adjacencyList.get(target);\n if (targetEdges) {\n targetEdges.delete(source);\n }\n }\n\n this.edgeCount--;\n return true;\n }\n\n /**\n * Check if a node exists in the graph\n */\n hasNode(id: NodeId): boolean {\n return this.nodeMap.has(id);\n }\n\n /**\n * Check if an edge exists in the graph\n */\n hasEdge(source: NodeId, target: NodeId): boolean {\n const sourceEdges = this.adjacencyList.get(source);\n return sourceEdges ? sourceEdges.has(target) : false;\n }\n\n /**\n * Get a node by ID\n */\n getNode(id: NodeId): Node | undefined {\n return this.nodeMap.get(id);\n }\n\n /**\n * Get an edge by source and target\n */\n getEdge(source: NodeId, target: NodeId): Edge | undefined {\n const sourceEdges = this.adjacencyList.get(source);\n return sourceEdges ? sourceEdges.get(target) : undefined;\n }\n\n /**\n * Get the number of nodes in the graph\n */\n get nodeCount(): number {\n return this.nodeMap.size;\n }\n\n /**\n * Get the number of edges in the graph\n */\n get totalEdgeCount(): number {\n return this.edgeCount;\n }\n\n /**\n * Check if the graph is directed\n */\n get isDirected(): boolean {\n return this.config.directed;\n }\n\n /**\n * Get all nodes in the graph\n */\n nodes(): IterableIterator<Node> {\n return this.nodeMap.values();\n }\n\n /**\n * Get all edges in the graph\n */\n *edges(): IterableIterator<Edge> {\n for (const [source, edges] of this.adjacencyList) {\n for (const edge of edges.values()) {\n // For undirected graphs, only yield each edge once\n if (!this.config.directed && source > edge.target) {\n continue;\n }\n\n yield edge;\n }\n }\n }\n\n /**\n * Get neighbors of a node (outgoing edges)\n */\n neighbors(nodeId: NodeId): IterableIterator<NodeId> {\n const edges = this.adjacencyList.get(nodeId);\n return edges ? edges.keys() : new Map().keys();\n }\n\n /**\n * Get incoming neighbors of a node (directed graphs only)\n */\n inNeighbors(nodeId: NodeId): IterableIterator<NodeId> {\n if (!this.config.directed) {\n return this.neighbors(nodeId);\n }\n\n const edges = this.incomingEdges.get(nodeId);\n return edges ? edges.keys() : new Map().keys();\n }\n\n /**\n * Get outgoing neighbors of a node\n */\n outNeighbors(nodeId: NodeId): IterableIterator<NodeId> {\n return this.neighbors(nodeId);\n }\n\n /**\n * Get the degree of a node\n */\n degree(nodeId: NodeId): number {\n if (this.config.directed) {\n return this.inDegree(nodeId) + this.outDegree(nodeId);\n }\n\n const edges = this.adjacencyList.get(nodeId);\n return edges ? edges.size : 0;\n }\n\n /**\n * Get the in-degree of a node\n */\n inDegree(nodeId: NodeId): number {\n if (!this.config.directed) {\n return this.degree(nodeId);\n }\n\n const edges = this.incomingEdges.get(nodeId);\n return edges ? edges.size : 0;\n }\n\n /**\n * Get the out-degree of a node\n */\n outDegree(nodeId: NodeId): number {\n const edges = this.adjacencyList.get(nodeId);\n return edges ? edges.size : 0;\n }\n\n /**\n * Create a copy of the graph\n */\n clone(): Graph {\n const cloned = new Graph(this.config);\n\n // Copy nodes\n for (const node of this.nodeMap.values()) {\n cloned.addNode(node.id, node.data ? {... node.data} : undefined);\n }\n\n // Copy edges\n for (const edge of this.edges()) {\n cloned.addEdge(\n edge.source,\n edge.target,\n edge.weight,\n edge.data ? {... edge.data} : undefined,\n );\n }\n\n return cloned;\n }\n\n /**\n * Get graph configuration\n */\n getConfig(): GraphConfig {\n return {... this.config};\n }\n\n /**\n * Clear all nodes and edges from the graph\n */\n clear(): void {\n this.nodeMap.clear();\n this.adjacencyList.clear();\n this.incomingEdges.clear();\n this.edgeCount = 0;\n }\n\n /**\n * Get the number of unique edges in the graph\n * For undirected graphs, each edge is counted once\n */\n get uniqueEdgeCount(): number {\n if (this.config.directed) {\n return this.edgeCount;\n }\n\n // For undirected graphs, we need to count each edge only once\n let count = 0;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for (const _edge of this.edges()) {\n count++;\n }\n return count;\n }\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.hammingWeight4 = exports.hammingWeight = void 0;\n// fast function to compute the Hamming weight of a 32-bit unsigned integer\nfunction hammingWeight(v) {\n v -= (v >>> 1) & 0x55555555; // works with signed or unsigned shifts\n v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);\n return (((v + (v >>> 4)) & 0xf0f0f0f) * 0x1010101) >>> 24;\n}\nexports.hammingWeight = hammingWeight;\n// fast function to compute the Hamming weight of four 32-bit unsigned integers\nfunction hammingWeight4(v1, v2, v3, v4) {\n v1 -= (v1 >>> 1) & 0x55555555; // works with signed or unsigned shifts\n v2 -= (v2 >>> 1) & 0x55555555; // works with signed or unsigned shifts\n v3 -= (v3 >>> 1) & 0x55555555; // works with signed or unsigned shifts\n v4 -= (v4 >>> 1) & 0x55555555; // works with signed or unsigned shifts\n v1 = (v1 & 0x33333333) + ((v1 >>> 2) & 0x33333333);\n v2 = (v2 & 0x33333333) + ((v2 >>> 2) & 0x33333333);\n v3 = (v3 & 0x33333333) + ((v3 >>> 2) & 0x33333333);\n v4 = (v4 & 0x33333333) + ((v4 >>> 2) & 0x33333333);\n v1 = (v1 + (v1 >>> 4)) & 0xf0f0f0f;\n v2 = (v2 + (v2 >>> 4)) & 0xf0f0f0f;\n v3 = (v3 + (v3 >>> 4)) & 0xf0f0f0f;\n v4 = (v4 + (v4 >>> 4)) & 0xf0f0f0f;\n return ((v1 + v2 + v3 + v4) * 0x1010101) >>> 24;\n}\nexports.hammingWeight4 = hammingWeight4;\n//# sourceMappingURL=utils.js.map","\"use strict\";\n/**\n * TypedFastBitSet.js : a fast bit set implementation in JavaScript.\n * (c) the authors\n * Licensed under the Apache License, Version 2.0.\n *\n * Speed-optimized BitSet implementation for modern browsers and JavaScript engines.\n *\n * Alternative version to TypedFastBitSet\n * This starts of as storing entries as an array in a Uint32Array Typed Array\n * The largest set value is first in the array. Everything else has no defined order\n * The largest set value is used when converting into a bitset to correctly size new Array\n * Once more than 256 entries have been added structure will convert to a bitset if it will create a smaller array\n * Very sparse data will remain an array until 1024 entries where it will convert to a bitset\n */\nvar __values = (this && this.__values) || function(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.SparseTypedFastBitSet = void 0;\nvar utils_1 = require(\"./utils\");\nvar Type;\n(function (Type) {\n Type[Type[\"ARRAY\"] = 0] = \"ARRAY\";\n Type[Type[\"BITSET\"] = 1] = \"BITSET\";\n Type[Type[\"MIXED\"] = 2] = \"MIXED\";\n})(Type || (Type = {}));\nfunction isIterable(obj) {\n if (obj) {\n return obj[Symbol.iterator] !== undefined;\n }\n return false;\n}\n/**\n * you can provide an iterable\n * an exception is thrown if typed arrays are not supported\n */\nvar SparseTypedFastBitSet = /** @class */ (function () {\n function SparseTypedFastBitSet(iterable, data) {\n var e_1, _a;\n if (data === void 0) { data = new Uint32Array(8); }\n this.data = data;\n // -1 means we are bitset\n this.arraySize = 0;\n if (isIterable(iterable)) {\n try {\n for (var iterable_1 = __values(iterable), iterable_1_1 = iterable_1.next(); !iterable_1_1.done; iterable_1_1 = iterable_1.next()) {\n var key = iterable_1_1.value;\n this.add(key);\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (iterable_1_1 && !iterable_1_1.done && (_a = iterable_1.return)) _a.call(iterable_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n }\n }\n Object.defineProperty(SparseTypedFastBitSet.prototype, \"words\", {\n get: function () {\n if (this.arraySize !== -1) {\n this.data = this.toBitset();\n this.arraySize = -1;\n }\n return this.data;\n },\n enumerable: false,\n configurable: true\n });\n SparseTypedFastBitSet.prototype.toBitset = function () {\n var array = this.data;\n // currently converts its internal type to bitset\n var count = (array[0] + 32) >>> 5;\n var newWords = new Uint32Array(count << 1);\n for (var i = 0; i < this.arraySize; i++) {\n var add = array[i];\n newWords[add >>> 5] |= 1 << add;\n }\n return newWords;\n };\n /**\n * Add the value (Set the bit at index to true)\n */\n SparseTypedFastBitSet.prototype.add = function (index) {\n var type = this.resize(index);\n if (type === Type.ARRAY) {\n var array = this.data;\n // zero will match the fill value so make sure match is within set area\n // store biggest index first just for resize help\n if (this.arraySize === 0) {\n array[this.arraySize++] = index;\n return;\n }\n var offset = array.indexOf(index);\n if (offset === -1 || offset >= this.arraySize) {\n var biggest = array[0];\n if (index > biggest) {\n array[0] = index;\n array[this.arraySize++] = biggest;\n }\n else {\n array[this.arraySize++] = index;\n }\n }\n }\n else {\n this.data[index >>> 5] |= 1 << index;\n }\n };\n /**\n * If the value was not in the set, add it, otherwise remove it (flip bit at index)\n */\n SparseTypedFastBitSet.prototype.flip = function (index) {\n var type = this.resize(index);\n if (type === Type.ARRAY) {\n var array = this.data;\n var arrayIndex = array.indexOf(index);\n if (arrayIndex === -1) {\n if (this.arraySize > 0 && index > array[0]) {\n array[this.arraySize++] = array[0];\n array[0] = index;\n }\n else {\n array[this.arraySize++] = index;\n }\n }\n else {\n if (arrayIndex === 0 && this.arraySize > 1) {\n // removing our largest marker need to find next largest\n var largest = array[1];\n var largestIndex = 1;\n for (var i = 2; i < this.arraySize; i++) {\n if (array[i] > largest) {\n largest = array[i];\n largestIndex = i;\n }\n }\n array[0] = array[largestIndex];\n array[largestIndex] = array[--this.arraySize];\n }\n else {\n array[arrayIndex] = array[--this.arraySize];\n }\n }\n }\n else {\n this.data[index >>> 5] ^= 1 << index;\n }\n };\n /**\n * Remove all values, reset memory usage\n */\n SparseTypedFastBitSet.prototype.clear = function () {\n this.arraySize = 0;\n this.data = new Uint32Array(8);\n };\n /**\n * Set the bit at index to false\n */\n SparseTypedFastBitSet.prototype.remove = function (index) {\n var type = this.resize(index);\n if (type === Type.ARRAY) {\n var array = this.data;\n var arrayIndex = array.indexOf(index);\n if (arrayIndex !== -1 && arrayIndex < this.arraySize) {\n if (arrayIndex == this.arraySize - 1) {\n this.arraySize--;\n }\n else if (arrayIndex === 0 && this.arraySize > 1) {\n // removing our largest marker need to find next largest\n var largest = array[1];\n var largestIndex = 1;\n for (var i = 2; i < this.arraySize; i++) {\n if (array[i] > largest) {\n largest = array[i];\n largestIndex = i;\n }\n }\n array[0] = array[largestIndex];\n array[largestIndex] = array[--this.arraySize];\n }\n else {\n array[arrayIndex] = array[--this.arraySize];\n }\n }\n }\n else {\n this.data[index >>> 5] &= ~(1 << index);\n }\n };\n /**\n * Set bits from start (inclusive) to end (exclusive)\n */\n SparseTypedFastBitSet.prototype.addRange = function (start, end) {\n if (start >= end) {\n return;\n }\n var type = this.resize(end, end - start - 1);\n if (type === Type.ARRAY) {\n var array = this.data;\n var biggestAdd = end-- - 1;\n if (this.arraySize === 0) {\n array[this.arraySize++] = biggestAdd;\n }\n else {\n var offset = array.indexOf(biggestAdd);\n if (offset === -1 || offset >= this.arraySize) {\n var biggest = array[0];\n if (biggestAdd > biggest) {\n array[0] = biggestAdd;\n array[this.arraySize++] = biggest;\n }\n else {\n array[this.arraySize++] = biggestAdd;\n }\n }\n }\n for (; start < end; start++) {\n var offset = array.indexOf(start);\n if (offset === -1 || offset >= this.arraySize) {\n array[this.arraySize++] = start;\n }\n }\n }\n else {\n var words = this.data;\n var firstword = start >> 5;\n var endword = (end - 1) >> 5;\n if (firstword === endword) {\n words[firstword] |= (~0 << start) & (~0 >>> -end);\n return;\n }\n words[firstword] |= ~0 << start;\n words.fill(~0, firstword + 1, endword);\n words[endword] |= ~0 >>> -end;\n }\n };\n /**\n * Remove bits from start (inclusive) to end (exclusive)\n */\n SparseTypedFastBitSet.prototype.removeRange = function (start, end) {\n if (start >= end) {\n return;\n }\n if (this.arraySize !== -1) {\n var array = this.data;\n var findBiggest = false;\n for (var i = 0; i < this.arraySize; i++) {\n if (array[i] >= start && array[i] < end) {\n if (i === 0) {\n findBiggest = true;\n }\n array[i--] = array[--this.arraySize];\n }\n }\n if (findBiggest && this.arraySize > 1) {\n var largest = array[0];\n var largestIndex = 0;\n for (var i = 1; i < this.arraySize; i++) {\n if (array[i] > largest) {\n largest = array[i];\n largestIndex = i;\n }\n }\n var current = array[0];\n array[0] = array[largestIndex];\n array[largestIndex] = current;\n }\n }\n else {\n var words = this.data;\n start = Math.min(start, (words.length << 5) - 1);\n end = Math.min(end, (words.length << 5) - 1);\n var firstword = start >> 5;\n var endword = (end - 1) >> 5;\n if (firstword === endword) {\n words[firstword] &= ~((~0 << start) & (~0 >>> -end));\n return;\n }\n words[firstword] &= ~(~0 << start);\n words.fill(0, firstword + 1, endword);\n words[endword] &= ~(~0 >>> -end);\n }\n };\n /**\n * @returns true if no bit is set\n */\n SparseTypedFastBitSet.prototype.isEmpty = function () {\n if (this.arraySize === 0) {\n return true;\n }\n if (this.arraySize > 0) {\n return false;\n }\n var words = this.data;\n var c = words.length;\n for (var i = 0; i < c; i++) {\n if (words[i] !== 0)\n return false;\n }\n return true;\n };\n /**\n * Is the value contained in the set? Is the bit at index true or false?\n */\n SparseTypedFastBitSet.prototype.has = function (index) {\n if (this.arraySize === -1) {\n return (this.data[index >>> 5] & (1 << index)) !== 0;\n }\n else {\n var offset = this.data.indexOf(index);\n return offset !== -1 && offset < this.arraySize;\n }\n };\n /**\n * Tries to add the value (Set the bit at index to true)\n *\n * @returns 1 if the value was added, 0 if the value was already present\n */\n SparseTypedFastBitSet.prototype.checkedAdd = function (index) {\n var type = this.resize(index);\n if (type === Type.ARRAY) {\n var array = this.data;\n if (this.arraySize === 0) {\n array[this.arraySize++] = index;\n return 1;\n }\n var offset = array.indexOf(index);\n if (offset === -1 || offset >= this.arraySize) {\n var biggest = array[0];\n if (index > biggest) {\n array[0] = index;\n array[this.arraySize++] = biggest;\n }\n else {\n array[this.arraySize++] = index;\n }\n return 1;\n }\n return 0;\n }\n else {\n var words = this.data;\n var word = words[index >>> 5];\n var newword = word | (1 << index);\n words[index >>> 5] = newword;\n return ((newword ^ word) >>> index);\n }\n };\n /**\n * Reduce the memory usage to a minimum\n */\n SparseTypedFastBitSet.prototype.trim = function () {\n var size = this.size();\n if (this.arraySize === -1) {\n var words = this.data;\n var nl = words.length;\n while (nl > 0 && words[nl - 1] === 0) {\n nl--;\n }\n // sparse array will be smaller\n if (size < nl) {\n var newArray = new Uint32Array(size);\n var pos = 0 | 0;\n var c = words.length;\n for (var k = 0; k < c; ++k) {\n var w = words[k];\n while (w != 0) {\n var t = w & -w;\n newArray[pos++] = (k << 5) + (0, utils_1.hammingWeight)((t - 1) | 0);\n w ^= t;\n }\n }\n var first = newArray[0];\n newArray[0] = newArray[size - 1];\n newArray[size - 1] = first;\n this.data = newArray;\n this.arraySize = size;\n }\n else {\n this.data = words.slice(0, nl);\n }\n }\n else {\n // dense bitset will be smaller\n if (this.arraySize > 0 && this.data[0] >>> 5 < size) {\n var count = (this.data[0] + 32) >>> 5;\n var newWords = new Uint32Array(count);\n for (var i = 0; i < this.arraySize; i++) {\n var add = this.data[i];\n newWords[add >>> 5] |= 1 << add;\n }\n this.data = newWords;\n this.arraySize = -1;\n }\n else {\n this.data = this.data.slice(0, this.arraySize);\n }\n }\n };\n /**\n * Resize the bitset so that we can write a value at index\n */\n SparseTypedFastBitSet.prototype.resize = function (index, capacity) {\n if (capacity === void 0) { capacity = 0; }\n if (this.arraySize === -1) {\n var words = this.data;\n if (words.length << 5 > index)\n return Type.BITSET;\n var count = (index + 32) >>> 5; // just what is needed\n var newwords = new Uint32Array(count << 1);\n newwords.set(words); // hopefully, this copy is fast\n this.data = newwords;\n return Type.BITSET;\n }\n else {\n var array = this.data;\n if (this.arraySize + capacity < array.length) {\n return Type.ARRAY;\n }\n if (array.length + capacity < 256) {\n var newData = new Uint32Array((array.length + capacity) << 1);\n newData.set(array);\n this.data = newData;\n return Type.ARRAY;\n }\n else {\n var count = (Math.max(array[0], index) + 32) >>> 5;\n // very sparse grow array some more\n if (count > array.length + capacity &&\n (array.length + capacity) << 1 < 1024) {\n var newData = new Uint32Array((array.length + capacity) << 1);\n newData.set(array);\n this.data = newData;\n return Type.ARRAY;\n }\n else {\n var newwords = new Uint32Array(count << 1);\n for (var i = 0; i < this.arraySize; i++) {\n var add = array[i];\n newwords[add >>> 5] |= 1 << add;\n }\n this.arraySize = -1;\n this.data = newwords;\n return Type.BITSET;\n }\n }\n }\n };\n /**\n * How many values stored in the set? How many set bits?\n */\n SparseTypedFastBitSet.prototype.size = function () {\n if (this.arraySize === -1) {\n var words = this.data;\n var answer = 0;\n var c = words.length;\n var k = 0 | 0;\n for (; k + 4 < c; k += 4) {\n answer += (0, utils_1.hammingWeight4)(words[k] | 0, words[k + 1] | 0, words[k + 2] | 0, words[k + 3] | 0);\n }\n for (; k < c; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k] | 0);\n }\n return answer;\n }\n else {\n return this.arraySize;\n }\n };\n /**\n * @returns the set bit locations (values)\n */\n SparseTypedFastBitSet.prototype.array = function () {\n if (this.arraySize === -1) {\n var words = this.data;\n var answer = new Array(this.size());\n var pos = 0 | 0;\n var c = words.length;\n for (var k = 0; k < c; ++k) {\n var w = words[k];\n while (w != 0) {\n var t = w & -w;\n answer[pos++] = (k << 5) + (0, utils_1.hammingWeight)((t - 1) | 0);\n w ^= t;\n }\n }\n return answer;\n }\n else {\n var array = this.data;\n var answer = new Array(this.arraySize);\n for (var i = 0; i < this.arraySize; i++) {\n answer[i] = array[i];\n }\n return answer;\n }\n };\n SparseTypedFastBitSet.prototype.forEach = function (fnc) {\n if (this.arraySize === -1) {\n var words = this.data;\n var c = words.length;\n for (var k = 0; k < c; ++k) {\n var w = words[k];\n while (w != 0) {\n var t = w & -w;\n fnc(((k << 5) + (0, utils_1.hammingWeight)(t - 1)) | 0);\n w ^= t;\n }\n }\n }\n else {\n var array = this.data;\n for (var i = 0; i < this.arraySize; i++) {\n var v = array[i];\n fnc(v);\n if (v !== array[i]) {\n i--;\n }\n }\n }\n };\n /**\n * Iterator of set bit locations (values)\n */\n SparseTypedFastBitSet.prototype[Symbol.iterator] = function () {\n var _a, _b;\n if (this.arraySize === -1) {\n var words_1 = this.data;\n var c_1 = words_1.length;\n var k_1 = 0;\n var w_1 = words_1[k_1];\n return _a = {},\n _a[Symbol.iterator] = function () {\n return this;\n },\n _a.next = function () {\n while (k_1 < c_1) {\n if (w_1 !== 0) {\n var t = w_1 & -w_1;\n var value = (k_1 << 5) + (0, utils_1.hammingWeight)((t - 1) | 0);\n w_1 ^= t;\n return { done: false, value: value };\n }\n else {\n k_1++;\n if (k_1 < c_1) {\n w_1 = words_1[k_1];\n }\n }\n }\n return { done: true, value: undefined };\n },\n _a;\n }\n else {\n var array_1 = this.data;\n var arraySize_1 = this.arraySize;\n var i_1 = 0;\n return _b = {},\n _b[Symbol.iterator] = function () {\n return this;\n },\n _b.next = function () {\n if (i_1 < arraySize_1) {\n var v = array_1[i_1];\n var result = { done: false, value: v };\n if (v !== array_1[i_1]) {\n i_1--;\n }\n i_1++;\n return result;\n }\n else {\n return { done: true, value: undefined };\n }\n },\n _b;\n }\n };\n /**\n * Creates a copy of this bitmap\n */\n SparseTypedFastBitSet.prototype.clone = function () {\n var bitset = new SparseTypedFastBitSet(undefined, new Uint32Array(this.data) // Correction : pas d'annotation générique\n );\n bitset.arraySize = this.arraySize;\n return bitset;\n };\n /**\n * Check if this bitset intersects with another one,\n * no bitmap is modified\n */\n SparseTypedFastBitSet.prototype.intersects = function (otherbitmap) {\n var order = SparseTypedFastBitSet.order(this, otherbitmap);\n switch (order.type) {\n case Type.BITSET: {\n var firstWords = order.first.words;\n var secondWords = order.second.words;\n var newcount = Math.min(firstWords.length, secondWords.length);\n for (var k = 0 | 0; k < newcount; ++k) {\n if ((firstWords[k] & secondWords[k]) !== 0)\n return true;\n }\n return false;\n }\n case Type.MIXED:\n case Type.ARRAY: {\n for (var i = 0; i < order.first.arraySize; i++) {\n if (order.second.has(order.first.data[i])) {\n return true;\n }\n }\n return false;\n }\n }\n };\n /**\n * Computes the intersection between this bitset and another one,\n * the current bitmap is modified (and returned by the function)\n */\n SparseTypedFastBitSet.prototype.intersection = function (otherbitmap) {\n if (this.arraySize === -1) {\n if (!(otherbitmap instanceof SparseTypedFastBitSet) ||\n otherbitmap.arraySize === -1) {\n var words = this.data;\n var otherWords = otherbitmap.words;\n var newcount = Math.min(words.length, otherWords.length);\n var k = 0 | 0;\n for (; k + 7 < newcount; k += 8) {\n words[k] &= otherWords[k];\n words[k + 1] &= otherWords[k + 1];\n words[k + 2] &= otherWords[k + 2];\n words[k + 3] &= otherWords[k + 3];\n words[k + 4] &= otherWords[k + 4];\n words[k + 5] &= otherWords[k + 5];\n words[k + 6] &= otherWords[k + 6];\n words[k + 7] &= otherWords[k + 7];\n }\n for (; k < newcount; ++k) {\n words[k] &= otherWords[k];\n }\n var c = words.length;\n for (k = newcount; k < c; ++k) {\n words[k] = 0;\n }\n return this;\n }\n else {\n var newWord = new Uint32Array(otherbitmap.data.length);\n // iterate through target as it will be smaller\n var otherArray = otherbitmap.data;\n var newSize = 0;\n for (var i = 0; i < otherbitmap.arraySize; i++) {\n var index = otherArray[i];\n if (this.has(index)) {\n if (newSize > 0 && index > newWord[0]) {\n newWord[newSize++] = newWord[0];\n newWord[0] = index;\n }\n else {\n newWord[newSize++] = index;\n }\n }\n }\n this.data = newWord;\n this.arraySize = newSize;\n return this;\n }\n }\n else {\n var array = this.data;\n for (var i = 0; i < this.arraySize; i++) {\n var v = array[i];\n if (otherbitmap.has(v)) {\n if (i > 0 && v > array[0]) {\n array[i] = array[0];\n array[0] = v;\n }\n }\n else {\n array[i--] = array[--this.arraySize];\n }\n }\n return this;\n }\n };\n /**\n * Computes the size of the intersection between this bitset and another one\n */\n SparseTypedFastBitSet.prototype.intersection_size = function (otherbitmap) {\n var order = SparseTypedFastBitSet.order(this, otherbitmap);\n switch (order.type) {\n case Type.BITSET: {\n var words = order.first.words;\n var otherWords = order.second.words;\n var newcount = Math.min(words.length, otherWords.length);\n var answer = 0 | 0;\n for (var k = 0 | 0; k < newcount; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k] & otherWords[k]);\n }\n return answer;\n }\n case Type.MIXED:\n case Type.ARRAY: {\n var answer = 0;\n var array = order.first.data;\n for (var i = 0; i < order.first.arraySize; i++) {\n if (order.second.has(array[i])) {\n answer++;\n }\n }\n return answer;\n }\n }\n };\n /**\n * Computes the intersection between this bitset and another one,\n * a new bitmap is generated\n */\n SparseTypedFastBitSet.prototype.new_intersection = function (otherbitmap) {\n var order = SparseTypedFastBitSet.order(this, otherbitmap);\n switch (order.type) {\n case Type.BITSET: {\n var words = order.first.words;\n var otherWords = order.second.words;\n var count = Math.min(words.length, otherWords.length);\n var newWords = new Uint32Array(count);\n var k = 0 | 0;\n for (; k + 7 < count; k += 8) {\n newWords[k] = words[k] & otherWords[k];\n newWords[k + 1] = words[k + 1] & otherWords[k + 1];\n newWords[k + 2] = words[k + 2] & otherWords[k + 2];\n newWords[k + 3] = words[k + 3] & otherWords[k + 3];\n newWords[k + 4] = words[k + 4] & otherWords[k + 4];\n newWords[k + 5] = words[k + 5] & otherWords[k + 5];\n newWords[k + 6] = words[k + 6] & otherWords[k + 6];\n newWords[k + 7] = words[k + 7] & otherWords[k + 7];\n }\n for (; k < count; ++k) {\n newWords[k] = words[k] & otherWords[k];\n }\n var answer = new SparseTypedFastBitSet(undefined, newWords);\n answer.arraySize = -1;\n return answer;\n }\n case Type.MIXED:\n case Type.ARRAY: {\n var newArray = new Uint32Array(order.first.data.length);\n // iterate through target as it will be smaller\n var newSize = 0;\n var array = order.first.data;\n for (var i = 0; i < order.first.arraySize; i++) {\n var index = array[i];\n if (order.second.has(index)) {\n if (newSize > 0 && index > newArray[0]) {\n newArray[newSize++] = newArray[0];\n newArray[0] = index;\n }\n else {\n newArray[newSize++] = index;\n }\n }\n }\n var answer = new SparseTypedFastBitSet(undefined, newArray);\n answer.arraySize = newSize;\n return answer;\n }\n }\n };\n /**\n * Computes the intersection between this bitset and another one,\n * the current bitmap is modified\n */\n SparseTypedFastBitSet.prototype.equals = function (otherbitmap) {\n if (this === otherbitmap) {\n return true;\n }\n var order = SparseTypedFastBitSet.order(this, otherbitmap);\n switch (order.type) {\n case Type.BITSET: {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var mcount = Math.min(words.length, otherWords.length);\n for (var k = 0 | 0; k < mcount; ++k) {\n if (words[k] != otherWords[k])\n return false;\n }\n if (words.length < otherWords.length) {\n var c = otherWords.length;\n for (var k = words.length; k < c; ++k) {\n if (otherWords[k] != 0)\n return false;\n }\n }\n else if (otherWords.length < words.length) {\n var c = words.length;\n for (var k = otherWords.length; k < c; ++k) {\n if (words[k] != 0)\n return false;\n }\n }\n return true;\n }\n case Type.ARRAY:\n case Type.MIXED: {\n if (order.first.size() !== order.second.size()) {\n return false;\n }\n var array = order.first.data;\n for (var i = 0; i < order.first.arraySize; i++) {\n if (!order.second.has(array[i])) {\n return false;\n }\n }\n return true;\n }\n }\n };\n /**\n * Computes the difference between this bitset and another one,\n * the current bitset is modified (and returned by the function)\n */\n SparseTypedFastBitSet.prototype.difference = function (otherbitmap) {\n if (this.arraySize === -1) {\n if (!(otherbitmap instanceof SparseTypedFastBitSet) ||\n otherbitmap.arraySize === -1) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var newcount = Math.min(words.length, otherWords.length);\n var k = 0 | 0;\n for (; k + 7 < newcount; k += 8) {\n words[k] &= ~otherWords[k];\n words[k + 1] &= ~otherWords[k + 1];\n words[k + 2] &= ~otherWords[k + 2];\n words[k + 3] &= ~otherWords[k + 3];\n words[k + 4] &= ~otherWords[k + 4];\n words[k + 5] &= ~otherWords[k + 5];\n words[k + 6] &= ~otherWords[k + 6];\n words[k + 7] &= ~otherWords[k + 7];\n }\n for (; k < newcount; ++k) {\n words[k] &= ~otherWords[k];\n }\n return this;\n }\n else {\n var otherArray = otherbitmap.data;\n for (var i = 0; i < otherbitmap.arraySize; i++) {\n var index = otherArray[i];\n if (this.has(index)) {\n this.remove(index);\n }\n }\n return this;\n }\n }\n else {\n var array = this.data;\n var findBiggest = false;\n for (var i = 0; i < this.arraySize; i++) {\n if (otherbitmap.has(array[i])) {\n if (i === 0) {\n findBiggest = true;\n }\n array[i--] = array[--this.arraySize];\n }\n }\n if (findBiggest && this.arraySize > 1) {\n var largest = array[0];\n var largestIndex = 0;\n for (var i = 1; i < this.arraySize; i++) {\n if (array[i] > largest) {\n largest = array[i];\n largestIndex = i;\n }\n }\n var current = array[0];\n array[0] = array[largestIndex];\n array[largestIndex] = current;\n }\n return this;\n }\n };\n /**\n * Computes the difference between this bitset and another one,\n * the other bitset is modified (and returned by the function)\n *\n * (for this set A and other set B, this computes B = A - B and returns B)\n */\n SparseTypedFastBitSet.prototype.difference2 = function (otherbitmap) {\n if (this.arraySize === -1 ||\n !(otherbitmap instanceof SparseTypedFastBitSet)) {\n var words = this.words;\n var mincount = Math.min(words.length, otherbitmap.words.length);\n otherbitmap.resize((words.length << 5) - 1);\n var otherWords = otherbitmap.words;\n var k = 0 | 0;\n for (; k + 7 < mincount; k += 8) {\n otherWords[k] = words[k] & ~otherWords[k];\n otherWords[k + 1] = words[k + 1] & ~otherWords[k + 1];\n otherWords[k + 2] = words[k + 2] & ~otherWords[k + 2];\n otherWords[k + 3] = words[k + 3] & ~otherWords[k + 3];\n otherWords[k + 4] = words[k + 4] & ~otherWords[k + 4];\n otherWords[k + 5] = words[k + 5] & ~otherWords[k + 5];\n otherWords[k + 6] = words[k + 6] & ~otherWords[k + 6];\n otherWords[k + 7] = words[k + 7] & ~otherWords[k + 7];\n }\n for (; k < mincount; ++k) {\n otherWords[k] = words[k] & ~otherWords[k];\n }\n // remaining words are all part of difference\n for (; k < words.length; ++k) {\n otherWords[k] = words[k];\n }\n otherWords.fill(0, k);\n return otherbitmap;\n }\n else {\n var array = new Uint32Array(this.data);\n var arraySize = this.arraySize;\n var findBiggest = false;\n for (var i = 0; i < arraySize; i++) {\n if (otherbitmap.has(array[i])) {\n if (i === 0) {\n findBiggest = true;\n }\n array[i--] = array[--arraySize];\n }\n }\n if (findBiggest && arraySize > 1) {\n var largest = array[0];\n var largestIndex = 0;\n for (var i = 1; i < arraySize; i++) {\n if (array[i] > largest) {\n largest = array[i];\n largestIndex = i;\n }\n }\n var current = array[0];\n array[0] = array[largestIndex];\n array[largestIndex] = current;\n }\n otherbitmap.data = array;\n otherbitmap.arraySize = arraySize;\n return otherbitmap;\n }\n };\n /**\n * Computes the difference between this bitset and another one,\n * a new bitmap is generated\n */\n SparseTypedFastBitSet.prototype.new_difference = function (otherbitmap) {\n return this.clone().difference(otherbitmap);\n };\n /**\n * Computes the size of the difference between this bitset and another one\n */\n SparseTypedFastBitSet.prototype.difference_size = function (otherbitmap) {\n if (this.arraySize === -1) {\n if (!(otherbitmap instanceof SparseTypedFastBitSet) ||\n otherbitmap.arraySize === -1) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var newcount = Math.min(words.length, otherWords.length);\n var answer = 0 | 0;\n var k = 0 | 0;\n for (; k < newcount; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k] & ~otherWords[k]);\n }\n var c = words.length;\n for (; k < c; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k]);\n }\n return answer;\n }\n else {\n var answer = this.size();\n var otherArray = otherbitmap.data;\n for (var i = 0; i < otherbitmap.arraySize; i++) {\n var index = otherArray[i];\n if (this.has(index)) {\n answer--;\n }\n }\n return answer;\n }\n }\n else {\n var answer = this.arraySize;\n var array = this.data;\n for (var i = 0; i < this.arraySize; i++) {\n if (otherbitmap.has(array[i])) {\n answer--;\n }\n }\n return answer;\n }\n };\n /**\n * Computes the changed elements (XOR) between this bitset and another one,\n * the current bitset is modified (and returned by the function)\n */\n SparseTypedFastBitSet.prototype.change = function (otherbitmap) {\n if (this.arraySize === -1) {\n if (!(otherbitmap instanceof SparseTypedFastBitSet) ||\n otherbitmap.arraySize === -1) {\n var otherWords = otherbitmap.words;\n var mincount = Math.min(this.words.length, otherWords.length);\n this.resize((otherWords.length << 5) - 1);\n var words = this.words;\n var k = 0 | 0;\n for (; k + 7 < mincount; k += 8) {\n words[k] ^= otherWords[k];\n words[k + 1] ^= otherWords[k + 1];\n words[k + 2] ^= otherWords[k + 2];\n words[k + 3] ^= otherWords[k + 3];\n words[k + 4] ^= otherWords[k + 4];\n words[k + 5] ^= otherWords[k + 5];\n words[k + 6] ^= otherWords[k + 6];\n words[k + 7] ^= otherWords[k + 7];\n }\n for (; k < mincount; ++k) {\n words[k] ^= otherWords[k];\n }\n // remaining words are all part of change\n for (; k < otherWords.length; ++k) {\n words[k] = otherWords[k];\n }\n return this;\n }\n else if (otherbitmap.arraySize > 0) {\n var otherArray = otherbitmap.data;\n this.resize(otherArray[0]);\n var words = this.words;\n for (var i = 0; i < otherbitmap.arraySize; i++) {\n var index = otherArray[i];\n if ((words[index >>> 5] & (1 << index)) !== 0) {\n words[index >>> 5] &= ~(1 << index);\n }\n else {\n words[index >>> 5] |= 1 << index;\n }\n }\n return this;\n }\n else {\n return this;\n }\n }\n else {\n if (!(otherbitmap instanceof SparseTypedFastBitSet) ||\n otherbitmap.arraySize === -1) {\n var words = new Uint32Array(Math.max(otherbitmap.words.length, this.arraySize > 0 ? this.data[0] << (5 + 32) : 0));\n words.set(otherbitmap.words);\n var array = this.data;\n for (var i = 0; i < this.arraySize; i++) {\n var index = array[i];\n if ((words[index >>> 5] & (1 << index)) !== 0) {\n words[index >>> 5] &= ~(1 << index);\n }\n else {\n words[index >>> 5] |= 1 << index;\n }\n }\n this.data = words;\n this.arraySize = -1;\n }\n else {\n var otherArray = otherbitmap.data;\n for (var i = 0; i < otherbitmap.arraySize; i++) {\n var index = otherArray[i];\n if (this.has(index)) {\n this.remove(index);\n }\n else {\n this.add(index);\n }\n }\n }\n return this;\n }\n };\n /**\n * Computes the change between this bitset and another one,\n * a new bitmap is generated\n */\n SparseTypedFastBitSet.prototype.new_change = function (otherbitmap) {\n var order = SparseTypedFastBitSet.order(this, otherbitmap);\n switch (order.type) {\n case Type.BITSET: {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var count = Math.max(words.length, otherWords.length);\n var answer = new SparseTypedFastBitSet(undefined, new Uint32Array(count));\n answer.arraySize = -1;\n var mcount = Math.min(words.length, otherWords.length);\n var k = 0;\n for (; k + 7 < mcount; k += 8) {\n answer.words[k] = words[k] ^ otherWords[k];\n answer.words[k + 1] = words[k + 1] ^ otherWords[k + 1];\n answer.words[k + 2] = words[k + 2] ^ otherWords[k + 2];\n answer.words[k + 3] = words[k + 3] ^ otherWords[k + 3];\n answer.words[k + 4] = words[k + 4] ^ otherWords[k + 4];\n answer.words[k + 5] = words[k + 5] ^ otherWords[k + 5];\n answer.words[k + 6] = words[k + 6] ^ otherWords[k + 6];\n answer.words[k + 7] = words[k + 7] ^ otherWords[k + 7];\n }\n for (; k < mcount; ++k) {\n answer.words[k] = words[k] ^ otherWords[k];\n }\n var c = words.length;\n for (k = mcount; k < c; ++k) {\n answer.words[k] = words[k];\n }\n var c2 = otherWords.length;\n for (k = mcount; k < c2; ++k) {\n answer.words[k] = otherWords[k];\n }\n return answer;\n }\n case Type.MIXED: {\n var words = new Uint32Array(Math.max(order.second.words.length, order.first.arraySize > 0 ? (order.first.data[0] + 32) << 5 : 0));\n words.set(order.second.words);\n var array = order.first.data;\n for (var i = 0; i < order.first.arraySize; i++) {\n var index = array[i];\n if ((words[index >>> 5] & (1 << index)) !== 0) {\n words[index >>> 5] &= ~(1 << index);\n }\n else {\n words[index >>> 5] |= 1 << index;\n }\n }\n var answer = new SparseTypedFastBitSet(undefined, words);\n answer.arraySize = -1;\n return answer;\n }\n case Type.ARRAY: {\n var newArray = new Uint32Array(order.first.data.length + order.second.data.length);\n newArray.set(order.second.data);\n // iterate through target as it will be smaller\n var newSize = order.second.arraySize;\n var array = order.first.data;\n for (var i = 0; i < order.first.arraySize; i++) {\n var index = array[i];\n var offset = newArray.indexOf(index);\n if (offset !== -1 && offset < newSize) {\n newArray[offset] = newArray[--newSize];\n }\n else {\n newArray[newSize++] = index;\n }\n }\n if (newSize > 1) {\n var largest = newArray[0];\n var largestIndex = 0;\n for (var i = 1; i < newSize; i++) {\n if (newArray[i] > largest) {\n largest = newArray[i];\n largestIndex = i;\n }\n }\n var current = newArray[0];\n newArray[0] = newArray[largestIndex];\n newArray[largestIndex] = current;\n }\n var answer = new SparseTypedFastBitSet(undefined, newArray);\n answer.arraySize = newSize;\n return answer;\n }\n }\n };\n /**\n * Computes the number of changed elements between this bitset and another one\n */\n SparseTypedFastBitSet.prototype.change_size = function (otherbitmap) {\n var order = SparseTypedFastBitSet.order(this, otherbitmap);\n switch (order.type) {\n case Type.BITSET: {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var mincount = Math.min(words.length, otherWords.length);\n var answer = 0 | 0;\n var k = 0 | 0;\n for (; k < mincount; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k] ^ otherWords[k]);\n }\n var longer = words.length > otherWords.length ? this : otherbitmap;\n var c = longer.words.length;\n for (; k < c; ++k) {\n answer += (0, utils_1.hammingWeight)(longer.words[k]);\n }\n return answer;\n }\n case Type.MIXED: {\n var array = order.first.data;\n var answer = order.second.size();\n for (var i = 0; i < order.first.arraySize; i++) {\n var index = array[i];\n if (order.second.has(index)) {\n answer--;\n }\n else {\n answer++;\n }\n }\n return answer;\n }\n case Type.ARRAY: {\n // iterate through target as it will be smaller\n var answer = order.second.arraySize;\n var array = order.first.data;\n for (var i = 0; i < order.first.arraySize; i++) {\n var index = array[i];\n if (order.second.has(index)) {\n answer--;\n }\n else {\n answer++;\n }\n }\n return answer;\n }\n }\n };\n /**\n * @returns a string representation\n */\n SparseTypedFastBitSet.prototype.toString = function () {\n return \"{\" + this.array().join(\",\") + \"}\";\n };\n /**\n * Computes the union between this bitset and another one,\n * the current bitset is modified (and returned by the function)\n */\n SparseTypedFastBitSet.prototype.union = function (otherbitmap) {\n if (!(otherbitmap instanceof SparseTypedFastBitSet) ||\n otherbitmap.arraySize === -1) {\n if (this.arraySize !== -1) {\n this.data = this.toBitset();\n this.arraySize = -1;\n }\n var words = this.data;\n var otherWords = otherbitmap.words;\n var mcount = Math.min(words.length, otherWords.length);\n var k = 0 | 0;\n for (; k + 7 < mcount; k += 8) {\n words[k] |= otherWords[k];\n words[k + 1] |= otherWords[k + 1];\n words[k + 2] |= otherWords[k + 2];\n words[k + 3] |= otherWords[k + 3];\n words[k + 4] |= otherWords[k + 4];\n words[k + 5] |= otherWords[k + 5];\n words[k + 6] |= otherWords[k + 6];\n words[k + 7] |= otherWords[k + 7];\n }\n for (; k < mcount; ++k) {\n words[k] |= otherWords[k];\n }\n if (words.length < otherWords.length) {\n this.resize((otherWords.length << 5) - 1);\n words = this.data;\n var c = otherWords.length;\n for (k = mcount; k < c; ++k) {\n words[k] = otherWords[k];\n }\n }\n return this;\n }\n else {\n var otherArray = otherbitmap.data;\n for (var i = 0; i < otherbitmap.arraySize; i++) {\n var index = otherArray[i];\n this.add(index);\n }\n return this;\n }\n };\n /**\n * Computes the union between this bitset and another one,\n * a new bitmap is generated\n */\n SparseTypedFastBitSet.prototype.new_union = function (otherbitmap) {\n if (!(otherbitmap instanceof SparseTypedFastBitSet) ||\n otherbitmap.arraySize === -1) {\n var words = this.data;\n if (this.arraySize !== -1) {\n words = this.toBitset();\n }\n var otherWords = otherbitmap.words;\n var count = Math.max(words.length, otherWords.length);\n var answer = new SparseTypedFastBitSet(undefined, new Uint32Array(count));\n answer.arraySize = -1;\n var mcount = Math.min(words.length, otherWords.length);\n for (var k = 0; k < mcount; ++k) {\n answer.words[k] = words[k] | otherWords[k];\n }\n var c = words.length;\n for (var k = mcount; k < c; ++k) {\n answer.words[k] = words[k];\n }\n var c2 = otherWords.length;\n for (var k = mcount; k < c2; ++k) {\n answer.words[k] = otherWords[k];\n }\n return answer;\n }\n else {\n var answer = this.clone();\n var otherArray = otherbitmap.data;\n for (var i = 0; i < otherbitmap.arraySize; i++) {\n var index = otherArray[i];\n answer.add(index);\n }\n return answer;\n }\n };\n /**\n * Computes the size union between this bitset and another one\n */\n SparseTypedFastBitSet.prototype.union_size = function (otherbitmap) {\n var order = SparseTypedFastBitSet.order(this, otherbitmap);\n switch (order.type) {\n case Type.BITSET: {\n var words = order.first.words;\n var otherWords = order.second.words;\n var mcount = Math.min(words.length, otherWords.length);\n var answer = 0 | 0;\n for (var k = 0 | 0; k < mcount; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k] | otherWords[k]);\n }\n if (words.length < otherWords.length) {\n var c = otherWords.length;\n for (var k = words.length; k < c; ++k) {\n answer += (0, utils_1.hammingWeight)(otherWords[k] | 0);\n }\n }\n else {\n var c = words.length;\n for (var k = otherWords.length; k < c; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k] | 0);\n }\n }\n return answer;\n }\n case Type.ARRAY:\n case Type.MIXED: {\n var answer = order.second.size();\n var array = order.first.data;\n for (var i = 0; i < order.first.arraySize; i++) {\n if (!order.second.has(array[i])) {\n answer++;\n }\n }\n return answer;\n }\n }\n };\n /**\n * will put array based one first and return type if both array smallest first\n */\n SparseTypedFastBitSet.order = function (first, second) {\n if (!(first instanceof SparseTypedFastBitSet) || first.arraySize === -1) {\n if (!(second instanceof SparseTypedFastBitSet) ||\n second.arraySize === -1) {\n return {\n first: first,\n second: second,\n type: Type.BITSET,\n };\n }\n else {\n return {\n first: second,\n second: first,\n type: Type.MIXED,\n };\n }\n }\n else {\n if (!(second instanceof SparseTypedFastBitSet) ||\n second.arraySize === -1) {\n return {\n first: first,\n second: second,\n type: Type.MIXED,\n };\n }\n else {\n if (second.arraySize > first.arraySize) {\n return {\n first: first,\n second: second,\n type: Type.ARRAY,\n };\n }\n else {\n return {\n first: second,\n second: first,\n type: Type.ARRAY,\n };\n }\n }\n }\n };\n return SparseTypedFastBitSet;\n}());\nexports.SparseTypedFastBitSet = SparseTypedFastBitSet;\n//# sourceMappingURL=SparseTypedFastBitSet.js.map","\"use strict\";\n/**\n * TypedFastBitSet.js : a fast bit set implementation in JavaScript.\n * (c) the authors\n * Licensed under the Apache License, Version 2.0.\n *\n * Speed-optimized BitSet implementation for modern browsers and JavaScript engines.\n *\n * A BitSet is an ideal data structure to implement a Set when values being stored are\n * reasonably small integers. It can be orders of magnitude faster than a generic set implementation.\n * The FastBitSet implementation optimizes for speed, leveraging commonly available features\n * like typed arrays.\n *\n * Simple usage :\n * const b = new TypedFastBitSet();// initially empty\n * // will throw exception if typed arrays are not supported\n * b.add(1);// add the value \"1\"\n * b.has(1); // check that the value is present! (will return true)\n * b.add(2);\n * console.log(\"\"+b);// should display {1,2}\n * b.add(10);\n * b.array(); // would return [1,2,10]\n *\n * let c = new FastBitSet([1,2,3,10]); // create bitset initialized with values 1,2,3,10\n * c.difference(b); // from c, remove elements that are in b (modifies c)\n * c.difference2(b); // from c, remove elements that are in b (modifies b)\n * c.change(b); // c will contain elements that are in b or in c, but not both\n * const su = c.union_size(b);// compute the size of the union (bitsets are unchanged)\n * c.union(b); // c will contain all elements that are in c and b\n * const s1 = c.intersection_size(b);// compute the size of the intersection (bitsets are unchanged)\n * c.intersection(b); // c will only contain elements that are in both c and b\n * c = b.clone(); // create a (deep) copy of b and assign it to c.\n * c.equals(b); // check whether c and b are equal\n *\n * See README.md file for a more complete description.\n *\n * You can install the library under node with the command line\n * npm install typedfastbitset\n */\nvar __values = (this && this.__values) || function(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.TypedFastBitSet = void 0;\nvar utils_1 = require(\"./utils\");\nfunction isIterable(obj) {\n if (obj) {\n return obj[Symbol.iterator] !== undefined;\n }\n return false;\n}\n/**\n * you can provide an iterable\n * an exception is thrown if typed arrays are not supported\n */\nvar TypedFastBitSet = /** @class */ (function () {\n function TypedFastBitSet(iterable, words) {\n var e_1, _a;\n if (words === void 0) { words = new Uint32Array(8); }\n this.words = words;\n if (isIterable(iterable)) {\n try {\n for (var iterable_1 = __values(iterable), iterable_1_1 = iterable_1.next(); !iterable_1_1.done; iterable_1_1 = iterable_1.next()) {\n var key = iterable_1_1.value;\n this.add(key);\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (iterable_1_1 && !iterable_1_1.done && (_a = iterable_1.return)) _a.call(iterable_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n }\n }\n /**\n * @returns a new TypedFastBitset given a Uint32Array of words\n */\n TypedFastBitSet.fromWords = function (words) {\n return new TypedFastBitSet(undefined, words);\n };\n /**\n * Add the value (Set the bit at index to true)\n */\n TypedFastBitSet.prototype.add = function (index) {\n this.resize(index);\n this.words[index >>> 5] |= 1 << index;\n };\n /**\n * If the value was not in the set, add it, otherwise remove it (flip bit at index)\n */\n TypedFastBitSet.prototype.flip = function (index) {\n this.resize(index);\n this.words[index >>> 5] ^= 1 << index;\n };\n /**\n * Remove all values, reset memory usage\n */\n TypedFastBitSet.prototype.clear = function () {\n this.words = new Uint32Array(8);\n };\n /**\n * Set the bit at index to false\n */\n TypedFastBitSet.prototype.remove = function (index) {\n this.resize(index);\n this.words[index >>> 5] &= ~(1 << index);\n };\n /**\n * Set bits from start (inclusive) to end (exclusive)\n */\n TypedFastBitSet.prototype.addRange = function (start, end) {\n if (start >= end) {\n return;\n }\n if (this.words.length << 5 <= end) {\n this.resize(end);\n }\n var words = this.words;\n var firstword = start >> 5;\n var endword = (end - 1) >> 5;\n if (firstword === endword) {\n words[firstword] |= (~0 << start) & (~0 >>> -end);\n return;\n }\n words[firstword] |= ~0 << start;\n words.fill(~0, firstword + 1, endword);\n words[endword] |= ~0 >>> -end;\n };\n /**\n * Remove bits from start (inclusive) to end (exclusive)\n */\n TypedFastBitSet.prototype.removeRange = function (start, end) {\n var words = this.words;\n start = Math.min(start, (words.length << 5) - 1);\n end = Math.min(end, (words.length << 5) - 1);\n if (start >= end) {\n return;\n }\n var firstword = start >> 5;\n var endword = (end - 1) >> 5;\n if (firstword === endword) {\n words[firstword] &= ~((~0 << start) & (~0 >>> -end));\n return;\n }\n words[firstword] &= ~(~0 << start);\n words.fill(0, firstword + 1, endword);\n words[endword] &= ~(~0 >>> -end);\n };\n /**\n * @returns true if no bit is set\n */\n TypedFastBitSet.prototype.isEmpty = function () {\n var words = this.words;\n var c = words.length;\n for (var i = 0; i < c; i++) {\n if (words[i] !== 0)\n return false;\n }\n return true;\n };\n /**\n * Is the value contained in the set? Is the bit at index true or false?\n */\n TypedFastBitSet.prototype.has = function (index) {\n return (this.words[index >>> 5] & (1 << index)) !== 0;\n };\n /**\n * Is any value of the (exclusive) range contained in the set?\n */\n TypedFastBitSet.prototype.hasAnyInRange = function (start, end) {\n if (start >= end)\n return false;\n var words = this.words;\n start = Math.min(start, (words.length << 5) - 1);\n end = Math.min(end, (words.length << 5) - 1);\n var firstword = start >>> 5;\n var endword = (end - 1) >> 5;\n if (firstword === endword)\n return (words[firstword] & ((~0 << start) & (~0 >>> -end))) !== 0;\n if ((words[firstword] & (~0 << start)) !== 0)\n return true;\n for (var index = firstword + 1; index < endword - 1; index++)\n if (words[index] !== 0)\n return true;\n return (words[endword] & (~0 >>> -end)) !== 0;\n };\n /**\n * Tries to add the value (Set the bit at index to true)\n *\n * @returns 1 if the value was added, 0 if the value was already present\n */\n TypedFastBitSet.prototype.checkedAdd = function (index) {\n var words = this.words;\n this.resize(index);\n var word = words[index >>> 5];\n var newword = word | (1 << index);\n words[index >>> 5] = newword;\n return ((newword ^ word) >>> index);\n };\n /**\n * Reduce the memory usage to a minimum\n */\n TypedFastBitSet.prototype.trim = function () {\n var words = this.words;\n var nl = words.length;\n while (nl > 0 && words[nl - 1] === 0) {\n nl--;\n }\n this.words = words.slice(0, nl);\n };\n /**\n * Resize the bitset so that we can write a value at index\n */\n TypedFastBitSet.prototype.resize = function (index) {\n var words = this.words;\n if (words.length << 5 > index)\n return;\n var count = (index + 32) >>> 5; // just what is needed\n var newwords = new Uint32Array(count << 1);\n newwords.set(words); // hopefully, this copy is fast\n this.words = newwords;\n };\n /**\n * @returns How many values stored in the set? How many set bits?\n */\n TypedFastBitSet.prototype.size = function () {\n var words = this.words;\n var answer = 0;\n var c = words.length;\n var k = 0 | 0;\n for (; k + 4 < c; k += 4) {\n answer += (0, utils_1.hammingWeight4)(words[k] | 0, words[k + 1] | 0, words[k + 2] | 0, words[k + 3] | 0);\n }\n for (; k < c; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k] | 0);\n }\n return answer;\n };\n /**\n * @returns an array with the set bit locations (values)\n */\n TypedFastBitSet.prototype.array = function () {\n var words = this.words;\n var answer = new Array(this.size());\n var pos = 0 | 0;\n var c = words.length;\n for (var k = 0; k < c; ++k) {\n var w = words[k];\n while (w != 0) {\n var t = w & -w;\n answer[pos++] = (k << 5) + (0, utils_1.hammingWeight)((t - 1) | 0);\n w ^= t;\n }\n }\n return answer;\n };\n TypedFastBitSet.prototype.forEach = function (fnc) {\n var words = this.words;\n var c = words.length;\n for (var k = 0; k < c; ++k) {\n var w = words[k];\n while (w != 0) {\n var t = w & -w;\n fnc(((k << 5) + (0, utils_1.hammingWeight)(t - 1)) | 0);\n w ^= t;\n }\n }\n };\n /**\n * Iterator of set bit locations (values)\n */\n TypedFastBitSet.prototype[Symbol.iterator] = function () {\n var _a;\n var words = this.words;\n var c = words.length;\n var k = 0;\n var w = words[k];\n return _a = {},\n _a[Symbol.iterator] = function () {\n return this;\n },\n _a.next = function () {\n while (k < c) {\n if (w !== 0) {\n var t = w & -w;\n var value = (k << 5) + (0, utils_1.hammingWeight)((t - 1) | 0);\n w ^= t;\n return { done: false, value: value };\n }\n else {\n k++;\n if (k < c) {\n w = words[k];\n }\n }\n }\n return { done: true, value: undefined };\n },\n _a;\n };\n /**\n * @returns a copy of this bitmap\n */\n TypedFastBitSet.prototype.clone = function () {\n return TypedFastBitSet.fromWords(new Uint32Array(this.words));\n };\n /**\n * Check if this bitset intersects with another one,\n * no bitmap is modified\n */\n TypedFastBitSet.prototype.intersects = function (otherbitmap) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var newcount = Math.min(words.length, otherWords.length);\n for (var k = 0 | 0; k < newcount; ++k) {\n if ((words[k] & otherWords[k]) !== 0)\n return true;\n }\n return false;\n };\n /**\n * Computes the intersection between this bitset and another one,\n * the current bitmap is modified (and returned by the function)\n */\n TypedFastBitSet.prototype.intersection = function (otherbitmap) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var newcount = Math.min(words.length, otherWords.length);\n var k = 0 | 0;\n for (; k + 7 < newcount; k += 8) {\n words[k] &= otherWords[k];\n words[k + 1] &= otherWords[k + 1];\n words[k + 2] &= otherWords[k + 2];\n words[k + 3] &= otherWords[k + 3];\n words[k + 4] &= otherWords[k + 4];\n words[k + 5] &= otherWords[k + 5];\n words[k + 6] &= otherWords[k + 6];\n words[k + 7] &= otherWords[k + 7];\n }\n for (; k < newcount; ++k) {\n words[k] &= otherWords[k];\n }\n var c = words.length;\n for (k = newcount; k < c; ++k) {\n words[k] = 0;\n }\n return this;\n };\n /**\n * Computes the size of the intersection between this bitset and another one\n */\n TypedFastBitSet.prototype.intersection_size = function (otherbitmap) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var newcount = Math.min(words.length, otherWords.length);\n var answer = 0 | 0;\n for (var k = 0 | 0; k < newcount; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k] & otherWords[k]);\n }\n return answer;\n };\n /**\n * Computes the intersection between this bitset and another one,\n * a new bitmap is generated\n */\n TypedFastBitSet.prototype.new_intersection = function (otherbitmap) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var count = Math.min(words.length, otherWords.length);\n var newWords = new Uint32Array(count);\n var k = 0 | 0;\n for (; k + 7 < count; k += 8) {\n newWords[k] = words[k] & otherWords[k];\n newWords[k + 1] = words[k + 1] & otherWords[k + 1];\n newWords[k + 2] = words[k + 2] & otherWords[k + 2];\n newWords[k + 3] = words[k + 3] & otherWords[k + 3];\n newWords[k + 4] = words[k + 4] & otherWords[k + 4];\n newWords[k + 5] = words[k + 5] & otherWords[k + 5];\n newWords[k + 7] = words[k + 7] & otherWords[k + 7];\n newWords[k + 6] = words[k + 6] & otherWords[k + 6];\n }\n for (; k < count; ++k) {\n newWords[k] = words[k] & otherWords[k];\n }\n return new TypedFastBitSet(undefined, newWords);\n };\n /**\n * Computes the intersection between this bitset and another one,\n * the current bitmap is modified\n */\n TypedFastBitSet.prototype.equals = function (otherbitmap) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var mcount = Math.min(words.length, otherWords.length);\n for (var k = 0 | 0; k < mcount; ++k) {\n if (words[k] != otherWords[k])\n return false;\n }\n if (words.length < otherWords.length) {\n var c = otherWords.length;\n for (var k = words.length; k < c; ++k) {\n if (otherWords[k] != 0)\n return false;\n }\n }\n else if (otherWords.length < words.length) {\n var c = words.length;\n for (var k = otherWords.length; k < c; ++k) {\n if (words[k] != 0)\n return false;\n }\n }\n return true;\n };\n /**\n * Computes the difference between this bitset and another one,\n * the current bitset is modified (and returned by the function)\n */\n TypedFastBitSet.prototype.difference = function (otherbitmap) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var newcount = Math.min(words.length, otherWords.length);\n var k = 0 | 0;\n for (; k + 7 < newcount; k += 8) {\n words[k] &= ~otherWords[k];\n words[k + 1] &= ~otherWords[k + 1];\n words[k + 2] &= ~otherWords[k + 2];\n words[k + 3] &= ~otherWords[k + 3];\n words[k + 4] &= ~otherWords[k + 4];\n words[k + 5] &= ~otherWords[k + 5];\n words[k + 6] &= ~otherWords[k + 6];\n words[k + 7] &= ~otherWords[k + 7];\n }\n for (; k < newcount; ++k) {\n words[k] &= ~otherWords[k];\n }\n return this;\n };\n /**\n * Computes the difference between this bitset and another one,\n * the other bitset is modified (and returned by the function)\n *\n * (for this set A and other set B, this computes B = A - B and returns B)\n */\n TypedFastBitSet.prototype.difference2 = function (otherbitmap) {\n var mincount = Math.min(this.words.length, otherbitmap.words.length);\n otherbitmap.resize((this.words.length << 5) - 1);\n var words = this.words;\n var otherWords = otherbitmap.words;\n var k = 0 | 0;\n for (; k + 7 < mincount; k += 8) {\n otherWords[k] = words[k] & ~otherWords[k];\n otherWords[k + 1] = words[k + 1] & ~otherWords[k + 1];\n otherWords[k + 2] = words[k + 2] & ~otherWords[k + 2];\n otherWords[k + 3] = words[k + 3] & ~otherWords[k + 3];\n otherWords[k + 4] = words[k + 4] & ~otherWords[k + 4];\n otherWords[k + 5] = words[k + 5] & ~otherWords[k + 5];\n otherWords[k + 6] = words[k + 6] & ~otherWords[k + 6];\n otherWords[k + 7] = words[k + 7] & ~otherWords[k + 7];\n }\n for (; k < mincount; ++k) {\n otherWords[k] = this.words[k] & ~otherWords[k];\n }\n // remaining words are all part of difference\n for (; k < this.words.length; ++k) {\n otherWords[k] = this.words[k];\n }\n otherWords.fill(0, k);\n return otherbitmap;\n };\n /**\n * Computes the difference between this bitset and another one,\n * a new bitmap is generated\n */\n TypedFastBitSet.prototype.new_difference = function (otherbitmap) {\n return this.clone().difference(otherbitmap); // should be fast enough\n };\n /**\n * Computes the size of the difference between this bitset and another one\n */\n TypedFastBitSet.prototype.difference_size = function (otherbitmap) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var newcount = Math.min(words.length, otherWords.length);\n var answer = 0 | 0;\n var k = 0 | 0;\n for (; k < newcount; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k] & ~otherWords[k]);\n }\n var c = words.length;\n for (; k < c; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k]);\n }\n return answer;\n };\n /**\n * Computes the changed elements (XOR) between this bitset and another one,\n * the current bitset is modified (and returned by the function)\n */\n TypedFastBitSet.prototype.change = function (otherbitmap) {\n var otherWords = otherbitmap.words;\n var mincount = Math.min(this.words.length, otherWords.length);\n this.resize((otherWords.length << 5) - 1);\n var words = this.words;\n var k = 0 | 0;\n for (; k + 7 < mincount; k += 8) {\n words[k] ^= otherWords[k];\n words[k + 1] ^= otherWords[k + 1];\n words[k + 2] ^= otherWords[k + 2];\n words[k + 3] ^= otherWords[k + 3];\n words[k + 4] ^= otherWords[k + 4];\n words[k + 5] ^= otherWords[k + 5];\n words[k + 6] ^= otherWords[k + 6];\n words[k + 7] ^= otherWords[k + 7];\n }\n for (; k < mincount; ++k) {\n words[k] ^= otherWords[k];\n }\n // remaining words are all part of change\n for (; k < otherWords.length; ++k) {\n words[k] = otherWords[k];\n }\n return this;\n };\n /**\n * Computes the change between this bitset and another one,\n * a new bitmap is generated\n */\n TypedFastBitSet.prototype.new_change = function (otherbitmap) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var count = Math.max(words.length, otherWords.length);\n var newWords = new Uint32Array(count);\n var mcount = Math.min(words.length, otherWords.length);\n var k = 0;\n for (; k + 7 < mcount; k += 8) {\n newWords[k] = words[k] ^ otherWords[k];\n newWords[k + 1] = words[k + 1] ^ otherWords[k + 1];\n newWords[k + 2] = words[k + 2] ^ otherWords[k + 2];\n newWords[k + 3] = words[k + 3] ^ otherWords[k + 3];\n newWords[k + 4] = words[k + 4] ^ otherWords[k + 4];\n newWords[k + 5] = words[k + 5] ^ otherWords[k + 5];\n newWords[k + 6] = words[k + 6] ^ otherWords[k + 6];\n newWords[k + 7] = words[k + 7] ^ otherWords[k + 7];\n }\n for (; k < mcount; ++k) {\n newWords[k] = words[k] ^ otherWords[k];\n }\n var c = words.length;\n for (k = mcount; k < c; ++k) {\n newWords[k] = words[k];\n }\n var c2 = otherWords.length;\n for (k = mcount; k < c2; ++k) {\n newWords[k] = otherWords[k];\n }\n return new TypedFastBitSet(undefined, newWords);\n };\n /**\n * Computes the number of changed elements between this bitset and another one\n */\n TypedFastBitSet.prototype.change_size = function (otherbitmap) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var mincount = Math.min(words.length, otherWords.length);\n var answer = 0 | 0;\n var k = 0 | 0;\n for (; k < mincount; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k] ^ otherWords[k]);\n }\n var longer = words.length > otherWords.length ? this : otherbitmap;\n var c = longer.words.length;\n for (; k < c; ++k) {\n answer += (0, utils_1.hammingWeight)(longer.words[k]);\n }\n return answer;\n };\n /**\n * @returns a string representation\n */\n TypedFastBitSet.prototype.toString = function () {\n return \"{\" + this.array().join(\",\") + \"}\";\n };\n /**\n * Computes the union between this bitset and another one,\n * the current bitset is modified (and returned by the function)\n */\n TypedFastBitSet.prototype.union = function (otherbitmap) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var mcount = Math.min(words.length, otherWords.length);\n var k = 0 | 0;\n for (; k + 7 < mcount; k += 8) {\n words[k] |= otherWords[k];\n words[k + 1] |= otherWords[k + 1];\n words[k + 2] |= otherWords[k + 2];\n words[k + 3] |= otherWords[k + 3];\n words[k + 4] |= otherWords[k + 4];\n words[k + 5] |= otherWords[k + 5];\n words[k + 6] |= otherWords[k + 6];\n words[k + 7] |= otherWords[k + 7];\n }\n for (; k < mcount; ++k) {\n words[k] |= otherWords[k];\n }\n if (words.length < otherWords.length) {\n this.resize((otherWords.length << 5) - 1);\n words = this.words;\n var c = otherWords.length;\n for (k = mcount; k < c; ++k) {\n words[k] = otherWords[k];\n }\n }\n return this;\n };\n /**\n * Computes the union between this bitset and another one,\n * a new bitmap is generated\n */\n TypedFastBitSet.prototype.new_union = function (otherbitmap) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var count = Math.max(words.length, otherWords.length);\n var newWords = new Uint32Array(count);\n var mcount = Math.min(words.length, otherWords.length);\n for (var k = 0; k < mcount; ++k) {\n newWords[k] = words[k] | otherWords[k];\n }\n var c = words.length;\n for (var k = mcount; k < c; ++k) {\n newWords[k] = words[k];\n }\n var c2 = otherWords.length;\n for (var k = mcount; k < c2; ++k) {\n newWords[k] = otherWords[k];\n }\n return new TypedFastBitSet(undefined, newWords);\n };\n /**\n * Computes the size union between this bitset and another one\n */\n TypedFastBitSet.prototype.union_size = function (otherbitmap) {\n var words = this.words;\n var otherWords = otherbitmap.words;\n var mcount = Math.min(words.length, otherWords.length);\n var answer = 0 | 0;\n for (var k = 0 | 0; k < mcount; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k] | otherWords[k]);\n }\n if (words.length < otherWords.length) {\n var c = otherWords.length;\n for (var k = words.length; k < c; ++k) {\n answer += (0, utils_1.hammingWeight)(otherWords[k] | 0);\n }\n }\n else {\n var c = words.length;\n for (var k = otherWords.length; k < c; ++k) {\n answer += (0, utils_1.hammingWeight)(words[k] | 0);\n }\n }\n return answer;\n };\n return TypedFastBitSet;\n}());\nexports.TypedFastBitSet = TypedFastBitSet;\n//# sourceMappingURL=TypedFastBitSet.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\n__exportStar(require(\"./SparseTypedFastBitSet\"), exports);\n__exportStar(require(\"./TypedFastBitSet\"), exports);\n//# sourceMappingURL=index.js.map","import {TypedFastBitSet} from \"typedfastbitset\";\n\n/**\n * Wrapper around TypedFastBitSet with graph-specific optimizations\n *\n * Provides efficient bit-packed set operations optimized for graph algorithms\n * with 8x memory reduction compared to standard JavaScript Set for boolean values.\n */\nexport class GraphBitSet {\n private bitset: TypedFastBitSet;\n private _cardinality = 0;\n\n constructor(capacity?: number) {\n this.bitset = new TypedFastBitSet();\n if (capacity) {\n // Pre-allocate for known size\n this.bitset.resize(capacity);\n }\n }\n\n /**\n * Add a single element\n */\n add(index: number): void {\n if (!this.bitset.has(index)) {\n this.bitset.add(index);\n this._cardinality++;\n }\n }\n\n /**\n * Remove a single element\n */\n remove(index: number): void {\n if (this.bitset.has(index)) {\n this.bitset.remove(index);\n this._cardinality--;\n }\n }\n\n /**\n * Check if element exists\n */\n has(index: number): boolean {\n return this.bitset.has(index);\n }\n\n /**\n * Clear all elements\n */\n clear(): void {\n this.bitset.clear();\n this._cardinality = 0;\n }\n\n /**\n * Check if empty\n */\n isEmpty(): boolean {\n return this._cardinality === 0;\n }\n\n /**\n * Optimized for graph algorithms - add range of indices\n */\n addRange(start: number, end: number): void {\n for (let i = start; i < end; i++) {\n if (!this.bitset.has(i)) {\n this.bitset.add(i);\n this._cardinality++;\n }\n }\n }\n\n /**\n * Fast cardinality tracking\n */\n size(): number {\n return this._cardinality;\n }\n\n /**\n * Batch operations for frontier management - swap contents\n */\n swap(other: GraphBitSet): void {\n [this.bitset, other.bitset] = [other.bitset, this.bitset];\n [this._cardinality, other._cardinality] = [other._cardinality, this._cardinality];\n }\n\n /**\n * Efficient iteration\n */\n *[Symbol.iterator](): Generator<number> {\n // Use TypedFastBitSet's optimized iteration\n yield* this.bitset;\n }\n\n /**\n * Set operations with cardinality tracking\n */\n union(other: GraphBitSet): void {\n const result = this.bitset.union(other.bitset);\n this.bitset = result;\n\n const size = this.bitset.size();\n this._cardinality = size;\n }\n\n intersection(other: GraphBitSet): void {\n const result = this.bitset.intersection(other.bitset);\n this.bitset = result;\n\n const size = this.bitset.size();\n this._cardinality = size;\n }\n\n difference(other: GraphBitSet): void {\n const result = this.bitset.difference(other.bitset);\n this.bitset = result;\n\n const size = this.bitset.size();\n this._cardinality = size;\n }\n\n /**\n * Clone the bitset\n */\n clone(): GraphBitSet {\n const cloned = new GraphBitSet();\n cloned.bitset = this.bitset.clone();\n\n cloned._cardinality = this._cardinality;\n return cloned;\n }\n}\n\n/**\n * Specialized bit array for visited tracking\n *\n * More memory efficient than GraphBitSet for simple boolean arrays\n * that don't need set operations.\n */\nexport class VisitedBitArray {\n private words: Uint32Array;\n private wordCount: number;\n private _size: number;\n\n constructor(size: number) {\n this._size = size;\n this.wordCount = Math.ceil(size / 32);\n this.words = new Uint32Array(this.wordCount);\n }\n\n /**\n * Set bit at index\n */\n set(index: number): void {\n if (index < 0 || index >= this._size) {\n throw new Error(`Index ${String(index)} out of bounds [0, ${String(this._size)})`);\n }\n\n const wordIndex = index >>> 5; // divide by 32\n const bitIndex = index & 31; // modulo 32\n const word = this.words[wordIndex];\n if (word !== undefined) {\n this.words[wordIndex] = word | (1 << bitIndex);\n }\n }\n\n /**\n * Get bit at index\n */\n get(index: number): boolean {\n if (index < 0 || index >= this._size) {\n return false;\n }\n\n const wordIndex = index >>> 5;\n const bitIndex = index & 31;\n const word = this.words[wordIndex];\n return word !== undefined && (word & (1 << bitIndex)) !== 0;\n }\n\n /**\n * Clear all bits\n */\n clear(): void {\n this.words.fill(0);\n }\n\n /**\n * Toggle bit at index\n */\n toggle(index: number): void {\n if (index < 0 || index >= this._size) {\n throw new Error(`Index ${String(index)} out of bounds [0, ${String(this._size)})`);\n }\n\n const wordIndex = index >>> 5;\n const bitIndex = index & 31;\n const word = this.words[wordIndex];\n if (word !== undefined) {\n this.words[wordIndex] = word ^ (1 << bitIndex);\n }\n }\n\n /**\n * Population count for statistics\n */\n popcount(): number {\n let count = 0;\n for (let i = 0; i < this.wordCount; i++) {\n const word = this.words[i];\n if (word !== undefined) {\n count += this.popcountWord(word);\n }\n }\n return count;\n }\n\n /**\n * Efficient population count for a single word\n * Uses bit manipulation tricks for fast counting\n */\n private popcountWord(n: number): number {\n let x = n;\n x = x - ((x >>> 1) & 0x55555555);\n x = (x & 0x33333333) + ((x >>> 2) & 0x33333333);\n return (((x + (x >>> 4)) & 0xF0F0F0F) * 0x1010101) >>> 24;\n }\n\n /**\n * Get size of the bit array\n */\n size(): number {\n return this._size;\n }\n\n /**\n * Check if all bits are zero\n */\n isEmpty(): boolean {\n for (let i = 0; i < this.wordCount; i++) {\n if (this.words[i] !== 0) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Set multiple bits from array\n */\n setMultiple(indices: number[]): void {\n for (const index of indices) {\n this.set(index);\n }\n }\n\n /**\n * Get indices of all set bits\n */\n getSetIndices(): number[] {\n const indices: number[] = [];\n for (let wordIndex = 0; wordIndex < this.wordCount; wordIndex++) {\n const word = this.words[wordIndex];\n if (!word || word === 0) {\n continue;\n }\n\n for (let bitIndex = 0; bitIndex < 32; bitIndex++) {\n if (word & (1 << bitIndex)) {\n const index = (wordIndex << 5) + bitIndex;\n if (index < this._size) {\n indices.push(index);\n }\n }\n }\n }\n return indices;\n }\n}\n\n/**\n * Bit-packed distance array for BFS\n *\n * Optimized for storing distances using 16-bit integers (up to 65,535 levels)\n * Still provides 2x memory savings compared to standard 32-bit numbers\n */\nexport class CompactDistanceArray {\n private data: Uint16Array;\n private _size: number;\n private static readonly INFINITY = 65535;\n\n constructor(size: number) {\n this._size = size;\n this.data = new Uint16Array(size);\n this.data.fill(CompactDistanceArray.INFINITY); // Initialize with max value (unvisited)\n }\n\n /**\n * Set distance at index\n */\n set(index: number, distance: number): void {\n if (distance >= CompactDistanceArray.INFINITY) {\n throw new Error(`Distance exceeds maximum value (${String(CompactDistanceArray.INFINITY - 1)})`);\n }\n\n this.data[index] = distance;\n }\n\n /**\n * Get distance at index\n */\n get(index: number): number {\n const value = this.data[index];\n return value ?? CompactDistanceArray.INFINITY; // Default to unvisited\n }\n\n /**\n * Check if node has been visited\n */\n isVisited(index: number): boolean {\n return this.data[index] !== CompactDistanceArray.INFINITY;\n }\n\n /**\n * Reset all distances\n */\n clear(): void {\n this.data.fill(CompactDistanceArray.INFINITY);\n }\n\n /**\n * Get size\n */\n size(): number {\n return this._size;\n }\n}\n","import type {NodeId} from \"../types/index.js\";\nimport {CompactDistanceArray, GraphBitSet} from \"./bit-packed.js\";\nimport {CSRGraph} from \"./csr-graph.js\";\n\n/**\n * Options for Direction-Optimized BFS\n */\nexport interface DirectionOptimizedBFSOptions {\n alpha?: number; // Default: 15 - Controls top-down to bottom-up switch\n beta?: number; // Default: 18 - Controls bottom-up to top-down switch\n}\n\n/**\n * Result of BFS traversal\n */\nexport interface BFSResult<TNodeId> {\n distances: Map<TNodeId, number>;\n parents: Map<TNodeId, TNodeId | null>;\n visitedCount: number;\n}\n\n/**\n * Direction-Optimized Breadth-First Search\n *\n * Dynamically switches between top-down and bottom-up search strategies\n * based on the size of the frontier. Particularly effective for low-diameter\n * graphs like social networks.\n *\n * Based on: Beamer, S., Asanović, K., & Patterson, D. (2012).\n * \"Direction-optimizing breadth-first search.\" SC'12.\n */\nexport class DirectionOptimizedBFS<TNodeId = NodeId> {\n private graph: CSRGraph<TNodeId>;\n private alpha: number;\n private beta: number;\n\n // Data structures\n private parent: Int32Array; // -1 = unvisited, -2 = source, else parent ID\n private frontier: GraphBitSet; // Current frontier bitmap\n private nextFrontier: GraphBitSet; // Next level frontier\n private distances: CompactDistanceArray;\n\n constructor(graph: CSRGraph<TNodeId>, options?: DirectionOptimizedBFSOptions) {\n this.graph = graph;\n this.alpha = options?.alpha ?? 15;\n this.beta = options?.beta ?? 18;\n\n const nodeCount = graph.nodeCount();\n this.parent = new Int32Array(nodeCount).fill(-1);\n this.frontier = new GraphBitSet(nodeCount);\n this.nextFrontier = new GraphBitSet(nodeCount);\n this.distances = new CompactDistanceArray(nodeCount);\n }\n\n /**\n * Perform BFS from a single source\n */\n search(source: TNodeId): BFSResult<TNodeId> {\n const sourceIndex = this.graph.nodeToIndex(source);\n this.parent[sourceIndex] = -2; // Mark as source\n this.frontier.add(sourceIndex);\n this.distances.set(sourceIndex, 0);\n\n // let currentDistance = 0; // Variable not used\n // Initialize edgesToCheck to total edges to prevent immediate switch to bottom-up\n let edgesToCheck = this.graph.edgeCount();\n let scoutCount = 0; // Will be set after first top-down step\n let awakeCount = 1; // Number of nodes in current frontier\n let oldAwakeCount = 0;\n\n // Direction tracking\n let useBottomUp = false;\n\n while (!this.frontier.isEmpty()) {\n oldAwakeCount = awakeCount;\n\n if (useBottomUp) {\n // Check if we should switch back to top-down\n if (awakeCount >= oldAwakeCount ||\n awakeCount > this.graph.nodeCount() / this.beta) {\n useBottomUp = false;\n }\n } else {\n // Check if we should switch to bottom-up\n if (scoutCount > edgesToCheck / this.alpha) {\n useBottomUp = true;\n }\n }\n\n if (useBottomUp) {\n awakeCount = this.bottomUpStep();\n } else {\n scoutCount = this.topDownStep();\n awakeCount = this.nextFrontier.size();\n }\n\n // Swap frontiers\n this.frontier.swap(this.nextFrontier);\n this.nextFrontier.clear();\n\n // currentDistance++; // Variable not used\n edgesToCheck = this.calculateEdgesToCheck();\n }\n\n return this.buildResult();\n }\n\n /**\n * Top-down BFS step - explore from frontier\n */\n private topDownStep(): number {\n let scoutCount = 0;\n\n // Iterate through frontier nodes\n for (const node of this.frontier) {\n const currentDistance = this.distances.get(node);\n\n for (const neighbor of this.graph.iterateNeighborIndices(node)) {\n if (this.parent[neighbor] === -1) {\n this.parent[neighbor] = node;\n this.distances.set(neighbor, currentDistance + 1);\n this.nextFrontier.add(neighbor);\n scoutCount += this.graph.outDegreeByIndex(neighbor);\n }\n }\n }\n\n return scoutCount;\n }\n\n /**\n * Bottom-up BFS step - check unvisited nodes\n */\n private bottomUpStep(): number {\n const nodeCount = this.graph.nodeCount();\n let awakeCount = 0;\n\n // Check all unvisited nodes\n for (let node = 0; node < nodeCount; node++) {\n if (this.parent[node] === -1) {\n // Use incoming edges for bottom-up traversal\n for (const neighbor of this.graph.iterateIncomingNeighborIndices(node)) {\n if (this.frontier.has(neighbor)) {\n this.parent[node] = neighbor;\n const neighborDist = this.distances.get(neighbor);\n this.distances.set(node, neighborDist + 1);\n this.nextFrontier.add(node);\n awakeCount++;\n break; // Found a parent, no need to check more\n }\n }\n }\n }\n\n return awakeCount;\n }\n\n /**\n * Calculate edges to check for switching heuristic\n */\n private calculateEdgesToCheck(): number {\n let count = 0;\n for (const node of this.frontier) {\n count += this.graph.outDegreeByIndex(node);\n }\n return count;\n }\n\n /**\n * Build result map from internal data structures\n */\n private buildResult(): BFSResult<TNodeId> {\n const distances = new Map<TNodeId, number>();\n const parents = new Map<TNodeId, TNodeId | null>();\n let visitedCount = 0;\n\n for (let i = 0; i < this.graph.nodeCount(); i++) {\n if (this.parent[i] !== -1) {\n const nodeId = this.graph.indexToNodeId(i);\n distances.set(nodeId, this.distances.get(i));\n\n if (this.parent[i] === -2) {\n // Source node\n parents.set(nodeId, null);\n } else {\n // Regular node with parent\n const parentIndex = this.parent[i];\n if (parentIndex !== undefined && parentIndex >= 0) {\n parents.set(nodeId, this.graph.indexToNodeId(parentIndex));\n }\n }\n\n visitedCount++;\n }\n }\n\n return {distances, parents, visitedCount};\n }\n\n /**\n * Perform multi-source BFS\n */\n searchMultiple(sources: TNodeId[]): BFSResult<TNodeId> {\n // Initialize multiple sources\n for (const source of sources) {\n const sourceIndex = this.graph.nodeToIndex(source);\n this.parent[sourceIndex] = -2; // Mark as source\n this.frontier.add(sourceIndex);\n this.distances.set(sourceIndex, 0);\n }\n\n // let currentDistance = 0; // Variable not used\n let edgesToCheck = 0;\n let scoutCount = 0;\n\n // Calculate initial edges to check\n for (const node of this.frontier) {\n const degree = this.graph.outDegreeByIndex(node);\n edgesToCheck += degree;\n scoutCount += degree;\n }\n\n let awakeCount = sources.length;\n let oldAwakeCount = 0;\n let useBottomUp = false;\n\n while (!this.frontier.isEmpty()) {\n oldAwakeCount = awakeCount;\n\n if (useBottomUp) {\n if (awakeCount >= oldAwakeCount ||\n awakeCount > this.graph.nodeCount() / this.beta) {\n useBottomUp = false;\n }\n } else {\n if (scoutCount > edgesToCheck / this.alpha) {\n useBottomUp = true;\n }\n }\n\n if (useBottomUp) {\n awakeCount = this.bottomUpStep();\n } else {\n scoutCount = this.topDownStep();\n awakeCount = this.nextFrontier.size();\n }\n\n this.frontier.swap(this.nextFrontier);\n this.nextFrontier.clear();\n\n // currentDistance++; // Variable not used\n edgesToCheck = this.calculateEdgesToCheck();\n }\n\n return this.buildResult();\n }\n\n /**\n * Reset internal state for reuse\n */\n reset(): void {\n this.parent.fill(-1);\n this.frontier.clear();\n this.nextFrontier.clear();\n this.distances.clear();\n }\n}\n\n/**\n * Convenience function for single-source BFS\n */\nexport function directionOptimizedBFS<TNodeId = NodeId>(\n graph: CSRGraph<TNodeId>,\n source: TNodeId,\n options?: DirectionOptimizedBFSOptions,\n): BFSResult<TNodeId> {\n const bfs = new DirectionOptimizedBFS(graph, options);\n return bfs.search(source);\n}\n\n/**\n * Convenience function for multi-source BFS\n */\nexport function directionOptimizedBFSMultiple<TNodeId = NodeId>(\n graph: CSRGraph<TNodeId>,\n sources: TNodeId[],\n options?: DirectionOptimizedBFSOptions,\n): BFSResult<TNodeId> {\n const bfs = new DirectionOptimizedBFS(graph, options);\n return bfs.searchMultiple(sources);\n}\n","import type {NodeId} from \"../types/index.js\";\n\n/**\n * Interface for read-only graph operations\n */\nexport interface ReadonlyGraph<TNodeId = NodeId> {\n nodeCount(): number;\n edgeCount(): number;\n hasNode(nodeId: TNodeId): boolean;\n hasEdge(source: TNodeId, target: TNodeId): boolean;\n neighbors(nodeId: TNodeId): IterableIterator<TNodeId>;\n outDegree(nodeId: TNodeId): number;\n nodes(): IterableIterator<TNodeId>;\n}\n\n/**\n * Internal data structure for CSR representation\n */\ninterface CSRGraphData<TNodeId> {\n // Row pointers: indices where each node's edges start\n rowPointers: Uint32Array;\n\n // Column indices: destination nodes for each edge\n columnIndices: Uint32Array;\n\n // Edge weights (optional)\n edgeWeights?: Float32Array;\n\n // Reverse edges for bottom-up BFS (optional)\n reverseRowPointers?: Uint32Array;\n reverseColumnIndices?: Uint32Array;\n\n // Node ID mapping\n nodeIdToIndex: Map<TNodeId, number>;\n indexToNodeId: TNodeId[];\n}\n\n/**\n * Compressed Sparse Row (CSR) graph representation\n *\n * Provides cache-efficient graph storage with sequential memory access patterns.\n * Optimized for traversal operations and sparse graphs.\n */\nexport class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {\n private data: CSRGraphData<TNodeId>;\n\n constructor(adjacencyList: Map<TNodeId, TNodeId[]>, weights?: Map<string, number>, buildReverse = true) {\n this.data = this.buildCSR(adjacencyList, weights, buildReverse);\n }\n\n /**\n * Build CSR structure from adjacency list\n */\n private buildCSR(\n adjacencyList: Map<TNodeId, TNodeId[]>,\n weights?: Map<string, number>,\n buildReverse = true,\n ): CSRGraphData<TNodeId> {\n // Collect all unique nodes (both sources and targets)\n const allNodes = new Set<TNodeId>();\n for (const [source, neighbors] of adjacencyList) {\n allNodes.add(source);\n for (const neighbor of neighbors) {\n allNodes.add(neighbor);\n }\n }\n\n // Sort nodes for consistent ordering. Numeric IDs sort numerically,\n // string IDs sort lexicographically for predictable iteration order.\n const nodes = Array.from(allNodes).sort((a, b) => {\n if (typeof a === \"number\" && typeof b === \"number\") {\n return a - b;\n }\n\n return String(a).localeCompare(String(b));\n });\n const nodeCount = nodes.length;\n\n // Build node mappings\n const nodeIdToIndex = new Map<TNodeId, number>();\n const indexToNodeId: TNodeId[] = [];\n\n nodes.forEach((nodeId, index) => {\n nodeIdToIndex.set(nodeId, index);\n indexToNodeId[index] = nodeId;\n });\n\n // Count total edges\n let edgeCount = 0;\n for (const neighbors of adjacencyList.values()) {\n edgeCount += neighbors.length;\n }\n\n // Allocate arrays\n const rowPointers = new Uint32Array(nodeCount + 1);\n const columnIndices = new Uint32Array(edgeCount);\n const edgeWeights = weights ? new Float32Array(edgeCount) : undefined;\n\n // Build CSR structure\n let currentEdge = 0;\n for (let i = 0; i < nodeCount; i++) {\n rowPointers[i] = currentEdge;\n const nodeId = indexToNodeId[i];\n if (nodeId === undefined) {\n throw new Error(`Invalid node index ${String(i)}`);\n }\n\n const neighbors = adjacencyList.get(nodeId) ?? [];\n\n // Sort neighbors for better cache locality and binary search\n const sortedNeighbors = neighbors\n .map((n) => {\n const index = nodeIdToIndex.get(n);\n if (index === undefined) {\n throw new Error(`Node ${String(n)} not found in nodeIdToIndex map`);\n }\n\n return {id: n, index};\n })\n .sort((a, b) => a.index - b.index);\n\n for (const neighbor of sortedNeighbors) {\n columnIndices[currentEdge] = neighbor.index;\n\n if (edgeWeights && weights) {\n const edgeKey = `${String(nodeId)}-${String(neighbor.id)}`;\n const weight = weights.get(edgeKey);\n if (weight !== undefined) {\n edgeWeights[currentEdge] = weight;\n } else {\n edgeWeights[currentEdge] = 1;\n }\n }\n\n currentEdge++;\n }\n }\n rowPointers[nodeCount] = currentEdge;\n\n const result: CSRGraphData<TNodeId> = {\n rowPointers,\n columnIndices,\n nodeIdToIndex,\n indexToNodeId,\n };\n\n if (edgeWeights) {\n result.edgeWeights = edgeWeights;\n }\n\n // Build reverse edges for bottom-up BFS\n if (buildReverse) {\n const reverseAdjacency = new Map<number, number[]>();\n for (let i = 0; i < nodeCount; i++) {\n reverseAdjacency.set(i, []);\n }\n\n // Build reverse adjacency from forward edges\n for (let i = 0; i < nodeCount; i++) {\n const start = rowPointers[i];\n const end = rowPointers[i + 1];\n if (start !== undefined && end !== undefined) {\n for (let j = start; j < end; j++) {\n const target = columnIndices[j];\n if (target !== undefined) {\n reverseAdjacency.get(target)?.push(i);\n }\n }\n }\n }\n\n // Build reverse CSR\n const reverseRowPointers = new Uint32Array(nodeCount + 1);\n const reverseColumnIndices = new Uint32Array(edgeCount);\n\n let reverseEdge = 0;\n for (let i = 0; i < nodeCount; i++) {\n reverseRowPointers[i] = reverseEdge;\n const incoming = reverseAdjacency.get(i) ?? [];\n incoming.sort((a, b) => a - b);\n\n for (const source of incoming) {\n reverseColumnIndices[reverseEdge++] = source;\n }\n }\n reverseRowPointers[nodeCount] = reverseEdge;\n\n result.reverseRowPointers = reverseRowPointers;\n result.reverseColumnIndices = reverseColumnIndices;\n }\n\n return result;\n }\n\n // Core API methods\n nodeCount(): number {\n return this.data.indexToNodeId.length;\n }\n\n edgeCount(): number {\n return this.data.columnIndices.length;\n }\n\n hasNode(nodeId: TNodeId): boolean {\n return this.data.nodeIdToIndex.has(nodeId);\n }\n\n hasEdge(source: TNodeId, target: TNodeId): boolean {\n const sourceIndex = this.data.nodeIdToIndex.get(source);\n const targetIndex = this.data.nodeIdToIndex.get(target);\n\n if (sourceIndex === undefined || targetIndex === undefined) {\n return false;\n }\n\n const start = this.data.rowPointers[sourceIndex];\n const end = this.data.rowPointers[sourceIndex + 1];\n\n // Binary search for target in sorted neighbors\n if (start === undefined || end === undefined) {\n return false;\n }\n\n return this.binarySearch(this.data.columnIndices, targetIndex, start, end) !== -1;\n }\n\n /**\n * Get neighbors as node IDs\n */\n neighbors(nodeId: TNodeId): IterableIterator<TNodeId> {\n const nodeIndex = this.data.nodeIdToIndex.get(nodeId);\n if (nodeIndex === undefined) {\n return new Set<TNodeId>().values();\n }\n\n const start = this.data.rowPointers[nodeIndex];\n const end = this.data.rowPointers[nodeIndex + 1];\n\n const {columnIndices, indexToNodeId} = this.data;\n function* generateNeighbors(): Generator<TNodeId> {\n if (start !== undefined && end !== undefined) {\n for (let i = start; i < end; i++) {\n const idx = columnIndices[i];\n if (idx !== undefined) {\n const nodeId = indexToNodeId[idx];\n if (nodeId !== undefined) {\n yield nodeId;\n }\n }\n }\n }\n }\n\n return generateNeighbors();\n }\n\n /**\n * Get all nodes\n */\n nodes(): IterableIterator<TNodeId> {\n return this.data.indexToNodeId.values();\n }\n\n /**\n * Get neighbors as indices (internal use)\n */\n getNeighborIndices(nodeIndex: number): number[] {\n if (nodeIndex < 0 || nodeIndex >= this.data.indexToNodeId.length) {\n return [];\n }\n\n const start = this.data.rowPointers[nodeIndex];\n const end = this.data.rowPointers[nodeIndex + 1];\n if (start === undefined || end === undefined) {\n return [];\n }\n\n return Array.from(this.data.columnIndices.subarray(start, end));\n }\n\n outDegree(nodeId: TNodeId): number {\n const nodeIndex = this.data.nodeIdToIndex.get(nodeId);\n if (nodeIndex === undefined) {\n return 0;\n }\n\n return this.outDegreeByIndex(nodeIndex);\n }\n\n /**\n * Get out-degree by index (internal use)\n */\n outDegreeByIndex(nodeIndex: number): number {\n const start = this.data.rowPointers[nodeIndex];\n const end = this.data.rowPointers[nodeIndex + 1];\n if (start !== undefined && end !== undefined) {\n return end - start;\n }\n\n return 0;\n }\n\n /**\n * Iterator support for neighbor indices\n */\n *iterateNeighborIndices(nodeIndex: number): Generator<number> {\n const start = this.data.rowPointers[nodeIndex];\n const end = this.data.rowPointers[nodeIndex + 1];\n\n if (start !== undefined && end !== undefined) {\n for (let i = start; i < end; i++) {\n const value = this.data.columnIndices[i];\n if (value !== undefined) {\n yield value;\n }\n }\n }\n }\n\n /**\n * Iterator support for incoming neighbor indices (for bottom-up BFS)\n */\n *iterateIncomingNeighborIndices(nodeIndex: number): Generator<number> {\n if (!this.data.reverseRowPointers || !this.data.reverseColumnIndices) {\n return;\n }\n\n const start = this.data.reverseRowPointers[nodeIndex];\n const end = this.data.reverseRowPointers[nodeIndex + 1];\n\n if (start !== undefined && end !== undefined) {\n for (let i = start; i < end; i++) {\n const value = this.data.reverseColumnIndices[i];\n if (value !== undefined) {\n yield value;\n }\n }\n }\n }\n\n /**\n * Convert node ID to index\n */\n nodeToIndex(nodeId: TNodeId): number {\n const index = this.data.nodeIdToIndex.get(nodeId);\n if (index === undefined) {\n throw new Error(`Node ${String(nodeId)} not found in graph`);\n }\n\n return index;\n }\n\n /**\n * Convert index to node ID\n */\n indexToNodeId(index: number): TNodeId {\n const nodeId = this.data.indexToNodeId[index];\n if (nodeId === undefined) {\n throw new Error(`Index ${String(index)} out of bounds`);\n }\n\n return nodeId;\n }\n\n /**\n * Get edge weight\n */\n getEdgeWeight(source: TNodeId, target: TNodeId): number | undefined {\n if (!this.data.edgeWeights) {\n return undefined;\n }\n\n const sourceIndex = this.data.nodeIdToIndex.get(source);\n const targetIndex = this.data.nodeIdToIndex.get(target);\n\n if (sourceIndex === undefined || targetIndex === undefined) {\n return undefined;\n }\n\n const start = this.data.rowPointers[sourceIndex];\n const end = this.data.rowPointers[sourceIndex + 1];\n\n if (start === undefined || end === undefined) {\n return undefined;\n }\n\n const edgeIndex = this.binarySearch(this.data.columnIndices, targetIndex, start, end);\n if (edgeIndex === -1) {\n return undefined;\n }\n\n return this.data.edgeWeights[edgeIndex];\n }\n\n /**\n * Binary search for target in sorted array\n */\n private binarySearch(arr: Uint32Array, target: number, start: number, end: number): number {\n let left = start;\n let right = end - 1;\n\n while (left <= right) {\n const mid = (left + right) >>> 1;\n const value = arr[mid];\n\n if (value === undefined) {\n return -1;\n }\n\n if (value === target) {\n return mid;\n }\n\n if (value < target) {\n left = mid + 1;\n } else {\n right = mid - 1;\n }\n }\n\n return -1;\n }\n\n /**\n * Create CSR graph from standard Graph\n */\n static fromGraph<TNodeId = NodeId>(graph: {\n nodes(): IterableIterator<{id: TNodeId}>;\n neighbors(nodeId: TNodeId): IterableIterator<TNodeId>;\n hasNode(nodeId: TNodeId): boolean;\n getEdge?(source: TNodeId, target: TNodeId): {weight?: number} | undefined;\n }): CSRGraph<TNodeId> {\n const adjacencyList = new Map<TNodeId, TNodeId[]>();\n const weights = new Map<string, number>();\n\n // Build adjacency list\n for (const node of graph.nodes()) {\n const neighbors: TNodeId[] = [];\n for (const neighbor of graph.neighbors(node.id)) {\n neighbors.push(neighbor);\n\n // Get edge weight if available\n if (graph.getEdge) {\n const edge = graph.getEdge(node.id, neighbor);\n if (edge?.weight !== undefined) {\n weights.set(`${String(node.id)}-${String(neighbor)}`, edge.weight);\n }\n }\n }\n adjacencyList.set(node.id, neighbors);\n }\n\n return new CSRGraph(adjacencyList, weights.size > 0 ? weights : undefined);\n }\n}\n","import type {Graph} from \"../core/graph.js\";\nimport type {NodeId} from \"../types/index.js\";\nimport {CSRGraph, type ReadonlyGraph} from \"./csr-graph.js\";\n\n/**\n * Adapter to convert standard Graph to CSR format\n *\n * Provides transparent conversion while maintaining API compatibility\n */\nexport class GraphAdapter<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {\n private csrGraph: CSRGraph<TNodeId>;\n\n constructor(graph: Graph | ReadonlyGraph<TNodeId>) {\n // Check if already a CSRGraph\n if (graph instanceof CSRGraph) {\n this.csrGraph = graph as CSRGraph<TNodeId>;\n } else {\n // Convert to CSR format\n this.csrGraph = this.convertToCSR(graph);\n }\n }\n\n /**\n * Convert standard graph to CSR format\n */\n private convertToCSR(graph: Graph | ReadonlyGraph<TNodeId>): CSRGraph<TNodeId> {\n const adjacencyList = new Map<TNodeId, TNodeId[]>();\n const weights = new Map<string, number>();\n\n // Handle both Graph and ReadonlyGraph interfaces\n if (\"nodes\" in graph && typeof graph.nodes === \"function\") {\n // Build adjacency list from Graph\n for (const node of graph.nodes()) {\n const nodeId = (node as {id: TNodeId}).id;\n const neighbors: TNodeId[] = [];\n\n const graphTyped = graph as Graph;\n for (const neighborId of graphTyped.neighbors(nodeId as NodeId)) {\n neighbors.push(neighborId as TNodeId);\n\n // Get edge weight if available\n if (\"getEdge\" in graph && typeof graph.getEdge === \"function\") {\n const edge = graphTyped.getEdge(nodeId as NodeId, neighborId);\n if (edge?.weight !== undefined) {\n weights.set(`${String(nodeId)}-${String(neighborId)}`, edge.weight);\n }\n }\n }\n\n adjacencyList.set(nodeId, neighbors);\n }\n } else if (\"nodeIds\" in graph && typeof graph.nodeIds === \"function\") {\n // Handle ReadonlyGraph with nodeIds method\n interface ReadonlyGraphWithNodeIds {\n nodeIds(): Iterable<TNodeId>;\n edges?(): Iterable<{source: TNodeId, target: TNodeId, weight?: number}>;\n }\n const readonlyGraph = graph as ReadonlyGraphWithNodeIds;\n for (const nodeId of readonlyGraph.nodeIds()) {\n adjacencyList.set(nodeId, []);\n }\n\n // Build adjacency from edges\n if (\"edges\" in readonlyGraph && typeof readonlyGraph.edges === \"function\") {\n for (const edge of readonlyGraph.edges()) {\n const neighbors = adjacencyList.get(edge.source);\n if (neighbors) {\n neighbors.push(edge.target);\n if (edge.weight !== undefined) {\n weights.set(`${String(edge.source)}-${String(edge.target)}`, edge.weight);\n }\n }\n }\n }\n }\n\n return new CSRGraph(adjacencyList, weights.size > 0 ? weights : undefined);\n }\n\n // Delegate all methods to CSR implementation\n nodeCount(): number {\n return this.csrGraph.nodeCount();\n }\n\n edgeCount(): number {\n return this.csrGraph.edgeCount();\n }\n\n hasNode(nodeId: TNodeId): boolean {\n return this.csrGraph.hasNode(nodeId);\n }\n\n hasEdge(source: TNodeId, target: TNodeId): boolean {\n return this.csrGraph.hasEdge(source, target);\n }\n\n neighbors(nodeId: TNodeId): IterableIterator<TNodeId> {\n return this.csrGraph.neighbors(nodeId);\n }\n\n outDegree(nodeId: TNodeId): number {\n return this.csrGraph.outDegree(nodeId);\n }\n\n nodes(): IterableIterator<TNodeId> {\n return this.csrGraph.nodes();\n }\n\n /**\n * Get the underlying CSR graph\n */\n getCSRGraph(): CSRGraph<TNodeId> {\n return this.csrGraph;\n }\n}\n\n/**\n * Configuration for graph algorithm optimizations\n */\nexport interface GraphAlgorithmConfig {\n // Enable optimizations\n useDirectionOptimizedBFS?: boolean;\n useCSRFormat?: boolean;\n useBitPackedStructures?: boolean;\n\n // Algorithm-specific parameters\n bfsAlpha?: number;\n bfsBeta?: number;\n\n // Memory vs speed tradeoffs\n preallocateSize?: number;\n enableCaching?: boolean;\n}\n\n/**\n * Configure optimizations globally\n * @deprecated This function is a no-op and will be removed in a future version\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function configureOptimizations(_config: GraphAlgorithmConfig): void {\n // No-op for backward compatibility\n}\n\n/**\n * Get current configuration\n * @deprecated This function returns empty config and will be removed in a future version\n */\nexport function getOptimizationConfig(): GraphAlgorithmConfig {\n return {};\n}\n\n/**\n * Check if a graph is already in CSR format\n */\nexport function isCSRGraph<TNodeId = NodeId>(graph: unknown): graph is CSRGraph<TNodeId> {\n return graph instanceof CSRGraph;\n}\n\n/**\n * Convert any graph to CSR format\n */\nexport function toCSRGraph<TNodeId = NodeId>(\n graph: Graph | ReadonlyGraph<TNodeId> | CSRGraph<TNodeId>,\n): CSRGraph<TNodeId> {\n if (isCSRGraph<TNodeId>(graph)) {\n return graph;\n }\n\n const adapter = new GraphAdapter<TNodeId>(graph);\n return adapter.getCSRGraph();\n}\n\n/**\n * Create an optimized graph from nodes and edges\n */\nexport function createOptimizedGraph<TNodeId = NodeId>(\n nodes: TNodeId[],\n edges: [TNodeId, TNodeId, number?][],\n): CSRGraph<TNodeId> {\n const adjacencyList = new Map<TNodeId, TNodeId[]>();\n const weights = new Map<string, number>();\n\n // Initialize nodes\n for (const node of nodes) {\n adjacencyList.set(node, []);\n }\n\n // Add edges\n for (const [source, target, weight] of edges) {\n const neighbors = adjacencyList.get(source);\n if (neighbors) {\n neighbors.push(target);\n if (weight !== undefined) {\n weights.set(`${String(source)}-${String(target)}`, weight);\n }\n }\n }\n\n return new CSRGraph(adjacencyList, weights.size > 0 ? weights : undefined);\n}\n","import {Graph} from \"../core/graph.js\";\nimport type {NodeId} from \"../types/index.js\";\n\n/**\n * Reconstructs a path from source to target using a predecessor map\n * @param target - The target node\n * @param predecessor - Map of node to its predecessor in the path\n * @returns Array of nodes from source to target, or empty array if no path exists\n */\nexport function reconstructPath<T>(\n target: T,\n predecessor: Map<T, T | null>,\n): T[] {\n const path: T[] = [];\n let current: T | null = target;\n\n // Build path backwards from target to source\n while (current !== null) {\n path.unshift(current);\n const pred = predecessor.get(current);\n if (pred === undefined) {\n // No path exists\n return [];\n }\n\n current = pred;\n }\n\n return path;\n}\n\n/**\n * Find common neighbors between two nodes\n * @param graph - The graph\n * @param source - First node\n * @param target - Second node\n * @param directed - Whether to consider edge direction\n * @returns Set of common neighbor node IDs\n */\nexport function getCommonNeighbors(\n graph: Graph,\n source: NodeId,\n target: NodeId,\n directed = false,\n): Set<NodeId> {\n const sourceNeighbors = new Set(\n directed ? graph.outNeighbors(source) : graph.neighbors(source),\n );\n const targetNeighbors = new Set(\n directed ? graph.outNeighbors(target) : graph.neighbors(target),\n );\n\n const common = new Set<NodeId>();\n for (const neighbor of sourceNeighbors) {\n if (targetNeighbors.has(neighbor)) {\n common.add(neighbor);\n }\n }\n\n return common;\n}\n\n/**\n * Find common neighbors for link prediction in directed graphs\n * This finds nodes that form a path from source to target (source->X->target)\n * @param graph - The graph\n * @param source - First node\n * @param target - Second node\n * @returns Set of intermediate node IDs\n */\nexport function getIntermediateNodes(\n graph: Graph,\n source: NodeId,\n target: NodeId,\n): Set<NodeId> {\n const sourceOutNeighbors = new Set(graph.outNeighbors(source));\n const targetInNeighbors = new Set(graph.inNeighbors(target));\n\n const common = new Set<NodeId>();\n for (const neighbor of sourceOutNeighbors) {\n if (targetInNeighbors.has(neighbor)) {\n common.add(neighbor);\n }\n }\n\n return common;\n}\n\n/**\n * Generate a consistent edge key for undirected graphs\n * @param source - Source node\n * @param target - Target node\n * @param isDirected - Whether the graph is directed\n * @returns A consistent edge identifier\n */\nexport function getEdgeKey(\n source: NodeId,\n target: NodeId,\n isDirected: boolean,\n): string {\n if (isDirected) {\n return `${String(source)}->${String(target)}`;\n }\n\n // For undirected graphs, sort to ensure consistency\n const [first, second] = source < target ? [source, target] : [target, source];\n return `${String(first)}-${String(second)}`;\n}\n\n/**\n * Calculate total edge weight in a graph\n * @param graph - The graph\n * @returns Total weight of all edges\n */\nexport function getTotalEdgeWeight(graph: Graph): number {\n let totalWeight = 0;\n for (const edge of graph.edges()) {\n totalWeight += edge.weight ?? 1;\n }\n return graph.isDirected ? totalWeight : totalWeight / 2;\n}\n\n/**\n * Get node degree with optional mode for directed graphs\n * @param graph - The graph\n * @param nodeId - The node ID\n * @param mode - Degree mode for directed graphs\n * @returns Node degree\n */\nexport function getNodeDegree(\n graph: Graph,\n nodeId: NodeId,\n mode: \"in\" | \"out\" | \"total\" = \"total\",\n): number {\n if (!graph.isDirected || mode === \"total\") {\n return graph.degree(nodeId);\n }\n\n if (mode === \"in\") {\n return graph.inDegree(nodeId);\n }\n\n return graph.outDegree(nodeId);\n}\n\n/**\n * Convert directed graph to undirected\n * @param graph - The directed graph\n * @returns A new undirected graph\n */\nexport function makeUndirected(graph: Graph): Graph {\n if (!graph.isDirected) {\n return graph;\n }\n\n const undirected = new Graph({directed: false});\n\n // Add all nodes\n for (const node of graph.nodes()) {\n undirected.addNode(node.id, node.data);\n }\n\n // Add edges (will automatically be made bidirectional)\n for (const edge of graph.edges()) {\n // For undirected, we only add each edge once\n if (!undirected.hasEdge(edge.source, edge.target)) {\n undirected.addEdge(edge.source, edge.target, edge.weight, edge.data);\n }\n }\n\n return undirected;\n}\n\n/**\n * Renumber communities consecutively starting from 0\n * @param communities - Map of node to community ID\n * @returns Map with renumbered community IDs\n */\nexport function renumberCommunities<T>(\n communities: Map<T, number>,\n): Map<T, number> {\n const uniqueCommunities = new Set(communities.values());\n const remapping = new Map<number, number>();\n let newId = 0;\n\n for (const community of uniqueCommunities) {\n remapping.set(community, newId++);\n }\n\n const renumbered = new Map<T, number>();\n for (const [node, community] of communities) {\n const newCommunity = remapping.get(community);\n if (newCommunity !== undefined) {\n renumbered.set(node, newCommunity);\n }\n }\n\n return renumbered;\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport {CSRGraph} from \"../../optimized/csr-graph.js\";\nimport {DirectionOptimizedBFS} from \"../../optimized/direction-optimized-bfs.js\";\nimport {toCSRGraph} from \"../../optimized/graph-adapter.js\";\nimport type {NodeId, ShortestPathResult, TraversalOptions, TraversalResult} from \"../../types/index.js\";\nimport {reconstructPath} from \"../../utils/graph-utilities.js\";\n\n/**\n * Unified BFS implementation that automatically optimizes for large graphs\n *\n * This module provides a single, user-friendly BFS implementation that:\n * - Automatically uses Direction-Optimized BFS for large graphs (>10k nodes)\n * - Maintains backward compatibility with existing APIs\n * - Requires no configuration or understanding of optimization thresholds\n * - Provides the best performance by default\n */\n\n// Cache for CSR conversions to avoid repeated conversions\nconst csrCache = new WeakMap<Graph, CSRGraph>();\n\n/**\n * Get or create CSR representation of a graph\n */\nfunction getCSRGraph(graph: Graph): CSRGraph {\n let csrGraph = csrCache.get(graph);\n if (!csrGraph) {\n csrGraph = toCSRGraph(graph);\n csrCache.set(graph, csrGraph);\n }\n\n return csrGraph;\n}\n\n/**\n * Perform breadth-first search starting from a given node\n *\n * Automatically uses the most optimized implementation based on graph size.\n * No configuration needed - just call this function for the best performance.\n */\nexport function breadthFirstSearch(\n graph: Graph,\n startNode: NodeId,\n options: TraversalOptions = {},\n): TraversalResult {\n if (!graph.hasNode(startNode)) {\n throw new Error(`Start node ${String(startNode)} not found in graph`);\n }\n\n // Automatically use optimized implementation for large graphs\n if (graph.nodeCount > 10000) {\n return breadthFirstSearchOptimized(graph, startNode, options);\n }\n\n // Standard implementation for smaller graphs\n return breadthFirstSearchStandard(graph, startNode, options);\n}\n\n/**\n * Standard BFS implementation for smaller graphs\n */\nfunction breadthFirstSearchStandard(\n graph: Graph,\n startNode: NodeId,\n options: TraversalOptions = {},\n): TraversalResult {\n const visited = new Set<NodeId>();\n const queue: {node: NodeId, level: number}[] = [];\n const order: NodeId[] = [];\n const tree = new Map<NodeId, NodeId | null>();\n\n // Initialize with start node\n queue.push({node: startNode, level: 0});\n visited.add(startNode);\n tree.set(startNode, null);\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (!current) {\n break;\n }\n\n order.push(current.node);\n\n // Call visitor callback if provided\n if (options.visitCallback) {\n options.visitCallback(current.node, current.level);\n }\n\n // Early termination if target found\n if (options.targetNode && current.node === options.targetNode) {\n break;\n }\n\n // Explore neighbors\n for (const neighbor of graph.neighbors(current.node)) {\n if (!visited.has(neighbor)) {\n visited.add(neighbor);\n tree.set(neighbor, current.node);\n queue.push({node: neighbor, level: current.level + 1});\n }\n }\n }\n\n return {visited, order, tree};\n}\n\n/**\n * Optimized BFS implementation using Direction-Optimized BFS\n */\nfunction breadthFirstSearchOptimized(\n graph: Graph,\n startNode: NodeId,\n options: TraversalOptions = {},\n): TraversalResult {\n const csrGraph = getCSRGraph(graph);\n\n const dobfs = new DirectionOptimizedBFS(csrGraph, {\n alpha: 15.0,\n beta: 20.0,\n });\n\n const result = dobfs.search(startNode);\n\n // Convert result to TraversalResult format\n const visited = new Set<NodeId>();\n const order: NodeId[] = [];\n const tree = new Map<NodeId, NodeId | null>();\n\n // Build traversal order using BFS from distances\n const nodesByDistance = new Map<number, NodeId[]>();\n let maxDistance = 0;\n\n for (const [nodeId, distance] of result.distances) {\n visited.add(nodeId);\n tree.set(nodeId, result.parents.get(nodeId) ?? null);\n\n if (!nodesByDistance.has(distance)) {\n nodesByDistance.set(distance, []);\n }\n\n nodesByDistance.get(distance)?.push(nodeId);\n maxDistance = Math.max(maxDistance, distance);\n }\n\n // Reconstruct BFS order\n for (let d = 0; d <= maxDistance; d++) {\n const nodes = nodesByDistance.get(d);\n if (nodes) {\n order.push(... nodes);\n }\n }\n\n // Handle visit callback if provided\n if (options.visitCallback) {\n for (const [nodeId, distance] of result.distances) {\n options.visitCallback(nodeId, distance);\n }\n }\n\n return {visited, order, tree};\n}\n\n/**\n * Find shortest path between two nodes using BFS\n *\n * Automatically optimized for large graphs. Returns null if no path exists.\n */\nexport function shortestPathBFS(\n graph: Graph,\n source: NodeId,\n target: NodeId,\n): ShortestPathResult | null {\n if (!graph.hasNode(source)) {\n throw new Error(`Source node ${String(source)} not found in graph`);\n }\n\n if (!graph.hasNode(target)) {\n throw new Error(`Target node ${String(target)} not found in graph`);\n }\n\n // Special case: source equals target\n if (source === target) {\n return {\n distance: 0,\n path: [source],\n predecessor: new Map([[source, null]]),\n };\n }\n\n // Use optimized implementation for large graphs\n if (graph.nodeCount > 10000) {\n return shortestPathBFSOptimized(graph, source, target);\n }\n\n // Standard implementation\n return shortestPathBFSStandard(graph, source, target);\n}\n\n/**\n * Standard shortest path BFS\n */\nfunction shortestPathBFSStandard(\n graph: Graph,\n source: NodeId,\n target: NodeId,\n): ShortestPathResult | null {\n const visited = new Set<NodeId>();\n const queue: {node: NodeId, distance: number}[] = [];\n const predecessor = new Map<NodeId, NodeId | null>();\n\n // Initialize BFS\n queue.push({node: source, distance: 0});\n visited.add(source);\n predecessor.set(source, null);\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (!current) {\n break;\n }\n\n // Target found\n if (current.node === target) {\n const path = reconstructPath(target, predecessor);\n return {\n distance: current.distance,\n path,\n predecessor,\n };\n }\n\n // Explore neighbors\n for (const neighbor of graph.neighbors(current.node)) {\n if (!visited.has(neighbor)) {\n visited.add(neighbor);\n predecessor.set(neighbor, current.node);\n queue.push({node: neighbor, distance: current.distance + 1});\n }\n }\n }\n\n // No path found\n return null;\n}\n\n/**\n * Optimized shortest path using Direction-Optimized BFS\n */\nfunction shortestPathBFSOptimized(\n graph: Graph,\n source: NodeId,\n target: NodeId,\n): ShortestPathResult | null {\n const csrGraph = getCSRGraph(graph);\n\n const dobfs = new DirectionOptimizedBFS(csrGraph, {\n alpha: 15.0,\n beta: 20.0,\n });\n\n // Perform BFS\n const result = dobfs.search(source);\n\n // Check if target was reached\n const distance = result.distances.get(target);\n if (distance === undefined) {\n return null; // No path found\n }\n\n // Reconstruct path\n const path = reconstructPath(target, result.parents);\n\n return {\n distance,\n path,\n predecessor: result.parents,\n };\n}\n\n/**\n * Find shortest paths from source to all reachable nodes\n *\n * Automatically optimized for large graphs.\n */\nexport function singleSourceShortestPathBFS(\n graph: Graph,\n source: NodeId,\n): Map<NodeId, ShortestPathResult> {\n if (!graph.hasNode(source)) {\n throw new Error(`Source node ${String(source)} not found in graph`);\n }\n\n // Use optimized implementation for large graphs\n if (graph.nodeCount > 10000) {\n return singleSourceShortestPathBFSOptimized(graph, source);\n }\n\n // Standard implementation\n return singleSourceShortestPathBFSStandard(graph, source);\n}\n\n/**\n * Standard single-source shortest paths\n */\nfunction singleSourceShortestPathBFSStandard(\n graph: Graph,\n source: NodeId,\n): Map<NodeId, ShortestPathResult> {\n const results = new Map<NodeId, ShortestPathResult>();\n const visited = new Set<NodeId>();\n const queue: {node: NodeId, distance: number}[] = [];\n const predecessor = new Map<NodeId, NodeId | null>();\n const distances = new Map<NodeId, number>();\n\n // Initialize BFS\n queue.push({node: source, distance: 0});\n visited.add(source);\n predecessor.set(source, null);\n distances.set(source, 0);\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (!current) {\n break;\n }\n\n // Explore neighbors\n for (const neighbor of graph.neighbors(current.node)) {\n if (!visited.has(neighbor)) {\n visited.add(neighbor);\n predecessor.set(neighbor, current.node);\n distances.set(neighbor, current.distance + 1);\n queue.push({node: neighbor, distance: current.distance + 1});\n }\n }\n }\n\n // Build results after BFS completes\n // This avoids copying the predecessor map for each node\n for (const [node, distance] of distances) {\n const path = reconstructPath(node, predecessor);\n results.set(node, {\n distance,\n path,\n predecessor, // Share the same predecessor map\n });\n }\n\n return results;\n}\n\n/**\n * Optimized single-source shortest paths\n */\nfunction singleSourceShortestPathBFSOptimized(\n graph: Graph,\n source: NodeId,\n): Map<NodeId, ShortestPathResult> {\n const csrGraph = getCSRGraph(graph);\n\n const dobfs = new DirectionOptimizedBFS(csrGraph, {\n alpha: 15.0,\n beta: 20.0,\n });\n\n const bfsResult = dobfs.search(source);\n\n // Convert to expected format\n const results = new Map<NodeId, ShortestPathResult>();\n\n for (const [nodeId, distance] of bfsResult.distances) {\n // Reconstruct path for each node\n const path = reconstructPath(nodeId, bfsResult.parents);\n\n results.set(nodeId, {\n distance,\n path,\n predecessor: bfsResult.parents, // Share the same predecessor map\n });\n }\n\n return results;\n}\n\n/**\n * Check if the graph is bipartite using BFS coloring\n *\n * Note: This function does not use Direction-Optimized BFS as the\n * coloring logic is specific and doesn't benefit from the optimization.\n */\nexport function isBipartite(graph: Graph): boolean {\n if (graph.isDirected) {\n throw new Error(\"Bipartite test requires an undirected graph\");\n }\n\n const color = new Map<NodeId, 0 | 1>();\n const visited = new Set<NodeId>();\n\n // Check each connected component\n for (const node of Array.from(graph.nodes())) {\n if (!visited.has(node.id)) {\n const queue: NodeId[] = [node.id];\n color.set(node.id, 0);\n visited.add(node.id);\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (!current) {\n break;\n }\n\n const currentColor = color.get(current);\n if (currentColor === undefined) {\n continue;\n }\n\n for (const neighbor of Array.from(graph.neighbors(current))) {\n if (!visited.has(neighbor)) {\n // Color with opposite color\n color.set(neighbor, currentColor === 0 ? 1 : 0);\n visited.add(neighbor);\n queue.push(neighbor);\n } else if (color.get(neighbor) === currentColor) {\n // Same color as current node - not bipartite\n return false;\n }\n }\n }\n }\n }\n\n return true;\n}\n","import {Graph} from \"../../core/graph.js\";\nimport type {NodeId, TraversalOptions, TraversalResult} from \"../../types/index.js\";\n\n/**\n * Depth-First Search (DFS) implementation\n *\n * Explores graph by going as deep as possible before backtracking.\n * Useful for cycle detection, topological sorting, and connectivity analysis.\n */\n\n/**\n * DFS traversal options\n */\nexport interface DFSOptions extends TraversalOptions {\n recursive?: boolean; // Use recursive implementation (default: false for browser safety)\n preOrder?: boolean; // Visit nodes in pre-order (default: true)\n}\n\n/**\n * Perform depth-first search starting from a given node\n */\nexport function depthFirstSearch(\n graph: Graph,\n startNode: NodeId,\n options: DFSOptions = {},\n): TraversalResult {\n if (!graph.hasNode(startNode)) {\n throw new Error(`Start node ${String(startNode)} not found in graph`);\n }\n\n const visited = new Set<NodeId>();\n const order: NodeId[] = [];\n const tree = new Map<NodeId, NodeId | null>();\n\n if (options.recursive) {\n dfsRecursive(graph, startNode, visited, order, tree, options, 0);\n } else {\n dfsIterative(graph, startNode, visited, order, tree, options);\n }\n\n return {visited, order, tree};\n}\n\n/**\n * Iterative DFS implementation (safer for browsers)\n */\nfunction dfsIterative(\n graph: Graph,\n startNode: NodeId,\n visited: Set<NodeId>,\n order: NodeId[],\n tree: Map<NodeId, NodeId | null>,\n options: DFSOptions,\n): void {\n if (options.preOrder === false) {\n // For post-order, use a simpler recursive approach to ensure correctness\n dfsRecursive(graph, startNode, visited, order, tree, options, 0, null);\n return;\n }\n\n const stack: {node: NodeId, parent: NodeId | null, depth: number}[] = [];\n stack.push({node: startNode, parent: null, depth: 0});\n\n while (stack.length > 0) {\n const current = stack.pop();\n if (!current) {\n break;\n }\n\n if (!visited.has(current.node)) {\n visited.add(current.node);\n tree.set(current.node, current.parent);\n\n // Pre-order processing\n order.push(current.node);\n\n // Call visitor callback if provided\n if (options.visitCallback) {\n options.visitCallback(current.node, current.depth);\n }\n\n // Early termination if target found\n if (options.targetNode && current.node === options.targetNode) {\n break;\n }\n\n // Add neighbors to stack in reverse order to maintain left-to-right traversal\n const neighbors = Array.from(graph.neighbors(current.node));\n for (let i = neighbors.length - 1; i >= 0; i--) {\n const neighbor = neighbors[i];\n if (neighbor !== undefined && !visited.has(neighbor)) {\n stack.push({node: neighbor, parent: current.node, depth: current.depth + 1});\n }\n }\n }\n }\n}\n\n/**\n * Recursive DFS implementation\n */\nfunction dfsRecursive(\n graph: Graph,\n node: NodeId,\n visited: Set<NodeId>,\n order: NodeId[],\n tree: Map<NodeId, NodeId | null>,\n options: DFSOptions,\n depth: number,\n parent: NodeId | null = null,\n): void {\n visited.add(node);\n tree.set(node, parent);\n\n // Pre-order processing\n if (options.preOrder !== false) {\n order.push(node);\n\n if (options.visitCallback) {\n options.visitCallback(node, depth);\n }\n\n // Early termination if target found\n if (options.targetNode && node === options.targetNode) {\n return;\n }\n }\n\n // Recursively visit neighbors\n for (const neighbor of Array.from(graph.neighbors(node))) {\n if (!visited.has(neighbor)) {\n dfsRecursive(graph, neighbor, visited, order, tree, options, depth + 1, node);\n }\n }\n\n // Post-order processing\n if (options.preOrder === false) {\n order.push(node);\n\n if (options.visitCallback) {\n options.visitCallback(node, depth);\n }\n }\n}\n\n/**\n * Detect cycles in a graph using DFS\n */\nexport function hasCycleDFS(graph: Graph): boolean {\n const visited = new Set<NodeId>();\n\n // Check each unvisited node for cycles\n for (const node of Array.from(graph.nodes())) {\n if (!visited.has(node.id)) {\n if (graph.isDirected) {\n const recursionStack = new Set<NodeId>();\n if (hasCycleUtilDirected(graph, node.id, visited, recursionStack)) {\n return true;\n }\n } else {\n if (hasCycleUtilUndirected(graph, node.id, visited, null)) {\n return true;\n }\n }\n }\n }\n\n return false;\n}\n\n/**\n * Utility function for cycle detection in directed graphs\n */\nfunction hasCycleUtilDirected(\n graph: Graph,\n node: NodeId,\n visited: Set<NodeId>,\n recursionStack: Set<NodeId>,\n): boolean {\n visited.add(node);\n recursionStack.add(node);\n\n // Check all neighbors\n for (const neighbor of Array.from(graph.neighbors(node))) {\n if (!visited.has(neighbor)) {\n if (hasCycleUtilDirected(graph, neighbor, visited, recursionStack)) {\n return true;\n }\n } else if (recursionStack.has(neighbor)) {\n // Back edge found - cycle detected\n return true;\n }\n }\n\n recursionStack.delete(node);\n return false;\n}\n\n/**\n * Utility function for cycle detection in undirected graphs\n */\nfunction hasCycleUtilUndirected(\n graph: Graph,\n node: NodeId,\n visited: Set<NodeId>,\n parent: NodeId | null,\n): boolean {\n visited.add(node);\n\n // Check all neighbors\n for (const neighbor of Array.from(graph.neighbors(node))) {\n if (!visited.has(neighbor)) {\n if (hasCycleUtilUndirected(graph, neighbor, visited, node)) {\n return true;\n }\n } else if (neighbor !== parent) {\n // Found a visited node that's not the parent - cycle detected\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Topological sorting using DFS (for directed acyclic graphs)\n */\nexport function topologicalSort(graph: Graph): NodeId[] | null {\n if (!graph.isDirected) {\n throw new Error(\"Topological sort requires a directed graph\");\n }\n\n // First check if graph has cycles\n if (hasCycleDFS(graph)) {\n return null; // Cannot topologically sort a graph with cycles\n }\n\n const visited = new Set<NodeId>();\n const stack: NodeId[] = [];\n\n // Perform DFS from each unvisited node\n for (const node of Array.from(graph.nodes())) {\n if (!visited.has(node.id)) {\n topologicalSortUtil(graph, node.id, visited, stack);\n }\n }\n\n // Return nodes in reverse order of finishing times\n return stack.reverse();\n}\n\n/**\n * Utility function for topological sorting\n */\nfunction topologicalSortUtil(\n graph: Graph,\n node: NodeId,\n visited: Set<NodeId>,\n stack: NodeId[],\n): void {\n visited.add(node);\n\n // Visit all neighbors first\n for (const neighbor of Array.from(graph.neighbors(node))) {\n if (!visited.has(neighbor)) {\n topologicalSortUtil(graph, neighbor, visited, stack);\n }\n }\n\n // Add current node to stack after visiting all neighbors\n stack.push(node);\n}\n\n/**\n * Find strongly connected components using DFS (for directed graphs)\n */\nexport function findStronglyConnectedComponents(graph: Graph): NodeId[][] {\n if (!graph.isDirected) {\n throw new Error(\"Strongly connected components require a directed graph\");\n }\n\n const visited = new Set<NodeId>();\n const finishOrder: NodeId[] = [];\n\n // Step 1: Get nodes in order of finishing times\n for (const node of Array.from(graph.nodes())) {\n if (!visited.has(node.id)) {\n dfsFinishOrder(graph, node.id, visited, finishOrder);\n }\n }\n\n // Step 2: Create transpose graph (reverse all edges)\n const transposeGraph = createTransposeGraph(graph);\n\n // Step 3: DFS on transpose graph in reverse finish order\n const visited2 = new Set<NodeId>();\n const components: NodeId[][] = [];\n\n for (let i = finishOrder.length - 1; i >= 0; i--) {\n const node = finishOrder[i];\n if (node !== undefined && !visited2.has(node)) {\n const component: NodeId[] = [];\n dfsCollectComponent(transposeGraph, node, visited2, component);\n components.push(component);\n }\n }\n\n return components;\n}\n\n/**\n * DFS to record finish order\n */\nfunction dfsFinishOrder(\n graph: Graph,\n node: NodeId,\n visited: Set<NodeId>,\n finishOrder: NodeId[],\n): void {\n visited.add(node);\n\n for (const neighbor of Array.from(graph.neighbors(node))) {\n if (!visited.has(neighbor)) {\n dfsFinishOrder(graph, neighbor, visited, finishOrder);\n }\n }\n\n finishOrder.push(node);\n}\n\n/**\n * DFS to collect nodes in a component\n */\nfunction dfsCollectComponent(\n graph: Graph,\n node: NodeId,\n visited: Set<NodeId>,\n component: NodeId[],\n): void {\n visited.add(node);\n component.push(node);\n\n for (const neighbor of Array.from(graph.neighbors(node))) {\n if (!visited.has(neighbor)) {\n dfsCollectComponent(graph, neighbor, visited, component);\n }\n }\n}\n\n/**\n * Create transpose (reverse) of a directed graph\n */\nfunction createTransposeGraph(graph: Graph): Graph {\n const transpose = new Graph({directed: true});\n\n // Add all nodes\n for (const node of Array.from(graph.nodes())) {\n transpose.addNode(node.id, node.data);\n }\n\n // Add reverse edges\n for (const edge of Array.from(graph.edges())) {\n transpose.addEdge(edge.target, edge.source, edge.weight, edge.data);\n }\n\n return transpose;\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport type {NodeId, ShortestPathResult} from \"../../types/index.js\";\nimport {reconstructPath} from \"../../utils/graph-utilities.js\";\n\n/**\n * Bellman-Ford algorithm implementation for single-source shortest paths\n *\n * Finds shortest paths from a source node to all other nodes in a weighted graph.\n * Unlike Dijkstra's algorithm, it can handle negative edge weights and detect\n * negative cycles.\n */\n\n/**\n * Bellman-Ford algorithm options\n */\nexport interface BellmanFordOptions {\n /**\n * Target node for early termination (optional)\n */\n target?: NodeId;\n}\n\n/**\n * Result of Bellman-Ford algorithm\n */\nexport interface BellmanFordResult {\n /**\n * Distance from source to each reachable node\n */\n distances: Map<NodeId, number>;\n /**\n * Predecessor of each node in shortest path tree\n */\n predecessors: Map<NodeId, NodeId | null>;\n /**\n * Whether a negative cycle was detected\n */\n hasNegativeCycle: boolean;\n /**\n * Nodes involved in negative cycle (if any)\n */\n negativeCycleNodes: NodeId[];\n}\n\n/**\n * Find shortest paths from source using Bellman-Ford algorithm\n */\nexport function bellmanFord(\n graph: Graph,\n source: NodeId,\n options: BellmanFordOptions = {},\n): BellmanFordResult {\n if (!graph.hasNode(source)) {\n throw new Error(`Source node ${String(source)} not found in graph`);\n }\n\n const distances = new Map<NodeId, number>();\n const predecessors = new Map<NodeId, NodeId | null>();\n const nodes = Array.from(graph.nodes()).map((node) => node.id);\n\n // Initialize distances\n for (const nodeId of nodes) {\n distances.set(nodeId, nodeId === source ? 0 : Infinity);\n predecessors.set(nodeId, null);\n }\n\n // Relax edges |V| - 1 times\n for (let i = 0; i < nodes.length - 1; i++) {\n let updated = false;\n\n for (const edge of Array.from(graph.edges())) {\n const u = edge.source;\n const v = edge.target;\n const weight = edge.weight ?? 1;\n\n const distanceU = distances.get(u);\n const distanceV = distances.get(v);\n\n if (distanceU !== undefined && distanceV !== undefined && distanceU !== Infinity) {\n const newDistance = distanceU + weight;\n\n if (newDistance < distanceV) {\n distances.set(v, newDistance);\n predecessors.set(v, u);\n updated = true;\n\n // Early termination if target reached\n if (options.target && v === options.target) {\n break;\n }\n }\n }\n }\n\n // If no update in this iteration, we can stop early\n if (!updated) {\n break;\n }\n }\n\n // Check for negative cycles\n const negativeCycleNodes: NodeId[] = [];\n let hasNegativeCycle = false;\n\n for (const edge of graph.edges()) {\n const u = edge.source;\n const v = edge.target;\n const weight = edge.weight ?? 1;\n\n const distanceU = distances.get(u);\n const distanceV = distances.get(v);\n\n if (distanceU !== undefined && distanceV !== undefined && distanceU !== Infinity) {\n const newDistance = distanceU + weight;\n\n if (newDistance < distanceV) {\n hasNegativeCycle = true;\n negativeCycleNodes.push(v);\n }\n }\n }\n\n return {\n distances,\n predecessors,\n hasNegativeCycle,\n negativeCycleNodes,\n };\n}\n\n/**\n * Find shortest path between two specific nodes using Bellman-Ford\n */\nexport function bellmanFordPath(\n graph: Graph,\n source: NodeId,\n target: NodeId,\n): ShortestPathResult | null {\n if (!graph.hasNode(source)) {\n throw new Error(`Source node ${String(source)} not found in graph`);\n }\n\n if (!graph.hasNode(target)) {\n throw new Error(`Target node ${String(target)} not found in graph`);\n }\n\n const result = bellmanFord(graph, source, {target});\n\n if (result.hasNegativeCycle) {\n throw new Error(\"Graph contains a negative cycle\");\n }\n\n const distance = result.distances.get(target);\n\n if (distance === undefined || distance === Infinity) {\n return null; // No path exists\n }\n\n // Reconstruct path\n const path = reconstructPath(target, result.predecessors);\n\n return {\n distance,\n path,\n predecessor: result.predecessors,\n };\n}\n\n/**\n * Check if graph has negative cycles using Bellman-Ford\n */\nexport function hasNegativeCycle(graph: Graph): boolean {\n const nodes = Array.from(graph.nodes());\n\n if (nodes.length === 0) {\n return false;\n }\n\n // Need to check from multiple sources in case of disconnected components\n const checked = new Set<NodeId>();\n\n for (const node of nodes) {\n if (!checked.has(node.id)) {\n const result = bellmanFord(graph, node.id);\n\n if (result.hasNegativeCycle) {\n return true;\n }\n\n // Mark all reachable nodes as checked\n for (const [nodeId, distance] of Array.from(result.distances)) {\n if (distance !== Infinity) {\n checked.add(nodeId);\n }\n }\n }\n }\n\n return false;\n}\n\n","/**\n * Priority Queue implementation using a binary heap\n *\n * Optimized for graph algorithms requiring efficient priority-based operations.\n * Uses a min-heap by default but supports custom comparison functions.\n */\nexport class PriorityQueue<T> {\n private heap: {item: T, priority: number}[];\n private compareFn: (a: number, b: number) => number;\n\n constructor(compareFn?: (a: number, b: number) => number) {\n this.heap = [];\n // Default to min-heap (smaller priority values have higher priority)\n this.compareFn = compareFn ?? ((a, b) => a - b);\n }\n\n /**\n * Add an item with the given priority to the queue\n */\n enqueue(item: T, priority: number): void {\n const element = {item, priority};\n this.heap.push(element);\n this.heapifyUp(this.heap.length - 1);\n }\n\n /**\n * Remove and return the item with the highest priority\n */\n dequeue(): T | undefined {\n if (this.heap.length === 0) {\n return undefined;\n }\n\n if (this.heap.length === 1) {\n return this.heap.pop()?.item;\n }\n\n const root = this.heap[0];\n const lastElement = this.heap.pop();\n\n if (!root) {\n return undefined;\n }\n\n if (lastElement) {\n this.heap[0] = lastElement;\n this.heapifyDown(0);\n }\n\n return root.item;\n }\n\n /**\n * View the item with the highest priority without removing it\n */\n peek(): T | undefined {\n const first = this.heap[0];\n return first ? first.item : undefined;\n }\n\n /**\n * Check if the queue is empty\n */\n isEmpty(): boolean {\n return this.heap.length === 0;\n }\n\n /**\n * Get the number of items in the queue\n */\n size(): number {\n return this.heap.length;\n }\n\n /**\n * Update the priority of an item if it exists in the queue\n * Returns true if the item was found and updated\n */\n updatePriority(item: T, newPriority: number): boolean {\n const index = this.heap.findIndex((element) => element.item === item);\n\n if (index === -1) {\n return false;\n }\n\n const element = this.heap[index];\n if (!element) {\n return false;\n }\n\n const oldPriority = element.priority;\n element.priority = newPriority;\n\n // Determine whether to heapify up or down based on priority change\n if (this.compareFn(newPriority, oldPriority) < 0) {\n this.heapifyUp(index);\n } else if (this.compareFn(newPriority, oldPriority) > 0) {\n this.heapifyDown(index);\n }\n\n return true;\n }\n\n /**\n * Clear all items from the queue\n */\n clear(): void {\n this.heap = [];\n }\n\n /**\n * Convert queue to array (for testing/debugging)\n */\n toArray(): {item: T, priority: number}[] {\n return [... this.heap];\n }\n\n /**\n * Move element up the heap until heap property is satisfied\n */\n private heapifyUp(index: number): void {\n if (index === 0) {\n return;\n }\n\n const parentIndex = Math.floor((index - 1) / 2);\n\n const current = this.heap[index];\n const parent = this.heap[parentIndex];\n\n if (current && parent && this.compareFn(current.priority, parent.priority) < 0) {\n this.swap(index, parentIndex);\n this.heapifyUp(parentIndex);\n }\n }\n\n /**\n * Move element down the heap until heap property is satisfied\n */\n private heapifyDown(index: number): void {\n const leftChildIndex = (2 * index) + 1;\n const rightChildIndex = (2 * index) + 2;\n let targetIndex = index;\n\n // Find the child with highest priority (lowest value for min-heap)\n const leftChild = this.heap[leftChildIndex];\n const target = this.heap[targetIndex];\n\n if (leftChildIndex < this.heap.length && leftChild && target &&\n this.compareFn(leftChild.priority, target.priority) < 0) {\n targetIndex = leftChildIndex;\n }\n\n const rightChild = this.heap[rightChildIndex];\n const newTarget = this.heap[targetIndex];\n\n if (rightChildIndex < this.heap.length && rightChild && newTarget &&\n this.compareFn(rightChild.priority, newTarget.priority) < 0) {\n targetIndex = rightChildIndex;\n }\n\n // If we found a child with higher priority, swap and continue\n if (targetIndex !== index) {\n this.swap(index, targetIndex);\n this.heapifyDown(targetIndex);\n }\n }\n\n /**\n * Swap two elements in the heap\n */\n private swap(i: number, j: number): void {\n const temp = this.heap[i];\n const other = this.heap[j];\n if (temp && other) {\n this.heap[i] = other;\n this.heap[j] = temp;\n }\n }\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport {PriorityQueue} from \"../../data-structures/priority-queue.js\";\nimport type {NodeId, ShortestPathResult} from \"../../types/index.js\";\n\ninterface SearchState {\n distances: Map<NodeId, number>;\n previous: Map<NodeId, NodeId | null>;\n visited: Set<NodeId>;\n frontier: PriorityQueue<NodeId>;\n}\n\n/**\n * Bidirectional Dijkstra's algorithm implementation\n *\n * Performs simultaneous forward and backward searches to find shortest paths\n * more efficiently than standard Dijkstra for point-to-point queries.\n *\n * Time Complexity: O(2 * sqrt(V + E) log V) expected for random graphs\n * Space Complexity: O(V)\n *\n * Key optimizations:\n * - Alternating expansion based on frontier size\n * - Early termination when searches meet\n * - Efficient meeting point detection\n */\nexport class BidirectionalDijkstra {\n private graph: Graph;\n private forwardSearch: SearchState;\n private backwardSearch: SearchState;\n private meetingNode: NodeId | null = null;\n private shortestDistance = Infinity;\n\n constructor(graph: Graph) {\n this.graph = graph;\n this.forwardSearch = this.initSearchState();\n this.backwardSearch = this.initSearchState();\n }\n\n private initSearchState(): SearchState {\n return {\n distances: new Map(),\n previous: new Map(),\n visited: new Set(),\n frontier: new PriorityQueue<NodeId>(),\n };\n }\n\n /**\n * Find shortest path between source and target nodes\n */\n public findShortestPath(source: NodeId, target: NodeId): ShortestPathResult | null {\n // Reset state for new search\n this.reset();\n if (!this.graph.hasNode(source)) {\n throw new Error(`Source node ${String(source)} not found in graph`);\n }\n\n if (!this.graph.hasNode(target)) {\n throw new Error(`Target node ${String(target)} not found in graph`);\n }\n\n // Special case: source equals target\n if (source === target) {\n return {\n distance: 0,\n path: [source],\n predecessor: new Map([[source, null]]),\n };\n }\n\n // Initialize forward search from source\n this.forwardSearch.distances.set(source, 0);\n this.forwardSearch.previous.set(source, null);\n this.forwardSearch.frontier.enqueue(source, 0);\n\n // Initialize backward search from target\n this.backwardSearch.distances.set(target, 0);\n this.backwardSearch.previous.set(target, null);\n this.backwardSearch.frontier.enqueue(target, 0);\n\n // Main search loop\n while (!this.forwardSearch.frontier.isEmpty() ||\n !this.backwardSearch.frontier.isEmpty()) {\n // Alternate between forward and backward search\n // Choose the search with smaller frontier for better performance\n let searchExpanded = false;\n\n if (!this.forwardSearch.frontier.isEmpty() &&\n (this.backwardSearch.frontier.isEmpty() ||\n this.forwardSearch.frontier.size() <= this.backwardSearch.frontier.size())) {\n if (this.expandSearch(this.forwardSearch, this.backwardSearch, true)) {\n break;\n }\n\n searchExpanded = true;\n }\n\n if (!this.backwardSearch.frontier.isEmpty() && !searchExpanded) {\n if (this.expandSearch(this.backwardSearch, this.forwardSearch, false)) {\n break;\n }\n }\n\n // Continue until both frontiers are empty or we've found an optimal path\n if (this.forwardSearch.frontier.isEmpty() &&\n this.backwardSearch.frontier.isEmpty()) {\n break;\n }\n }\n\n if (this.meetingNode === null) {\n return null;\n }\n\n return {\n distance: this.shortestDistance,\n path: this.reconstructPath(),\n predecessor: new Map(), // Combined from both searches\n };\n }\n\n private expandSearch(\n search: SearchState,\n oppositeSearch: SearchState,\n isForward: boolean,\n ): boolean {\n const current = search.frontier.dequeue();\n if (current === undefined) {\n return false;\n }\n\n const distance = search.distances.get(current);\n if (distance === undefined) {\n return false;\n }\n\n if (search.visited.has(current)) {\n return false;\n }\n\n search.visited.add(current);\n\n // Check if we've met the opposite search\n if (oppositeSearch.distances.has(current)) {\n const totalDistance = distance + (oppositeSearch.distances.get(current) ?? 0);\n if (totalDistance < this.shortestDistance) {\n this.shortestDistance = totalDistance;\n this.meetingNode = current;\n }\n }\n\n // Explore neighbors\n const neighbors = isForward ?\n Array.from(this.graph.neighbors(current)) :\n Array.from(this.graph.inNeighbors(current));\n\n for (const neighbor of neighbors) {\n if (search.visited.has(neighbor)) {\n continue;\n }\n\n const edge = isForward ?\n this.graph.getEdge(current, neighbor) :\n this.graph.getEdge(neighbor, current);\n\n if (!edge) {\n continue;\n }\n\n const edgeWeight = edge.weight ?? 1;\n if (edgeWeight < 0) {\n throw new Error(\"Bidirectional Dijkstra does not support negative edge weights\");\n }\n\n const newDistance = distance + edgeWeight;\n const currentNeighborDistance = search.distances.get(neighbor);\n\n if (!search.distances.has(neighbor) ||\n newDistance < (currentNeighborDistance ?? Infinity)) {\n search.distances.set(neighbor, newDistance);\n search.previous.set(neighbor, current);\n search.frontier.enqueue(neighbor, newDistance);\n }\n }\n\n return false;\n }\n\n private getMinDistance(frontier: PriorityQueue<NodeId>): number {\n if (frontier.isEmpty()) {\n return Infinity;\n }\n\n // Since we can't peek at priority directly, we estimate based on the smallest known distance\n const minDist = Infinity;\n\n // For a more accurate implementation, we'd need to track the minimum distance\n // For now, we'll use a simple heuristic\n return minDist;\n }\n\n private reconstructPath(): NodeId[] {\n if (!this.meetingNode) {\n return [];\n }\n\n const path: NodeId[] = [];\n\n // Reconstruct forward path\n let current: NodeId | null = this.meetingNode;\n const forwardPath: NodeId[] = [];\n\n while (current !== null) {\n forwardPath.push(current);\n current = this.forwardSearch.previous.get(current) ?? null;\n }\n\n // Add forward path in reverse order (except meeting node)\n for (let i = forwardPath.length - 1; i > 0; i--) {\n const node = forwardPath[i];\n if (node !== undefined) {\n path.push(node);\n }\n }\n\n // Add meeting node\n path.push(this.meetingNode);\n\n // Reconstruct and add backward path\n current = this.backwardSearch.previous.get(this.meetingNode) ?? null;\n while (current !== null) {\n path.push(current);\n current = this.backwardSearch.previous.get(current) ?? null;\n }\n\n return path;\n }\n\n /**\n * Reset the search state for reuse\n */\n public reset(): void {\n this.forwardSearch = this.initSearchState();\n this.backwardSearch = this.initSearchState();\n this.meetingNode = null;\n this.shortestDistance = Infinity;\n }\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport {PriorityQueue} from \"../../data-structures/priority-queue.js\";\nimport type {DijkstraOptions, NodeId, ShortestPathResult} from \"../../types/index.js\";\nimport {reconstructPath} from \"../../utils/graph-utilities.js\";\nimport {BidirectionalDijkstra} from \"./bidirectional-dijkstra.js\";\n\n/**\n * Dijkstra's algorithm implementation for single-source shortest paths\n *\n * Finds shortest paths from a source node to all other nodes in a weighted graph\n * with non-negative edge weights using a priority queue for efficiency.\n */\n\n/**\n * Find shortest paths from source to all reachable nodes using Dijkstra's algorithm\n */\nexport function dijkstra(\n graph: Graph,\n source: NodeId,\n options: DijkstraOptions = {},\n): Map<NodeId, ShortestPathResult> {\n if (!graph.hasNode(source)) {\n throw new Error(`Source node ${String(source)} not found in graph`);\n }\n\n const distances = new Map<NodeId, number>();\n const previous = new Map<NodeId, NodeId | null>();\n const visited = new Set<NodeId>();\n const pq = new PriorityQueue<NodeId>();\n\n // Initialize distances\n for (const node of Array.from(graph.nodes())) {\n const distance = node.id === source ? 0 : Infinity;\n distances.set(node.id, distance);\n previous.set(node.id, null);\n pq.enqueue(node.id, distance);\n }\n\n while (!pq.isEmpty()) {\n const currentNode = pq.dequeue();\n if (currentNode === undefined) {\n break;\n }\n\n const currentDistance = distances.get(currentNode);\n if (currentDistance === undefined) {\n continue;\n }\n\n // Skip if already visited (can happen with priority queue updates)\n if (visited.has(currentNode)) {\n continue;\n }\n\n visited.add(currentNode);\n\n // Early termination if target reached\n if (options.target && currentNode === options.target) {\n break;\n }\n\n // Skip if this node is unreachable\n if (currentDistance === Infinity) {\n break;\n }\n\n // Check all neighbors\n for (const neighbor of Array.from(graph.neighbors(currentNode))) {\n if (visited.has(neighbor)) {\n continue;\n }\n\n const edge = graph.getEdge(currentNode, neighbor);\n if (!edge) {\n continue;\n }\n\n const edgeWeight = edge.weight ?? 1;\n\n if (edgeWeight < 0) {\n throw new Error(\"Dijkstra's algorithm does not support negative edge weights\");\n }\n\n const tentativeDistance = currentDistance + edgeWeight;\n const neighborDistance = distances.get(neighbor);\n if (neighborDistance === undefined) {\n continue;\n }\n\n // Found a shorter path\n if (tentativeDistance < neighborDistance) {\n distances.set(neighbor, tentativeDistance);\n previous.set(neighbor, currentNode);\n // Add to priority queue with new distance\n pq.enqueue(neighbor, tentativeDistance);\n }\n }\n }\n\n // Build results\n const results = new Map<NodeId, ShortestPathResult>();\n\n for (const [nodeId, distance] of distances) {\n if (distance < Infinity) {\n const path = reconstructPath(nodeId, previous);\n results.set(nodeId, {\n distance,\n path,\n predecessor: new Map(previous),\n });\n }\n }\n\n return results;\n}\n\n/**\n * Find shortest path between two specific nodes using optimized Dijkstra's algorithm\n *\n * Uses bidirectional search by default for improved performance on point-to-point queries.\n * Automatically falls back to standard Dijkstra for very small graphs or when explicitly disabled.\n */\nexport function dijkstraPath(\n graph: Graph,\n source: NodeId,\n target: NodeId,\n options: DijkstraOptions = {},\n): ShortestPathResult | null {\n if (!graph.hasNode(source)) {\n throw new Error(`Source node ${String(source)} not found in graph`);\n }\n\n if (!graph.hasNode(target)) {\n throw new Error(`Target node ${String(target)} not found in graph`);\n }\n\n // Special case: source equals target\n if (source === target) {\n return {\n distance: 0,\n path: [source],\n predecessor: new Map([[source, null]]),\n };\n }\n\n // Use bidirectional search by default for point-to-point queries\n // Only disable if explicitly requested or graph is very small (overhead dominates)\n const useBidirectional = options.bidirectional !== false && graph.nodeCount > 10;\n\n if (useBidirectional) {\n const biDijkstra = new BidirectionalDijkstra(graph);\n return biDijkstra.findShortestPath(source, target);\n }\n\n // Fallback to standard dijkstra\n const results = dijkstra(graph, source, {target});\n return results.get(target) ?? null;\n}\n\n/**\n * Single-source shortest paths with early termination optimization\n */\nexport function singleSourceShortestPath(\n graph: Graph,\n source: NodeId,\n cutoff?: number,\n): Map<NodeId, number> {\n if (!graph.hasNode(source)) {\n throw new Error(`Source node ${String(source)} not found in graph`);\n }\n\n const distances = new Map<NodeId, number>();\n const visited = new Set<NodeId>();\n const pq = new PriorityQueue<NodeId>();\n\n // Initialize distances\n for (const node of Array.from(graph.nodes())) {\n const distance = node.id === source ? 0 : Infinity;\n distances.set(node.id, distance);\n pq.enqueue(node.id, distance);\n }\n\n while (!pq.isEmpty()) {\n const currentNode = pq.dequeue();\n if (currentNode === undefined) {\n break;\n }\n\n const currentDistance = distances.get(currentNode);\n if (currentDistance === undefined) {\n continue;\n }\n\n // Skip if already visited\n if (visited.has(currentNode)) {\n continue;\n }\n\n visited.add(currentNode);\n\n // Skip if unreachable or beyond cutoff\n if (currentDistance === Infinity || (cutoff !== undefined && currentDistance > cutoff)) {\n break;\n }\n\n // Check all neighbors\n for (const neighbor of Array.from(graph.neighbors(currentNode))) {\n if (visited.has(neighbor)) {\n continue;\n }\n\n const edge = graph.getEdge(currentNode, neighbor);\n if (!edge) {\n continue;\n }\n\n const edgeWeight = edge.weight ?? 1;\n const tentativeDistance = currentDistance + edgeWeight;\n const neighborDistance = distances.get(neighbor);\n if (neighborDistance === undefined) {\n continue;\n }\n\n // Found a shorter path\n if (tentativeDistance < neighborDistance) {\n distances.set(neighbor, tentativeDistance);\n pq.enqueue(neighbor, tentativeDistance);\n }\n }\n }\n\n // Filter out unreachable nodes and apply cutoff\n const result = new Map<NodeId, number>();\n\n for (const [nodeId, distance] of distances) {\n if (distance < Infinity && (cutoff === undefined || distance <= cutoff)) {\n result.set(nodeId, distance);\n }\n }\n\n return result;\n}\n\n/**\n * All-pairs shortest paths using repeated Dijkstra\n * Note: For dense graphs, consider Floyd-Warshall algorithm instead\n */\nexport function allPairsShortestPath(graph: Graph): Map<NodeId, Map<NodeId, number>> {\n const results = new Map<NodeId, Map<NodeId, number>>();\n\n for (const node of Array.from(graph.nodes())) {\n const distances = singleSourceShortestPath(graph, node.id);\n results.set(node.id, distances);\n }\n\n return results;\n}\n\n","import {Graph} from \"../../core/graph.js\";\nimport type {NodeId} from \"../../types/index.js\";\n\nexport interface FloydWarshallResult {\n distances: Map<NodeId, Map<NodeId, number>>;\n predecessors: Map<NodeId, Map<NodeId, NodeId | null>>;\n hasNegativeCycle: boolean;\n}\n\nexport function floydWarshall(graph: Graph): FloydWarshallResult {\n const nodes = Array.from(graph.nodes()).map((n) => n.id);\n const distances = new Map<NodeId, Map<NodeId, number>>();\n const predecessors = new Map<NodeId, Map<NodeId, NodeId | null>>();\n\n for (const node of nodes) {\n distances.set(node, new Map());\n predecessors.set(node, new Map());\n\n const nodeDistances = distances.get(node);\n const nodePredecessors = predecessors.get(node);\n\n if (!nodeDistances || !nodePredecessors) {\n continue;\n }\n\n for (const other of nodes) {\n if (node === other) {\n nodeDistances.set(other, 0);\n nodePredecessors.set(other, null);\n } else {\n nodeDistances.set(other, Infinity);\n nodePredecessors.set(other, null);\n }\n }\n }\n\n for (const edge of Array.from(graph.edges())) {\n const weight = edge.weight ?? 1;\n const sourceDistances = distances.get(edge.source);\n const sourcePredecessors = predecessors.get(edge.source);\n\n if (sourceDistances && sourcePredecessors) {\n sourceDistances.set(edge.target, weight);\n sourcePredecessors.set(edge.target, edge.source);\n }\n\n if (!graph.isDirected) {\n const targetDistances = distances.get(edge.target);\n const targetPredecessors = predecessors.get(edge.target);\n\n if (targetDistances && targetPredecessors) {\n targetDistances.set(edge.source, weight);\n targetPredecessors.set(edge.source, edge.target);\n }\n }\n }\n\n for (const k of nodes) {\n for (const i of nodes) {\n for (const j of nodes) {\n const distancesI = distances.get(i);\n const distancesK = distances.get(k);\n const predecessorsI = predecessors.get(i);\n const predecessorsK = predecessors.get(k);\n\n if (!distancesI || !distancesK || !predecessorsI || !predecessorsK) {\n continue;\n }\n\n const distIK = distancesI.get(k);\n const distKJ = distancesK.get(j);\n const distIJ = distancesI.get(j);\n\n if (distIK === undefined || distKJ === undefined || distIJ === undefined) {\n continue;\n }\n\n if (distIK + distKJ < distIJ) {\n distancesI.set(j, distIK + distKJ);\n const predKJ = predecessorsK.get(j);\n predecessorsI.set(j, predKJ ?? null);\n }\n }\n }\n }\n\n let hasNegativeCycle = false;\n for (const node of nodes) {\n const nodeDistances = distances.get(node);\n if (!nodeDistances) {\n continue;\n }\n\n const selfDistance = nodeDistances.get(node);\n if (selfDistance !== undefined && selfDistance < 0) {\n hasNegativeCycle = true;\n break;\n }\n }\n\n return {\n distances,\n predecessors,\n hasNegativeCycle,\n };\n}\n\nexport function floydWarshallPath(\n graph: Graph,\n source: NodeId,\n target: NodeId,\n): {path: NodeId[], distance: number} | null {\n const result = floydWarshall(graph);\n\n if (!graph.hasNode(source) || !graph.hasNode(target)) {\n return null;\n }\n\n const sourceDistances = result.distances.get(source);\n if (!sourceDistances) {\n return null;\n }\n\n const distance = sourceDistances.get(target);\n if (distance === undefined || distance === Infinity) {\n return null;\n }\n\n const path: NodeId[] = [];\n let current: NodeId | null = target;\n\n while (current !== null && current !== source) {\n path.unshift(current);\n\n const sourcePredecessors = result.predecessors.get(source);\n if (!sourcePredecessors) {\n return null;\n }\n\n current = sourcePredecessors.get(current) ?? null;\n\n if (path.length > graph.nodeCount) {\n return null;\n }\n }\n\n if (current === source) {\n path.unshift(source);\n return {path, distance};\n }\n\n return null;\n}\n\nexport function transitiveClosure(graph: Graph): Map<NodeId, Set<NodeId>> {\n const result = floydWarshall(graph);\n const closure = new Map<NodeId, Set<NodeId>>();\n\n for (const [source, distances] of Array.from(result.distances)) {\n const reachable = new Set<NodeId>();\n for (const [target, distance] of Array.from(distances)) {\n if (distance < Infinity) {\n reachable.add(target);\n }\n }\n closure.set(source, reachable);\n }\n\n return closure;\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport {PriorityQueue} from \"../../data-structures/priority-queue.js\";\nimport {CSRGraph} from \"../../optimized/csr-graph.js\";\nimport {DirectionOptimizedBFS} from \"../../optimized/direction-optimized-bfs.js\";\nimport {toCSRGraph} from \"../../optimized/graph-adapter.js\";\nimport type {NodeId} from \"../../types/index.js\";\n\n/**\n * Threshold for switching to CSR-optimized implementations.\n * Based on benchmarks showing CSR benefits at this scale due to\n * improved cache locality and reduced memory allocation overhead.\n */\nconst LARGE_GRAPH_THRESHOLD = 10000;\n\n/**\n * BFS that tracks shortest path counts (for betweenness centrality)\n *\n * This variant of BFS computes:\n * - Shortest distances from source to all reachable nodes\n * - All predecessors on shortest paths\n * - Number of shortest paths (sigma)\n * - Stack of nodes in reverse BFS order\n */\nexport function bfsWithPathCounting(\n graph: Graph,\n source: NodeId,\n options: {optimized?: boolean} = {},\n): {\n distances: Map<NodeId, number>;\n predecessors: Map<NodeId, NodeId[]>;\n sigma: Map<NodeId, number>;\n stack: NodeId[];\n } {\n const useOptimized = options.optimized ?? false;\n\n // Use CSR format for large graphs\n if (useOptimized && graph.nodeCount > LARGE_GRAPH_THRESHOLD) {\n const csrGraph = toCSRGraph(graph);\n return bfsWithPathCountingCSR(csrGraph, source);\n }\n\n const distances = new Map<NodeId, number>();\n const predecessors = new Map<NodeId, NodeId[]>();\n const sigma = new Map<NodeId, number>();\n const stack: NodeId[] = [];\n const queue: NodeId[] = [];\n\n // Initialize\n distances.set(source, 0);\n sigma.set(source, 1);\n queue.push(source);\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (current === undefined) {\n continue;\n }\n\n stack.push(current);\n\n const currentDistance = distances.get(current) ?? 0;\n const currentSigma = sigma.get(current) ?? 0;\n\n // Process neighbors\n const neighbors = graph.neighbors(current);\n for (const neighbor of neighbors) {\n // First time visiting this neighbor\n if (!distances.has(neighbor)) {\n distances.set(neighbor, currentDistance + 1);\n queue.push(neighbor);\n }\n\n // Found a shortest path to neighbor\n if (distances.get(neighbor) === currentDistance + 1) {\n const neighborSigma = sigma.get(neighbor) ?? 0;\n sigma.set(neighbor, neighborSigma + currentSigma);\n\n const preds = predecessors.get(neighbor) ?? [];\n preds.push(current);\n predecessors.set(neighbor, preds);\n }\n }\n }\n\n return {\n distances,\n predecessors,\n sigma,\n stack,\n };\n}\n\n/**\n * BFS that only returns distances (for closeness centrality)\n *\n * Optimized variant that skips predecessor tracking\n */\nexport function bfsDistancesOnly(\n graph: Graph,\n source: NodeId,\n cutoff?: number,\n options: {optimized?: boolean} = {},\n): Map<NodeId, number> {\n const useOptimized = options.optimized ?? false;\n\n // Use CSR format for large graphs\n if (useOptimized && graph.nodeCount > LARGE_GRAPH_THRESHOLD) {\n const csrGraph = toCSRGraph(graph);\n return bfsDistancesOnlyCSR(csrGraph, source, cutoff);\n }\n\n const distances = new Map<NodeId, number>();\n const queue: NodeId[] = [];\n\n distances.set(source, 0);\n queue.push(source);\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (current === undefined) {\n continue;\n }\n\n const currentDistance = distances.get(current) ?? 0;\n\n // Stop if we've reached the cutoff distance\n if (cutoff !== undefined && currentDistance >= cutoff) {\n continue;\n }\n\n const neighbors = graph.neighbors(current);\n for (const neighbor of neighbors) {\n if (!distances.has(neighbor)) {\n distances.set(neighbor, currentDistance + 1);\n queue.push(neighbor);\n }\n }\n }\n\n return distances;\n}\n\n/**\n * BFS for bipartite checking with partition sets\n *\n * Returns whether the graph is bipartite and the two partitions if it is\n */\nexport function bfsColoringWithPartitions(\n graph: Graph,\n): {\n isBipartite: boolean;\n partitions?: [Set<NodeId>, Set<NodeId>];\n } {\n const colors = new Map<NodeId, number>();\n const partitionA = new Set<NodeId>();\n const partitionB = new Set<NodeId>();\n\n // Handle disconnected components\n for (const node of graph.nodes()) {\n if (!colors.has(node.id)) {\n const queue: NodeId[] = [node.id];\n colors.set(node.id, 0);\n partitionA.add(node.id);\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (current === undefined) {\n continue;\n }\n\n const currentColor = colors.get(current) ?? 0;\n const nextColor = 1 - currentColor;\n\n for (const neighbor of graph.neighbors(current)) {\n if (!colors.has(neighbor)) {\n colors.set(neighbor, nextColor);\n queue.push(neighbor);\n\n if (nextColor === 0) {\n partitionA.add(neighbor);\n } else {\n partitionB.add(neighbor);\n }\n } else if (colors.get(neighbor) === currentColor) {\n // Same color as current node - not bipartite\n return {isBipartite: false};\n }\n }\n }\n }\n }\n\n return {\n isBipartite: true,\n partitions: [partitionA, partitionB],\n };\n}\n\n/**\n * BFS for finding augmenting paths (for flow algorithms)\n *\n * Finds a path from source to sink in a residual graph with positive capacity\n */\nexport function bfsAugmentingPath(\n residualGraph: Map<string, Map<string, number>>,\n source: string,\n sink: string,\n): {\n path: string[];\n pathCapacity: number;\n} | null {\n const parent = new Map<string, string | null>();\n const queue: string[] = [];\n\n parent.set(source, null);\n queue.push(source);\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (current === undefined) {\n continue;\n }\n\n if (current === sink) {\n // Reconstruct path\n const path: string[] = [];\n let node: string | null = sink;\n let pathCapacity = Infinity;\n\n while (node !== null) {\n path.unshift(node);\n const parentNode = parent.get(node);\n\n if (parentNode !== null && parentNode !== undefined) {\n const capacity = residualGraph.get(parentNode)?.get(node) ?? 0;\n pathCapacity = Math.min(pathCapacity, capacity);\n }\n\n node = parentNode ?? null;\n }\n\n return {path, pathCapacity};\n }\n\n const neighbors = residualGraph.get(current);\n if (neighbors) {\n for (const [neighbor, capacity] of neighbors) {\n if (!parent.has(neighbor) && capacity > 0) {\n parent.set(neighbor, current);\n queue.push(neighbor);\n }\n }\n }\n }\n\n return null;\n}\n\n/**\n * BFS for weighted graphs using priority queue (simplified Dijkstra)\n *\n * Returns distances from source using edge weights\n */\nexport function bfsWeightedDistances(\n graph: Graph,\n source: NodeId,\n cutoff?: number,\n options: {optimized?: boolean} = {},\n): Map<NodeId, number> {\n const useOptimized = options.optimized ?? false;\n\n // Use CSR format for large graphs\n if (useOptimized && graph.nodeCount > LARGE_GRAPH_THRESHOLD) {\n const csrGraph = toCSRGraph(graph);\n return bfsWeightedDistancesCSR(csrGraph, source, cutoff);\n }\n\n const distances = new Map<NodeId, number>();\n const visited = new Set<NodeId>();\n\n // Use efficient priority queue instead of array-based queue\n const queue = new PriorityQueue<NodeId>();\n\n distances.set(source, 0);\n queue.enqueue(source, 0);\n\n while (!queue.isEmpty()) {\n const current = queue.dequeue();\n if (current === undefined) {\n continue;\n }\n\n const currentDist = distances.get(current) ?? 0;\n\n if (visited.has(current)) {\n continue;\n }\n\n visited.add(current);\n\n // Stop if we've reached the cutoff distance\n if (cutoff !== undefined && currentDist >= cutoff) {\n continue;\n }\n\n for (const neighbor of graph.neighbors(current)) {\n if (!visited.has(neighbor)) {\n const edge = graph.getEdge(current, neighbor);\n const weight = edge?.weight ?? 1;\n const newDistance = currentDist + weight;\n\n const oldDistance = distances.get(neighbor);\n if (oldDistance === undefined || newDistance < oldDistance) {\n distances.set(neighbor, newDistance);\n queue.enqueue(neighbor, newDistance);\n }\n }\n }\n }\n\n return distances;\n}\n\n/**\n * CSR-optimized version of bfsWithPathCounting\n */\nfunction bfsWithPathCountingCSR(\n graph: CSRGraph,\n source: NodeId,\n): {\n distances: Map<NodeId, number>;\n predecessors: Map<NodeId, NodeId[]>;\n sigma: Map<NodeId, number>;\n stack: NodeId[];\n } {\n const distances = new Map<NodeId, number>();\n const predecessors = new Map<NodeId, NodeId[]>();\n const sigma = new Map<NodeId, number>();\n const stack: NodeId[] = [];\n const queue: NodeId[] = [];\n\n // Initialize\n distances.set(source, 0);\n sigma.set(source, 1);\n queue.push(source);\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (current === undefined) {\n continue;\n }\n\n stack.push(current);\n\n const currentDistance = distances.get(current) ?? 0;\n const currentSigma = sigma.get(current) ?? 0;\n\n // Process neighbors using CSR iteration\n for (const neighbor of graph.neighbors(current)) {\n // First time visiting this neighbor\n if (!distances.has(neighbor)) {\n distances.set(neighbor, currentDistance + 1);\n queue.push(neighbor);\n }\n\n // Found a shortest path to neighbor\n if (distances.get(neighbor) === currentDistance + 1) {\n const neighborSigma = sigma.get(neighbor) ?? 0;\n sigma.set(neighbor, neighborSigma + currentSigma);\n\n const preds = predecessors.get(neighbor) ?? [];\n preds.push(current);\n predecessors.set(neighbor, preds);\n }\n }\n }\n\n return {\n distances,\n predecessors,\n sigma,\n stack,\n };\n}\n\n/**\n * CSR-optimized version of bfsDistancesOnly\n */\nfunction bfsDistancesOnlyCSR(\n graph: CSRGraph,\n source: NodeId,\n cutoff?: number,\n): Map<NodeId, number> {\n // Use Direction-Optimized BFS for best performance\n if (graph.nodeCount() > LARGE_GRAPH_THRESHOLD) {\n const dobfs = new DirectionOptimizedBFS(graph);\n const result = dobfs.search(source);\n\n // Filter by cutoff if specified\n if (cutoff !== undefined) {\n const filtered = new Map<NodeId, number>();\n for (const [nodeId, distance] of result.distances) {\n if (distance <= cutoff) {\n filtered.set(nodeId, distance);\n }\n }\n return filtered;\n }\n\n return result.distances;\n }\n\n // Fallback to standard BFS on CSR\n const distances = new Map<NodeId, number>();\n const queue: NodeId[] = [];\n\n distances.set(source, 0);\n queue.push(source);\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (current === undefined) {\n continue;\n }\n\n const currentDistance = distances.get(current) ?? 0;\n\n // Stop if we've reached the cutoff distance\n if (cutoff !== undefined && currentDistance >= cutoff) {\n continue;\n }\n\n for (const neighbor of graph.neighbors(current)) {\n if (!distances.has(neighbor)) {\n distances.set(neighbor, currentDistance + 1);\n queue.push(neighbor);\n }\n }\n }\n\n return distances;\n}\n\n/**\n * CSR-optimized version of bfsWeightedDistances\n */\nfunction bfsWeightedDistancesCSR(\n graph: CSRGraph,\n source: NodeId,\n cutoff?: number,\n): Map<NodeId, number> {\n const distances = new Map<NodeId, number>();\n const visited = new Set<NodeId>();\n\n // Use efficient priority queue\n const queue = new PriorityQueue<NodeId>();\n\n distances.set(source, 0);\n queue.enqueue(source, 0);\n\n while (!queue.isEmpty()) {\n const current = queue.dequeue();\n if (current === undefined) {\n continue;\n }\n\n const currentDist = distances.get(current) ?? 0;\n\n if (visited.has(current)) {\n continue;\n }\n\n visited.add(current);\n\n // Stop if we've reached the cutoff distance\n if (cutoff !== undefined && currentDist >= cutoff) {\n continue;\n }\n\n for (const neighbor of graph.neighbors(current)) {\n if (!visited.has(neighbor)) {\n // Use actual edge weight from CSR graph, default to 1\n const weight = graph.getEdgeWeight(current, neighbor) ?? 1;\n const newDistance = currentDist + weight;\n\n const oldDistance = distances.get(neighbor);\n if (oldDistance === undefined || newDistance < oldDistance) {\n distances.set(neighbor, newDistance);\n queue.enqueue(neighbor, newDistance);\n }\n }\n }\n }\n\n return distances;\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport type {NodeId} from \"../../types/index.js\";\nimport {bfsWithPathCounting} from \"../traversal/bfs-variants.js\";\n\n/**\n * Betweenness centrality implementation using Brandes' algorithm\n *\n * Measures the extent to which a node lies on paths between other nodes.\n * Uses the fast O(VE) algorithm by Ulrik Brandes.\n */\n\n/**\n * Betweenness centrality options\n */\nexport interface BetweennessCentralityOptions {\n /**\n * Whether to normalize the centrality values (default: false)\n */\n normalized?: boolean;\n /**\n * Whether to use endpoints in path counting (default: false)\n */\n endpoints?: boolean;\n /**\n * Whether to use optimized BFS implementation for large graphs\n */\n optimized?: boolean;\n}\n\n/**\n * Result of Brandes algorithm computation for a single source\n */\ninterface BrandesResult {\n stack: NodeId[];\n predecessors: Map<NodeId, NodeId[]>;\n sigma: Map<NodeId, number>;\n distance: Map<NodeId, number>;\n}\n\n/**\n * Run single-source shortest path computation using BFS\n */\nfunction brandesSingleSource(graph: Graph, source: NodeId, optimized?: boolean): BrandesResult {\n const result = bfsWithPathCounting(graph, source, optimized !== undefined ? {optimized} : {});\n\n return {\n stack: result.stack,\n predecessors: result.predecessors,\n sigma: result.sigma,\n distance: result.distances,\n };\n}\n\n/**\n * Accumulate betweenness contributions from a single source\n */\nfunction accumulateBetweenness(\n result: BrandesResult,\n source: NodeId,\n centrality: Record<string, number>,\n options: BetweennessCentralityOptions,\n): void {\n const {stack, predecessors, sigma} = result;\n const delta = new Map<NodeId, number>();\n\n // Initialize delta\n for (const node of stack) {\n delta.set(node, 0);\n }\n\n // Accumulation - back-propagation of dependencies\n // Process nodes in reverse BFS order\n for (let i = stack.length - 1; i >= 0; i--) {\n const w = stack[i];\n if (!w) {\n continue;\n }\n\n const wPreds = predecessors.get(w) ?? [];\n const wSigma = sigma.get(w) ?? 0;\n const wDelta = delta.get(w) ?? 0;\n\n for (const v of wPreds) {\n const vSigma = sigma.get(v) ?? 0;\n const vDelta = delta.get(v) ?? 0;\n\n if (vSigma > 0 && wSigma > 0) {\n let contribution = (vSigma / wSigma) * (1 + wDelta);\n\n // Apply endpoints option: when false, exclude endpoint contributions\n if (!options.endpoints) {\n // For standard betweenness, don't count paths that only involve endpoints\n const isTargetEndpoint = wPreds.length === 0 && w !== source;\n if (isTargetEndpoint) {\n contribution = 0; // Exclude endpoint contributions\n }\n }\n\n delta.set(v, vDelta + contribution);\n }\n }\n\n if (w !== source) {\n const currentCentrality = centrality[String(w)] ?? 0;\n centrality[String(w)] = currentCentrality + wDelta;\n }\n }\n}\n\n/**\n * Accumulate edge betweenness contributions from a single source\n */\nfunction accumulateEdgeBetweenness(\n result: BrandesResult,\n source: NodeId,\n edgeCentrality: Map<string, number>,\n options: BetweennessCentralityOptions,\n): void {\n const {stack, predecessors, sigma} = result;\n const delta = new Map<NodeId, number>();\n\n // Initialize delta\n for (const node of stack) {\n delta.set(node, 0);\n }\n\n // Accumulation for edges\n // Process nodes in reverse BFS order\n for (let i = stack.length - 1; i >= 0; i--) {\n const w = stack[i];\n if (!w) {\n continue;\n }\n\n const wPreds = predecessors.get(w) ?? [];\n const wSigma = sigma.get(w) ?? 0;\n const wDelta = delta.get(w) ?? 0;\n\n for (const v of wPreds) {\n const vSigma = sigma.get(v) ?? 0;\n\n if (vSigma > 0 && wSigma > 0) {\n let edgeContribution = (vSigma / wSigma) * (1 + wDelta);\n\n // Apply endpoints option for edge betweenness\n if (!options.endpoints) {\n const isTargetEndpoint = wPreds.length === 0 && w !== source;\n if (isTargetEndpoint) {\n edgeContribution = 0; // Exclude endpoint contributions\n }\n }\n\n // Update edge centrality\n const edgeKey = `${String(v)}-${String(w)}`;\n const currentEdgeCentrality = edgeCentrality.get(edgeKey) ?? 0;\n edgeCentrality.set(edgeKey, currentEdgeCentrality + edgeContribution);\n\n // Update node delta\n const vDelta = delta.get(v) ?? 0;\n delta.set(v, vDelta + edgeContribution);\n }\n }\n }\n}\n\n/**\n * Apply normalization to centrality values\n */\nfunction normalizeCentrality(\n centrality: Record<string, number>,\n nodeCount: number,\n isDirected: boolean,\n): void {\n const n = nodeCount;\n const normalizationFactor = isDirected ?\n (n - 1) * (n - 2) :\n ((n - 1) * (n - 2)) / 2;\n\n if (normalizationFactor > 0) {\n for (const key in centrality) {\n const value = centrality[key];\n if (value !== undefined) {\n centrality[key] = value / normalizationFactor;\n }\n }\n }\n}\n\n/**\n * Calculate betweenness centrality for all nodes using Brandes' algorithm\n */\nexport function betweennessCentrality(\n graph: Graph,\n options: BetweennessCentralityOptions = {},\n): Record<string, number> {\n const nodes = Array.from(graph.nodes()).map((node) => node.id);\n const centrality: Record<string, number> = {};\n\n // Initialize centrality scores\n for (const nodeId of nodes) {\n centrality[String(nodeId)] = 0;\n }\n\n // Brandes' algorithm - run from each source\n for (const source of nodes) {\n const result = brandesSingleSource(graph, source, options.optimized);\n accumulateBetweenness(result, source, centrality, options);\n }\n\n // For undirected graphs, divide by 2 (each shortest path is counted twice)\n if (!graph.isDirected) {\n for (const nodeId of nodes) {\n const key = String(nodeId);\n const value = centrality[key];\n if (value !== undefined) {\n centrality[key] = value / 2;\n }\n }\n }\n\n // Normalization\n if (options.normalized) {\n normalizeCentrality(centrality, nodes.length, graph.isDirected);\n }\n\n return centrality;\n}\n\n/**\n * Calculate betweenness centrality for a specific node\n */\nexport function nodeBetweennessCentrality(\n graph: Graph,\n targetNode: NodeId,\n options: BetweennessCentralityOptions = {},\n): number {\n if (!graph.hasNode(targetNode)) {\n throw new Error(`Node ${String(targetNode)} not found in graph`);\n }\n\n const allCentralities = betweennessCentrality(graph, options);\n return allCentralities[String(targetNode)] ?? 0;\n}\n\n/**\n * Calculate edge betweenness centrality\n */\nexport function edgeBetweennessCentrality(\n graph: Graph,\n options: BetweennessCentralityOptions = {},\n): Map<string, number> {\n const nodes = Array.from(graph.nodes()).map((node) => node.id);\n const edgeCentrality = new Map<string, number>();\n\n // Initialize edge centrality scores\n for (const edge of Array.from(graph.edges())) {\n const edgeKey = `${String(edge.source)}-${String(edge.target)}`;\n edgeCentrality.set(edgeKey, 0);\n }\n\n // Modified Brandes' algorithm for edge betweenness\n for (const source of nodes) {\n const result = brandesSingleSource(graph, source, options.optimized);\n accumulateEdgeBetweenness(result, source, edgeCentrality, options);\n }\n\n // For undirected graphs, divide by 2 (each shortest path is counted twice)\n if (!graph.isDirected) {\n for (const [edgeKey, centrality] of Array.from(edgeCentrality)) {\n edgeCentrality.set(edgeKey, centrality / 2);\n }\n }\n\n // Normalization for edges\n if (options.normalized) {\n const n = nodes.length;\n const normalizationFactor = graph.isDirected ?\n (n - 1) * (n - 2) :\n ((n - 1) * (n - 2)) / 2;\n\n if (normalizationFactor > 0) {\n for (const [edgeKey, centrality] of Array.from(edgeCentrality)) {\n edgeCentrality.set(edgeKey, centrality / normalizationFactor);\n }\n }\n }\n\n return edgeCentrality;\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport type {NodeId} from \"../../types/index.js\";\nimport {bfsDistancesOnly, bfsWeightedDistances} from \"../traversal/bfs-variants.js\";\n\n/**\n * Closeness centrality implementation\n *\n * Measures how close a node is to all other nodes in the graph.\n * Uses BFS to compute shortest path distances efficiently.\n */\n\n/**\n * Closeness centrality options\n */\nexport interface ClosenessCentralityOptions {\n /**\n * Whether to normalize the centrality values (default: false)\n */\n normalized?: boolean;\n /**\n * Use harmonic mean instead of reciprocal of sum (default: false)\n * Better for disconnected graphs\n */\n harmonic?: boolean;\n /**\n * Consider only nodes within this distance (default: undefined = all nodes)\n */\n cutoff?: number;\n /**\n * Whether to use optimized BFS implementation for large graphs\n */\n optimized?: boolean;\n}\n\n/**\n * Calculate closeness centrality from distances\n */\nfunction calculateClosenessFromDistances(\n distances: Map<NodeId, number>,\n sourceNode: NodeId,\n totalNodes: number,\n options: ClosenessCentralityOptions,\n): number {\n if (distances.size <= 1) {\n return 0; // No other nodes reachable\n }\n\n let centrality = 0;\n\n if (options.harmonic) {\n // Harmonic centrality: sum of reciprocals of distances\n for (const [targetNode, distance] of distances) {\n if (targetNode !== sourceNode && distance > 0 && distance < Infinity) {\n centrality += 1 / distance;\n }\n }\n\n // Normalization for harmonic centrality\n if (options.normalized && totalNodes > 1) {\n centrality = centrality / (totalNodes - 1);\n }\n } else {\n // Standard closeness: reciprocal of sum of distances\n let totalDistance = 0;\n let reachableNodes = 0;\n\n for (const [targetNode, distance] of distances) {\n if (targetNode !== sourceNode && distance < Infinity) {\n totalDistance += distance;\n reachableNodes++;\n }\n }\n\n if (totalDistance > 0) {\n centrality = 1 / totalDistance;\n\n // Wasserman and Faust normalization for disconnected graphs\n if (options.normalized && totalNodes > 1) {\n centrality = centrality * reachableNodes / (totalNodes - 1);\n }\n }\n }\n\n return centrality;\n}\n\n/**\n * Calculate closeness centrality for all nodes in the graph\n *\n * Closeness centrality measures how close a node is to all other nodes\n * in the graph. It is the reciprocal of the sum of the shortest path\n * distances to all other reachable nodes.\n *\n * @param graph - The input graph\n * @param options - Algorithm options\n * @returns Centrality scores for each node\n *\n * @example\n * ```typescript\n * const graph = new Graph();\n * graph.addEdge(\"A\", \"B\");\n * graph.addEdge(\"B\", \"C\");\n *\n * const centrality = closenessCentrality(graph);\n * // { A: 0.5, B: 1.0, C: 0.5 }\n * ```\n *\n * Time Complexity: O(V * (V + E)) for unweighted graphs\n * Space Complexity: O(V)\n */\nexport function closenessCentrality(\n graph: Graph,\n options: ClosenessCentralityOptions = {},\n): Record<string, number> {\n const nodes = Array.from(graph.nodes()).map((node) => node.id);\n const centrality: Record<string, number> = {};\n\n for (const sourceNode of nodes) {\n centrality[String(sourceNode)] = nodeClosenessCentrality(graph, sourceNode, options);\n }\n\n return centrality;\n}\n\n/**\n * Calculate closeness centrality for a specific node\n */\nexport function nodeClosenessCentrality(\n graph: Graph,\n node: NodeId,\n options: ClosenessCentralityOptions = {},\n): number {\n if (!graph.hasNode(node)) {\n throw new Error(`Node ${String(node)} not found in graph`);\n }\n\n // Use optimized BFS variant for unweighted graphs\n const distances = bfsDistancesOnly(graph, node, options.cutoff, options.optimized !== undefined ? {optimized: options.optimized} : {});\n const totalNodes = graph.nodeCount;\n\n return calculateClosenessFromDistances(distances, node, totalNodes, options);\n}\n\n/**\n * Calculate weighted closeness centrality using Dijkstra's algorithm\n */\nexport function weightedClosenessCentrality(\n graph: Graph,\n options: ClosenessCentralityOptions = {},\n): Record<string, number> {\n const nodes = Array.from(graph.nodes()).map((node) => node.id);\n const centrality: Record<string, number> = {};\n\n for (const sourceNode of nodes) {\n centrality[String(sourceNode)] = nodeWeightedClosenessCentrality(graph, sourceNode, options);\n }\n\n return centrality;\n}\n\n/**\n * Calculate weighted closeness centrality for a specific node using Dijkstra\n */\nexport function nodeWeightedClosenessCentrality(\n graph: Graph,\n node: NodeId,\n options: ClosenessCentralityOptions = {},\n): number {\n if (!graph.hasNode(node)) {\n throw new Error(`Node ${String(node)} not found in graph`);\n }\n\n // Use optimized weighted BFS variant (simplified Dijkstra)\n const distances = bfsWeightedDistances(graph, node, options.cutoff, options.optimized !== undefined ? {optimized: options.optimized} : {});\n const totalNodes = graph.nodeCount;\n\n return calculateClosenessFromDistances(distances, node, totalNodes, options);\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport type {CentralityOptions, CentralityResult} from \"../../types/index.js\";\n\n/**\n * Degree centrality implementation\n *\n * Measures the importance of a node based on the number of connections it has.\n * The most basic centrality measure that simply counts incident edges.\n */\n\n/**\n * Calculate degree centrality for all nodes in the graph\n */\nexport function degreeCentrality(\n graph: Graph,\n options: CentralityOptions = {},\n): CentralityResult {\n const centrality: CentralityResult = {};\n const {nodeCount} = graph;\n\n // Calculate normalization factor (same for both directed and undirected graphs)\n const maxPossibleDegree = nodeCount - 1;\n\n for (const node of graph.nodes()) {\n let degree: number;\n\n if (graph.isDirected && options.mode) {\n // For directed graphs, calculate specific degree type\n switch (options.mode) {\n case \"in\": {\n degree = graph.inDegree(node.id);\n break;\n }\n case \"out\": {\n degree = graph.outDegree(node.id);\n break;\n }\n case \"total\": {\n degree = graph.degree(node.id);\n break;\n }\n default: {\n degree = graph.degree(node.id);\n }\n }\n } else {\n // For undirected graphs or default case\n degree = graph.degree(node.id);\n }\n\n // Apply normalization if requested\n const normalizedDegree = options.normalized && maxPossibleDegree > 0 ?\n degree / maxPossibleDegree :\n degree;\n\n centrality[node.id.toString()] = normalizedDegree;\n }\n\n return centrality;\n}\n\n/**\n * Calculate degree centrality for a specific node\n */\nexport function nodeDegreeCentrality(\n graph: Graph,\n nodeId: string | number,\n options: CentralityOptions = {},\n): number {\n if (!graph.hasNode(nodeId)) {\n throw new Error(`Node ${String(nodeId)} not found in graph`);\n }\n\n const {nodeCount} = graph;\n let degree: number;\n\n if (graph.isDirected && options.mode) {\n switch (options.mode) {\n case \"in\": {\n degree = graph.inDegree(nodeId);\n break;\n }\n case \"out\": {\n degree = graph.outDegree(nodeId);\n break;\n }\n case \"total\": {\n degree = graph.degree(nodeId);\n break;\n }\n default: {\n degree = graph.degree(nodeId);\n }\n }\n } else {\n degree = graph.degree(nodeId);\n }\n\n // Apply normalization if requested\n const maxPossibleDegree = nodeCount - 1;\n\n return options.normalized && maxPossibleDegree > 0 ?\n degree / maxPossibleDegree :\n degree;\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport {PriorityQueue} from \"../../data-structures/priority-queue.js\";\nimport type {NodeId} from \"../../types/index.js\";\n\n/**\n * Delta-based PageRank implementation for faster convergence\n *\n * This algorithm tracks changes (deltas) between iterations and only processes\n * nodes with significant changes, dramatically reducing computation for graphs\n * where only some nodes are actively changing their PageRank values.\n *\n * Key optimizations:\n * - Only active nodes (with significant deltas) are processed\n * - Early termination for converged vertices\n * - Priority queue processing for high-impact updates\n * - Adaptive convergence detection per vertex\n *\n * Expected speedup: 10-100x for incremental updates on large graphs\n */\n\nexport interface DeltaPageRankOptions {\n /**\n * Damping factor (probability of following a link) (default: 0.85)\n */\n dampingFactor?: number;\n /**\n * Convergence tolerance (default: 1e-6)\n */\n tolerance?: number;\n /**\n * Maximum number of iterations (default: 100)\n */\n maxIterations?: number;\n /**\n * Minimum delta to keep vertex active (default: tolerance / 10)\n */\n deltaThreshold?: number;\n /**\n * Personalization vector for Personalized PageRank (default: null)\n */\n personalization?: Map<NodeId, number>;\n /**\n * Weight attribute for weighted PageRank (default: null = unweighted)\n */\n weight?: string;\n}\n\nexport class DeltaPageRank {\n private graph: Graph;\n private scores: Map<NodeId, number>;\n private deltas: Map<NodeId, number>;\n private activeNodes: Set<NodeId>;\n private outDegrees: Map<NodeId, number>;\n private outWeights: Map<NodeId, number>;\n private danglingNodes: Set<NodeId>;\n private nodeCount: number;\n\n constructor(graph: Graph) {\n if (!graph.isDirected) {\n throw new Error(\"DeltaPageRank requires a directed graph\");\n }\n\n this.graph = graph;\n this.scores = new Map();\n this.deltas = new Map();\n this.activeNodes = new Set();\n this.outDegrees = new Map();\n this.outWeights = new Map();\n this.danglingNodes = new Set();\n this.nodeCount = graph.nodeCount;\n\n this.initialize();\n }\n\n private initialize(): void {\n const initialValue = 1.0 / this.nodeCount;\n\n // Initialize data structures\n for (const node of this.graph.nodes()) {\n const nodeId = node.id;\n this.scores.set(nodeId, 0); // Start with zero, will add initial value as delta\n this.deltas.set(nodeId, initialValue);\n this.activeNodes.add(nodeId);\n\n // Precompute out-degrees and weights\n let outDegree = 0;\n let totalOutWeight = 0;\n\n for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {\n outDegree++;\n const edge = this.graph.getEdge(nodeId, neighbor);\n totalOutWeight += edge?.weight ?? 1;\n }\n\n this.outDegrees.set(nodeId, outDegree);\n this.outWeights.set(nodeId, totalOutWeight);\n\n if (outDegree === 0) {\n this.danglingNodes.add(nodeId);\n }\n }\n }\n\n public compute(options: DeltaPageRankOptions = {}): Map<NodeId, number> {\n const {\n dampingFactor = 0.85,\n tolerance = 1e-6,\n maxIterations = 100,\n deltaThreshold = tolerance / 10,\n personalization,\n weight,\n } = options;\n\n if (dampingFactor < 0 || dampingFactor > 1) {\n throw new Error(\"Damping factor must be between 0 and 1\");\n }\n\n if (this.nodeCount === 0) {\n return new Map();\n }\n\n // Normalize personalization vector if provided\n let personalVector: Map<NodeId, number> | null = null;\n if (personalization) {\n personalVector = new Map(personalization);\n this.normalizeMap(personalVector);\n }\n\n const randomJump = (1 - dampingFactor) / this.nodeCount;\n let iteration = 0;\n\n while (this.activeNodes.size > 0 && iteration < maxIterations) {\n iteration++;\n\n // Create next iteration's deltas\n const nextDeltas = new Map<NodeId, number>();\n\n // Initialize all nodes with zero delta\n for (const node of this.graph.nodes()) {\n nextDeltas.set(node.id, 0);\n }\n\n // Handle dangling nodes contribution\n let danglingSum = 0;\n for (const danglingNode of this.danglingNodes) {\n const currentScore = this.scores.get(danglingNode) ?? 0;\n const delta = this.deltas.get(danglingNode) ?? 0;\n danglingSum += currentScore + delta;\n }\n\n if (danglingSum > 0) {\n const danglingContribution = dampingFactor * danglingSum / this.nodeCount;\n for (const node of this.graph.nodes()) {\n const nodeId = node.id;\n const currentDelta = nextDeltas.get(nodeId) ?? 0;\n if (personalVector) {\n const personalContrib = danglingContribution * (personalVector.get(nodeId) ?? 0);\n nextDeltas.set(nodeId, currentDelta + personalContrib);\n } else {\n nextDeltas.set(nodeId, currentDelta + danglingContribution);\n }\n }\n }\n\n // Process only active nodes\n for (const nodeId of this.activeNodes) {\n const delta = this.deltas.get(nodeId) ?? 0;\n\n // Skip if delta is too small\n if (Math.abs(delta) < deltaThreshold) {\n continue;\n }\n\n // Apply delta to score\n const currentScore = this.scores.get(nodeId) ?? 0;\n this.scores.set(nodeId, currentScore + delta);\n\n const outWeight = this.outWeights.get(nodeId) ?? 0;\n if (outWeight > 0) {\n // Distribute delta to neighbors\n for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {\n let edgeWeight = 1;\n if (weight) {\n const edge = this.graph.getEdge(nodeId, neighbor);\n edgeWeight = edge?.weight ?? 1;\n }\n\n const contribution = dampingFactor * delta * (edgeWeight / outWeight);\n const currentDelta = nextDeltas.get(neighbor) ?? 0;\n nextDeltas.set(neighbor, currentDelta + contribution);\n }\n }\n }\n\n // Add teleportation probability as delta\n for (const node of this.graph.nodes()) {\n const nodeId = node.id;\n const currentDelta = nextDeltas.get(nodeId) ?? 0;\n if (personalVector) {\n nextDeltas.set(nodeId, currentDelta + ((1 - dampingFactor) * (personalVector.get(nodeId) ?? 0)));\n } else {\n nextDeltas.set(nodeId, currentDelta + randomJump);\n }\n }\n\n // Find active nodes for next iteration\n const nextActive = new Set<NodeId>();\n let maxDelta = 0;\n\n for (const [nodeId, delta] of nextDeltas) {\n maxDelta = Math.max(maxDelta, Math.abs(delta));\n if (Math.abs(delta) >= deltaThreshold) {\n nextActive.add(nodeId);\n }\n }\n\n // Update for next iteration\n this.deltas = nextDeltas;\n this.activeNodes = nextActive;\n\n // Global convergence check\n if (maxDelta < tolerance) {\n break;\n }\n }\n\n // Normalize final scores\n this.normalizeMap(this.scores);\n\n return new Map(this.scores);\n }\n\n /**\n * Update PageRank scores after graph modification\n * This is where delta-based approach really shines\n */\n public update(\n modifiedNodes: Set<NodeId>,\n options: DeltaPageRankOptions = {},\n ): Map<NodeId, number> {\n // Mark modified nodes and their neighbors as active\n this.activeNodes.clear();\n\n for (const nodeId of modifiedNodes) {\n this.activeNodes.add(nodeId);\n\n // Add incoming neighbors\n for (const neighbor of Array.from(this.graph.inNeighbors(nodeId))) {\n this.activeNodes.add(neighbor);\n }\n\n // Add outgoing neighbors\n for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {\n this.activeNodes.add(neighbor);\n }\n }\n\n // Recompute only for active nodes\n return this.compute(options);\n }\n\n private normalizeMap(map: Map<NodeId, number>): void {\n let sum = 0;\n for (const value of map.values()) {\n sum += value;\n }\n\n if (sum > 0) {\n for (const [key, value] of Array.from(map)) {\n map.set(key, value / sum);\n }\n }\n }\n}\n\n/**\n * Priority queue based implementation for even better performance\n * Processes nodes in order of their delta magnitude\n */\nexport class PriorityDeltaPageRank {\n private graph: Graph;\n private scores: Map<NodeId, number>;\n private priorityQueue: PriorityQueue<NodeId>;\n private nodeDeltas: Map<NodeId, number>;\n private outWeights: Map<NodeId, number>;\n private danglingNodes: Set<NodeId>;\n private nodeCount: number;\n\n constructor(graph: Graph) {\n if (!graph.isDirected) {\n throw new Error(\"PriorityDeltaPageRank requires a directed graph\");\n }\n\n this.graph = graph;\n this.scores = new Map();\n this.nodeDeltas = new Map();\n this.outWeights = new Map();\n this.danglingNodes = new Set();\n this.nodeCount = graph.nodeCount;\n\n // Priority queue ordered by delta magnitude (larger deltas have higher priority)\n this.priorityQueue = new PriorityQueue<NodeId>((a, b) => b - a);\n\n this.initialize();\n }\n\n private initialize(): void {\n const initialValue = 1.0 / this.nodeCount;\n\n // Initialize all nodes with initial delta\n for (const node of this.graph.nodes()) {\n const nodeId = node.id;\n this.scores.set(nodeId, 0); // Start with zero scores\n this.nodeDeltas.set(nodeId, initialValue);\n this.priorityQueue.enqueue(nodeId, initialValue);\n\n // Precompute out-weights\n let totalOutWeight = 0;\n let outDegree = 0;\n\n for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {\n outDegree++;\n const edge = this.graph.getEdge(nodeId, neighbor);\n totalOutWeight += edge?.weight ?? 1;\n }\n\n this.outWeights.set(nodeId, totalOutWeight);\n\n if (outDegree === 0) {\n this.danglingNodes.add(nodeId);\n }\n }\n }\n\n public computeWithPriority(options: DeltaPageRankOptions = {}): Map<NodeId, number> {\n const {\n dampingFactor = 0.85,\n tolerance = 1e-6,\n maxIterations = 100,\n deltaThreshold = tolerance / 10,\n weight,\n } = options;\n\n let iteration = 0;\n let processedCount = 0;\n\n while (!this.priorityQueue.isEmpty() && iteration < maxIterations) {\n const nodeId = this.priorityQueue.dequeue();\n if (nodeId === undefined) {\n break;\n }\n\n const delta = this.nodeDeltas.get(nodeId) ?? 0;\n\n // Skip if delta is too small\n if (Math.abs(delta) < deltaThreshold) {\n continue;\n }\n\n // Apply delta to node's score\n const currentScore = this.scores.get(nodeId) ?? 0;\n this.scores.set(nodeId, currentScore + delta);\n this.nodeDeltas.set(nodeId, 0);\n\n // Distribute delta to neighbors\n const outWeight = this.outWeights.get(nodeId) ?? 0;\n if (outWeight > 0) {\n for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {\n let edgeWeight = 1;\n if (weight) {\n const edge = this.graph.getEdge(nodeId, neighbor);\n edgeWeight = edge?.weight ?? 1;\n }\n\n const contribution = dampingFactor * delta * (edgeWeight / outWeight);\n const currentNeighborDelta = this.nodeDeltas.get(neighbor) ?? 0;\n const newDelta = currentNeighborDelta + contribution;\n this.nodeDeltas.set(neighbor, newDelta);\n\n // Re-enqueue neighbor with updated priority\n if (Math.abs(newDelta) >= deltaThreshold) {\n this.priorityQueue.enqueue(neighbor, Math.abs(newDelta));\n }\n }\n }\n\n processedCount++;\n\n // Periodic convergence check\n if (processedCount % 1000 === 0) {\n let maxDelta = 0;\n for (const d of this.nodeDeltas.values()) {\n maxDelta = Math.max(maxDelta, Math.abs(d));\n }\n if (maxDelta < tolerance) {\n break;\n }\n }\n\n iteration++;\n }\n\n // Apply any remaining deltas\n for (const [nodeId, delta] of this.nodeDeltas) {\n if (Math.abs(delta) >= deltaThreshold) {\n const currentScore = this.scores.get(nodeId) ?? 0;\n this.scores.set(nodeId, currentScore + delta);\n }\n }\n\n // Add teleportation probability\n const teleport = (1 - dampingFactor) / this.nodeCount;\n for (const [nodeId, score] of this.scores) {\n this.scores.set(nodeId, score + teleport);\n }\n\n // Normalize final scores\n this.normalizeMap(this.scores);\n\n return new Map(this.scores);\n }\n\n private normalizeMap(map: Map<NodeId, number>): void {\n let sum = 0;\n for (const value of map.values()) {\n sum += value;\n }\n\n if (sum > 0) {\n for (const [key, value] of Array.from(map)) {\n map.set(key, value / sum);\n }\n }\n }\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport type {CentralityOptions, CentralityResult} from \"../../types/index.js\";\n\n/**\n * Eigenvector centrality implementation\n *\n * Measures the influence of a node based on the influence of its neighbors.\n * A node has high eigenvector centrality if it is connected to nodes\n * that themselves have high eigenvector centrality.\n *\n * Time complexity: O(V + E) per iteration\n * Space complexity: O(V)\n */\n\nexport interface EigenvectorCentralityOptions extends CentralityOptions {\n maxIterations?: number; // Maximum iterations (default: 100)\n tolerance?: number; // Convergence tolerance (default: 1e-6)\n startVector?: Map<string, number>; // Initial vector (optional)\n}\n\n/**\n * Calculate eigenvector centrality for all nodes in the graph\n * Uses the power iteration method to find the dominant eigenvector\n */\nexport function eigenvectorCentrality(\n graph: Graph,\n options: EigenvectorCentralityOptions = {},\n): CentralityResult {\n const {\n maxIterations = 100,\n tolerance = 1e-6,\n normalized = true,\n startVector,\n } = options;\n\n const centrality: CentralityResult = {};\n const nodes = Array.from(graph.nodes());\n const nodeIds = nodes.map((node) => node.id);\n\n if (nodeIds.length === 0) {\n return centrality;\n }\n\n // Initialize the eigenvector\n let currentVector = new Map<string, number>();\n let previousVector = new Map<string, number>();\n\n if (startVector) {\n // Use provided start vector\n for (const nodeId of nodeIds) {\n const key = nodeId.toString();\n currentVector.set(key, startVector.get(key) ?? 1.0 / Math.sqrt(nodeIds.length));\n }\n } else {\n // Initialize with uniform distribution\n const initialValue = 1.0 / Math.sqrt(nodeIds.length);\n for (const nodeId of nodeIds) {\n currentVector.set(nodeId.toString(), initialValue);\n }\n }\n\n // Power iteration\n for (let iteration = 0; iteration < maxIterations; iteration++) {\n previousVector = new Map(currentVector);\n currentVector = new Map();\n\n // Update each node's centrality based on neighbors\n for (const nodeId of nodeIds) {\n let sum = 0;\n const neighbors = Array.from(graph.neighbors(nodeId));\n\n for (const neighbor of neighbors) {\n const neighborKey = neighbor.toString();\n const prevValue = previousVector.get(neighborKey);\n sum += prevValue ?? 0;\n }\n\n currentVector.set(nodeId.toString(), sum);\n }\n\n // Normalize the vector\n let norm = 0;\n for (const value of Array.from(currentVector.values())) {\n norm += value * value;\n }\n norm = Math.sqrt(norm);\n\n if (norm === 0) {\n // Graph has no edges or is disconnected\n for (const nodeId of nodeIds) {\n centrality[nodeId.toString()] = 0;\n }\n return centrality;\n }\n\n // Normalize the vector\n for (const [nodeId, value] of Array.from(currentVector)) {\n currentVector.set(nodeId, value / norm);\n }\n\n // Check for convergence\n let maxDiff = 0;\n for (const [nodeId, value] of Array.from(currentVector)) {\n const prevValue = previousVector.get(nodeId) ?? 0;\n const diff = Math.abs(value - prevValue);\n maxDiff = Math.max(maxDiff, diff);\n }\n\n if (maxDiff < tolerance) {\n break;\n }\n }\n\n // Prepare results\n for (const [nodeId, value] of Array.from(currentVector)) {\n centrality[nodeId] = value;\n }\n\n // Additional normalization if requested (normalize to [0,1] range)\n if (normalized) {\n let maxValue = 0;\n let minValue = Number.POSITIVE_INFINITY;\n\n for (const value of Object.values(centrality)) {\n maxValue = Math.max(maxValue, value);\n minValue = Math.min(minValue, value);\n }\n\n const range = maxValue - minValue;\n if (range > 0) {\n for (const nodeId of Object.keys(centrality)) {\n const centralityValue = centrality[nodeId];\n if (centralityValue !== undefined) {\n centrality[nodeId] = (centralityValue - minValue) / range;\n }\n }\n } else {\n // All values are the same, set to 1\n for (const nodeId of Object.keys(centrality)) {\n centrality[nodeId] = maxValue > 0 ? 1 : 0;\n }\n }\n }\n\n return centrality;\n}\n\n/**\n * Calculate eigenvector centrality for a specific node\n */\nexport function nodeEigenvectorCentrality(\n graph: Graph,\n nodeId: string | number,\n options: EigenvectorCentralityOptions = {},\n): number {\n if (!graph.hasNode(nodeId)) {\n throw new Error(`Node ${String(nodeId)} not found in graph`);\n }\n\n const centrality = eigenvectorCentrality(graph, options);\n return centrality[nodeId.toString()] ?? 0;\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport type {CentralityOptions} from \"../../types/index.js\";\n\n/**\n * HITS (Hyperlink-Induced Topic Search) algorithm implementation\n *\n * Identifies hub and authority scores for nodes in a graph.\n * - Authorities: nodes with valuable information (pointed to by hubs)\n * - Hubs: nodes that point to many authorities\n *\n * Originally designed for web page ranking but applicable to any directed network.\n *\n * Time complexity: O(V + E) per iteration\n * Space complexity: O(V)\n */\n\nexport interface HITSResult {\n hubs: Record<string, number>;\n authorities: Record<string, number>;\n}\n\nexport interface HITSOptions extends CentralityOptions {\n maxIterations?: number; // Maximum iterations (default: 100)\n tolerance?: number; // Convergence tolerance (default: 1e-6)\n}\n\n/**\n * Calculate HITS hub and authority scores for all nodes in the graph\n * Uses iterative method with normalization\n */\nexport function hits(\n graph: Graph,\n options: HITSOptions = {},\n): HITSResult {\n const {\n maxIterations = 100,\n tolerance = 1e-6,\n normalized = true,\n } = options;\n\n const hubs: Record<string, number> = {};\n const authorities: Record<string, number> = {};\n\n const nodes = Array.from(graph.nodes());\n const nodeIds = nodes.map((node) => node.id);\n\n if (nodeIds.length === 0) {\n return {hubs, authorities};\n }\n\n // Initialize scores\n let currentHubs = new Map<string, number>();\n let currentAuthorities = new Map<string, number>();\n let previousHubs = new Map<string, number>();\n let previousAuthorities = new Map<string, number>();\n\n // Start with uniform distribution\n const initialValue = 1.0 / Math.sqrt(nodeIds.length);\n for (const nodeId of nodeIds) {\n const key = nodeId.toString();\n currentHubs.set(key, initialValue);\n currentAuthorities.set(key, initialValue);\n }\n\n // Iterative computation\n for (let iteration = 0; iteration < maxIterations; iteration++) {\n previousHubs = new Map(currentHubs);\n previousAuthorities = new Map(currentAuthorities);\n\n // Update authority scores\n // Authority score = sum of hub scores of nodes pointing to it\n const newAuthorities = new Map<string, number>();\n for (const nodeId of nodeIds) {\n let authorityScore = 0;\n const inNeighbors = Array.from(graph.inNeighbors(nodeId));\n\n for (const inNeighbor of inNeighbors) {\n const neighborKey = inNeighbor.toString();\n authorityScore += previousHubs.get(neighborKey) ?? 0;\n }\n\n newAuthorities.set(nodeId.toString(), authorityScore);\n }\n\n // Update hub scores\n // Hub score = sum of authority scores of nodes it points to\n const newHubs = new Map<string, number>();\n for (const nodeId of nodeIds) {\n let hubScore = 0;\n const outNeighbors = Array.from(graph.outNeighbors(nodeId));\n\n for (const outNeighbor of outNeighbors) {\n const neighborKey = outNeighbor.toString();\n hubScore += previousAuthorities.get(neighborKey) ?? 0;\n }\n\n newHubs.set(nodeId.toString(), hubScore);\n }\n\n // Normalize authority scores\n let authNorm = 0;\n for (const value of Array.from(newAuthorities.values())) {\n authNorm += value * value;\n }\n authNorm = Math.sqrt(authNorm);\n\n if (authNorm > 0) {\n for (const [nodeId, value] of Array.from(newAuthorities)) {\n newAuthorities.set(nodeId, value / authNorm);\n }\n }\n\n // Normalize hub scores\n let hubNorm = 0;\n for (const value of Array.from(newHubs.values())) {\n hubNorm += value * value;\n }\n hubNorm = Math.sqrt(hubNorm);\n\n if (hubNorm > 0) {\n for (const [nodeId, value] of Array.from(newHubs)) {\n newHubs.set(nodeId, value / hubNorm);\n }\n }\n\n currentAuthorities = newAuthorities;\n currentHubs = newHubs;\n\n // Check for convergence\n let maxDiff = 0;\n for (const [nodeId, value] of currentHubs) {\n const prevValue = previousHubs.get(nodeId) ?? 0;\n const diff = Math.abs(value - prevValue);\n maxDiff = Math.max(maxDiff, diff);\n }\n for (const [nodeId, value] of currentAuthorities) {\n const prevValue = previousAuthorities.get(nodeId) ?? 0;\n const diff = Math.abs(value - prevValue);\n maxDiff = Math.max(maxDiff, diff);\n }\n\n if (maxDiff < tolerance) {\n break;\n }\n }\n\n // Prepare results\n for (const [nodeId, value] of currentHubs) {\n hubs[nodeId] = value;\n }\n for (const [nodeId, value] of currentAuthorities) {\n authorities[nodeId] = value;\n }\n\n // The algorithm already normalizes to unit L2 norm during iterations\n // Additional max normalization is only applied if explicitly requested\n if (!normalized) {\n // If normalization is explicitly disabled, normalize to [0, 1] range\n let maxHub = 0;\n let maxAuth = 0;\n\n for (const value of Object.values(hubs)) {\n maxHub = Math.max(maxHub, value);\n }\n for (const value of Object.values(authorities)) {\n maxAuth = Math.max(maxAuth, value);\n }\n\n if (maxHub > 0) {\n for (const nodeId of Object.keys(hubs)) {\n const hubValue = hubs[nodeId];\n if (hubValue !== undefined) {\n hubs[nodeId] = hubValue / maxHub;\n }\n }\n }\n\n if (maxAuth > 0) {\n for (const nodeId of Object.keys(authorities)) {\n const authValue = authorities[nodeId];\n if (authValue !== undefined) {\n authorities[nodeId] = authValue / maxAuth;\n }\n }\n }\n }\n\n return {hubs, authorities};\n}\n\n/**\n * Calculate HITS scores for a specific node\n */\nexport function nodeHITS(\n graph: Graph,\n nodeId: string | number,\n options: HITSOptions = {},\n): {hub: number, authority: number} {\n if (!graph.hasNode(nodeId)) {\n throw new Error(`Node ${String(nodeId)} not found in graph`);\n }\n\n const result = hits(graph, options);\n const key = nodeId.toString();\n\n return {\n hub: result.hubs[key] ?? 0,\n authority: result.authorities[key] ?? 0,\n };\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport type {CentralityOptions, CentralityResult} from \"../../types/index.js\";\n\n/**\n * Katz centrality implementation\n *\n * A generalization of eigenvector centrality that gives each node a base amount\n * of influence regardless of its position in the network. Uses an attenuation\n * factor (alpha) to control how much a node's centrality depends on its neighbors.\n *\n * Katz centrality = alpha * sum(neighbors' centrality) + beta\n *\n * Time complexity: O(V + E) per iteration\n * Space complexity: O(V)\n */\n\nexport interface KatzCentralityOptions extends CentralityOptions {\n alpha?: number; // Attenuation factor (default: 0.1)\n beta?: number; // Base centrality weight (default: 1.0)\n maxIterations?: number; // Maximum iterations (default: 100)\n tolerance?: number; // Convergence tolerance (default: 1e-6)\n}\n\n/**\n * Calculate Katz centrality for all nodes in the graph\n * Uses iterative method to compute centrality scores\n */\nexport function katzCentrality(\n graph: Graph,\n options: KatzCentralityOptions = {},\n): CentralityResult {\n const {\n alpha = 0.1,\n beta = 1.0,\n maxIterations = 100,\n tolerance = 1e-6,\n normalized = true,\n } = options;\n\n const centrality: CentralityResult = {};\n const nodes = Array.from(graph.nodes());\n const nodeIds = nodes.map((node) => node.id);\n\n if (nodeIds.length === 0) {\n return centrality;\n }\n\n // Check if alpha is valid (should be less than 1/lambda_max)\n // For simplicity, we'll trust the user's choice or use conservative default\n\n // Initialize centrality scores\n let currentScores = new Map<string, number>();\n let previousScores = new Map<string, number>();\n\n // Start with beta for all nodes\n for (const nodeId of nodeIds) {\n currentScores.set(nodeId.toString(), beta);\n }\n\n // Iterative computation\n for (let iteration = 0; iteration < maxIterations; iteration++) {\n previousScores = new Map(currentScores);\n currentScores = new Map();\n\n // Update each node's centrality\n for (const nodeId of nodeIds) {\n let sum = 0;\n\n // For directed graphs, use in-neighbors\n // For undirected graphs, use all neighbors\n const neighbors = graph.isDirected ?\n Array.from(graph.inNeighbors(nodeId)) :\n graph.neighbors(nodeId);\n\n for (const neighbor of neighbors) {\n const neighborKey = neighbor.toString();\n sum += previousScores.get(neighborKey) ?? 0;\n }\n\n currentScores.set(nodeId.toString(), (alpha * sum) + beta);\n }\n\n // Check for convergence\n let maxDiff = 0;\n for (const [nodeId, value] of Array.from(currentScores)) {\n const prevValue = previousScores.get(nodeId) ?? 0;\n const diff = Math.abs(value - prevValue);\n maxDiff = Math.max(maxDiff, diff);\n }\n\n if (maxDiff < tolerance) {\n break;\n }\n }\n\n // Prepare results\n for (const [nodeId, value] of Array.from(currentScores)) {\n centrality[nodeId] = value;\n }\n\n // Normalize if requested\n if (normalized) {\n let maxValue = 0;\n let minValue = Number.POSITIVE_INFINITY;\n\n for (const value of Object.values(centrality)) {\n maxValue = Math.max(maxValue, value);\n minValue = Math.min(minValue, value);\n }\n\n const range = maxValue - minValue;\n if (range > 0) {\n for (const nodeId of Object.keys(centrality)) {\n const centralityValue = centrality[nodeId];\n if (centralityValue !== undefined) {\n centrality[nodeId] = (centralityValue - minValue) / range;\n }\n }\n }\n }\n\n return centrality;\n}\n\n/**\n * Calculate Katz centrality for a specific node\n */\nexport function nodeKatzCentrality(\n graph: Graph,\n nodeId: string | number,\n options: KatzCentralityOptions = {},\n): number {\n if (!graph.hasNode(nodeId)) {\n throw new Error(`Node ${String(nodeId)} not found in graph`);\n }\n\n const centrality = katzCentrality(graph, options);\n return centrality[nodeId.toString()] ?? 0;\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport type {NodeId} from \"../../types/index.js\";\n\n/**\n * Simplified Delta-based PageRank that matches the standard algorithm\n * but only processes active nodes for efficiency.\n *\n * Key optimization: Supports incremental updates when graph structure changes,\n * avoiding full recomputation from scratch.\n */\nexport class SimpleDeltaPageRank {\n private graph: Graph;\n private nodeCount: number;\n private previousScores: Map<NodeId, number> | null = null;\n\n constructor(graph: Graph) {\n if (!graph.isDirected) {\n throw new Error(\"PageRank requires a directed graph\");\n }\n\n this.graph = graph;\n this.nodeCount = graph.nodeCount;\n }\n\n public compute(options: {\n dampingFactor?: number;\n tolerance?: number;\n maxIterations?: number;\n personalization?: Map<NodeId, number>;\n weight?: string;\n } = {}): Map<NodeId, number> {\n const {\n dampingFactor = 0.85,\n tolerance = 1e-6,\n maxIterations = 100,\n personalization,\n weight,\n } = options;\n\n if (this.nodeCount === 0) {\n return new Map();\n }\n\n // Initialize scores\n const scores = new Map<NodeId, number>();\n const newScores = new Map<NodeId, number>();\n\n for (const node of this.graph.nodes()) {\n scores.set(node.id, 1.0 / this.nodeCount);\n }\n\n // Precompute out-degrees and weights\n const outWeights = new Map<NodeId, number>();\n const danglingNodes = new Set<NodeId>();\n\n for (const node of this.graph.nodes()) {\n let totalWeight = 0;\n let outDegree = 0;\n\n for (const neighbor of Array.from(this.graph.neighbors(node.id))) {\n outDegree++;\n const edge = this.graph.getEdge(node.id, neighbor);\n totalWeight += edge?.weight ?? 1;\n }\n\n outWeights.set(node.id, totalWeight);\n if (outDegree === 0) {\n danglingNodes.add(node.id);\n }\n }\n\n // Normalize personalization vector if provided\n let personalVector: Map<NodeId, number> | null = null;\n if (personalization) {\n personalVector = new Map(personalization);\n this.normalizeMap(personalVector);\n }\n\n // Power iteration with active node tracking\n let activeNodes = new Set<NodeId>(scores.keys());\n let iteration = 0;\n\n for (iteration = 0; iteration < maxIterations; iteration++) {\n // Initialize new scores\n for (const nodeId of scores.keys()) {\n if (personalVector) {\n newScores.set(nodeId, (1 - dampingFactor) * (personalVector.get(nodeId) ?? 0));\n } else {\n newScores.set(nodeId, (1 - dampingFactor) / this.nodeCount);\n }\n }\n\n // Handle dangling nodes\n let danglingSum = 0;\n for (const danglingNode of danglingNodes) {\n danglingSum += scores.get(danglingNode) ?? 0;\n }\n\n if (danglingSum > 0) {\n const danglingContribution = dampingFactor * danglingSum / this.nodeCount;\n for (const nodeId of scores.keys()) {\n const current = newScores.get(nodeId) ?? 0;\n if (personalVector) {\n const personalContrib = danglingContribution * (personalVector.get(nodeId) ?? 0);\n newScores.set(nodeId, current + personalContrib);\n } else {\n newScores.set(nodeId, current + danglingContribution);\n }\n }\n }\n\n // Propagate rank from active nodes only\n for (const nodeId of activeNodes) {\n const currentRank = scores.get(nodeId) ?? 0;\n const nodeOutWeight = outWeights.get(nodeId) ?? 0;\n\n if (nodeOutWeight > 0) {\n for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {\n let edgeWeight = 1;\n if (weight) {\n const edge = this.graph.getEdge(nodeId, neighbor);\n edgeWeight = edge?.weight ?? 1;\n }\n\n const contribution = dampingFactor * currentRank * (edgeWeight / nodeOutWeight);\n const neighborRank = newScores.get(neighbor) ?? 0;\n newScores.set(neighbor, neighborRank + contribution);\n }\n }\n }\n\n // Check convergence and identify active nodes\n const nextActive = new Set<NodeId>();\n let maxDiff = 0;\n\n for (const nodeId of scores.keys()) {\n const oldRank = scores.get(nodeId) ?? 0;\n const newRank = newScores.get(nodeId) ?? 0;\n const diff = Math.abs(newRank - oldRank);\n maxDiff = Math.max(maxDiff, diff);\n\n // Mark as active if change is significant\n if (diff > tolerance / 10) {\n nextActive.add(nodeId);\n // Also mark neighbors as potentially active\n for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {\n nextActive.add(neighbor);\n }\n for (const neighbor of Array.from(this.graph.inNeighbors(nodeId))) {\n nextActive.add(neighbor);\n }\n }\n }\n\n // Swap score maps\n scores.clear();\n for (const [k, v] of newScores) {\n scores.set(k, v);\n }\n newScores.clear();\n\n activeNodes = nextActive;\n\n if (maxDiff < tolerance) {\n break;\n }\n }\n\n // Store scores for potential incremental updates\n this.previousScores = new Map(scores);\n\n return scores;\n }\n\n /**\n * Perform incremental update after graph modification.\n * This is where delta-based approach provides significant speedup.\n *\n * @param modifiedNodes Set of nodes that were modified (edges added/removed)\n * @param options Computation options\n * @returns Updated PageRank scores\n */\n public update(\n modifiedNodes: Set<NodeId>,\n options: {\n dampingFactor?: number;\n tolerance?: number;\n maxIterations?: number;\n personalization?: Map<NodeId, number>;\n weight?: string;\n } = {},\n ): Map<NodeId, number> {\n if (!this.previousScores) {\n // No previous computation, do full compute\n return this.compute(options);\n }\n\n const {\n dampingFactor = 0.85,\n tolerance = 1e-6,\n maxIterations = 100,\n personalization,\n weight,\n } = options;\n\n // Initialize scores from previous computation\n const scores = new Map(this.previousScores);\n const newScores = new Map<NodeId, number>();\n\n // Ensure all current nodes are included\n for (const node of this.graph.nodes()) {\n if (!scores.has(node.id)) {\n scores.set(node.id, 1.0 / this.nodeCount);\n }\n }\n\n // Start with only modified nodes and their neighbors as active\n let activeNodes = new Set<NodeId>();\n for (const nodeId of modifiedNodes) {\n activeNodes.add(nodeId);\n // Add incoming neighbors\n for (const neighbor of Array.from(this.graph.inNeighbors(nodeId))) {\n activeNodes.add(neighbor);\n }\n // Add outgoing neighbors\n for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {\n activeNodes.add(neighbor);\n }\n }\n\n // Recompute out-weights for modified nodes\n const outWeights = new Map<NodeId, number>();\n const danglingNodes = new Set<NodeId>();\n\n for (const node of this.graph.nodes()) {\n let totalWeight = 0;\n let outDegree = 0;\n\n for (const neighbor of Array.from(this.graph.neighbors(node.id))) {\n outDegree++;\n const edge = this.graph.getEdge(node.id, neighbor);\n totalWeight += edge?.weight ?? 1;\n }\n\n outWeights.set(node.id, totalWeight);\n if (outDegree === 0) {\n danglingNodes.add(node.id);\n }\n }\n\n // Normalize personalization vector if provided\n let personalVector: Map<NodeId, number> | null = null;\n if (personalization) {\n personalVector = new Map(personalization);\n this.normalizeMap(personalVector);\n }\n\n // Run limited iterations focusing on active nodes\n let iteration = 0;\n\n for (iteration = 0; iteration < maxIterations && activeNodes.size > 0; iteration++) {\n // Initialize new scores\n for (const nodeId of scores.keys()) {\n if (personalVector) {\n newScores.set(nodeId, (1 - dampingFactor) * (personalVector.get(nodeId) ?? 0));\n } else {\n newScores.set(nodeId, (1 - dampingFactor) / this.nodeCount);\n }\n }\n\n // Handle dangling nodes\n let danglingSum = 0;\n for (const danglingNode of danglingNodes) {\n danglingSum += scores.get(danglingNode) ?? 0;\n }\n\n if (danglingSum > 0) {\n const danglingContribution = dampingFactor * danglingSum / this.nodeCount;\n for (const nodeId of scores.keys()) {\n const current = newScores.get(nodeId) ?? 0;\n if (personalVector) {\n const personalContrib = danglingContribution * (personalVector.get(nodeId) ?? 0);\n newScores.set(nodeId, current + personalContrib);\n } else {\n newScores.set(nodeId, current + danglingContribution);\n }\n }\n }\n\n // Propagate rank from ALL nodes (not just active)\n // This ensures correctness\n for (const nodeId of scores.keys()) {\n const currentRank = scores.get(nodeId) ?? 0;\n const nodeOutWeight = outWeights.get(nodeId) ?? 0;\n\n if (nodeOutWeight > 0) {\n for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {\n let edgeWeight = 1;\n if (weight) {\n const edge = this.graph.getEdge(nodeId, neighbor);\n edgeWeight = edge?.weight ?? 1;\n }\n\n const contribution = dampingFactor * currentRank * (edgeWeight / nodeOutWeight);\n const neighborRank = newScores.get(neighbor) ?? 0;\n newScores.set(neighbor, neighborRank + contribution);\n }\n }\n }\n\n // Check convergence only for active nodes\n const nextActive = new Set<NodeId>();\n let maxDiff = 0;\n\n for (const nodeId of activeNodes) {\n const oldRank = scores.get(nodeId) ?? 0;\n const newRank = newScores.get(nodeId) ?? 0;\n const diff = Math.abs(newRank - oldRank);\n maxDiff = Math.max(maxDiff, diff);\n\n // Mark as active if change is significant\n if (diff > tolerance / 10) {\n nextActive.add(nodeId);\n // Also mark neighbors as potentially active\n for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {\n nextActive.add(neighbor);\n }\n for (const neighbor of Array.from(this.graph.inNeighbors(nodeId))) {\n nextActive.add(neighbor);\n }\n }\n }\n\n // Swap score maps\n scores.clear();\n for (const [k, v] of newScores) {\n scores.set(k, v);\n }\n newScores.clear();\n\n activeNodes = nextActive;\n\n if (maxDiff < tolerance) {\n break;\n }\n }\n\n // Store scores for future incremental updates\n this.previousScores = new Map(scores);\n\n return scores;\n }\n\n private normalizeMap(map: Map<NodeId, number>): void {\n let sum = 0;\n for (const value of map.values()) {\n sum += value;\n }\n\n if (sum > 0) {\n for (const [key, value] of Array.from(map)) {\n map.set(key, value / sum);\n }\n }\n }\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport type {NodeId} from \"../../types/index.js\";\nimport {SimpleDeltaPageRank} from \"./delta-pagerank-simple.js\";\n\n/**\n * PageRank algorithm implementation\n *\n * Measures the importance of nodes in a directed graph based on the\n * structure of incoming links. Originally designed for ranking web pages.\n */\n\n/**\n * PageRank algorithm options\n */\nexport interface PageRankOptions {\n /**\n * Damping factor (probability of following a link) (default: 0.85)\n */\n dampingFactor?: number;\n /**\n * Maximum number of iterations (default: 100)\n */\n maxIterations?: number;\n /**\n * Convergence tolerance (default: 1e-6)\n */\n tolerance?: number;\n /**\n * Initial PageRank values for nodes (default: uniform distribution)\n */\n initialRanks?: Map<NodeId, number>;\n /**\n * Personalization vector for Personalized PageRank (default: null)\n */\n personalization?: Map<NodeId, number>;\n /**\n * Weight attribute for weighted PageRank (default: null = unweighted)\n */\n weight?: string;\n /**\n * Use delta-based optimization for faster convergence.\n * Defaults to true for graphs with >100 nodes, false for smaller graphs.\n * Set explicitly to override automatic heuristic.\n */\n useDelta?: boolean;\n}\n\n/**\n * PageRank algorithm result\n */\nexport interface PageRankResult {\n /**\n * PageRank scores for each node\n */\n ranks: Record<string, number>;\n /**\n * Number of iterations until convergence\n */\n iterations: number;\n /**\n * Whether the algorithm converged\n */\n converged: boolean;\n}\n\n/**\n * Calculate PageRank for all nodes in the graph\n *\n * Uses delta-based optimization by default for improved performance on larger graphs.\n * Automatically falls back to standard algorithm for very small graphs.\n *\n * The delta-based approach provides significant speedup for:\n * - Incremental updates after graph modifications\n * - Graphs with localized changes\n * - Early convergence detection per vertex\n *\n * For initial computation on small-medium graphs, standard algorithm may be faster\n * due to lower overhead.\n */\nexport function pageRank(\n graph: Graph,\n options: PageRankOptions = {},\n): PageRankResult {\n const {\n dampingFactor = 0.85,\n maxIterations = 100,\n tolerance = 1e-6,\n initialRanks,\n personalization,\n weight,\n } = options;\n\n if (!graph.isDirected) {\n throw new Error(\"PageRank requires a directed graph\");\n }\n\n if (dampingFactor < 0 || dampingFactor > 1) {\n throw new Error(\"Damping factor must be between 0 and 1\");\n }\n\n const nodes = Array.from(graph.nodes()).map((node) => node.id);\n const n = nodes.length;\n\n if (n === 0) {\n return {ranks: {}, iterations: 0, converged: true};\n }\n\n // Use delta-based optimization by default for larger graphs\n // Only disable if explicitly requested or graph is very small (overhead dominates)\n const shouldUseDelta = options.useDelta !== false && n > 100;\n\n if (shouldUseDelta) {\n // Use optimized delta-based implementation\n\n const deltaOptions: {\n dampingFactor: number;\n tolerance: number;\n maxIterations: number;\n personalization?: Map<NodeId, number>;\n weight?: string;\n } = {\n dampingFactor,\n tolerance,\n maxIterations,\n };\n\n if (personalization) {\n deltaOptions.personalization = personalization;\n }\n\n if (weight) {\n deltaOptions.weight = weight;\n }\n\n const deltaPageRank = new SimpleDeltaPageRank(graph);\n const deltaRanks = deltaPageRank.compute(deltaOptions);\n\n // Convert to string-keyed record\n const result: Record<string, number> = {};\n for (const [nodeId, rank] of deltaRanks) {\n result[String(nodeId)] = rank;\n }\n\n return {\n ranks: result,\n iterations: maxIterations, // For now, assume we used all iterations\n converged: true,\n };\n }\n\n // Initialize PageRank values\n let ranks = new Map<NodeId, number>();\n if (initialRanks) {\n for (const nodeId of nodes) {\n ranks.set(nodeId, initialRanks.get(nodeId) ?? 1 / n);\n }\n } else {\n for (const nodeId of nodes) {\n ranks.set(nodeId, 1 / n);\n }\n }\n\n // Normalize initial ranks\n normalizeRanks(ranks);\n\n // Calculate out-degrees and handle dangling nodes\n const outDegrees = new Map<NodeId, number>();\n const outWeights = new Map<NodeId, number>();\n const danglingNodes: NodeId[] = [];\n\n for (const nodeId of nodes) {\n let outDegree = 0;\n let totalOutWeight = 0;\n\n for (const neighbor of Array.from(graph.neighbors(nodeId))) {\n outDegree++;\n if (weight) {\n const edge = graph.getEdge(nodeId, neighbor);\n const edgeWeight = edge?.weight ?? 1;\n totalOutWeight += edgeWeight;\n } else {\n totalOutWeight += 1;\n }\n }\n\n outDegrees.set(nodeId, outDegree);\n outWeights.set(nodeId, totalOutWeight);\n\n if (outDegree === 0) {\n danglingNodes.push(nodeId);\n }\n }\n\n // Setup personalization vector\n let personalVector: Map<NodeId, number> | null = null;\n if (personalization) {\n personalVector = new Map(personalization);\n normalizeRanks(personalVector);\n }\n\n let converged = false;\n let iteration = 0;\n\n // Power iteration\n for (iteration = 0; iteration < maxIterations; iteration++) {\n const newRanks = new Map<NodeId, number>();\n\n // Initialize with teleportation probability\n for (const nodeId of nodes) {\n if (personalVector) {\n newRanks.set(nodeId, (1 - dampingFactor) * (personalVector.get(nodeId) ?? 0));\n } else {\n newRanks.set(nodeId, (1 - dampingFactor) / n);\n }\n }\n\n // Handle dangling nodes\n let danglingSum = 0;\n for (const danglingNode of danglingNodes) {\n danglingSum += ranks.get(danglingNode) ?? 0;\n }\n\n if (danglingSum > 0) {\n const danglingContribution = dampingFactor * danglingSum / n;\n for (const nodeId of nodes) {\n const currentRank = newRanks.get(nodeId) ?? 0;\n if (personalVector) {\n const personalContrib = danglingContribution * (personalVector.get(nodeId) ?? 0);\n newRanks.set(nodeId, currentRank + personalContrib);\n } else {\n newRanks.set(nodeId, currentRank + danglingContribution);\n }\n }\n }\n\n // Propagate rank from each node to its neighbors\n for (const nodeId of nodes) {\n const currentRank = ranks.get(nodeId) ?? 0;\n const nodeOutWeight = outWeights.get(nodeId) ?? 0;\n\n if (nodeOutWeight > 0) {\n for (const neighbor of Array.from(graph.neighbors(nodeId))) {\n let edgeWeight = 1;\n if (weight) {\n const edge = graph.getEdge(nodeId, neighbor);\n edgeWeight = edge?.weight ?? 1;\n }\n\n const contribution = dampingFactor * currentRank * (edgeWeight / nodeOutWeight);\n const neighborRank = newRanks.get(neighbor) ?? 0;\n newRanks.set(neighbor, neighborRank + contribution);\n }\n }\n }\n\n // Check for convergence\n let maxDiff = 0;\n for (const nodeId of nodes) {\n const oldRank = ranks.get(nodeId) ?? 0;\n const newRank = newRanks.get(nodeId) ?? 0;\n maxDiff = Math.max(maxDiff, Math.abs(newRank - oldRank));\n }\n\n ranks = newRanks;\n\n if (maxDiff < tolerance) {\n converged = true;\n break;\n }\n }\n\n // Convert to string-keyed record\n const result: Record<string, number> = {};\n for (const nodeId of nodes) {\n result[String(nodeId)] = ranks.get(nodeId) ?? 0;\n }\n\n return {\n ranks: result,\n iterations: iteration + 1,\n converged,\n };\n}\n\n/**\n * Calculate Personalized PageRank for a specific set of source nodes\n */\nexport function personalizedPageRank(\n graph: Graph,\n personalNodes: NodeId[],\n options: Omit<PageRankOptions, \"personalization\"> = {},\n): PageRankResult {\n // Handle empty personal nodes by falling back to standard PageRank\n if (personalNodes.length === 0) {\n return pageRank(graph, options);\n }\n\n const nodes = Array.from(graph.nodes()).map((node) => node.id);\n const personalization = new Map<NodeId, number>();\n\n // Initialize personalization vector\n for (const nodeId of nodes) {\n personalization.set(nodeId, 0);\n }\n\n // Set equal probability for personal nodes\n const personalValue = 1 / personalNodes.length;\n for (const personalNode of personalNodes) {\n if (!graph.hasNode(personalNode)) {\n throw new Error(`Personal node ${String(personalNode)} not found in graph`);\n }\n\n personalization.set(personalNode, personalValue);\n }\n\n return pageRank(graph, {\n ... options,\n personalization,\n });\n}\n\n/**\n * Calculate PageRank centrality (normalized PageRank scores)\n */\nexport function pageRankCentrality(\n graph: Graph,\n options: PageRankOptions = {},\n): Record<string, number> {\n const result = pageRank(graph, options);\n return result.ranks;\n}\n\n/**\n * Get the top-k nodes by PageRank score\n */\nexport function topPageRankNodes(\n graph: Graph,\n k: number,\n options: PageRankOptions = {},\n): {node: NodeId, rank: number}[] {\n const result = pageRank(graph, options);\n\n const nodeRanks: {node: NodeId, rank: number}[] = [];\n for (const [nodeStr, rank] of Object.entries(result.ranks)) {\n nodeRanks.push({node: nodeStr as NodeId, rank});\n }\n\n // Sort by rank in descending order\n nodeRanks.sort((a, b) => b.rank - a.rank);\n\n return nodeRanks.slice(0, k);\n}\n\n/**\n * Normalize ranks so they sum to 1\n */\nfunction normalizeRanks(ranks: Map<NodeId, number>): void {\n let sum = 0;\n for (const rank of ranks.values()) {\n sum += rank;\n }\n\n if (sum > 0) {\n for (const [nodeId, rank] of Array.from(ranks)) {\n ranks.set(nodeId, rank / sum);\n }\n }\n}\n","import type {NodeId} from \"../types/index.js\";\n\n/**\n * Union-Find (Disjoint Set) data structure with path compression and union by rank\n *\n * Efficiently supports dynamic connectivity queries and is essential for\n * algorithms like connected components and minimum spanning trees.\n */\nexport class UnionFind {\n private parent: Map<NodeId, NodeId>;\n private rank: Map<NodeId, number>;\n private componentCount: number;\n\n constructor(elements: NodeId[]) {\n this.parent = new Map();\n this.rank = new Map();\n this.componentCount = elements.length;\n\n // Initialize each element as its own parent with rank 0\n for (const element of elements) {\n this.parent.set(element, element);\n this.rank.set(element, 0);\n }\n }\n\n /**\n * Find the root of the set containing the element with path compression\n */\n find(element: NodeId): NodeId {\n const parent = this.parent.get(element);\n\n if (parent === undefined) {\n throw new Error(`Element ${String(element)} not found in UnionFind`);\n }\n\n // Path compression: make every node on the path point directly to the root\n if (parent !== element) {\n this.parent.set(element, this.find(parent));\n }\n\n const result = this.parent.get(element);\n if (result === undefined) {\n throw new Error(`Element ${String(element)} not found in UnionFind`);\n }\n\n return result;\n }\n\n /**\n * Union two sets using union by rank\n */\n union(elementA: NodeId, elementB: NodeId): void {\n const rootA = this.find(elementA);\n const rootB = this.find(elementB);\n\n // Already in the same set\n if (rootA === rootB) {\n return;\n }\n\n const rankA = this.rank.get(rootA);\n const rankB = this.rank.get(rootB);\n if (rankA === undefined || rankB === undefined) {\n throw new Error(\"Rank not found for root elements\");\n }\n\n // Union by rank: attach smaller tree under root of larger tree\n if (rankA < rankB) {\n this.parent.set(rootA, rootB);\n } else if (rankA > rankB) {\n this.parent.set(rootB, rootA);\n } else {\n // Same rank: make one root and increment its rank\n this.parent.set(rootB, rootA);\n this.rank.set(rootA, rankA + 1);\n }\n\n this.componentCount--;\n }\n\n /**\n * Check if two elements are in the same connected component\n */\n connected(elementA: NodeId, elementB: NodeId): boolean {\n try {\n return this.find(elementA) === this.find(elementB);\n } catch {\n return false;\n }\n }\n\n /**\n * Get the number of connected components\n */\n getComponentCount(): number {\n return this.componentCount;\n }\n\n /**\n * Get all elements that belong to the same component as the given element\n */\n getComponent(element: NodeId): NodeId[] {\n const root = this.find(element);\n const component: NodeId[] = [];\n\n for (const [node] of Array.from(this.parent)) {\n if (this.find(node) === root) {\n component.push(node);\n }\n }\n\n return component;\n }\n\n /**\n * Get all connected components as separate arrays\n */\n getAllComponents(): NodeId[][] {\n const componentMap = new Map<NodeId, NodeId[]>();\n\n for (const [node] of Array.from(this.parent)) {\n const root = this.find(node);\n\n if (!componentMap.has(root)) {\n componentMap.set(root, []);\n }\n\n const component = componentMap.get(root);\n if (component) {\n component.push(node);\n }\n }\n\n return Array.from(componentMap.values());\n }\n\n /**\n * Get the size of the component containing the given element\n */\n getComponentSize(element: NodeId): number {\n return this.getComponent(element).length;\n }\n\n /**\n * Add a new element to the data structure\n */\n addElement(element: NodeId): void {\n if (this.parent.has(element)) {\n return; // Element already exists\n }\n\n this.parent.set(element, element);\n this.rank.set(element, 0);\n this.componentCount++;\n }\n\n /**\n * Check if an element exists in the data structure\n */\n hasElement(element: NodeId): boolean {\n return this.parent.has(element);\n }\n\n /**\n * Get the total number of elements\n */\n size(): number {\n return this.parent.size;\n }\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport {UnionFind} from \"../../data-structures/union-find.js\";\nimport type {NodeId} from \"../../types/index.js\";\n\n/**\n * Connected components algorithms\n *\n * Finds connected components in undirected graphs and strongly connected\n * components in directed graphs using various efficient algorithms.\n */\n\n/**\n * Find connected components in an undirected graph using Union-Find\n */\nexport function connectedComponents(graph: Graph): NodeId[][] {\n if (graph.isDirected) {\n throw new Error(\"Connected components algorithm requires an undirected graph. Use stronglyConnectedComponents for directed graphs.\");\n }\n\n const nodes = Array.from(graph.nodes()).map((node) => node.id);\n\n if (nodes.length === 0) {\n return [];\n }\n\n const unionFind = new UnionFind(nodes);\n\n // Union connected nodes\n for (const edge of Array.from(graph.edges())) {\n unionFind.union(edge.source, edge.target);\n }\n\n return unionFind.getAllComponents();\n}\n\n/**\n * Find connected components using DFS (alternative implementation)\n */\nexport function connectedComponentsDFS(graph: Graph): NodeId[][] {\n if (graph.isDirected) {\n throw new Error(\"Connected components algorithm requires an undirected graph\");\n }\n\n const visited = new Set<NodeId>();\n const components: NodeId[][] = [];\n\n for (const node of Array.from(graph.nodes())) {\n if (!visited.has(node.id)) {\n const component: NodeId[] = [];\n dfsComponent(graph, node.id, visited, component);\n components.push(component);\n }\n }\n\n return components;\n}\n\n/**\n * DFS helper for connected components\n */\nfunction dfsComponent(\n graph: Graph,\n nodeId: NodeId,\n visited: Set<NodeId>,\n component: NodeId[],\n): void {\n visited.add(nodeId);\n component.push(nodeId);\n\n for (const neighbor of Array.from(graph.neighbors(nodeId))) {\n if (!visited.has(neighbor)) {\n dfsComponent(graph, neighbor, visited, component);\n }\n }\n}\n\n/**\n * Find the number of connected components\n */\nexport function numberOfConnectedComponents(graph: Graph): number {\n return connectedComponents(graph).length;\n}\n\n/**\n * Check if the graph is connected (has exactly one connected component)\n */\nexport function isConnected(graph: Graph): boolean {\n return numberOfConnectedComponents(graph) <= 1;\n}\n\n/**\n * Find the largest connected component\n */\nexport function largestConnectedComponent(graph: Graph): NodeId[] {\n const components = connectedComponents(graph);\n\n if (components.length === 0) {\n return [];\n }\n\n return components.reduce((largest, current) =>\n current.length > largest.length ? current : largest,\n );\n}\n\n/**\n * Get the connected component containing a specific node\n */\nexport function getConnectedComponent(graph: Graph, nodeId: NodeId): NodeId[] {\n if (!graph.hasNode(nodeId)) {\n throw new Error(`Node ${String(nodeId)} not found in graph`);\n }\n\n if (graph.isDirected) {\n throw new Error(\"Connected components algorithm requires an undirected graph\");\n }\n\n const visited = new Set<NodeId>();\n const component: NodeId[] = [];\n\n dfsComponent(graph, nodeId, visited, component);\n\n return component;\n}\n\n/**\n * Find strongly connected components using Tarjan's algorithm\n */\nexport function stronglyConnectedComponents(graph: Graph): NodeId[][] {\n if (!graph.isDirected) {\n throw new Error(\"Strongly connected components require a directed graph\");\n }\n\n const nodes = Array.from(graph.nodes()).map((node) => node.id);\n const components: NodeId[][] = [];\n const indices = new Map<NodeId, number>();\n const lowLinks = new Map<NodeId, number>();\n const onStack = new Set<NodeId>();\n const stack: NodeId[] = [];\n let index = 0;\n\n function tarjanSCC(nodeId: NodeId): void {\n // Set the depth index for this node\n indices.set(nodeId, index);\n lowLinks.set(nodeId, index);\n index++;\n stack.push(nodeId);\n onStack.add(nodeId);\n\n // Consider successors\n for (const neighbor of Array.from(graph.neighbors(nodeId))) {\n if (!indices.has(neighbor)) {\n // Successor has not yet been visited; recurse on it\n tarjanSCC(neighbor);\n const nodeLL = lowLinks.get(nodeId) ?? 0;\n const neighborLL = lowLinks.get(neighbor) ?? 0;\n lowLinks.set(nodeId, Math.min(nodeLL, neighborLL));\n } else if (onStack.has(neighbor)) {\n // Successor is in stack and hence in the current SCC\n const nodeLL = lowLinks.get(nodeId) ?? 0;\n const neighborIndex = indices.get(neighbor) ?? 0;\n lowLinks.set(nodeId, Math.min(nodeLL, neighborIndex));\n }\n }\n\n // If nodeId is a root node, pop the stack and create an SCC\n const nodeIndex = indices.get(nodeId) ?? 0;\n const nodeLowLink = lowLinks.get(nodeId) ?? 0;\n\n if (nodeLowLink === nodeIndex) {\n const component: NodeId[] = [];\n let w: NodeId;\n\n do {\n const popped = stack.pop();\n if (popped === undefined) {\n break;\n }\n\n w = popped;\n\n onStack.delete(w);\n component.push(w);\n } while (w !== nodeId);\n\n components.push(component);\n }\n }\n\n for (const nodeId of nodes) {\n if (!indices.has(nodeId)) {\n tarjanSCC(nodeId);\n }\n }\n\n return components;\n}\n\n/**\n * Check if a directed graph is strongly connected\n */\nexport function isStronglyConnected(graph: Graph): boolean {\n if (!graph.isDirected) {\n throw new Error(\"Strong connectivity check requires a directed graph\");\n }\n\n const components = stronglyConnectedComponents(graph);\n return components.length <= 1;\n}\n\n/**\n * Find weakly connected components in a directed graph\n * (treat the graph as undirected for connectivity)\n */\nexport function weaklyConnectedComponents(graph: Graph): NodeId[][] {\n if (!graph.isDirected) {\n throw new Error(\"Weakly connected components are for directed graphs. Use connectedComponents for undirected graphs.\");\n }\n\n const nodes = Array.from(graph.nodes()).map((node) => node.id);\n\n if (nodes.length === 0) {\n return [];\n }\n\n const unionFind = new UnionFind(nodes);\n\n // Union nodes connected by edges (ignore direction)\n for (const edge of Array.from(graph.edges())) {\n unionFind.union(edge.source, edge.target);\n }\n\n return unionFind.getAllComponents();\n}\n\n/**\n * Check if a directed graph is weakly connected\n */\nexport function isWeaklyConnected(graph: Graph): boolean {\n if (!graph.isDirected) {\n throw new Error(\"Weak connectivity check requires a directed graph\");\n }\n\n return weaklyConnectedComponents(graph).length <= 1;\n}\n\n/**\n * Find condensation graph (quotient graph of strongly connected components)\n */\nexport function condensationGraph(graph: Graph): {\n condensedGraph: Graph;\n componentMap: Map<NodeId, number>;\n components: NodeId[][];\n} {\n if (!graph.isDirected) {\n throw new Error(\"Condensation graph requires a directed graph\");\n }\n\n const components = stronglyConnectedComponents(graph);\n const componentMap = new Map<NodeId, number>();\n const condensedGraph = new (graph.constructor as new (config: {directed: boolean}) => Graph)({directed: true});\n\n // Map each node to its component index\n for (let i = 0; i < components.length; i++) {\n const component = components[i];\n if (component) {\n for (const nodeId of component) {\n componentMap.set(nodeId, i);\n }\n // Add component as a node in condensed graph\n condensedGraph.addNode(i);\n }\n }\n\n // Add edges between components\n const addedEdges = new Set<string>();\n\n for (const edge of Array.from(graph.edges())) {\n const sourceComponent = componentMap.get(edge.source);\n const targetComponent = componentMap.get(edge.target);\n\n if (sourceComponent !== undefined && targetComponent !== undefined &&\n sourceComponent !== targetComponent) {\n const edgeKey = `${String(sourceComponent)}-${String(targetComponent)}`;\n\n if (!addedEdges.has(edgeKey)) {\n condensedGraph.addEdge(sourceComponent, targetComponent);\n addedEdges.add(edgeKey);\n }\n }\n }\n\n return {\n condensedGraph,\n componentMap,\n components,\n };\n}\n","import {Graph} from \"../../core/graph.js\";\nimport {UnionFind} from \"../../data-structures/union-find.js\";\nimport type {Edge} from \"../../types/index.js\";\n\nexport interface MSTResult {\n edges: Edge[];\n totalWeight: number;\n}\n\nexport function kruskalMST(graph: Graph): MSTResult {\n if (graph.isDirected) {\n throw new Error(\"Kruskal's algorithm requires an undirected graph\");\n }\n\n const edges: Edge[] = [];\n const visitedEdges = new Set<string>();\n\n for (const edge of Array.from(graph.edges())) {\n const edgeKey = edge.source < edge.target ?\n `${String(edge.source)}-${String(edge.target)}` :\n `${String(edge.target)}-${String(edge.source)}`;\n\n if (!visitedEdges.has(edgeKey)) {\n visitedEdges.add(edgeKey);\n edges.push(edge);\n }\n }\n\n edges.sort((a, b) => (a.weight ?? 0) - (b.weight ?? 0));\n\n const nodes = Array.from(graph.nodes()).map((n) => n.id);\n const uf = new UnionFind(nodes);\n\n const mstEdges: Edge[] = [];\n let totalWeight = 0;\n\n for (const edge of edges) {\n if (!uf.connected(edge.source, edge.target)) {\n uf.union(edge.source, edge.target);\n mstEdges.push(edge);\n totalWeight += edge.weight ?? 0;\n\n if (mstEdges.length === graph.nodeCount - 1) {\n break;\n }\n }\n }\n\n if (mstEdges.length !== graph.nodeCount - 1) {\n throw new Error(\"Graph is not connected\");\n }\n\n return {\n edges: mstEdges,\n totalWeight,\n };\n}\n\nexport function minimumSpanningTree(graph: Graph): MSTResult {\n return kruskalMST(graph);\n}\n","import {Graph} from \"../../core/graph.js\";\nimport {PriorityQueue} from \"../../data-structures/priority-queue.js\";\nimport type {Edge, NodeId} from \"../../types/index.js\";\nimport type {MSTResult} from \"./kruskal.js\";\n\nexport function primMST(graph: Graph, startNode?: NodeId): MSTResult {\n if (graph.isDirected) {\n throw new Error(\"Prim's algorithm requires an undirected graph\");\n }\n\n const nodes = Array.from(graph.nodes());\n if (nodes.length === 0) {\n return {\n edges: [],\n totalWeight: 0,\n };\n }\n\n const start = startNode ?? nodes[0]?.id;\n if (!start) {\n return {\n edges: [],\n totalWeight: 0,\n };\n }\n\n if (!graph.hasNode(start)) {\n throw new Error(`Start node ${String(start)} not found in graph`);\n }\n\n const visited = new Set<NodeId>();\n const mstEdges: Edge[] = [];\n let totalWeight = 0;\n\n const pq = new PriorityQueue<Edge>();\n\n visited.add(start);\n\n for (const neighbor of Array.from(graph.neighbors(start))) {\n const edge = graph.getEdge(start, neighbor);\n if (edge) {\n pq.enqueue(edge, edge.weight ?? 0);\n }\n }\n\n while (!pq.isEmpty() && mstEdges.length < graph.nodeCount - 1) {\n const edge = pq.dequeue();\n if (!edge) {\n continue;\n }\n\n const unvisitedNode = visited.has(edge.source) ? edge.target : edge.source;\n\n if (visited.has(unvisitedNode)) {\n continue;\n }\n\n visited.add(unvisitedNode);\n mstEdges.push(edge);\n totalWeight += edge.weight ?? 0;\n\n for (const neighbor of Array.from(graph.neighbors(unvisitedNode))) {\n if (!visited.has(neighbor)) {\n const neighborEdge = graph.getEdge(unvisitedNode, neighbor);\n if (neighborEdge) {\n pq.enqueue(neighborEdge, neighborEdge.weight ?? 0);\n }\n }\n }\n }\n\n if (mstEdges.length !== graph.nodeCount - 1) {\n throw new Error(\"Graph is not connected\");\n }\n\n return {\n edges: mstEdges,\n totalWeight,\n };\n}\n","import {Graph} from \"../../core/graph.js\";\nimport type {CommunityResult, ComponentResult, GirvanNewmanOptions, NodeId} from \"../../types/index.js\";\nimport {connectedComponents} from \"../components/connected.js\";\n\n/**\n * Girvan-Newman community detection algorithm\n *\n * Implements the Girvan-Newman method for community detection by iteratively\n * removing edges with the highest betweenness centrality until the graph\n * splits into disconnected components.\n *\n * This is a divisive hierarchical clustering algorithm that produces a\n * dendrogram of community structures.\n *\n * References:\n * - Girvan, M., & Newman, M. E. J. (2002). Community structure in social\n * and biological networks. Proceedings of the National Academy of Sciences,\n * 99(12), 7821-7826.\n *\n * @param graph - The input graph\n * @param options - Algorithm options\n * @returns Array of community detection results representing the dendrogram\n */\nexport function girvanNewman(\n graph: Graph,\n options: GirvanNewmanOptions = {},\n): CommunityResult[] {\n const {maxCommunities} = options;\n const minCommunitySize = options.minCommunitySize ?? 1;\n const maxIterations = options.maxIterations ?? 100; // Prevent infinite loops\n\n const dendrogram: CommunityResult[] = [];\n const workingGraph = graph.clone();\n let iterations = 0;\n\n // Initial state: one large component\n let components = getConnectedComponentsResult(workingGraph);\n dendrogram.push({\n communities: components.components.filter((community) => community.length >= minCommunitySize),\n modularity: calculateModularity(graph, components.componentMap),\n });\n\n while (Array.from(workingGraph.edges()).length > 0 && iterations < maxIterations) {\n iterations++;\n // Calculate edge betweenness centrality\n const edgeBetweenness = calculateEdgeBetweenness(workingGraph);\n\n if (edgeBetweenness.size === 0) {\n break;\n }\n\n // Find edges with maximum betweenness\n const maxBetweenness = Math.max(... edgeBetweenness.values());\n const edgesToRemove: {source: NodeId, target: NodeId}[] = [];\n\n for (const [edgeKey, centrality] of edgeBetweenness) {\n if (Math.abs(centrality - maxBetweenness) < 1e-10) {\n const [source, target] = edgeKey.split(\"|\");\n if (source && target) {\n edgesToRemove.push({source, target});\n }\n }\n }\n\n // Remove edges with highest betweenness\n for (const {source, target} of edgesToRemove) {\n workingGraph.removeEdge(source, target);\n }\n\n // Find new connected components (communities)\n components = getConnectedComponentsResult(workingGraph);\n\n // Filter communities by minimum size\n const validCommunities = components.components.filter(\n (community) => community.length >= minCommunitySize,\n );\n\n // Calculate modularity for the new community structure\n const modularity = calculateModularity(graph, components.componentMap);\n\n dendrogram.push({\n communities: validCommunities,\n modularity,\n });\n\n // Stop if desired number of communities reached\n if (maxCommunities && validCommunities.length >= maxCommunities) {\n break;\n }\n\n // Stop if no more meaningful communities can be formed\n if (validCommunities.length === workingGraph.nodeCount) {\n break;\n }\n }\n\n return dendrogram;\n}\n\n/**\n * Calculate edge betweenness centrality for all edges in the graph\n *\n * Edge betweenness is the fraction of shortest paths that pass through the edge.\n * We adapt node betweenness centrality calculation to work with edges.\n */\nfunction calculateEdgeBetweenness(graph: Graph): Map<string, number> {\n const edgeBetweenness = new Map<string, number>();\n\n // Initialize all edges with 0 betweenness\n for (const edge of graph.edges()) {\n const edgeKey = getEdgeKey(edge.source, edge.target);\n edgeBetweenness.set(edgeKey, 0);\n }\n\n // For each node as source, calculate shortest paths and accumulate edge betweenness\n for (const sourceNode of graph.nodes()) {\n const source = sourceNode.id;\n\n // Run BFS to find all shortest paths from source\n const {distances, predecessors, pathCounts} = findAllShortestPaths(graph, source);\n\n // Calculate dependency for each node and accumulate edge betweenness\n const dependency = new Map<NodeId, number>();\n\n // Initialize dependency\n for (const node of graph.nodes()) {\n dependency.set(node.id, 0);\n }\n\n // Process nodes in order of decreasing distance\n const sortedNodes = Array.from(distances.keys())\n .filter((node) => {\n const distance = distances.get(node);\n return distance !== undefined && distance < Infinity;\n })\n .sort((a, b) => {\n const distanceA = distances.get(a);\n const distanceB = distances.get(b);\n if (distanceA === undefined || distanceB === undefined) {\n return 0;\n }\n\n return distanceB - distanceA;\n });\n\n for (const node of sortedNodes) {\n if (node === source) {\n continue;\n }\n\n const nodeDependency = dependency.get(node);\n const nodePathCount = pathCounts.get(node);\n\n if (nodeDependency === undefined || nodePathCount === undefined) {\n continue;\n }\n\n // Distribute dependency to predecessors\n const nodePredecessors = predecessors.get(node) ?? [];\n for (const predecessor of nodePredecessors) {\n const predPathCount = pathCounts.get(predecessor);\n if (predPathCount === undefined) {\n continue;\n }\n\n const edgeDependency = (predPathCount / nodePathCount) * (1 + nodeDependency);\n\n // Update predecessor dependency\n const currentDependency = dependency.get(predecessor);\n if (currentDependency !== undefined) {\n dependency.set(predecessor, currentDependency + edgeDependency);\n }\n\n // Update edge betweenness\n const edgeKey = getEdgeKey(predecessor, node);\n const currentBetweenness = edgeBetweenness.get(edgeKey) ?? 0;\n edgeBetweenness.set(edgeKey, currentBetweenness + edgeDependency);\n }\n }\n }\n\n // Normalize: divide by 2 for undirected graphs (each edge counted twice)\n if (!graph.isDirected) {\n for (const [edgeKey, betweenness] of edgeBetweenness) {\n edgeBetweenness.set(edgeKey, betweenness / 2);\n }\n }\n\n return edgeBetweenness;\n}\n\n/**\n * Find all shortest paths from a source node using optimized BFS\n */\nfunction findAllShortestPaths(graph: Graph, source: NodeId): {\n distances: Map<NodeId, number>;\n predecessors: Map<NodeId, NodeId[]>;\n pathCounts: Map<NodeId, number>;\n} {\n const distances = new Map<NodeId, number>();\n const predecessors = new Map<NodeId, NodeId[]>();\n const pathCounts = new Map<NodeId, number>();\n const queue: NodeId[] = [];\n const visited = new Set<NodeId>();\n\n // Only initialize for reachable nodes\n distances.set(source, 0);\n predecessors.set(source, []);\n pathCounts.set(source, 1);\n queue.push(source);\n\n // Optimized BFS with early termination\n let queueIndex = 0;\n while (queueIndex < queue.length) {\n const current = queue[queueIndex++];\n if (!current) {\n continue;\n }\n\n if (visited.has(current)) {\n continue;\n }\n\n visited.add(current);\n\n const currentDistance = distances.get(current);\n if (currentDistance === undefined) {\n continue;\n }\n\n for (const neighbor of graph.neighbors(current)) {\n // Skip if already processed\n if (visited.has(neighbor)) {\n continue;\n }\n\n const edgeWeight = 1; // Unweighted for community detection\n const newDistance = currentDistance + edgeWeight;\n const neighborDistance = distances.get(neighbor) ?? Infinity;\n\n if (newDistance < neighborDistance) {\n // Found shorter path\n distances.set(neighbor, newDistance);\n predecessors.set(neighbor, [current]);\n const currentPathCount = pathCounts.get(current);\n if (currentPathCount !== undefined) {\n pathCounts.set(neighbor, currentPathCount);\n }\n\n queue.push(neighbor);\n } else if (newDistance === neighborDistance) {\n // Found alternative shortest path\n const neighborPredecessors = predecessors.get(neighbor);\n if (neighborPredecessors) {\n neighborPredecessors.push(current);\n const currentPathCount = pathCounts.get(current);\n if (currentPathCount !== undefined) {\n pathCounts.set(neighbor, (pathCounts.get(neighbor) ?? 0) + currentPathCount);\n }\n }\n }\n }\n }\n\n return {distances, predecessors, pathCounts};\n}\n\n/**\n * Generate a consistent edge key for undirected graphs\n */\nfunction getEdgeKey(source: NodeId, target: NodeId): string {\n // For undirected graphs, ensure consistent ordering\n const sourceStr = String(source);\n const targetStr = String(target);\n\n if (sourceStr <= targetStr) {\n return `${sourceStr}|${targetStr}`;\n }\n\n return `${targetStr}|${sourceStr}`;\n}\n\n/**\n * Calculate modularity for a given community structure - optimized version\n */\nfunction calculateModularity(\n graph: Graph,\n communityMap: Map<NodeId, number>,\n): number {\n const totalEdgeWeight = getTotalEdgeWeight(graph);\n if (totalEdgeWeight === 0) {\n return 0;\n }\n\n let modularity = 0;\n const degrees = new Map<NodeId, number>();\n\n // Pre-calculate all degrees\n for (const node of graph.nodes()) {\n degrees.set(node.id, getNodeDegree(graph, node.id));\n }\n\n // Only iterate over existing edges\n for (const edge of graph.edges()) {\n const communityI = communityMap.get(edge.source);\n const communityJ = communityMap.get(edge.target);\n\n if (communityI === communityJ) {\n const edgeWeight = edge.weight ?? 1;\n const degreeI = degrees.get(edge.source);\n const degreeJ = degrees.get(edge.target);\n if (degreeI === undefined || degreeJ === undefined) {\n continue;\n }\n\n modularity += edgeWeight - ((degreeI * degreeJ) / (2 * totalEdgeWeight));\n }\n }\n\n return modularity / (2 * totalEdgeWeight);\n}\n\n/**\n * Calculate total edge weight in the graph\n */\nfunction getTotalEdgeWeight(graph: Graph): number {\n let totalWeight = 0;\n\n for (const edge of graph.edges()) {\n totalWeight += edge.weight ?? 1;\n }\n\n return totalWeight;\n}\n\n/**\n * Get the total degree (sum of edge weights) for a node\n */\nfunction getNodeDegree(graph: Graph, nodeId: NodeId): number {\n let degree = 0;\n\n for (const neighbor of graph.neighbors(nodeId)) {\n const edge = graph.getEdge(nodeId, neighbor);\n degree += edge?.weight ?? 1;\n }\n\n return degree;\n}\n\n/**\n * Convert connected components result to ComponentResult format\n */\nfunction getConnectedComponentsResult(graph: Graph): ComponentResult {\n const components = connectedComponents(graph);\n const componentMap = new Map<NodeId, number>();\n\n components.forEach((component, index) => {\n component.forEach((nodeId) => {\n componentMap.set(nodeId, index);\n });\n });\n\n return {components, componentMap};\n}\n\n","import {Graph} from \"../core/graph.js\";\nimport type {NodeId} from \"../types/index.js\";\n\n/**\n * Convert Graph class to Map representation\n * Used by community detection and flow algorithms\n */\nexport function graphToMap(graph: Graph): Map<string, Map<string, number>> {\n const map = new Map<string, Map<string, number>>();\n\n // Initialize all nodes\n for (const node of graph.nodes()) {\n map.set(String(node.id), new Map());\n }\n\n // Add edges with weights\n for (const edge of graph.edges()) {\n const source = String(edge.source);\n const target = String(edge.target);\n const weight = edge.weight ?? 1;\n\n const sourceMap = map.get(source);\n if (sourceMap) {\n sourceMap.set(target, weight);\n }\n\n // For undirected graphs, add reverse edge\n if (!graph.isDirected) {\n const targetMap = map.get(target);\n if (targetMap) {\n targetMap.set(source, weight);\n }\n }\n }\n\n return map;\n}\n\n/**\n * Convert Map representation to Graph class\n */\nexport function mapToGraph(\n map: Map<string, Map<string, number>>,\n isDirected = true,\n): Graph {\n const graph = new Graph({directed: isDirected});\n\n // Add all nodes first\n for (const node of map.keys()) {\n graph.addNode(node);\n }\n\n // Add edges\n const processedEdges = new Set<string>();\n\n for (const [source, neighbors] of map) {\n for (const [target, weight] of neighbors) {\n const edgeKey = isDirected ? `${source}->${target}` : [source, target].sort().join(\"-\");\n\n // Skip if we've already processed this edge (for undirected graphs)\n if (!isDirected && processedEdges.has(edgeKey)) {\n continue;\n }\n\n graph.addEdge(source, target, weight);\n processedEdges.add(edgeKey);\n }\n }\n\n return graph;\n}\n\n/**\n * Adapter for using Graph algorithms with Map representation\n * Implements a subset of Graph interface methods needed by algorithms\n */\nexport class GraphAdapter {\n private map: Map<string, Map<string, number>>;\n public readonly isDirected: boolean;\n\n constructor(map: Map<string, Map<string, number>>, isDirected = true) {\n this.map = map;\n this.isDirected = isDirected;\n }\n\n /**\n * Get all nodes\n */\n nodes(): {id: NodeId}[] {\n return Array.from(this.map.keys()).map((id) => ({id}));\n }\n\n /**\n * Get node count\n */\n get nodeCount(): number {\n return this.map.size;\n }\n\n /**\n * Check if node exists\n */\n hasNode(nodeId: NodeId): boolean {\n return this.map.has(String(nodeId));\n }\n\n /**\n * Get neighbors of a node\n */\n neighbors(nodeId: NodeId): NodeId[] {\n const neighbors = this.map.get(String(nodeId));\n if (!neighbors) {\n return [];\n }\n\n return Array.from(neighbors.keys());\n }\n\n /**\n * Get edge between two nodes\n */\n getEdge(source: NodeId, target: NodeId): {source: NodeId, target: NodeId, weight?: number} | null {\n const sourceNeighbors = this.map.get(String(source));\n if (!sourceNeighbors) {\n return null;\n }\n\n const weight = sourceNeighbors.get(String(target));\n if (weight === undefined) {\n return null;\n }\n\n return {source, target, weight};\n }\n\n /**\n * Check if edge exists\n */\n hasEdge(source: NodeId, target: NodeId): boolean {\n const sourceNeighbors = this.map.get(String(source));\n if (!sourceNeighbors) {\n return false;\n }\n\n return sourceNeighbors.has(String(target));\n }\n\n /**\n * Get all edges\n */\n edges(): {source: NodeId, target: NodeId, weight?: number}[] {\n const edges: {source: NodeId, target: NodeId, weight?: number}[] = [];\n const processedEdges = new Set<string>();\n\n for (const [source, neighbors] of this.map) {\n for (const [target, weight] of neighbors) {\n const edgeKey = this.isDirected ? `${source}->${target}` : [source, target].sort().join(\"-\");\n\n // Skip if we've already processed this edge (for undirected graphs)\n if (!this.isDirected && processedEdges.has(edgeKey)) {\n continue;\n }\n\n edges.push({source, target, weight});\n processedEdges.add(edgeKey);\n }\n }\n\n return edges;\n }\n\n /**\n * Get edge count\n */\n get edgeCount(): number {\n if (this.isDirected) {\n let count = 0;\n for (const neighbors of this.map.values()) {\n count += neighbors.size;\n }\n return count;\n }\n\n // For undirected graphs, count each edge once\n let count = 0;\n const counted = new Set<string>();\n\n for (const [source, neighbors] of this.map) {\n for (const target of neighbors.keys()) {\n const edgeKey = [source, target].sort().join(\"-\");\n if (!counted.has(edgeKey)) {\n counted.add(edgeKey);\n count++;\n }\n }\n }\n return count;\n }\n\n /**\n * Get node degree\n */\n degree(nodeId: NodeId): number {\n const neighbors = this.map.get(String(nodeId));\n return neighbors ? neighbors.size : 0;\n }\n\n /**\n * Get in-degree (for directed graphs)\n */\n inDegree(nodeId: NodeId): number {\n if (!this.isDirected) {\n return this.degree(nodeId);\n }\n\n let count = 0;\n const targetId = String(nodeId);\n\n for (const neighbors of this.map.values()) {\n if (neighbors.has(targetId)) {\n count++;\n }\n }\n\n return count;\n }\n\n /**\n * Get out-degree (for directed graphs)\n */\n outDegree(nodeId: NodeId): number {\n return this.degree(nodeId);\n }\n\n /**\n * Get underlying map representation\n */\n getMap(): Map<string, Map<string, number>> {\n return this.map;\n }\n}\n","/**\n * Seeded random number generator for reproducible results\n */\nexport class SeededRandom {\n private seed: number;\n private readonly m = 0x80000000; // 2**31\n private readonly a = 1103515245;\n private readonly c = 12345;\n\n constructor(seed: number) {\n // Handle negative seeds correctly\n this.seed = ((seed % this.m) + this.m) % this.m;\n }\n\n /**\n * Generate next random number between 0 and 1\n */\n next(): number {\n this.seed = ((this.a * this.seed) + this.c) % this.m;\n return this.seed / (this.m - 1);\n }\n\n /**\n * Create a generator function for backward compatibility\n */\n static createGenerator(seed: number): () => number {\n const rng = new SeededRandom(seed);\n return () => rng.next();\n }\n}\n\n/**\n * Fisher-Yates shuffle algorithm\n * @param array - Array to shuffle (will be modified in place)\n * @param rng - Optional random number generator (defaults to Math.random)\n * @returns The shuffled array (same reference as input)\n */\nexport function shuffle<T>(array: T[], rng: () => number = Math.random): T[] {\n for (let i = array.length - 1; i > 0; i--) {\n const j = Math.floor(rng() * (i + 1));\n const temp = array[i];\n const tempJ = array[j];\n if (temp !== undefined && tempJ !== undefined) {\n array[i] = tempJ;\n array[j] = temp;\n }\n }\n return array;\n}\n\n/**\n * Calculate Euclidean distance between two vectors\n * @param a - First vector\n * @param b - Second vector\n * @returns Euclidean distance\n * @throws Error if vectors have different lengths\n */\nexport function euclideanDistance(a: number[], b: number[]): number {\n if (a.length !== b.length) {\n throw new Error(\"Vectors must have same length\");\n }\n\n let sum = 0;\n for (let i = 0; i < a.length; i++) {\n const aVal = a[i];\n const bVal = b[i];\n if (aVal !== undefined && bVal !== undefined) {\n const diff = aVal - bVal;\n sum += diff * diff;\n }\n }\n return Math.sqrt(sum);\n}\n\nexport const normalize = {\n /**\n * Min-max normalization to [0, 1] range\n */\n minMax(values: Map<string, number>): void {\n const vals = Array.from(values.values());\n const min = Math.min(... vals);\n const max = Math.max(... vals);\n const range = max - min;\n\n if (range === 0) {\n return;\n }\n\n for (const [key, value] of values) {\n values.set(key, (value - min) / range);\n }\n },\n\n /**\n * Normalize by maximum value\n */\n byMax(values: Map<string, number>): void {\n const max = Math.max(... values.values());\n if (max === 0) {\n return;\n }\n\n for (const [key, value] of values) {\n values.set(key, value / max);\n }\n },\n\n /**\n * L2 (Euclidean) normalization\n */\n l2Norm(values: Map<string, number>): void {\n const sumSquares = Array.from(values.values())\n .reduce((sum, val) => sum + (val * val), 0);\n const norm = Math.sqrt(sumSquares);\n\n if (norm === 0) {\n return;\n }\n\n for (const [key, value] of values) {\n values.set(key, value / norm);\n }\n },\n\n /**\n * Normalize to sum to 1\n */\n sumToOne(values: Map<string, number>): void {\n const sum = Array.from(values.values())\n .reduce((acc, val) => acc + val, 0);\n\n if (sum === 0) {\n return;\n }\n\n for (const [key, value] of values) {\n values.set(key, value / sum);\n }\n },\n};\n","/**\n * Label Propagation Algorithm for Community Detection\n *\n * A fast, near-linear time algorithm that detects communities by\n * propagating labels through the network. Each node adopts the label\n * that most of its neighbors have.\n *\n * Reference: Raghavan et al. (2007) \"Near linear time algorithm to\n * detect community structures in large-scale networks\"\n */\n\nimport type {Graph} from \"../../core/graph.js\";\nimport {graphToMap} from \"../../utils/graph-converters.js\";\nimport {SeededRandom, shuffle} from \"../../utils/math-utilities.js\";\n\nexport interface LabelPropagationOptions {\n maxIterations?: number;\n randomSeed?: number;\n}\n\nexport interface LabelPropagationResult {\n communities: Map<string, number>;\n iterations: number;\n converged: boolean;\n}\n\n/**\n * Internal implementation of Label Propagation Algorithm\n */\nfunction labelPropagationImpl(\n graph: Map<string, Map<string, number>>,\n options: LabelPropagationOptions = {},\n): LabelPropagationResult {\n const {\n maxIterations = 100,\n randomSeed = 42,\n } = options;\n\n if (graph.size === 0) {\n return {\n communities: new Map(),\n iterations: 0,\n converged: true,\n };\n }\n\n // Initialize random number generator\n const random = SeededRandom.createGenerator(randomSeed);\n\n // Initialize labels - each node gets its own label\n const labels = new Map<string, number>();\n const nodes = Array.from(graph.keys());\n nodes.forEach((node, i) => labels.set(node, i));\n\n let iterations = 0;\n let converged = false;\n\n // Main loop\n while (iterations < maxIterations && !converged) {\n iterations++;\n converged = true;\n\n // Create random order for node updates\n const nodeOrder = [... nodes];\n shuffle(nodeOrder, random);\n\n // Update each node's label\n for (const node of nodeOrder) {\n const neighbors = graph.get(node);\n if (!neighbors || neighbors.size === 0) {\n continue;\n }\n\n // Count label frequencies among neighbors\n const labelCounts = new Map<number, number>();\n let maxCount = 0;\n const candidateLabels: number[] = [];\n\n for (const [neighbor, weight] of neighbors) {\n const neighborLabel = labels.get(neighbor);\n if (neighborLabel === undefined) {\n continue;\n }\n\n const count = (labelCounts.get(neighborLabel) ?? 0) + weight;\n labelCounts.set(neighborLabel, count);\n\n if (count > maxCount) {\n maxCount = count;\n candidateLabels.length = 0;\n candidateLabels.push(neighborLabel);\n } else if (count === maxCount) {\n candidateLabels.push(neighborLabel);\n }\n }\n\n // Choose label (break ties randomly)\n const currentLabel = labels.get(node);\n if (currentLabel === undefined) {\n continue;\n }\n\n let newLabel = currentLabel;\n\n if (candidateLabels.length > 0) {\n // Include current label if it has max count\n if (labelCounts.get(currentLabel) === maxCount) {\n candidateLabels.push(currentLabel);\n }\n\n // Random selection from candidates\n const index = Math.floor(random() * candidateLabels.length);\n const selectedLabel = candidateLabels[index];\n if (selectedLabel !== undefined) {\n newLabel = selectedLabel;\n }\n }\n\n // Update label if changed\n if (newLabel !== currentLabel) {\n labels.set(node, newLabel);\n converged = false;\n }\n }\n }\n\n // Renumber communities consecutively\n const uniqueLabels = new Set(labels.values());\n const labelMap = new Map<number, number>();\n let communityId = 0;\n\n for (const label of uniqueLabels) {\n labelMap.set(label, communityId++);\n }\n\n const communities = new Map<string, number>();\n for (const [node, label] of labels) {\n const mappedLabel = labelMap.get(label);\n if (mappedLabel !== undefined) {\n communities.set(node, mappedLabel);\n }\n }\n\n return {\n communities,\n iterations,\n converged,\n };\n}\n\n/**\n * Internal implementation of Asynchronous Label Propagation\n * Updates all nodes simultaneously (can lead to oscillations)\n */\nfunction labelPropagationAsyncImpl(\n graph: Map<string, Map<string, number>>,\n options: LabelPropagationOptions = {},\n): LabelPropagationResult {\n const {\n maxIterations = 100,\n } = options;\n\n if (graph.size === 0) {\n return {\n communities: new Map(),\n iterations: 0,\n converged: true,\n };\n }\n\n // Initialize labels\n const labels = new Map<string, number>();\n const nodes = Array.from(graph.keys());\n nodes.forEach((node, i) => labels.set(node, i));\n\n let iterations = 0;\n let converged = false;\n\n // Main loop\n while (iterations < maxIterations && !converged) {\n iterations++;\n converged = true;\n\n // Store new labels\n const newLabels = new Map<string, number>();\n\n // Update all nodes simultaneously\n for (const node of nodes) {\n const neighbors = graph.get(node);\n if (!neighbors || neighbors.size === 0) {\n const nodeLabel = labels.get(node);\n if (nodeLabel !== undefined) {\n newLabels.set(node, nodeLabel);\n }\n\n continue;\n }\n\n // Count label frequencies\n const labelCounts = new Map<number, number>();\n let maxCount = 0;\n const nodeLabel = labels.get(node);\n if (nodeLabel === undefined) {\n continue;\n }\n\n let maxLabel = nodeLabel;\n\n for (const [neighbor, weight] of neighbors) {\n const neighborLabel = labels.get(neighbor);\n if (neighborLabel === undefined) {\n continue;\n }\n\n const count = (labelCounts.get(neighborLabel) ?? 0) + weight;\n labelCounts.set(neighborLabel, count);\n\n if (count > maxCount || (count === maxCount && neighborLabel < maxLabel)) {\n maxCount = count;\n maxLabel = neighborLabel;\n }\n }\n\n newLabels.set(node, maxLabel);\n\n if (maxLabel !== labels.get(node)) {\n converged = false;\n }\n }\n\n // Apply new labels\n for (const [node, label] of newLabels) {\n labels.set(node, label);\n }\n }\n\n // Renumber communities\n const uniqueLabels = new Set(labels.values());\n const labelMap = new Map<number, number>();\n let communityId = 0;\n\n for (const label of uniqueLabels) {\n labelMap.set(label, communityId++);\n }\n\n const communities = new Map<string, number>();\n for (const [node, label] of labels) {\n const mappedLabel = labelMap.get(label);\n if (mappedLabel !== undefined) {\n communities.set(node, mappedLabel);\n }\n }\n\n return {\n communities,\n iterations,\n converged,\n };\n}\n\n/**\n * Internal implementation of Semi-supervised Label Propagation\n * Some nodes have fixed labels that don't change\n */\nfunction labelPropagationSemiSupervisedImpl(\n graph: Map<string, Map<string, number>>,\n seedLabels: Map<string, number>,\n options: LabelPropagationOptions = {},\n): LabelPropagationResult {\n const {\n maxIterations = 100,\n randomSeed = 42,\n } = options;\n\n // Initialize random number generator\n const random = SeededRandom.createGenerator(randomSeed);\n\n // Initialize labels\n const labels = new Map<string, number>();\n const nodes = Array.from(graph.keys());\n let labelCounter = Math.max(... Array.from(seedLabels.values())) + 1;\n\n for (const node of nodes) {\n if (seedLabels.has(node)) {\n const seedLabel = seedLabels.get(node);\n if (seedLabel !== undefined) {\n labels.set(node, seedLabel);\n }\n } else {\n labels.set(node, labelCounter++);\n }\n }\n\n let iterations = 0;\n let converged = false;\n\n // Main loop\n while (iterations < maxIterations && !converged) {\n iterations++;\n converged = true;\n\n // Create random order\n const nodeOrder = nodes.filter((n) => !seedLabels.has(n));\n shuffle(nodeOrder, random);\n\n // Update non-seed nodes\n for (const node of nodeOrder) {\n const neighbors = graph.get(node);\n if (!neighbors || neighbors.size === 0) {\n continue;\n }\n\n // Count label frequencies\n const labelCounts = new Map<number, number>();\n let maxCount = 0;\n const candidateLabels: number[] = [];\n\n for (const [neighbor, weight] of neighbors) {\n const neighborLabel = labels.get(neighbor);\n if (neighborLabel === undefined) {\n continue;\n }\n\n const count = (labelCounts.get(neighborLabel) ?? 0) + weight;\n labelCounts.set(neighborLabel, count);\n\n if (count > maxCount) {\n maxCount = count;\n candidateLabels.length = 0;\n candidateLabels.push(neighborLabel);\n } else if (count === maxCount) {\n candidateLabels.push(neighborLabel);\n }\n }\n\n // Choose label\n const currentLabel = labels.get(node);\n if (currentLabel === undefined) {\n continue;\n }\n\n let newLabel = currentLabel;\n\n if (candidateLabels.length > 0) {\n const index = Math.floor(random() * candidateLabels.length);\n const selectedLabel = candidateLabels[index];\n if (selectedLabel !== undefined) {\n newLabel = selectedLabel;\n }\n }\n\n if (newLabel !== currentLabel) {\n labels.set(node, newLabel);\n converged = false;\n }\n }\n }\n\n return {\n communities: labels,\n iterations,\n converged,\n };\n}\n\n/**\n * Label Propagation Algorithm\n * Each node adopts the most frequent label among its neighbors\n *\n * @param graph - Undirected graph (can be weighted)\n * @param options - Algorithm options\n * @returns Community assignments\n *\n * Time Complexity: O(m) per iteration, typically O(km) for k iterations\n * Space Complexity: O(n)\n */\nexport function labelPropagation(\n graph: Graph,\n options: LabelPropagationOptions = {},\n): LabelPropagationResult {\n // Convert Graph to Map representation\n const graphMap = graphToMap(graph);\n return labelPropagationImpl(graphMap, options);\n}\n\n/**\n * Asynchronous Label Propagation\n * Updates all nodes simultaneously (can lead to oscillations)\n *\n * @param graph - Undirected graph (can be weighted)\n * @param options - Algorithm options\n * @returns Community assignments\n */\nexport function labelPropagationAsync(\n graph: Graph,\n options: LabelPropagationOptions = {},\n): LabelPropagationResult {\n // Convert Graph to Map representation\n const graphMap = graphToMap(graph);\n return labelPropagationAsyncImpl(graphMap, options);\n}\n\n/**\n * Semi-supervised Label Propagation\n * Some nodes have fixed labels that don't change\n *\n * @param graph - Undirected graph (can be weighted)\n * @param seedLabels - Initial fixed labels for some nodes\n * @param options - Algorithm options\n * @returns Community assignments\n */\nexport function labelPropagationSemiSupervised(\n graph: Graph,\n seedLabels: Map<string, number>,\n options: LabelPropagationOptions = {},\n): LabelPropagationResult {\n // Convert Graph to Map representation\n const graphMap = graphToMap(graph);\n return labelPropagationSemiSupervisedImpl(graphMap, seedLabels, options);\n}\n\n","/**\n * Leiden Algorithm for Community Detection\n *\n * An improved version of the Louvain algorithm that guarantees\n * well-connected communities and provides better quality partitions.\n *\n * Reference: Traag, V.A., Waltman, L. & van Eck, N.J. (2019)\n * \"From Louvain to Leiden: guaranteeing well-connected communities\"\n */\n\nimport type {Graph} from \"../../core/graph.js\";\nimport {graphToMap} from \"../../utils/graph-converters.js\";\nimport {SeededRandom, shuffle} from \"../../utils/math-utilities.js\";\n\nexport interface LeidenOptions {\n resolution?: number;\n randomSeed?: number;\n maxIterations?: number;\n threshold?: number;\n}\n\nexport interface LeidenResult {\n communities: Map<string, number>;\n modularity: number;\n iterations: number;\n}\n\n/**\n * Internal implementation of Leiden algorithm for community detection\n * Improves upon Louvain by ensuring well-connected communities\n */\nfunction leidenImpl(\n inputGraph: Map<string, Map<string, number>>,\n options: LeidenOptions = {},\n): LeidenResult {\n const {\n resolution = 1.0,\n randomSeed = 42,\n maxIterations = 100,\n threshold = 1e-7,\n } = options;\n\n // Handle empty graph\n if (inputGraph.size === 0) {\n return {\n communities: new Map(),\n modularity: 0,\n iterations: 0,\n };\n }\n\n // Use a mutable variable for the current graph state\n let currentGraph = inputGraph;\n\n // Initialize random number generator\n const random = SeededRandom.createGenerator(randomSeed);\n\n // Calculate total weight\n let totalWeight = 0;\n const degrees = new Map<string, number>();\n\n for (const [node, neighbors] of currentGraph) {\n let degree = 0;\n for (const weight of neighbors.values()) {\n degree += weight;\n totalWeight += weight;\n }\n degrees.set(node, degree);\n }\n totalWeight /= 2; // Each edge counted twice\n\n // Initialize communities - each node in its own community\n const communities = new Map<string, number>();\n const nodes = Array.from(currentGraph.keys());\n nodes.forEach((node, i) => communities.set(node, i));\n\n let modularity = calculateModularity(currentGraph, communities, degrees, totalWeight, resolution);\n let bestModularity = modularity;\n let bestCommunities = new Map(communities);\n let iterations = 0;\n\n // Main Leiden loop\n while (iterations < maxIterations) {\n iterations++;\n let improved = false;\n\n // Phase 1: Local moving of nodes (fast)\n const nodeOrder = [... nodes];\n shuffle(nodeOrder, random);\n\n for (const node of nodeOrder) {\n const currentCommunity = communities.get(node);\n if (currentCommunity === undefined) {\n continue;\n }\n\n const neighborCommunities = getNeighborCommunities(node, currentGraph, communities);\n\n let bestCommunity = currentCommunity;\n let bestGain = 0;\n\n // Try moving to each neighbor community\n for (const [community] of neighborCommunities) {\n if (community === currentCommunity) {\n continue;\n }\n\n const gain = calculateModularityGain(\n node, community, currentGraph, communities, degrees, totalWeight, resolution,\n );\n\n if (gain > bestGain) {\n bestGain = gain;\n bestCommunity = community;\n }\n }\n\n // Move node if beneficial\n if (bestCommunity !== currentCommunity) {\n communities.set(node, bestCommunity);\n modularity += bestGain;\n improved = true;\n }\n }\n\n // Phase 2: Refinement (Leiden improvement over Louvain)\n // Create aggregate network based on current partition\n createAggregateNetwork(currentGraph, communities);\n\n // Refine partition using aggregate network\n const subsetPartition = refinePartition(\n currentGraph, communities,\n );\n\n // Apply refined partition\n for (const [node, newCommunity] of subsetPartition) {\n communities.set(node, newCommunity);\n }\n\n // Recalculate modularity\n modularity = calculateModularity(currentGraph, communities, degrees, totalWeight, resolution);\n\n // Check if we've improved\n if (modularity > bestModularity + threshold) {\n bestModularity = modularity;\n bestCommunities = new Map(communities);\n improved = true;\n }\n\n if (!improved) {\n break;\n }\n\n // Phase 3: Aggregate network (create super-nodes)\n const aggregated = aggregateCommunities(currentGraph, communities);\n if (aggregated.graph.size === currentGraph.size) {\n break;\n } // No aggregation possible\n\n // Continue with aggregated network\n const {graph: aggregatedGraph} = aggregated;\n currentGraph = aggregatedGraph;\n communities.clear();\n let communityId = 0;\n for (const node of currentGraph.keys()) {\n communities.set(node, communityId++);\n }\n }\n\n // Map back to original nodes\n const finalCommunities = new Map<string, number>();\n for (const [node, community] of bestCommunities) {\n finalCommunities.set(node, community);\n }\n\n // Renumber communities consecutively\n const communityRenumber = new Map<number, number>();\n let newId = 0;\n for (const community of new Set(finalCommunities.values())) {\n communityRenumber.set(community, newId++);\n }\n for (const [node, community] of finalCommunities) {\n const newCommunityId = communityRenumber.get(community);\n if (newCommunityId !== undefined) {\n finalCommunities.set(node, newCommunityId);\n }\n }\n\n return {\n communities: finalCommunities,\n modularity: bestModularity,\n iterations,\n };\n}\n\n/**\n * Calculate modularity of a partition\n */\nfunction calculateModularity(\n graph: Map<string, Map<string, number>>,\n communities: Map<string, number>,\n degrees: Map<string, number>,\n totalWeight: number,\n resolution: number,\n): number {\n let modularity = 0;\n const communityWeights = new Map<number, number>();\n\n // Calculate internal weights for each community\n for (const [node, neighbors] of graph) {\n const nodeCommunity = communities.get(node);\n if (nodeCommunity === undefined) {\n continue;\n }\n\n for (const [neighbor, weight] of neighbors) {\n const neighborCommunity = communities.get(neighbor);\n if (neighborCommunity === undefined) {\n continue;\n }\n\n if (nodeCommunity === neighborCommunity) {\n modularity += weight;\n }\n }\n\n const degree = degrees.get(node);\n if (degree !== undefined) {\n communityWeights.set(nodeCommunity, (communityWeights.get(nodeCommunity) ?? 0) + degree);\n }\n }\n\n // Handle empty graph or zero weight\n if (totalWeight === 0) {\n return 0;\n }\n\n // Normalize and apply resolution\n modularity /= (2 * totalWeight);\n\n // Subtract expected edges\n for (const weight of communityWeights.values()) {\n modularity -= resolution * ((weight / (2 * totalWeight)) ** 2);\n }\n\n return modularity;\n}\n\n/**\n * Get communities of neighbors\n */\nfunction getNeighborCommunities(\n node: string,\n graph: Map<string, Map<string, number>>,\n communities: Map<string, number>,\n): Map<number, number> {\n const neighborCommunities = new Map<number, number>();\n const neighbors = graph.get(node);\n\n if (neighbors) {\n for (const [neighbor, weight] of neighbors) {\n const community = communities.get(neighbor);\n if (community !== undefined) {\n neighborCommunities.set(community, (neighborCommunities.get(community) ?? 0) + weight);\n }\n }\n }\n\n return neighborCommunities;\n}\n\n/**\n * Calculate modularity gain from moving a node to a community\n */\nfunction calculateModularityGain(\n node: string,\n targetCommunity: number,\n graph: Map<string, Map<string, number>>,\n communities: Map<string, number>,\n degrees: Map<string, number>,\n totalWeight: number,\n resolution: number,\n): number {\n const currentCommunity = communities.get(node);\n const nodeDegree = degrees.get(node);\n if (currentCommunity === undefined || nodeDegree === undefined) {\n return 0;\n }\n\n // Weight of edges from node to target community\n let weightToTarget = 0;\n let weightToCurrent = 0;\n\n const neighbors = graph.get(node);\n if (neighbors) {\n for (const [neighbor, weight] of neighbors) {\n const neighborCommunity = communities.get(neighbor);\n if (neighborCommunity === undefined) {\n continue;\n }\n\n if (neighborCommunity === targetCommunity) {\n weightToTarget += weight;\n } else if (neighborCommunity === currentCommunity && neighbor !== node) {\n weightToCurrent += weight;\n }\n }\n }\n\n // Calculate community degrees\n let targetDegree = 0;\n let currentDegree = 0;\n\n for (const [n, c] of communities) {\n if (c === targetCommunity && n !== node) {\n const deg = degrees.get(n);\n if (deg !== undefined) {\n targetDegree += deg;\n }\n } else if (c === currentCommunity && n !== node) {\n const deg = degrees.get(n);\n if (deg !== undefined) {\n currentDegree += deg;\n }\n }\n }\n\n // Modularity gain calculation\n const m2 = 2 * totalWeight;\n const gain = ((weightToTarget - weightToCurrent) / totalWeight) -\n (resolution * nodeDegree * (targetDegree - currentDegree) / (m2 * m2));\n\n return gain;\n}\n\n/**\n * Create aggregate network where each community becomes a super-node\n */\nfunction createAggregateNetwork(\n graph: Map<string, Map<string, number>>,\n communities: Map<string, number>,\n): {\n aggregateGraph: Map<number, Map<number, number>>;\n nodeMapping: Map<string, number>;\n } {\n const aggregateGraph = new Map<number, Map<number, number>>();\n const nodeMapping = new Map<string, number>();\n\n // Create mapping from nodes to communities\n for (const [node, community] of communities) {\n nodeMapping.set(node, community);\n if (!aggregateGraph.has(community)) {\n aggregateGraph.set(community, new Map());\n }\n }\n\n // Aggregate edges\n for (const [node, neighbors] of graph) {\n const sourceCommunity = communities.get(node);\n if (sourceCommunity === undefined) {\n continue;\n }\n\n for (const [neighbor, weight] of neighbors) {\n const targetCommunity = communities.get(neighbor);\n if (targetCommunity === undefined) {\n continue;\n }\n\n const sourceNeighbors = aggregateGraph.get(sourceCommunity);\n if (sourceNeighbors) {\n const current = sourceNeighbors.get(targetCommunity) ?? 0;\n sourceNeighbors.set(targetCommunity, current + weight);\n }\n }\n }\n\n return {aggregateGraph, nodeMapping};\n}\n\n/**\n * Refine partition (Leiden-specific improvement)\n * Ensures well-connected communities by considering subsets\n */\nfunction refinePartition(\n originalGraph: Map<string, Map<string, number>>,\n communities: Map<string, number>,\n): Map<string, number> {\n const refined = new Map<string, number>();\n\n // For each community, check if it should be split\n const communityNodes = new Map<number, string[]>();\n for (const [node, community] of communities) {\n if (!communityNodes.has(community)) {\n communityNodes.set(community, []);\n }\n\n const nodes = communityNodes.get(community);\n if (nodes) {\n nodes.push(node);\n }\n }\n\n let newCommunityId = 0;\n\n for (const [community, nodes] of communityNodes) {\n if (nodes.length === 1) {\n // Single node community\n const singleNode = nodes[0];\n if (singleNode) {\n refined.set(singleNode, newCommunityId++);\n }\n\n continue;\n }\n\n // Check connectivity within community\n const subgraph = new Map<string, Set<string>>();\n for (const node of nodes) {\n subgraph.set(node, new Set());\n const neighbors = originalGraph.get(node);\n if (neighbors) {\n for (const [neighbor] of neighbors) {\n if (communities.get(neighbor) === community) {\n const nodeSet = subgraph.get(node);\n if (nodeSet) {\n nodeSet.add(neighbor);\n }\n }\n }\n }\n }\n\n // Find connected components within community\n const components = findConnectedComponents(subgraph);\n\n // Assign new community IDs to components\n for (const component of components) {\n for (const node of component) {\n refined.set(node, newCommunityId);\n }\n newCommunityId++;\n }\n }\n\n return refined;\n}\n\n/**\n * Find connected components in undirected graph\n */\nfunction findConnectedComponents(graph: Map<string, Set<string>>): Set<string>[] {\n const visited = new Set<string>();\n const components: Set<string>[] = [];\n\n for (const node of graph.keys()) {\n if (!visited.has(node)) {\n const component = new Set<string>();\n const queue = [node];\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (current === undefined || visited.has(current)) {\n continue;\n }\n\n visited.add(current);\n component.add(current);\n\n const neighbors = graph.get(current);\n if (neighbors) {\n for (const neighbor of neighbors) {\n if (!visited.has(neighbor)) {\n queue.push(neighbor);\n }\n }\n }\n }\n\n components.push(component);\n }\n }\n\n return components;\n}\n\n/**\n * Aggregate communities into super-nodes\n */\nfunction aggregateCommunities(\n graph: Map<string, Map<string, number>>,\n communities: Map<string, number>,\n): {\n graph: Map<string, Map<string, number>>;\n mapping: Map<string, string>;\n } {\n const aggregated = new Map<string, Map<string, number>>();\n const mapping = new Map<string, string>();\n\n // Create super-nodes\n const communityNodes = new Map<number, string>();\n for (const community of new Set(communities.values())) {\n const superNode = `super_${String(community)}`;\n communityNodes.set(community, superNode);\n aggregated.set(superNode, new Map());\n }\n\n // Map original nodes to super-nodes\n for (const [node, community] of communities) {\n const superNode = communityNodes.get(community);\n if (superNode !== undefined) {\n mapping.set(node, superNode);\n }\n }\n\n // Aggregate edges\n for (const [node, neighbors] of graph) {\n const sourceCommunity = communities.get(node);\n if (sourceCommunity === undefined) {\n continue;\n }\n\n const sourceSuper = communityNodes.get(sourceCommunity);\n if (sourceSuper === undefined) {\n continue;\n }\n\n for (const [neighbor, weight] of neighbors) {\n const targetCommunity = communities.get(neighbor);\n if (targetCommunity === undefined) {\n continue;\n }\n\n const targetSuper = communityNodes.get(targetCommunity);\n if (targetSuper === undefined) {\n continue;\n }\n\n if (sourceSuper !== targetSuper) {\n const sourceNeighbors = aggregated.get(sourceSuper);\n if (sourceNeighbors) {\n const current = sourceNeighbors.get(targetSuper) ?? 0;\n sourceNeighbors.set(targetSuper, current + weight);\n }\n }\n }\n }\n\n return {graph: aggregated, mapping};\n}\n\n/**\n * Leiden algorithm for community detection\n * Improves upon Louvain by ensuring well-connected communities\n *\n * @param graph - Undirected weighted graph - accepts Graph class or Map representation\n * @param options - Algorithm options\n * @returns Community assignments and modularity\n *\n * Time Complexity: O(m) per iteration, typically O(m log m) total\n * Space Complexity: O(n + m)\n */\nexport function leiden(\n graph: Graph,\n options: LeidenOptions = {},\n): LeidenResult {\n // Convert Graph to Map representation\n const graphMap = graphToMap(graph);\n return leidenImpl(graphMap, options);\n}\n\n","import type {Graph} from \"../../core/graph.js\";\nimport type {CommunityResult, NodeId} from \"../../types/index.js\";\n\n/**\n * Optimized Louvain community detection algorithm with early pruning and threshold cycling\n *\n * Key optimizations:\n * - Leaf node pruning: Skip nodes with degree 1\n * - Importance ordering: Process high-impact nodes first\n * - Threshold cycling: Adaptive convergence thresholds\n * - Early termination: Stop when changes become insignificant\n *\n * Expected speedup: 2-5x on large graphs with many leaf nodes\n */\n\nexport interface OptimizedLouvainOptions {\n /**\n * Resolution parameter (default: 1.0)\n */\n resolution?: number;\n /**\n * Maximum iterations per level (default: 100)\n */\n maxIterations?: number;\n /**\n * Convergence tolerance (default: 1e-6)\n */\n tolerance?: number;\n /**\n * Enable leaf node pruning (default: true)\n */\n pruneLeaves?: boolean;\n /**\n * Enable importance-based node ordering (default: true)\n */\n importanceOrdering?: boolean;\n /**\n * Base pruning threshold (default: 0.01)\n */\n pruningThreshold?: number;\n /**\n * Enable adaptive threshold cycling (default: true)\n */\n thresholdCycling?: boolean;\n}\n\ninterface PruningStats {\n leafNodesPruned: number;\n lowDegreeNodesPruned: number;\n stableNodesPruned: number;\n}\n\nexport class OptimizedLouvain {\n private graph: Graph;\n private communities: Map<NodeId, number>;\n private communityWeights: Map<number, number>;\n private nodeWeights: Map<NodeId, number>;\n private nodeDegrees: Map<NodeId, number>;\n private totalWeight: number;\n private pruningStats: PruningStats;\n\n constructor(graph: Graph) {\n this.graph = graph;\n this.communities = new Map();\n this.communityWeights = new Map();\n this.nodeWeights = new Map();\n this.nodeDegrees = new Map();\n this.totalWeight = 0;\n this.pruningStats = {\n leafNodesPruned: 0,\n lowDegreeNodesPruned: 0,\n stableNodesPruned: 0,\n };\n }\n\n /**\n * Run optimized Louvain algorithm\n */\n public detectCommunities(options: OptimizedLouvainOptions = {}): CommunityResult {\n const {\n resolution = 1.0,\n maxIterations = 100,\n tolerance = 1e-6,\n pruneLeaves = true,\n importanceOrdering = true,\n pruningThreshold = 0.01,\n thresholdCycling = true,\n } = options;\n\n // Initialize\n this.initialize();\n let modularity = this.calculateModularity(resolution);\n let iteration = 0;\n let improved = true;\n\n while (iteration < maxIterations && improved) {\n // Get nodes in optimal processing order\n const orderedNodes = importanceOrdering ?\n this.getNodesInImportanceOrder() :\n Array.from(this.graph.nodes()).map((n) => n.id);\n\n // Apply adaptive threshold\n const threshold = thresholdCycling ?\n this.getAdaptiveThreshold(iteration, pruningThreshold) :\n 0;\n\n // Perform local optimization\n improved = this.performLocalMoving(orderedNodes, {\n pruneLeaves,\n threshold,\n resolution,\n });\n\n if (improved) {\n const newModularity = this.calculateModularity(resolution);\n\n // Check convergence\n if (Math.abs(newModularity - modularity) < tolerance) {\n break;\n }\n\n modularity = newModularity;\n iteration++;\n }\n }\n\n // Convert community assignments to result format\n const communityGroups = new Map<number, NodeId[]>();\n\n for (const [nodeId, community] of this.communities) {\n if (!communityGroups.has(community)) {\n communityGroups.set(community, []);\n }\n\n const group = communityGroups.get(community);\n if (group) {\n group.push(nodeId);\n }\n }\n\n return {\n communities: Array.from(communityGroups.values()),\n modularity,\n iterations: iteration,\n };\n }\n\n /**\n * Initialize data structures\n */\n private initialize(): void {\n let communityId = 0;\n\n // Initialize each node in its own community\n for (const node of this.graph.nodes()) {\n this.communities.set(node.id, communityId);\n\n // Calculate node weight and degree\n let nodeWeight = 0;\n let degree = 0;\n\n for (const neighbor of Array.from(this.graph.neighbors(node.id))) {\n const edge = this.graph.getEdge(node.id, neighbor);\n const weight = edge?.weight ?? 1;\n nodeWeight += weight;\n degree++;\n }\n\n // For undirected graphs, also check incoming edges\n if (!this.graph.isDirected) {\n for (const neighbor of Array.from(this.graph.inNeighbors(node.id))) {\n if (!this.graph.hasEdge(node.id, neighbor)) {\n const edge = this.graph.getEdge(neighbor, node.id);\n const weight = edge?.weight ?? 1;\n nodeWeight += weight;\n degree++;\n }\n }\n }\n\n this.nodeWeights.set(node.id, nodeWeight);\n this.nodeDegrees.set(node.id, degree);\n this.communityWeights.set(communityId, nodeWeight);\n this.totalWeight += nodeWeight;\n\n communityId++;\n }\n\n // Total weight is sum of all edge weights\n // For undirected graphs, each edge is counted twice from both endpoints\n this.totalWeight = this.totalWeight / 2;\n }\n\n /**\n * Get nodes ordered by importance (degree * log(weight))\n */\n private getNodesInImportanceOrder(): NodeId[] {\n const nodeImportance = new Map<NodeId, number>();\n\n for (const [nodeId, degree] of this.nodeDegrees) {\n const weight = this.nodeWeights.get(nodeId) ?? 0;\n // Importance score: combination of degree and weight\n // High-degree nodes and nodes with heavy edges are processed first\n const importance = degree * Math.log(1 + weight);\n nodeImportance.set(nodeId, importance);\n }\n\n // Sort by importance (descending)\n return Array.from(nodeImportance.entries())\n .sort((a, b) => b[1] - a[1])\n .map(([nodeId]) => nodeId);\n }\n\n /**\n * Perform local moving phase with optimizations\n */\n private performLocalMoving(\n nodes: NodeId[],\n options: {\n pruneLeaves: boolean;\n threshold: number;\n resolution: number;\n },\n ): boolean {\n const {pruneLeaves, threshold, resolution} = options;\n let improvement = false;\n let hasChanged = true;\n\n while (hasChanged) {\n hasChanged = false;\n\n for (const nodeId of nodes) {\n // Early pruning: skip leaf nodes\n if (pruneLeaves && this.isLeafNode(nodeId)) {\n this.pruningStats.leafNodesPruned++;\n continue;\n }\n\n const currentCommunity = this.communities.get(nodeId) ?? 0;\n const neighborCommunities = this.getNeighborCommunities(nodeId);\n\n // Skip isolated nodes\n if (neighborCommunities.size === 0) {\n continue;\n }\n\n // Find best community to move to\n let bestCommunity = currentCommunity;\n let bestGain = 0;\n\n // Remove node from its current community to calculate gains\n this.removeNodeFromCommunity(nodeId, currentCommunity);\n\n for (const community of neighborCommunities) {\n const gain = this.calculateModularityGain(nodeId, community, resolution);\n\n // Apply threshold - only move if gain exceeds threshold\n if (gain > bestGain + threshold) {\n bestGain = gain;\n bestCommunity = community;\n }\n }\n\n // Try staying in current community\n const currentGain = this.calculateModularityGain(nodeId, currentCommunity, resolution);\n if (currentGain > bestGain + threshold) {\n bestGain = currentGain;\n bestCommunity = currentCommunity;\n }\n\n // Add node to best community\n this.addNodeToCommunity(nodeId, bestCommunity);\n\n // Track if node moved\n if (bestCommunity !== currentCommunity) {\n hasChanged = true;\n improvement = true;\n }\n }\n }\n\n return improvement;\n }\n\n /**\n * Check if node is a leaf (degree 1)\n */\n private isLeafNode(nodeId: NodeId): boolean {\n const degree = this.nodeDegrees.get(nodeId) ?? 0;\n return degree === 1;\n }\n\n /**\n * Get adaptive threshold that decreases with iterations\n */\n private getAdaptiveThreshold(iteration: number, baseThreshold: number): number {\n // Exponentially decay threshold with iterations\n // This allows coarse movements early and fine-tuning later\n return baseThreshold * Math.pow(0.5, iteration / 10);\n }\n\n /**\n * Calculate modularity gain from moving a node to a community\n */\n private calculateModularityGain(\n nodeId: NodeId,\n targetCommunity: number,\n resolution: number,\n ): number {\n const nodeWeight = this.nodeWeights.get(nodeId) ?? 0;\n\n // Sum of weights from node to target community\n let weightToTarget = 0;\n\n for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {\n if (this.communities.get(neighbor) === targetCommunity) {\n const edge = this.graph.getEdge(nodeId, neighbor);\n weightToTarget += edge?.weight ?? 1;\n }\n }\n\n // For undirected graphs, also check incoming edges\n if (!this.graph.isDirected) {\n for (const neighbor of Array.from(this.graph.inNeighbors(nodeId))) {\n if (this.communities.get(neighbor) === targetCommunity && !this.graph.hasEdge(nodeId, neighbor)) {\n const edge = this.graph.getEdge(neighbor, nodeId);\n weightToTarget += edge?.weight ?? 1;\n }\n }\n }\n\n // Weight of target community\n const targetWeight = this.communityWeights.get(targetCommunity) ?? 0;\n\n // Modularity gain formula\n const gain = (weightToTarget - ((resolution * nodeWeight * targetWeight) / (2 * this.totalWeight))) / this.totalWeight;\n\n return gain;\n }\n\n /**\n * Remove node from community (for gain calculation)\n */\n private removeNodeFromCommunity(nodeId: NodeId, community: number): void {\n const nodeWeight = this.nodeWeights.get(nodeId) ?? 0;\n this.communityWeights.set(community, (this.communityWeights.get(community) ?? 0) - nodeWeight);\n this.communities.delete(nodeId);\n }\n\n /**\n * Add node to community\n */\n private addNodeToCommunity(nodeId: NodeId, community: number): void {\n const nodeWeight = this.nodeWeights.get(nodeId) ?? 0;\n this.communityWeights.set(community, (this.communityWeights.get(community) ?? 0) + nodeWeight);\n this.communities.set(nodeId, community);\n }\n\n /**\n * Get neighboring communities of a node\n */\n private getNeighborCommunities(nodeId: NodeId): Set<number> {\n const communities = new Set<number>();\n\n for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {\n const community = this.communities.get(neighbor);\n if (community !== undefined) {\n communities.add(community);\n }\n }\n\n // For undirected graphs, also check incoming edges\n if (!this.graph.isDirected) {\n for (const neighbor of Array.from(this.graph.inNeighbors(nodeId))) {\n const community = this.communities.get(neighbor);\n if (community !== undefined) {\n communities.add(community);\n }\n }\n }\n\n return communities;\n }\n\n /**\n * Calculate total modularity\n */\n private calculateModularity(resolution: number): number {\n if (this.totalWeight === 0) {\n return 0;\n }\n\n let modularity = 0;\n\n // Sum over all communities\n const communityInternalWeights = new Map<number, number>();\n\n // Calculate internal weights for each community\n for (const node of this.graph.nodes()) {\n const nodeId = node.id;\n const community = this.communities.get(nodeId) ?? 0;\n\n for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {\n if (this.communities.get(neighbor) === community) {\n const edge = this.graph.getEdge(nodeId, neighbor);\n const weight = edge?.weight ?? 1;\n communityInternalWeights.set(community, (communityInternalWeights.get(community) ?? 0) + weight);\n }\n }\n }\n\n // Calculate modularity\n for (const [community, internalWeight] of communityInternalWeights) {\n const communityWeight = this.communityWeights.get(community) ?? 0;\n // For undirected graphs, internal weights are counted twice\n const aIn = this.graph.isDirected ? internalWeight : internalWeight / 2;\n const aTotal = communityWeight;\n\n // Modularity formula: sum of (fraction of edges within community - expected fraction)\n const actualFraction = aIn / this.totalWeight;\n const expectedFraction = resolution * Math.pow(aTotal / (2 * this.totalWeight), 2);\n modularity += actualFraction - expectedFraction;\n }\n\n return modularity;\n }\n\n /**\n * Get pruning statistics\n */\n public getPruningStats(): PruningStats {\n return {... this.pruningStats};\n }\n}\n\n/**\n * Optimized Louvain algorithm with automatic optimization selection\n */\nexport function louvainOptimized(\n graph: Graph,\n options: OptimizedLouvainOptions = {},\n): CommunityResult {\n const optimizer = new OptimizedLouvain(graph);\n return optimizer.detectCommunities(options);\n}\n","/**\n * Shared modularity calculation utilities for community detection algorithms\n *\n * Used by: Louvain, Leiden, Girvan-Newman\n */\nimport type {Graph} from \"../../core/graph.js\";\nimport type {NodeId} from \"../../types/index.js\";\n\n/**\n * Calculate total edge weight in the graph\n *\n * For undirected graphs, each edge is counted once.\n * For directed graphs, each directed edge is counted once.\n *\n * @param graph - The input graph\n * @returns Total sum of edge weights (default weight is 1)\n */\nexport function getTotalEdgeWeight(graph: Graph): number {\n let totalWeight = 0;\n\n for (const edge of graph.edges()) {\n totalWeight += edge.weight ?? 1;\n }\n\n return totalWeight;\n}\n\n/**\n * Get the total degree (sum of edge weights) for a node\n *\n * Computes the weighted degree by summing all edge weights incident to the node.\n *\n * @param graph - The input graph\n * @param nodeId - The node ID to compute degree for\n * @returns The weighted degree of the node\n */\nexport function getNodeDegree(graph: Graph, nodeId: NodeId): number {\n let degree = 0;\n\n for (const neighbor of graph.neighbors(nodeId)) {\n const edge = graph.getEdge(nodeId, neighbor);\n degree += edge?.weight ?? 1;\n }\n\n return degree;\n}\n\n/**\n * Get communities of neighboring nodes\n *\n * Returns the set of community IDs that neighbors of the given node belong to.\n *\n * @param graph - The input graph\n * @param nodeId - The node to get neighbor communities for\n * @param communities - Map from node IDs to community IDs\n * @returns Set of community IDs that neighbors belong to\n */\nexport function getNeighborCommunities(\n graph: Graph,\n nodeId: NodeId,\n communities: Map<NodeId, number>,\n): Set<number> {\n const neighborCommunities = new Set<number>();\n\n for (const neighbor of graph.neighbors(nodeId)) {\n const community = communities.get(neighbor);\n if (community !== undefined) {\n neighborCommunities.add(community);\n }\n }\n\n return neighborCommunities;\n}\n\n/**\n * Calculate modularity of a partition\n *\n * Modularity measures the quality of a community partition. It compares the\n * number of edges within communities to what would be expected in a random graph.\n *\n * Formula: Q = (1/2m) * Σ[A_ij - γ(k_i * k_j)/(2m)] * δ(c_i, c_j)\n * where:\n * - m = total edge weight\n * - A_ij = adjacency matrix entry (edge weight between i and j)\n * - k_i, k_j = degrees of nodes i and j\n * - γ = resolution parameter (higher values favor smaller communities)\n * - δ = Kronecker delta (1 if same community, 0 otherwise)\n *\n * @param graph - The input graph\n * @param communities - Map from node IDs to community IDs\n * @param resolution - Resolution parameter (default: 1.0)\n * @returns Modularity score (range typically -0.5 to 1.0)\n */\nexport function calculateModularity(\n graph: Graph,\n communities: Map<NodeId, number>,\n resolution = 1.0,\n): number {\n const totalEdgeWeight = getTotalEdgeWeight(graph);\n if (totalEdgeWeight === 0) {\n return 0;\n }\n\n let modularity = 0;\n\n // For undirected graphs, we need to be careful not to double-count edges\n const countedEdges = new Set<string>();\n\n // Calculate modularity: Q = (1/2m) * Σ[A_ij - γ(k_i * k_j)/(2m)] * δ(c_i, c_j)\n for (const nodeI of graph.nodes()) {\n for (const nodeJ of graph.nodes()) {\n // Skip if already counted this pair in undirected graph\n if (!graph.isDirected) {\n const nodeIStr = String(nodeI.id);\n const nodeJStr = String(nodeJ.id);\n const edgeKey = nodeIStr <= nodeJStr ? `${nodeIStr}-${nodeJStr}` : `${nodeJStr}-${nodeIStr}`;\n if (countedEdges.has(edgeKey)) {\n continue;\n }\n\n countedEdges.add(edgeKey);\n }\n\n if (communities.get(nodeI.id) === communities.get(nodeJ.id)) {\n const edge = graph.getEdge(nodeI.id, nodeJ.id);\n const reverseEdge = !graph.isDirected ? graph.getEdge(nodeJ.id, nodeI.id) : null;\n\n let edgeWeight = 0;\n if (edge) {\n edgeWeight += edge.weight ?? 1;\n }\n\n if (reverseEdge && nodeI.id !== nodeJ.id) {\n edgeWeight += reverseEdge.weight ?? 1;\n }\n\n const degreeI = getNodeDegree(graph, nodeI.id);\n const degreeJ = getNodeDegree(graph, nodeJ.id);\n\n modularity += edgeWeight - ((resolution * degreeI * degreeJ) / (2 * totalEdgeWeight));\n }\n }\n }\n\n return modularity / (2 * totalEdgeWeight);\n}\n","import {Graph} from \"../../core/graph.js\";\nimport type {CommunityResult, LouvainOptions, NodeId} from \"../../types/index.js\";\nimport {louvainOptimized} from \"./louvain-optimized.js\";\nimport {\n calculateModularity,\n getNeighborCommunities,\n getNodeDegree,\n getTotalEdgeWeight,\n} from \"./modularity-utils.js\";\n\n/**\n * Louvain community detection algorithm\n *\n * Implements the Louvain method for community detection in graphs.\n * Uses modularity optimization to find community structure.\n *\n * References:\n * - Blondel, V. D., Guillaume, J. L., Lambiotte, R., & Lefebvre, E. (2008).\n * Fast unfolding of communities in large networks.\n * Journal of statistical mechanics: theory and experiment, 2008(10), P10008.\n *\n * @param graph - The input graph\n * @param options - Algorithm options\n * @returns Community detection result with communities, modularity, and iterations\n */\nexport function louvain(\n graph: Graph,\n options: LouvainOptions = {},\n): CommunityResult {\n const resolution = options.resolution ?? 1.0;\n const maxIterations = options.maxIterations ?? 100;\n const tolerance = options.tolerance ?? 1e-6;\n\n // Use optimized version by default for larger graphs\n // Only disable if explicitly requested or graph is very small\n const shouldUseOptimized = options.useOptimized !== false && graph.nodeCount > 50;\n\n if (shouldUseOptimized) {\n return louvainOptimized(graph, {\n resolution,\n maxIterations,\n tolerance,\n // Enable all optimizations by default\n pruneLeaves: true,\n importanceOrdering: true,\n thresholdCycling: true,\n pruningThreshold: 0.01,\n });\n }\n\n // Initialize: each node in its own community\n const communities = initializeCommunities(graph);\n let modularity = calculateModularity(graph, communities, resolution);\n let iteration = 0;\n let improved = true;\n\n while (iteration < maxIterations && improved) {\n // Phase 1: Local optimization\n improved = louvainPhase1(graph, communities, resolution);\n\n if (improved) {\n const newModularity = calculateModularity(graph, communities, resolution);\n\n // Check for convergence\n if ((newModularity - modularity) < tolerance) {\n break;\n }\n\n modularity = newModularity;\n iteration++;\n }\n }\n\n return {\n communities: extractCommunities(communities),\n modularity: calculateModularity(graph, communities, resolution),\n iterations: iteration,\n };\n}\n\n/**\n * Initialize communities: each node in its own community\n */\nfunction initializeCommunities(graph: Graph): Map<NodeId, number> {\n const communities = new Map<NodeId, number>();\n let communityId = 0;\n\n for (const node of graph.nodes()) {\n communities.set(node.id, communityId++);\n }\n\n return communities;\n}\n\n/**\n * Phase 1 of Louvain algorithm: Local optimization\n * For each node, try moving to neighboring communities and keep the move\n * that provides the best modularity gain.\n */\nfunction louvainPhase1(\n graph: Graph,\n communities: Map<NodeId, number>,\n resolution: number,\n): boolean {\n let globalImprovement = false;\n let localImprovement = true;\n\n while (localImprovement) {\n localImprovement = false;\n\n for (const node of graph.nodes()) {\n const nodeId = node.id;\n const currentCommunity = communities.get(nodeId);\n\n if (currentCommunity === undefined) {\n continue;\n }\n\n // Calculate current modularity contribution\n const currentModularity = nodeModularityContribution(\n graph, nodeId, currentCommunity, communities, resolution,\n );\n\n let bestCommunity = currentCommunity;\n let bestModularity = currentModularity;\n\n // Try moving to neighboring communities\n const neighborCommunities = getNeighborCommunities(graph, nodeId, communities);\n\n for (const neighborCommunity of neighborCommunities) {\n if (neighborCommunity === currentCommunity) {\n continue;\n }\n\n const newModularity = nodeModularityContribution(\n graph, nodeId, neighborCommunity, communities, resolution,\n );\n\n if (newModularity > bestModularity) {\n bestModularity = newModularity;\n bestCommunity = neighborCommunity;\n }\n }\n\n // Move node if improvement found\n if (bestCommunity !== currentCommunity) {\n communities.set(nodeId, bestCommunity);\n localImprovement = true;\n globalImprovement = true;\n }\n }\n }\n\n return globalImprovement;\n}\n\n/**\n * Calculate modularity contribution of a node to a specific community\n */\nfunction nodeModularityContribution(\n graph: Graph,\n nodeId: NodeId,\n community: number,\n communities: Map<NodeId, number>,\n resolution: number,\n): number {\n const totalEdgeWeight = getTotalEdgeWeight(graph);\n if (totalEdgeWeight === 0) {\n return 0;\n }\n\n let internalLinks = 0;\n let nodeDegree = 0;\n let communityDegree = 0;\n\n // Calculate node's connections to the community\n for (const neighbor of graph.neighbors(nodeId)) {\n const edge = graph.getEdge(nodeId, neighbor);\n const weight = edge?.weight ?? 1;\n nodeDegree += weight;\n\n if (communities.get(neighbor) === community) {\n internalLinks += weight;\n }\n }\n\n // Calculate total degree of the community (excluding the node if it's currently in it)\n for (const [otherNodeId, otherCommunity] of communities) {\n if (otherCommunity === community && otherNodeId !== nodeId) {\n communityDegree += getNodeDegree(graph, otherNodeId);\n }\n }\n\n // Modularity formula: Q = (1/2m) * Σ[A_ij - (k_i * k_j)/(2m)] * δ(c_i, c_j)\n const modularityIncrease = (internalLinks - ((resolution * nodeDegree * communityDegree) / (2 * totalEdgeWeight))) / totalEdgeWeight;\n\n return modularityIncrease;\n}\n\n/**\n * Extract final community structure\n */\nfunction extractCommunities(communities: Map<NodeId, number>): NodeId[][] {\n const communityMap = new Map<number, NodeId[]>();\n\n for (const [nodeId, community] of communities) {\n if (!communityMap.has(community)) {\n communityMap.set(community, []);\n }\n\n const communityNodes = communityMap.get(community);\n if (communityNodes) {\n communityNodes.push(nodeId);\n }\n }\n\n return Array.from(communityMap.values());\n}\n","/**\n * Min Priority Queue implementation for graph algorithms\n */\nexport class MinPriorityQueue<T> {\n private heap: T[] = [];\n private compare: (a: T, b: T) => number;\n\n constructor(compareFunction?: (a: T, b: T) => number) {\n this.compare = compareFunction ?? ((a: T, b: T) => this.defaultCompare(a, b));\n }\n\n private defaultCompare(a: T, b: T): number {\n const aWithDistance = a as T & {distance?: number};\n const bWithDistance = b as T & {distance?: number};\n\n if (aWithDistance.distance !== undefined && bWithDistance.distance !== undefined) {\n return aWithDistance.distance - bWithDistance.distance;\n }\n\n return 0;\n }\n\n private parent(i: number): number {\n return Math.floor((i - 1) / 2);\n }\n\n private leftChild(i: number): number {\n return (2 * i) + 1;\n }\n\n private rightChild(i: number): number {\n return (2 * i) + 2;\n }\n\n private swap(i: number, j: number): void {\n const temp = this.heap[i];\n const temp2 = this.heap[j];\n if (temp !== undefined && temp2 !== undefined) {\n this.heap[i] = temp2;\n this.heap[j] = temp;\n }\n }\n\n private heapifyUp(index: number): void {\n while (index > 0) {\n const parentIndex = this.parent(index);\n const current = this.heap[index];\n const parent = this.heap[parentIndex];\n if (current !== undefined && parent !== undefined && this.compare(current, parent) < 0) {\n this.swap(index, parentIndex);\n index = parentIndex;\n } else {\n break;\n }\n }\n }\n\n private heapifyDown(index: number): void {\n while (index < this.heap.length) {\n let minIndex = index;\n const left = this.leftChild(index);\n const right = this.rightChild(index);\n\n const leftItem = this.heap[left];\n const minItem = this.heap[minIndex];\n if (left < this.heap.length && leftItem !== undefined && minItem !== undefined && this.compare(leftItem, minItem) < 0) {\n minIndex = left;\n }\n\n const rightItem = this.heap[right];\n const newMinItem = this.heap[minIndex];\n if (right < this.heap.length && rightItem !== undefined && newMinItem !== undefined && this.compare(rightItem, newMinItem) < 0) {\n minIndex = right;\n }\n\n if (minIndex !== index) {\n this.swap(index, minIndex);\n index = minIndex;\n } else {\n break;\n }\n }\n }\n\n insert(value: T): void {\n this.heap.push(value);\n this.heapifyUp(this.heap.length - 1);\n }\n\n extractMin(): T | undefined {\n if (this.heap.length === 0) {\n return undefined;\n }\n\n if (this.heap.length === 1) {\n return this.heap.pop();\n }\n\n const min = this.heap[0];\n const last = this.heap.pop();\n if (last !== undefined) {\n this.heap[0] = last;\n this.heapifyDown(0);\n }\n\n return min;\n }\n\n peek(): T | undefined {\n return this.heap[0];\n }\n\n isEmpty(): boolean {\n return this.heap.length === 0;\n }\n\n size(): number {\n return this.heap.length;\n }\n}\n","/**\n * Utility functions for pathfinding algorithms\n */\n\nexport const pathfindingUtils = {\n /**\n * Reconstructs a path from start to goal using the cameFrom map\n */\n reconstructPath<T>(cameFrom: Map<T, T>, goal: T): T[] {\n const path: T[] = [goal];\n let current = goal;\n\n while (cameFrom.has(current)) {\n const next = cameFrom.get(current);\n if (next === undefined) {\n break;\n }\n\n current = next;\n path.unshift(current);\n }\n\n return path;\n },\n\n /**\n * Creates a grid graph for testing pathfinding algorithms\n */\n createGridGraph(\n width: number,\n height: number,\n obstacles = new Set<string>(),\n ): Map<string, Map<string, number>> {\n const graph = new Map<string, Map<string, number>>();\n\n for (let x = 0; x < width; x++) {\n for (let y = 0; y < height; y++) {\n const node = `${String(x)},${String(y)}`;\n if (obstacles.has(node)) {\n continue;\n }\n\n const neighbors = new Map<string, number>();\n\n // Add 4-directional neighbors\n const directions = [\n [0, 1], [1, 0], [0, -1], [-1, 0],\n ];\n\n for (const dir of directions) {\n const dx = dir[0];\n const dy = dir[1];\n if (dx === undefined || dy === undefined) {\n continue;\n }\n\n const nx = x + dx;\n const ny = y + dy;\n const neighbor = `${String(nx)},${String(ny)}`;\n\n if (nx >= 0 && nx < width && ny >= 0 && ny < height && !obstacles.has(neighbor)) {\n neighbors.set(neighbor, 1); // Unit cost for grid movement\n }\n }\n\n graph.set(node, neighbors);\n }\n }\n\n return graph;\n },\n\n /**\n * Parses a grid coordinate string\n */\n parseGridCoordinate(coord: string): [number, number] {\n const parts = coord.split(\",\").map(Number);\n const x = parts[0];\n const y = parts[1];\n if (x === undefined || y === undefined) {\n throw new Error(`Invalid coordinate: ${coord}`);\n }\n\n return [x, y];\n },\n};\n\n","import {graphNode} from \"../utils/graphNode.js\";\nimport {MinPriorityQueue} from \"../utils/priorityQueue.js\";\nimport {pathfindingUtils} from \"./utils.js\";\n\n/**\n * A* pathfinding algorithm\n * Finds the shortest path from start to goal using a heuristic function\n *\n * @param graph - The graph represented as an adjacency list\n * @param start - The starting node\n * @param goal - The goal node\n * @param heuristic - Heuristic function that estimates distance from node to goal\n * @returns Object containing the shortest path and its cost, or null if no path exists\n *\n * Time Complexity: O(E) with good heuristic, O(b^d) worst case\n * Space Complexity: O(V)\n */\nexport function astar<T>(\n graph: Map<T, Map<T, number>>,\n start: T,\n goal: T,\n heuristic: (node: T, goal: T) => number,\n): {path: T[], cost: number} | null {\n if (!graph.has(start) || !graph.has(goal)) {\n return null;\n }\n\n // Priority queue ordered by f(n) = g(n) + h(n)\n const openSet = new MinPriorityQueue<graphNode<T>>();\n const gScore = new Map<T, number>(); // Cost from start to node\n const fScore = new Map<T, number>(); // Estimated total cost\n const cameFrom = new Map<T, T>();\n const closedSet = new Set<T>();\n\n // Initialize start node\n gScore.set(start, 0);\n fScore.set(start, heuristic(start, goal));\n const startFScore = fScore.get(start);\n if (startFScore === undefined) {\n return null;\n }\n\n openSet.insert({node: start, distance: startFScore});\n\n while (!openSet.isEmpty()) {\n const current = openSet.extractMin();\n if (!current) {\n break;\n }\n\n const currentNode = current.node;\n\n if (currentNode === goal) {\n // Reconstruct path\n const path = pathfindingUtils.reconstructPath(cameFrom, goal);\n const goalCost = gScore.get(goal);\n if (goalCost === undefined) {\n return null;\n }\n\n return {path, cost: goalCost};\n }\n\n closedSet.add(currentNode);\n\n const neighbors = graph.get(currentNode);\n if (!neighbors) {\n continue;\n }\n\n for (const [neighbor, weight] of neighbors) {\n if (closedSet.has(neighbor)) {\n continue;\n }\n\n const currentNodeGScore = gScore.get(currentNode);\n if (currentNodeGScore === undefined) {\n continue;\n }\n\n const tentativeGScore = currentNodeGScore + weight;\n const currentGScore = gScore.get(neighbor) ?? Infinity;\n\n if (tentativeGScore < currentGScore) {\n // This path to neighbor is better\n cameFrom.set(neighbor, currentNode);\n gScore.set(neighbor, tentativeGScore);\n fScore.set(neighbor, tentativeGScore + heuristic(neighbor, goal));\n\n // Add to open set if not already there\n const neighborFScore = fScore.get(neighbor);\n if (neighborFScore !== undefined) {\n openSet.insert({node: neighbor, distance: neighborFScore});\n }\n }\n }\n }\n\n return null; // No path found\n}\n\n/**\n * A* pathfinding with path reconstruction details\n * Returns detailed information about the search process\n */\nexport function astarWithDetails<T>(\n graph: Map<T, Map<T, number>>,\n start: T,\n goal: T,\n heuristic: (node: T, goal: T) => number,\n): {\n path: T[] | null;\n cost: number;\n visited: Set<T>;\n gScores: Map<T, number>;\n fScores: Map<T, number>;\n } {\n const openSet = new MinPriorityQueue<graphNode<T>>();\n const gScore = new Map<T, number>();\n const fScore = new Map<T, number>();\n const cameFrom = new Map<T, T>();\n const closedSet = new Set<T>();\n\n gScore.set(start, 0);\n fScore.set(start, heuristic(start, goal));\n const startFScore = fScore.get(start);\n if (startFScore === undefined) {\n return {\n path: null,\n cost: Infinity,\n visited: new Set(),\n gScores: new Map(),\n fScores: new Map(),\n };\n }\n\n openSet.insert({node: start, distance: startFScore});\n\n while (!openSet.isEmpty()) {\n const current = openSet.extractMin();\n if (!current) {\n break;\n }\n\n const currentNode = current.node;\n\n if (currentNode === goal) {\n const path = pathfindingUtils.reconstructPath(cameFrom, goal);\n return {\n path,\n cost: gScore.get(goal) ?? Infinity,\n visited: closedSet,\n gScores: gScore,\n fScores: fScore,\n };\n }\n\n closedSet.add(currentNode);\n\n const neighbors = graph.get(currentNode);\n if (!neighbors) {\n continue;\n }\n\n for (const [neighbor, weight] of neighbors) {\n if (closedSet.has(neighbor)) {\n continue;\n }\n\n const currentNodeGScore = gScore.get(currentNode);\n if (currentNodeGScore === undefined) {\n continue;\n }\n\n const tentativeGScore = currentNodeGScore + weight;\n const currentGScore = gScore.get(neighbor) ?? Infinity;\n\n if (tentativeGScore < currentGScore) {\n cameFrom.set(neighbor, currentNode);\n gScore.set(neighbor, tentativeGScore);\n fScore.set(neighbor, tentativeGScore + heuristic(neighbor, goal));\n const neighborFScore = fScore.get(neighbor);\n if (neighborFScore !== undefined) {\n openSet.insert({node: neighbor, distance: neighborFScore});\n }\n }\n }\n }\n\n return {\n path: null,\n cost: Infinity,\n visited: closedSet,\n gScores: gScore,\n fScores: fScore,\n };\n}\n\n/**\n * Common heuristic functions for A*\n */\nexport const heuristics = {\n /**\n * Manhattan distance heuristic for grid-based graphs\n */\n manhattan: (a: [number, number], b: [number, number]): number => {\n return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);\n },\n\n /**\n * Euclidean distance heuristic\n */\n euclidean: (a: [number, number], b: [number, number]): number => {\n return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2));\n },\n\n /**\n * Chebyshev distance heuristic (diagonal movement allowed)\n */\n chebyshev: (a: [number, number], b: [number, number]): number => {\n return Math.max(Math.abs(a[0] - b[0]), Math.abs(a[1] - b[1]));\n },\n\n /**\n * Zero heuristic (makes A* behave like Dijkstra)\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n zero: <T>(_a: T, _b: T): number => 0,\n};\n","import {bfsAugmentingPath} from \"../algorithms/traversal/bfs-variants.js\";\nimport type {Graph} from \"../core/graph.js\";\nimport {graphToMap} from \"../utils/graph-converters.js\";\n\n/**\n * Ford-Fulkerson Algorithm for Maximum Flow\n *\n * Finds the maximum flow from source to sink in a flow network\n * using the method of augmenting paths.\n */\n\nexport interface FlowEdge {\n from: string;\n to: string;\n capacity: number;\n flow: number;\n}\n\nexport interface FlowNetwork {\n nodes: Set<string>;\n edges: Map<string, Map<string, FlowEdge>>;\n}\n\nexport interface MaxFlowResult {\n maxFlow: number;\n flowGraph: Map<string, Map<string, number>>;\n minCut?: {source: Set<string>, sink: Set<string>, edges: [string, string][]};\n}\n\n/**\n * Create residual graph from original graph\n */\nfunction createResidualGraph(\n graph: Map<string, Map<string, number>>,\n): Map<string, Map<string, number>> {\n const residual = new Map<string, Map<string, number>>();\n\n for (const [u, neighbors] of graph) {\n residual.set(u, new Map());\n for (const [v, capacity] of neighbors) {\n const uResidualNeighbors = residual.get(u);\n if (uResidualNeighbors) {\n uResidualNeighbors.set(v, capacity);\n }\n }\n }\n\n return residual;\n}\n\n/**\n * Find augmenting path using DFS\n */\nfunction findAugmentingPathDFS(\n residualGraph: Map<string, Map<string, number>>,\n source: string,\n sink: string,\n): string[] | null {\n const visited = new Set<string>();\n const path: string[] = [];\n\n function dfs(node: string): boolean {\n if (node === sink) {\n path.push(node);\n return true;\n }\n\n visited.add(node);\n path.push(node);\n\n const neighbors = residualGraph.get(node);\n if (neighbors) {\n for (const [neighbor, capacity] of neighbors) {\n if (!visited.has(neighbor) && capacity > 0) {\n if (dfs(neighbor)) {\n return true;\n }\n }\n }\n }\n\n path.pop();\n return false;\n }\n\n if (dfs(source)) {\n return path;\n }\n\n return null;\n}\n\n/**\n * Update flow along an augmenting path\n */\nfunction updateFlow(\n residualGraph: Map<string, Map<string, number>>,\n flowGraph: Map<string, Map<string, number>>,\n originalGraph: Map<string, Map<string, number>>,\n path: string[],\n pathFlow: number,\n): void {\n for (let i = 0; i < path.length - 1; i++) {\n const u = path[i];\n const v = path[i + 1];\n if (!u || !v) {\n continue;\n }\n\n // Update residual graph\n const uEdges = residualGraph.get(u);\n if (uEdges) {\n const currentCapacity = uEdges.get(v);\n if (currentCapacity !== undefined) {\n uEdges.set(v, currentCapacity - pathFlow);\n }\n }\n\n // Add reverse edge\n if (!residualGraph.has(v)) {\n residualGraph.set(v, new Map());\n }\n\n const vEdges = residualGraph.get(v);\n if (vEdges) {\n vEdges.set(u, (vEdges.get(u) ?? 0) + pathFlow);\n }\n\n // Update flow graph\n if (originalGraph.get(u)?.has(v)) {\n const uFlowEdges = flowGraph.get(u);\n if (uFlowEdges) {\n const currentFlow = uFlowEdges.get(v) ?? 0;\n uFlowEdges.set(v, currentFlow + pathFlow);\n }\n } else if (originalGraph.get(v)?.has(u)) {\n // This is a reverse flow\n const vFlowEdges = flowGraph.get(v);\n if (vFlowEdges) {\n const currentFlow = vFlowEdges.get(u) ?? 0;\n vFlowEdges.set(u, currentFlow - pathFlow);\n }\n }\n }\n}\n\n/**\n * Find minimum cut from source side\n */\nfunction findMinCut(\n residualGraph: Map<string, Map<string, number>>,\n source: string,\n): {source: Set<string>, sink: Set<string>, edges: [string, string][]} {\n // Find all reachable nodes from source in residual graph\n const sourceSet = new Set<string>();\n const queue = [source];\n sourceSet.add(source);\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (!current) {\n continue;\n }\n\n const neighbors = residualGraph.get(current);\n\n if (neighbors) {\n for (const [neighbor, capacity] of neighbors) {\n if (!sourceSet.has(neighbor) && capacity > 0) {\n sourceSet.add(neighbor);\n queue.push(neighbor);\n }\n }\n }\n }\n\n // All other nodes are in sink set\n const sinkSet = new Set<string>();\n for (const node of residualGraph.keys()) {\n if (!sourceSet.has(node)) {\n sinkSet.add(node);\n }\n }\n\n // Find cut edges\n const cutEdges: [string, string][] = [];\n for (const u of sourceSet) {\n const neighbors = residualGraph.get(u);\n if (neighbors) {\n for (const v of neighbors.keys()) {\n if (sinkSet.has(v)) {\n cutEdges.push([u, v]);\n }\n }\n }\n }\n\n return {source: sourceSet, sink: sinkSet, edges: cutEdges};\n}\n\n/**\n * Core max flow algorithm implementation\n */\nfunction maxFlowCore(\n graph: Map<string, Map<string, number>>,\n source: string,\n sink: string,\n findPath: (residual: Map<string, Map<string, number>>, src: string, snk: string) => {path: string[], pathCapacity: number} | null,\n): MaxFlowResult {\n if (!graph.has(source) || !graph.has(sink)) {\n return {maxFlow: 0, flowGraph: new Map()};\n }\n\n // Create residual graph\n const residualGraph = createResidualGraph(graph);\n const flowGraph = new Map<string, Map<string, number>>();\n\n // Initialize flow graph\n for (const [u, neighbors] of graph) {\n flowGraph.set(u, new Map());\n for (const v of neighbors.keys()) {\n const uFlowNeighbors = flowGraph.get(u);\n if (uFlowNeighbors) {\n uFlowNeighbors.set(v, 0);\n }\n }\n }\n\n let maxFlow = 0;\n let pathResult = findPath(residualGraph, source, sink);\n\n while (pathResult !== null) {\n const {path, pathCapacity} = pathResult;\n\n // Update flow\n updateFlow(residualGraph, flowGraph, graph, path, pathCapacity);\n maxFlow += pathCapacity;\n\n // Find next path\n pathResult = findPath(residualGraph, source, sink);\n }\n\n // Find minimum cut\n const minCut = findMinCut(residualGraph, source);\n\n return {maxFlow, flowGraph, minCut};\n}\n\n/**\n * Internal implementation of Ford-Fulkerson algorithm using DFS\n */\nfunction fordFulkersonImpl(\n graph: Map<string, Map<string, number>>,\n source: string,\n sink: string,\n): MaxFlowResult {\n // Adapter function for DFS path finding\n const findPathDFS = (residual: Map<string, Map<string, number>>, src: string, snk: string): {path: string[], pathCapacity: number} | null => {\n const path = findAugmentingPathDFS(residual, src, snk);\n if (!path) {\n return null;\n }\n\n // Calculate path capacity\n let pathCapacity = Infinity;\n for (let i = 0; i < path.length - 1; i++) {\n const u = path[i];\n const v = path[i + 1];\n if (u && v) {\n const capacity = residual.get(u)?.get(v);\n if (capacity !== undefined) {\n pathCapacity = Math.min(pathCapacity, capacity);\n }\n }\n }\n\n return {path, pathCapacity};\n };\n\n return maxFlowCore(graph, source, sink, findPathDFS);\n}\n\n/**\n * Internal implementation of Edmonds-Karp algorithm\n */\nfunction edmondsKarpImpl(\n graph: Map<string, Map<string, number>>,\n source: string,\n sink: string,\n): MaxFlowResult {\n // Use BFS variant for path finding\n const findPathBFS = (residual: Map<string, Map<string, number>>, src: string, snk: string): {path: string[], pathCapacity: number} | null => {\n return bfsAugmentingPath(residual, src, snk);\n };\n\n return maxFlowCore(graph, source, sink, findPathBFS);\n}\n\n/**\n * Utility function to create a flow network for bipartite matching\n */\nexport function createBipartiteFlowNetwork(\n leftNodes: string[],\n rightNodes: string[],\n edges: [string, string][],\n): {graph: Map<string, Map<string, number>>, source: string, sink: string} {\n const graph = new Map<string, Map<string, number>>();\n const source = \"__source__\";\n const sink = \"__sink__\";\n\n // Add source connections to left nodes\n graph.set(source, new Map());\n for (const left of leftNodes) {\n const sourceNeighbors = graph.get(source);\n if (sourceNeighbors) {\n sourceNeighbors.set(left, 1);\n }\n\n graph.set(left, new Map());\n }\n\n // Add edges between left and right\n for (const [left, right] of edges) {\n if (!graph.has(left)) {\n graph.set(left, new Map());\n }\n\n const leftNeighbors = graph.get(left);\n if (leftNeighbors) {\n leftNeighbors.set(right, 1);\n }\n }\n\n // Add right node connections to sink\n for (const right of rightNodes) {\n if (!graph.has(right)) {\n graph.set(right, new Map());\n }\n\n const rightNeighbors = graph.get(right);\n if (rightNeighbors) {\n rightNeighbors.set(sink, 1);\n }\n }\n\n graph.set(sink, new Map());\n\n return {graph, source, sink};\n}\n\n/**\n * Ford-Fulkerson algorithm using DFS for finding augmenting paths\n *\n * @param graph - Adjacency list representation with capacities - accepts Graph class or Map\n * @param source - Source node\n * @param sink - Sink node\n * @returns Maximum flow value and flow graph\n *\n * Time Complexity: O(E * f) where f is the maximum flow\n * Space Complexity: O(V + E)\n */\nexport function fordFulkerson(\n graph: Graph,\n source: string,\n sink: string,\n): MaxFlowResult {\n // Convert Graph to Map representation\n const graphMap = graphToMap(graph);\n return fordFulkersonImpl(graphMap, source, sink);\n}\n\n/**\n * Edmonds-Karp algorithm (Ford-Fulkerson with BFS)\n * More efficient implementation with better time complexity\n *\n * @param graph - Adjacency list representation with capacities - accepts Graph class or Map\n * @param source - Source node\n * @param sink - Sink node\n * @returns Maximum flow value and flow graph\n *\n * Time Complexity: O(V * E²)\n */\nexport function edmondsKarp(\n graph: Graph | Map<string, Map<string, number>>,\n source: string,\n sink: string,\n): MaxFlowResult {\n // Convert Graph to Map representation if needed\n const graphMap = graph instanceof Map ? graph : graphToMap(graph);\n return edmondsKarpImpl(graphMap, source, sink);\n}\n","/**\n * Minimum Cut Algorithms\n *\n * Various algorithms for finding minimum cuts in graphs\n */\n\nimport type {Graph} from \"../core/graph.js\";\nimport {graphToMap} from \"../utils/graph-converters.js\";\nimport {fordFulkerson} from \"./ford-fulkerson.js\";\n\nexport interface MinCutResult {\n cutValue: number;\n partition1: Set<string>;\n partition2: Set<string>;\n cutEdges: {from: string, to: string, weight: number}[];\n}\n\n/**\n * Find minimum s-t cut using max flow\n * The minimum cut value equals the maximum flow value (max-flow min-cut theorem)\n *\n * @param graph - Weighted graph\n * @param source - Source node\n * @param sink - Sink node\n * @returns Minimum cut information\n *\n * Time Complexity: Same as max flow algorithm used\n */\nexport function minSTCut(\n graph: Graph,\n source: string,\n sink: string,\n): MinCutResult {\n const flowResult = fordFulkerson(graph, source, sink);\n\n if (!flowResult.minCut) {\n return {\n cutValue: 0,\n partition1: new Set(),\n partition2: new Set(),\n cutEdges: [],\n };\n }\n\n const cutEdges: {from: string, to: string, weight: number}[] = [];\n\n // Find actual cut edges and their weights\n for (const [u, v] of flowResult.minCut.edges) {\n const edge = graph.getEdge(u, v);\n const weight = edge?.weight ?? 0;\n if (weight > 0) {\n cutEdges.push({from: u, to: v, weight});\n }\n }\n\n return {\n cutValue: flowResult.maxFlow,\n partition1: flowResult.minCut.source,\n partition2: flowResult.minCut.sink,\n cutEdges,\n };\n}\n\n/**\n * Stoer-Wagner algorithm for finding global minimum cut\n * Finds the minimum cut that separates the graph into two parts\n *\n * @param graph - Undirected weighted graph - accepts Graph class or Map representation\n * @returns Global minimum cut\n *\n * Time Complexity: O(V³) or O(VE + V² log V) with heap\n */\nexport function stoerWagner(\n graph: Graph | Map<string, Map<string, number>>,\n): MinCutResult {\n // Convert Graph to Map representation if needed\n const graphMap = graph instanceof Map ? graph : graphToMap(graph);\n // Convert to undirected if necessary\n const undirectedGraph = makeUndirected(graphMap);\n // Keep a copy for finding cut edges later\n const originalGraph = makeUndirected(graphMap);\n\n if (undirectedGraph.size < 2) {\n return {\n cutValue: 0,\n partition1: new Set(undirectedGraph.keys()),\n partition2: new Set(),\n cutEdges: [],\n };\n }\n\n // Initialize\n const nodes = Array.from(undirectedGraph.keys());\n const originalNodes = new Set(nodes); // Keep track of original nodes\n let minCutValue = Infinity;\n let bestPartition = new Set<string>();\n const contractionMap = new Map<string, Set<string>>();\n\n // Initialize contraction map\n for (const node of nodes) {\n contractionMap.set(node, new Set([node]));\n }\n\n // Contract graph V-1 times\n while (nodes.length > 1) {\n const cut = minimumCutPhase(undirectedGraph, nodes);\n\n if (cut.value < minCutValue) {\n minCutValue = cut.value;\n // Store the actual nodes that would be in partition with t\n const cutTNodes = contractionMap.get(cut.t);\n if (cutTNodes) {\n bestPartition = new Set(cutTNodes);\n }\n }\n\n // Contract the last two nodes\n const tNodes = contractionMap.get(cut.t);\n const sNodes = contractionMap.get(cut.s);\n if (!tNodes || !sNodes) {\n continue;\n }\n\n for (const node of tNodes) {\n sNodes.add(node);\n }\n contractionMap.delete(cut.t);\n\n contractNodes(undirectedGraph, nodes, cut.s, cut.t);\n }\n\n // Build result\n const partition1 = bestPartition;\n const partition2 = new Set<string>();\n\n for (const node of originalNodes) {\n if (!partition1.has(node)) {\n partition2.add(node);\n }\n }\n\n // Find cut edges\n const cutEdges: {from: string, to: string, weight: number}[] = [];\n for (const u of partition1) {\n const neighbors = originalGraph.get(u);\n if (neighbors) {\n for (const [v, weight] of neighbors) {\n if (partition2.has(v)) {\n cutEdges.push({from: u, to: v, weight});\n }\n }\n }\n }\n\n return {\n cutValue: minCutValue,\n partition1,\n partition2,\n cutEdges,\n };\n}\n\n/**\n * Minimum cut phase of Stoer-Wagner algorithm\n */\nfunction minimumCutPhase(\n graph: Map<string, Map<string, number>>,\n nodes: string[],\n): {s: string, t: string, value: number, partition: string[]} {\n const n = nodes.length;\n const weight = new Map<string, number>();\n const added = new Set<string>();\n const order: string[] = [];\n\n // Initialize weights to 0\n for (const node of nodes) {\n weight.set(node, 0);\n }\n\n // Start with arbitrary node\n let lastAdded = nodes[0];\n if (!lastAdded) {\n return {s: \"\", t: \"\", value: 0, partition: []};\n }\n\n added.add(lastAdded);\n order.push(lastAdded);\n\n // Add remaining nodes\n for (let i = 1; i < n; i++) {\n // Update weights\n if (!lastAdded) {\n continue;\n }\n\n const neighbors = graph.get(lastAdded);\n if (neighbors) {\n for (const [neighbor, w] of neighbors) {\n if (!added.has(neighbor) && nodes.includes(neighbor)) {\n const currentWeight = weight.get(neighbor);\n if (currentWeight !== undefined) {\n weight.set(neighbor, currentWeight + w);\n }\n }\n }\n }\n\n // Find maximum weight node not yet added\n let maxWeight = -1;\n let maxNode = \"\";\n\n for (const node of nodes) {\n const nodeWeight = weight.get(node);\n if (!added.has(node) && nodeWeight !== undefined && nodeWeight > maxWeight) {\n maxWeight = nodeWeight;\n maxNode = node;\n }\n }\n\n added.add(maxNode);\n order.push(maxNode);\n lastAdded = maxNode;\n }\n\n const s = order[order.length - 2];\n const t = order[order.length - 1];\n if (!s || !t) {\n return {s: \"\", t: \"\", value: 0, partition: []};\n }\n\n const cutValue = weight.get(t) ?? 0;\n\n // Partition is all nodes except t\n const partition = order.slice(0, -1);\n\n return {s, t, value: cutValue, partition};\n}\n\n/**\n * Contract two nodes in the graph\n */\nfunction contractNodes(\n graph: Map<string, Map<string, number>>,\n nodes: string[],\n s: string,\n t: string,\n): void {\n // Merge t into s\n const sNeighbors = graph.get(s);\n const tNeighbors = graph.get(t);\n if (!sNeighbors || !tNeighbors) {\n return;\n }\n\n // Add t's edges to s\n for (const [neighbor, weight] of tNeighbors) {\n if (neighbor !== s) {\n sNeighbors.set(neighbor, (sNeighbors.get(neighbor) ?? 0) + weight);\n\n // Update neighbor's edge to point to s instead of t\n const neighborEdges = graph.get(neighbor);\n if (neighborEdges?.has(t)) {\n neighborEdges.delete(t);\n neighborEdges.set(s, (neighborEdges.get(s) ?? 0) + weight);\n }\n }\n }\n\n // Remove t from graph\n graph.delete(t);\n sNeighbors.delete(t);\n\n // Remove t from nodes array\n const index = nodes.indexOf(t);\n if (index > -1) {\n nodes.splice(index, 1);\n }\n}\n\n/**\n * Convert directed graph to undirected\n */\nfunction makeUndirected(\n graph: Map<string, Map<string, number>>,\n): Map<string, Map<string, number>> {\n const undirected = new Map<string, Map<string, number>>();\n\n // Initialize all nodes\n for (const node of graph.keys()) {\n undirected.set(node, new Map());\n }\n\n // Add edges in both directions\n for (const [u, neighbors] of graph) {\n for (const [v, weight] of neighbors) {\n const uNeighbors = undirected.get(u);\n if (uNeighbors) {\n uNeighbors.set(v, weight);\n }\n\n if (!undirected.has(v)) {\n undirected.set(v, new Map());\n }\n\n const vNeighbors = undirected.get(v);\n if (vNeighbors) {\n vNeighbors.set(u, weight);\n }\n }\n }\n\n return undirected;\n}\n\n/**\n * Karger's randomized min-cut algorithm\n * Probabilistic algorithm that finds min cut with high probability\n *\n * @param graph - Undirected graph - accepts Graph class or Map representation\n * @param iterations - Number of iterations (higher = better accuracy)\n * @returns Minimum cut found\n *\n * Time Complexity: O(V² * iterations)\n */\nexport function kargerMinCut(\n graph: Graph | Map<string, Map<string, number>>,\n iterations = 100,\n): MinCutResult {\n // Convert Graph to Map representation if needed\n const graphMap = graph instanceof Map ? graph : graphToMap(graph);\n let minCutValue = Infinity;\n let bestPartition1 = new Set<string>();\n let bestPartition2 = new Set<string>();\n\n for (let i = 0; i < iterations; i++) {\n const result = kargerSingleRun(graphMap);\n\n if (result.cutValue < minCutValue) {\n minCutValue = result.cutValue;\n bestPartition1 = result.partition1;\n bestPartition2 = result.partition2;\n }\n }\n\n // Find cut edges\n const cutEdges: {from: string, to: string, weight: number}[] = [];\n for (const u of bestPartition1) {\n const neighbors = graphMap.get(u);\n if (neighbors) {\n for (const [v, weight] of neighbors) {\n if (bestPartition2.has(v)) {\n cutEdges.push({from: u, to: v, weight});\n }\n }\n }\n }\n\n return {\n cutValue: minCutValue,\n partition1: bestPartition1,\n partition2: bestPartition2,\n cutEdges,\n };\n}\n\n/**\n * Single run of Karger's algorithm\n */\nfunction kargerSingleRun(\n graph: Map<string, Map<string, number>>,\n): {cutValue: number, partition1: Set<string>, partition2: Set<string>} {\n // Create a copy of the graph\n const workGraph = new Map<string, Map<string, number>>();\n const superNodes = new Map<string, Set<string>>();\n\n // Initialize\n for (const [node, neighbors] of graph) {\n workGraph.set(node, new Map(neighbors));\n superNodes.set(node, new Set([node]));\n }\n\n // Contract until 2 nodes remain\n while (workGraph.size > 2) {\n // Pick random edge\n const edges: [string, string, number][] = [];\n for (const [u, neighbors] of workGraph) {\n for (const [v, weight] of neighbors) {\n if (u < v) { // Avoid duplicates\n edges.push([u, v, weight]);\n }\n }\n }\n\n if (edges.length === 0) {\n break;\n }\n\n const randomIndex = Math.floor(Math.random() * edges.length);\n const edge = edges[randomIndex];\n if (!edge) {\n continue;\n }\n\n const [u, v] = edge;\n\n // Contract edge\n if (u && v) {\n contractKarger(workGraph, superNodes, u, v);\n }\n }\n\n // Calculate cut value\n const nodes = Array.from(workGraph.keys());\n if (nodes.length < 2) {\n return {\n cutValue: 0,\n partition1: new Set(),\n partition2: new Set(),\n };\n }\n\n const node1 = nodes[0];\n const node2 = nodes[1];\n if (!node1 || !node2) {\n return {\n cutValue: 0,\n partition1: new Set(),\n partition2: new Set(),\n };\n }\n\n const cutValue = workGraph.get(node1)?.get(node2) ?? 0;\n\n return {\n cutValue,\n partition1: superNodes.get(node1) ?? new Set(),\n partition2: superNodes.get(node2) ?? new Set(),\n };\n}\n\n/**\n * Contract edge in Karger's algorithm\n */\nfunction contractKarger(\n graph: Map<string, Map<string, number>>,\n superNodes: Map<string, Set<string>>,\n u: string,\n v: string,\n): void {\n // Merge v into u\n const uNeighbors = graph.get(u);\n const vNeighbors = graph.get(v);\n if (!uNeighbors || !vNeighbors) {\n return;\n }\n\n // Merge supernodes\n const uSuper = superNodes.get(u);\n const vSuper = superNodes.get(v);\n if (!uSuper || !vSuper) {\n return;\n }\n\n for (const node of vSuper) {\n uSuper.add(node);\n }\n\n // Merge edges\n for (const [neighbor, weight] of vNeighbors) {\n if (neighbor !== u) {\n uNeighbors.set(neighbor, (uNeighbors.get(neighbor) ?? 0) + weight);\n\n // Update neighbor's edges\n const neighborEdges = graph.get(neighbor);\n if (neighborEdges) {\n neighborEdges.delete(v);\n if (neighbor !== u) {\n neighborEdges.set(u, (neighborEdges.get(u) ?? 0) + weight);\n }\n }\n }\n }\n\n // Remove self-loops\n uNeighbors.delete(u);\n uNeighbors.delete(v);\n\n // Remove v\n graph.delete(v);\n superNodes.delete(v);\n}\n\n","/**\n * Hierarchical Clustering Algorithm\n *\n * Builds a hierarchy of clusters through agglomeration (bottom-up)\n * or division (top-down). Useful for understanding multi-scale\n * structure in graphs.\n */\n\nimport type {Graph} from \"../core/graph.js\";\n\n/**\n * Convert Graph to adjacency set representation for clustering\n */\nfunction graphToAdjacencySet(graph: Graph): Map<string, Set<string>> {\n const adjacency = new Map<string, Set<string>>();\n\n // Initialize all nodes\n for (const node of graph.nodes()) {\n adjacency.set(String(node.id), new Set());\n }\n\n // Add edges\n for (const edge of graph.edges()) {\n const source = String(edge.source);\n const target = String(edge.target);\n\n const sourceSet = adjacency.get(source);\n if (sourceSet) {\n sourceSet.add(target);\n }\n\n // For undirected graphs, add reverse edge\n if (!graph.isDirected) {\n const targetSet = adjacency.get(target);\n if (targetSet) {\n targetSet.add(source);\n }\n }\n }\n\n return adjacency;\n}\n\nexport interface ClusterNode<T> {\n id: string;\n members: Set<T>;\n left?: ClusterNode<T> | undefined;\n right?: ClusterNode<T> | undefined;\n distance: number;\n height: number;\n // For forest roots, store the individual trees\n trees?: ClusterNode<T>[] | undefined;\n}\n\nexport interface HierarchicalClusteringResult<T> {\n root: ClusterNode<T>;\n dendrogram: ClusterNode<T>[];\n clusters: Map<number, Set<T>[]>;\n}\n\nexport type LinkageMethod = \"single\" | \"complete\" | \"average\" | \"ward\";\n\n/**\n * Compute distance between two nodes based on graph structure\n */\nfunction computeGraphDistance<T>(\n graph: Map<T, Set<T>>,\n distances: Map<T, Map<T, number>>,\n): void {\n // Use BFS to compute shortest path distances\n for (const start of graph.keys()) {\n const dist = new Map<T, number>();\n const queue: T[] = [start];\n dist.set(start, 0);\n\n while (queue.length > 0) {\n const node = queue.shift();\n if (!node) {\n continue;\n }\n\n const neighbors = graph.get(node);\n\n if (neighbors) {\n for (const neighbor of neighbors) {\n if (!dist.has(neighbor)) {\n dist.set(neighbor, (dist.get(node) ?? 0) + 1);\n queue.push(neighbor);\n }\n }\n }\n }\n\n distances.set(start, dist);\n }\n}\n\n/**\n * Compute distance between two clusters based on linkage method\n */\nfunction clusterDistance<T>(\n cluster1: ClusterNode<T>,\n cluster2: ClusterNode<T>,\n distances: Map<T, Map<T, number>>,\n linkage: LinkageMethod,\n): number {\n const allDistances: number[] = [];\n\n for (const node1 of cluster1.members) {\n const node1Distances = distances.get(node1);\n if (!node1Distances) {\n continue;\n }\n\n for (const node2 of cluster2.members) {\n const dist = node1Distances.get(node2);\n if (dist !== undefined) {\n allDistances.push(dist);\n }\n }\n }\n\n if (allDistances.length === 0) {\n return Infinity;\n }\n\n switch (linkage) {\n case \"single\":\n return Math.min(... allDistances);\n case \"complete\":\n return Math.max(... allDistances);\n case \"average\":\n return allDistances.reduce((a, b) => a + b, 0) / allDistances.length;\n case \"ward\": {\n // Simplified Ward's method - minimize within-cluster variance\n const size1 = cluster1.members.size;\n const size2 = cluster2.members.size;\n const avgDist = allDistances.reduce((a, b) => a + b, 0) / allDistances.length;\n return avgDist * ((size1 * size2) / (size1 + size2));\n }\n default:\n return Math.min(... allDistances);\n }\n}\n\n/**\n * Internal implementation of agglomerative hierarchical clustering\n */\nfunction hierarchicalClusteringImpl<T>(\n graph: Map<T, Set<T>>,\n linkage: LinkageMethod = \"single\",\n): HierarchicalClusteringResult<T> {\n const nodes = Array.from(graph.keys());\n const n = nodes.length;\n\n if (n === 0) {\n return {\n root: {id: \"empty\", members: new Set(), distance: 0, height: 0},\n dendrogram: [],\n clusters: new Map(),\n };\n }\n\n // Compute pairwise distances\n const distances = new Map<T, Map<T, number>>();\n computeGraphDistance(graph, distances);\n\n // Initialize clusters - each node is its own cluster\n const clusters: ClusterNode<T>[] = nodes.map((node, i) => ({\n id: `leaf-${String(i)}`,\n members: new Set([node]),\n distance: 0,\n height: 0,\n }));\n\n const dendrogram: ClusterNode<T>[] = [... clusters];\n let clusterCount = n;\n\n // Distance matrix between clusters\n const clusterDistances = new Map<string, Map<string, number>>();\n\n // Initialize cluster distances\n for (let i = 0; i < clusters.length; i++) {\n const cluster1 = clusters[i];\n if (!cluster1) {\n continue;\n }\n\n const distMap = new Map<string, number>();\n for (let j = i + 1; j < clusters.length; j++) {\n const cluster2 = clusters[j];\n if (!cluster2) {\n continue;\n }\n\n const dist = clusterDistance(cluster1, cluster2, distances, linkage);\n distMap.set(cluster2.id, dist);\n }\n clusterDistances.set(cluster1.id, distMap);\n }\n\n // Active clusters\n const activeClusters = new Set(clusters);\n\n // Merge clusters until only one remains\n while (activeClusters.size > 1) {\n // Find closest pair of clusters\n let minDist = Infinity;\n let mergeCluster1: ClusterNode<T> | null = null;\n let mergeCluster2: ClusterNode<T> | null = null;\n\n for (const cluster1 of activeClusters) {\n const distMap = clusterDistances.get(cluster1.id);\n if (!distMap) {\n continue;\n }\n\n for (const cluster2 of activeClusters) {\n if (cluster1.id >= cluster2.id) {\n continue;\n }\n\n const dist = distMap.get(cluster2.id) ??\n clusterDistances.get(cluster2.id)?.get(cluster1.id) ??\n Infinity;\n\n if (dist < minDist) {\n minDist = dist;\n mergeCluster1 = cluster1;\n mergeCluster2 = cluster2;\n }\n }\n }\n\n if (!mergeCluster1 || !mergeCluster2 || minDist === Infinity) {\n // No valid merge found - create forest\n const trees = Array.from(activeClusters);\n const forestRoot: ClusterNode<T> = {\n id: `forest-${String(clusterCount++)}`,\n members: new Set(nodes),\n distance: Infinity,\n height: Math.max(... trees.map((t) => t.height)) + 1,\n trees,\n };\n dendrogram.push(forestRoot);\n activeClusters.clear();\n activeClusters.add(forestRoot);\n break;\n }\n\n // Create new cluster\n const newCluster: ClusterNode<T> = {\n id: `cluster-${String(clusterCount++)}`,\n members: new Set([... mergeCluster1.members, ... mergeCluster2.members]),\n left: mergeCluster1,\n right: mergeCluster2,\n distance: minDist,\n height: Math.max(mergeCluster1.height, mergeCluster2.height) + 1,\n };\n\n dendrogram.push(newCluster);\n\n // Update distances to new cluster\n const newDistMap = new Map<string, number>();\n for (const cluster of activeClusters) {\n if (cluster.id === mergeCluster1.id || cluster.id === mergeCluster2.id) {\n continue;\n }\n\n const dist = clusterDistance(newCluster, cluster, distances, linkage);\n newDistMap.set(cluster.id, dist);\n\n // Update reverse direction\n const clusterDistMap = clusterDistances.get(cluster.id);\n if (clusterDistMap) {\n clusterDistMap.set(newCluster.id, dist);\n }\n }\n clusterDistances.set(newCluster.id, newDistMap);\n\n // Remove merged clusters\n activeClusters.delete(mergeCluster1);\n activeClusters.delete(mergeCluster2);\n clusterDistances.delete(mergeCluster1.id);\n clusterDistances.delete(mergeCluster2.id);\n\n // Clean up references\n for (const distMap of clusterDistances.values()) {\n distMap.delete(mergeCluster1.id);\n distMap.delete(mergeCluster2.id);\n }\n\n activeClusters.add(newCluster);\n }\n\n // Root is the last remaining cluster\n const root = activeClusters.size > 0 ? Array.from(activeClusters)[0] : dendrogram[dendrogram.length - 1];\n\n // Generate clusters at different heights\n const clustersByLevel = new Map<number, Set<T>[]>();\n\n if (!root) {\n return {\n root: {id: \"empty\", members: new Set(), distance: 0, height: 0},\n dendrogram: [],\n clusters: new Map(),\n };\n }\n\n for (let h = 0; h <= root.height; h++) {\n clustersByLevel.set(h, cutDendrogram(root, h));\n }\n\n return {\n root,\n dendrogram,\n clusters: clustersByLevel,\n };\n}\n\n/**\n * Cut dendrogram at specific height to get clusters\n */\nexport function cutDendrogram<T>(\n root: ClusterNode<T>,\n height: number,\n): Set<T>[] {\n const clusters: Set<T>[] = [];\n\n function traverse(node: ClusterNode<T>): void {\n if (node.height <= height || (!node.left && !node.right)) {\n clusters.push(node.members);\n } else {\n if (node.trees) {\n // Handle forest nodes\n for (const tree of node.trees) {\n traverse(tree);\n }\n } else {\n if (node.left) {\n traverse(node.left);\n }\n\n if (node.right) {\n traverse(node.right);\n }\n }\n }\n }\n\n traverse(root);\n return clusters;\n}\n\n/**\n * Cut dendrogram to get exactly k clusters\n */\nexport function cutDendrogramKClusters<T>(\n root: ClusterNode<T>,\n k: number,\n): Set<T>[] {\n if (k <= 0) {\n return [];\n }\n\n if (k === 1) {\n return [root.members];\n }\n\n // Binary search for the right height\n let low = 0;\n let high = root.height;\n\n while (low < high) {\n const mid = Math.floor((low + high) / 2);\n const clusters = cutDendrogram(root, mid);\n\n if (clusters.length === k) {\n return clusters;\n } else if (clusters.length < k) {\n high = mid;\n } else {\n low = mid + 1;\n }\n }\n\n return cutDendrogram(root, low);\n}\n\n/**\n * Compute modularity-based hierarchical clustering\n * Uses modularity gain to decide merges\n */\nexport function modularityHierarchicalClustering(\n graph: Graph,\n): HierarchicalClusteringResult<string> {\n const adjacencySet = graphToAdjacencySet(graph);\n const nodes = Array.from(adjacencySet.keys());\n const n = nodes.length;\n\n if (n === 0) {\n return {\n root: {id: \"empty\", members: new Set(), distance: 0, height: 0},\n dendrogram: [],\n clusters: new Map(),\n };\n }\n\n // Compute degrees\n const degrees = new Map<string, number>();\n let totalEdges = 0;\n\n for (const [node, neighbors] of adjacencySet) {\n degrees.set(node, neighbors.size);\n totalEdges += neighbors.size;\n }\n\n // For undirected graphs\n totalEdges = totalEdges / 2;\n\n // Initialize clusters\n const clusters: ClusterNode<string>[] = nodes.map((node, i) => ({\n id: `leaf-${String(i)}`,\n members: new Set([node]),\n distance: 0,\n height: 0,\n }));\n\n const dendrogram: ClusterNode<string>[] = [... clusters];\n let clusterCount = n;\n\n // Active clusters\n const activeClusters = new Set(clusters);\n\n // Community assignments\n const communities = new Map<string, number>();\n nodes.forEach((node, i) => communities.set(node, i));\n\n // Merge clusters based on modularity gain\n while (activeClusters.size > 1) {\n let maxGain = -Infinity;\n let mergeCluster1: ClusterNode<string> | null = null;\n let mergeCluster2: ClusterNode<string> | null = null;\n\n for (const cluster1 of activeClusters) {\n for (const cluster2 of activeClusters) {\n if (cluster1.id >= cluster2.id) {\n continue;\n }\n\n // Calculate modularity gain\n let edgesBetween = 0;\n let degreeProduct = 0;\n\n for (const node1 of cluster1.members) {\n const neighbors = adjacencySet.get(node1);\n const degree1 = degrees.get(node1) ?? 0;\n\n for (const node2 of cluster2.members) {\n if (neighbors?.has(node2)) {\n edgesBetween++;\n }\n\n const degree2 = degrees.get(node2) ?? 0;\n degreeProduct += degree1 * degree2;\n }\n }\n\n const gain = (edgesBetween / totalEdges) -\n (degreeProduct / (4 * totalEdges * totalEdges));\n\n if (gain > maxGain) {\n maxGain = gain;\n mergeCluster1 = cluster1;\n mergeCluster2 = cluster2;\n }\n }\n }\n\n if (!mergeCluster1 || !mergeCluster2) {\n break;\n }\n\n // Create new cluster\n const newCluster: ClusterNode<string> = {\n id: `cluster-${String(clusterCount++)}`,\n members: new Set([... mergeCluster1.members, ... mergeCluster2.members]),\n left: mergeCluster1,\n right: mergeCluster2,\n distance: -maxGain, // Use negative gain as distance\n height: Math.max(mergeCluster1.height, mergeCluster2.height) + 1,\n };\n\n dendrogram.push(newCluster);\n\n // Remove old and add new\n activeClusters.delete(mergeCluster1);\n activeClusters.delete(mergeCluster2);\n activeClusters.add(newCluster);\n }\n\n // Root is the last remaining cluster\n const root = Array.from(activeClusters)[0] ?? dendrogram[dendrogram.length - 1];\n\n // Generate clusters at different heights\n const clustersByLevel = new Map<number, Set<string>[]>();\n\n if (!root) {\n return {\n root: {id: \"empty\", members: new Set(), distance: 0, height: 0},\n dendrogram: [],\n clusters: new Map(),\n };\n }\n\n for (let h = 0; h <= root.height; h++) {\n clustersByLevel.set(h, cutDendrogram(root, h));\n }\n\n return {\n root,\n dendrogram,\n clusters: clustersByLevel,\n };\n}\n\n/**\n * Agglomerative hierarchical clustering\n * Builds clusters bottom-up by merging closest pairs\n *\n * @param graph - Undirected graph - accepts Graph class or Map<T, Set<T>>\n * @param linkage - Linkage method for cluster distance\n * @returns Hierarchical clustering result\n *\n * Time Complexity: O(n³) naive, O(n² log n) with heap\n * Space Complexity: O(n²)\n */\nexport function hierarchicalClustering(\n graph: Graph,\n linkage: LinkageMethod = \"single\",\n): HierarchicalClusteringResult<string> {\n // Convert Graph to adjacency set representation\n const adjacencySet = graphToAdjacencySet(graph);\n return hierarchicalClusteringImpl(adjacencySet, linkage);\n}\n","/**\n * K-Core Decomposition Algorithm\n *\n * Finds the k-core subgraph where each node has at least k neighbors\n * within the subgraph. Used for identifying cohesive groups and\n * understanding graph structure.\n */\n\nimport type {Graph} from \"../core/graph.js\";\n\n/**\n * Convert Graph to adjacency set representation\n */\nfunction graphToAdjacencySet(graph: Graph): Map<string, Set<string>> {\n const adjacency = new Map<string, Set<string>>();\n\n // Initialize all nodes\n for (const node of graph.nodes()) {\n adjacency.set(String(node.id), new Set());\n }\n\n // Add edges\n for (const edge of graph.edges()) {\n const source = String(edge.source);\n const target = String(edge.target);\n\n const sourceSet = adjacency.get(source);\n if (sourceSet) {\n sourceSet.add(target);\n }\n\n // For undirected graphs, add reverse edge\n if (!graph.isDirected) {\n const targetSet = adjacency.get(target);\n if (targetSet) {\n targetSet.add(source);\n }\n }\n }\n\n return adjacency;\n}\n\nexport interface KCoreResult<T> {\n cores: Map<number, Set<T>>;\n coreness: Map<T, number>;\n maxCore: number;\n}\n\n/**\n * Internal implementation of K-Core decomposition algorithm\n */\nfunction kCoreDecompositionImpl<T>(\n graph: Map<T, Set<T>>,\n): KCoreResult<T> {\n if (graph.size === 0) {\n return {cores: new Map(), coreness: new Map(), maxCore: 0};\n }\n\n const n = graph.size;\n const nodes = Array.from(graph.keys());\n const nodeToIndex = new Map<T, number>();\n nodes.forEach((node, i) => nodeToIndex.set(node, i));\n\n // Initialize data structures\n const degree = new Array<number>(n).fill(0);\n const pos = new Array<number>(n).fill(0);\n const vert = new Array<number>(n).fill(0);\n const coreness = new Map<T, number>();\n\n // Initialize coreness for all nodes to 0\n for (let i = 0; i < n; i++) {\n const node = nodes[i];\n if (node !== undefined) {\n coreness.set(node, 0);\n }\n }\n\n // Compute initial degrees\n let maxDegree = 0;\n for (let i = 0; i < n; i++) {\n const node = nodes[i];\n if (!node) {\n continue;\n }\n\n const neighbors = graph.get(node);\n const nodeSize = neighbors ? neighbors.size : 0;\n\n degree[i] = nodeSize;\n maxDegree = Math.max(maxDegree, nodeSize);\n }\n\n // Count nodes of each degree\n const bin = new Array<number>(maxDegree + 1).fill(0);\n for (let i = 0; i < n; i++) {\n const deg = degree[i];\n if (deg !== undefined && deg >= 0 && deg < bin.length) {\n const currentCount = bin[deg];\n if (currentCount !== undefined) {\n bin[deg] = currentCount + 1;\n }\n }\n }\n\n // Starting position of each degree in sorted array\n let start = 0;\n for (let d = 0; d <= maxDegree; d++) {\n const temp = bin[d] ?? 0;\n bin[d] = start;\n start += temp;\n }\n\n // Sort nodes by degree\n for (let i = 0; i < n; i++) {\n const deg = degree[i];\n if (deg !== undefined && deg >= 0 && deg < bin.length) {\n const posIndex = bin[deg] ?? 0;\n pos[i] = posIndex;\n vert[posIndex] = i;\n const currentBin = bin[deg];\n if (currentBin !== undefined) {\n bin[deg] = currentBin + 1;\n }\n } else {\n // If we can't properly place the node in vert, set its position to -1\n // This shouldn't happen with our fixes, but just in case\n pos[i] = -1;\n }\n }\n\n // Recover starting positions\n for (let d = maxDegree; d > 0; d--) {\n bin[d] = bin[d - 1] ?? 0;\n }\n bin[0] = 0;\n\n // Main algorithm\n for (let i = 0; i < n; i++) {\n const v = vert[i];\n if (v === undefined) {\n continue;\n }\n\n const node = nodes[v];\n if (node === undefined) {\n continue;\n }\n\n const degreeV = degree[v];\n if (degreeV !== undefined) {\n coreness.set(node, degreeV);\n }\n\n // Process neighbors\n const neighbors = graph.get(node);\n if (!neighbors) {\n // Node has no neighbors, skip neighbor processing but coreness is already set\n continue;\n }\n\n for (const neighbor of neighbors) {\n const u = nodeToIndex.get(neighbor);\n if (u === undefined) {\n continue;\n }\n\n const degreeU = degree[u];\n const degreeV = degree[v];\n if (degreeU !== undefined && degreeV !== undefined && degreeU > degreeV) {\n const du = degreeU;\n const pu = pos[u];\n const pw = bin[du] ?? 0;\n const w = vert[pw];\n\n if (u !== w && w !== undefined && pw < n && pu !== undefined) {\n // Swap u and w in the sorted order\n vert[pu] = w;\n vert[pw] = u;\n pos[u] = pw;\n pos[w] = pu;\n }\n\n const currentBin = bin[du];\n if (currentBin !== undefined) {\n bin[du] = currentBin + 1;\n }\n\n degree[u] = degreeU - 1;\n }\n }\n }\n\n // Build cores map\n const cores = new Map<number, Set<T>>();\n let maxCore = 0;\n\n for (const [node, core] of coreness) {\n if (!cores.has(core)) {\n cores.set(core, new Set());\n }\n\n const coreSet = cores.get(core);\n if (coreSet) {\n coreSet.add(node);\n }\n\n maxCore = Math.max(maxCore, core);\n }\n\n return {cores, coreness, maxCore};\n}\n\n/**\n * Extract the k-core subgraph\n * Returns nodes that belong to k-core or higher\n *\n * @param graph - Undirected graph\n * @param k - Core number\n * @returns Set of nodes in k-core or higher\n */\nexport function getKCore(\n graph: Graph,\n k: number,\n): Set<string> {\n const {coreness} = kCoreDecomposition(graph);\n const kCore = new Set<string>();\n\n for (const [node, core] of coreness) {\n if (core >= k) {\n kCore.add(node);\n }\n }\n\n return kCore;\n}\n\n/**\n * Get the induced subgraph for k-core\n * Returns the actual subgraph containing only k-core nodes\n *\n * @param graph - Original graph\n * @param k - Core number\n * @returns K-core subgraph\n */\nexport function getKCoreSubgraph(\n graph: Graph,\n k: number,\n): Map<string, Set<string>> {\n const kCoreNodes = getKCore(graph, k);\n const adjacencySet = graphToAdjacencySet(graph);\n const subgraph = new Map<string, Set<string>>();\n\n for (const node of kCoreNodes) {\n const neighbors = adjacencySet.get(node);\n if (neighbors) {\n const coreNeighbors = new Set<string>();\n for (const neighbor of neighbors) {\n if (kCoreNodes.has(neighbor)) {\n coreNeighbors.add(neighbor);\n }\n }\n subgraph.set(node, coreNeighbors);\n }\n }\n\n return subgraph;\n}\n\n/**\n * Degeneracy ordering of the graph\n * Orders nodes by their coreness values\n *\n * @param graph - Undirected graph\n * @returns Array of nodes ordered by degeneracy\n */\nexport function degeneracyOrdering(\n graph: Graph,\n): string[] {\n const adjacencySet = graphToAdjacencySet(graph);\n const degree = new Map<string, number>();\n const remaining = new Map<string, Set<string>>();\n const ordering: string[] = [];\n\n // Initialize\n for (const [node, neighbors] of adjacencySet) {\n degree.set(node, neighbors.size);\n remaining.set(node, new Set(neighbors));\n }\n\n // Build ordering\n while (ordering.length < adjacencySet.size) {\n // Find minimum degree node\n let minDegree = Infinity;\n let minNode: string | undefined;\n\n for (const [node, deg] of degree) {\n if (!ordering.includes(node) && deg < minDegree) {\n minDegree = deg;\n minNode = node;\n }\n }\n\n if (minNode === undefined) {\n break;\n }\n\n ordering.push(minNode);\n\n // Update neighbors\n const neighbors = remaining.get(minNode);\n if (neighbors) {\n for (const neighbor of neighbors) {\n const neighborDegree = degree.get(neighbor);\n if (neighborDegree !== undefined) {\n degree.set(neighbor, neighborDegree - 1);\n }\n\n remaining.get(neighbor)?.delete(minNode);\n }\n }\n }\n\n return ordering;\n}\n\n/**\n * Find k-truss subgraph (triangular k-cores)\n * Each edge must be part of at least k-2 triangles\n *\n * @param graph - Undirected graph\n * @param k - Truss number (k >= 2)\n * @returns Edges in k-truss\n */\nexport function kTruss(\n graph: Graph,\n k: number,\n): Set<string> {\n if (k < 2) {\n throw new Error(\"k must be at least 2 for k-truss\");\n }\n\n const adjacencySet = graphToAdjacencySet(graph);\n\n // Count triangles for each edge\n const edgeTriangles = new Map<string, number>();\n const edges = new Set<string>();\n\n // Initialize edges\n for (const [u, neighbors] of adjacencySet) {\n for (const v of neighbors) {\n if (u < v) { // Avoid duplicates\n const edge = `${String(u)},${String(v)}`;\n edges.add(edge);\n edgeTriangles.set(edge, 0);\n }\n }\n }\n\n // Count triangles\n for (const [u, uNeighbors] of adjacencySet) {\n for (const v of uNeighbors) {\n if (u < v) {\n const vNeighbors = adjacencySet.get(v);\n if (vNeighbors) {\n // Find common neighbors (triangles)\n for (const w of uNeighbors) {\n if (v < w && vNeighbors.has(w)) {\n // Triangle found: u-v-w\n const edge1 = `${String(u)},${String(v)}`;\n const edge2 = `${String(u)},${String(w)}`;\n const edge3 = `${String(v)},${String(w)}`;\n\n const edge1Count = edgeTriangles.get(edge1);\n const edge2Count = edgeTriangles.get(edge2);\n const edge3Count = edgeTriangles.get(edge3);\n if (edge1Count !== undefined) {\n edgeTriangles.set(edge1, edge1Count + 1);\n }\n\n if (edge2Count !== undefined) {\n edgeTriangles.set(edge2, edge2Count + 1);\n }\n\n if (edge3Count !== undefined) {\n edgeTriangles.set(edge3, edge3Count + 1);\n }\n }\n }\n }\n }\n }\n }\n\n // Remove edges with insufficient triangles\n const kTrussEdges = new Set<string>(edges);\n let changed = true;\n\n while (changed) {\n changed = false;\n const toRemove = new Set<string>();\n\n for (const edge of kTrussEdges) {\n const triangleCount = edgeTriangles.get(edge);\n if (triangleCount !== undefined && triangleCount < k - 2) {\n toRemove.add(edge);\n changed = true;\n }\n }\n\n // Remove edges and update triangle counts\n for (const edge of toRemove) {\n kTrussEdges.delete(edge);\n const parts = edge.split(\",\");\n if (parts.length < 2) {\n continue;\n }\n\n const [u, v] = parts;\n if (!u || !v) {\n continue;\n }\n\n // Update triangle counts for affected edges\n const uNeighbors = adjacencySet.get(u);\n const vNeighbors = adjacencySet.get(v);\n\n if (uNeighbors && vNeighbors) {\n for (const w of uNeighbors) {\n if (vNeighbors.has(w)) {\n const edge1 = u < w ? `${String(u)},${String(w)}` : `${String(w)},${String(u)}`;\n const edge2 = v < w ? `${String(v)},${String(w)}` : `${String(w)},${String(v)}`;\n\n if (kTrussEdges.has(edge1)) {\n const edge1Count = edgeTriangles.get(edge1);\n if (edge1Count !== undefined) {\n edgeTriangles.set(edge1, edge1Count - 1);\n }\n }\n\n if (kTrussEdges.has(edge2)) {\n const edge2Count = edgeTriangles.get(edge2);\n if (edge2Count !== undefined) {\n edgeTriangles.set(edge2, edge2Count - 1);\n }\n }\n }\n }\n }\n }\n }\n\n return kTrussEdges;\n}\n\n/**\n * Convert directed graph to undirected for k-core analysis\n */\nexport function toUndirected<T>(\n directedGraph: Map<T, Map<T, number>>,\n): Map<T, Set<T>> {\n const undirected = new Map<T, Set<T>>();\n\n // Initialize all nodes\n for (const node of directedGraph.keys()) {\n undirected.set(node, new Set());\n }\n\n // Add edges in both directions\n for (const [u, neighbors] of directedGraph) {\n for (const v of neighbors.keys()) {\n const uNeighbors = undirected.get(u);\n if (uNeighbors) {\n uNeighbors.add(v);\n }\n\n if (!undirected.has(v)) {\n undirected.set(v, new Set());\n }\n\n const vNeighbors = undirected.get(v);\n if (vNeighbors) {\n vNeighbors.add(u);\n }\n }\n }\n\n return undirected;\n}\n\n/**\n * K-Core decomposition algorithm\n * Finds all k-cores in the graph and assigns coreness values to nodes\n *\n * @param graph - Undirected graph - accepts Graph class or Map<T, Set<T>>\n * @returns K-core decomposition results\n *\n * Time Complexity: O(V + E)\n * Space Complexity: O(V)\n */\nexport function kCoreDecomposition(\n graph: Graph,\n): KCoreResult<string> {\n // Convert Graph to adjacency set representation\n const adjacencySet = graphToAdjacencySet(graph);\n return kCoreDecompositionImpl(adjacencySet);\n}\n\n","import type {Graph} from \"../core/graph.js\";\nimport type {NodeId} from \"../types/index.js\";\n\n/**\n * Markov Clustering (MCL) algorithm implementation\n *\n * MCL simulates flow in graphs and finds clusters based on the notion that\n * random walks stay within clusters and rarely move between clusters.\n * The algorithm alternates between expansion (matrix squaring) and\n * inflation (element-wise powering and normalization).\n *\n * Time complexity: O(V³) per iteration\n * Space complexity: O(V²)\n */\n\nexport interface MCLOptions {\n expansion?: number; // Expansion parameter (default: 2)\n inflation?: number; // Inflation parameter (default: 2)\n maxIterations?: number; // Maximum iterations (default: 100)\n tolerance?: number; // Convergence tolerance (default: 1e-6)\n pruningThreshold?: number; // Pruning threshold (default: 1e-5)\n selfLoops?: boolean; // Add self-loops (default: true)\n}\n\nexport interface MCLResult {\n communities: NodeId[][];\n attractors: Set<NodeId>; // Attractor nodes (cluster representatives)\n iterations: number;\n converged: boolean;\n}\n\n/**\n * Perform Markov Clustering on a graph\n */\nexport function markovClustering(\n graph: Graph,\n options: MCLOptions = {},\n): MCLResult {\n const {\n expansion = 2,\n inflation = 2,\n maxIterations = 100,\n tolerance = 1e-6,\n pruningThreshold = 1e-5,\n selfLoops = true,\n } = options;\n\n const nodes = Array.from(graph.nodes());\n const nodeIds = nodes.map((node) => node.id);\n const n = nodeIds.length;\n\n if (n === 0) {\n return {\n communities: [],\n attractors: new Set(),\n iterations: 0,\n converged: true,\n };\n }\n\n // Build initial transition matrix\n let matrix = buildTransitionMatrix(graph, nodeIds, selfLoops);\n\n let converged = false;\n let iteration = 0;\n\n for (iteration = 0; iteration < maxIterations; iteration++) {\n const oldMatrix = matrix.map((row) => [... row]);\n\n // Expansion step (matrix multiplication)\n matrix = matrixPower(matrix, expansion);\n\n // Inflation step (element-wise powering and column normalization)\n matrix = inflate(matrix, inflation);\n\n // Pruning step (remove small values)\n matrix = prune(matrix, pruningThreshold);\n\n // Check for convergence\n if (hasConverged(oldMatrix, matrix, tolerance)) {\n converged = true;\n break;\n }\n }\n\n // Extract clusters from final matrix\n const {communities, attractors} = extractClusters(matrix, nodeIds);\n\n return {\n communities,\n attractors,\n iterations: iteration + 1,\n converged,\n };\n}\n\n/**\n * Build initial transition matrix from graph\n */\nfunction buildTransitionMatrix(graph: Graph, nodeIds: NodeId[], selfLoops: boolean): number[][] {\n const n = nodeIds.length;\n const matrix = Array.from({length: n}, (): number[] => Array(n).fill(0) as number[]);\n const nodeToIndex = new Map<NodeId, number>();\n\n nodeIds.forEach((id, index) => nodeToIndex.set(id, index));\n\n // Fill adjacency values\n for (let i = 0; i < n; i++) {\n const nodeId = nodeIds[i];\n if (!nodeId) {\n continue;\n }\n\n const neighbors = graph.neighbors(nodeId);\n\n for (const neighbor of neighbors) {\n const j = nodeToIndex.get(neighbor);\n if (j !== undefined) {\n const edge = graph.getEdge(nodeId, neighbor);\n const weight = edge?.weight ?? 1;\n const row = matrix[i];\n if (!row) {\n continue;\n }\n\n row[j] = weight;\n }\n }\n\n // Add self-loops\n if (selfLoops) {\n const row = matrix[i];\n if (!row) {\n continue;\n }\n\n row[i] = 1;\n }\n }\n\n // Column-normalize the matrix\n for (let j = 0; j < n; j++) {\n let colSum = 0;\n for (let i = 0; i < n; i++) {\n const val = matrix[i]?.[j];\n if (val !== undefined) {\n colSum += val;\n }\n }\n\n if (colSum > 0) {\n for (let i = 0; i < n; i++) {\n const row = matrix[i];\n if (!row) {\n continue;\n }\n\n const val = row[j];\n if (val !== undefined) {\n row[j] = val / colSum;\n }\n }\n }\n }\n\n return matrix;\n}\n\n/**\n * Raise matrix to a power (for expansion step)\n */\nfunction matrixPower(matrix: number[][], power: number): number[][] {\n if (power === 1) {\n return matrix;\n }\n\n if (power === 2) {\n return matrixMultiply(matrix, matrix);\n }\n\n let result = matrix;\n for (let i = 1; i < power; i++) {\n result = matrixMultiply(result, matrix);\n }\n return result;\n}\n\n/**\n * Multiply two matrices\n */\nfunction matrixMultiply(a: number[][], b: number[][]): number[][] {\n const n = a.length;\n const m = b[0]?.length ?? 0;\n const p = b.length;\n\n const result: number[][] = Array.from({length: n}, () => Array(m).fill(0) as number[]);\n\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < m; j++) {\n for (let k = 0; k < p; k++) {\n const aVal = a[i]?.[k] ?? 0;\n const bVal = b[k]?.[j] ?? 0;\n const resultRow = result[i];\n if (!resultRow) {\n continue;\n }\n\n const prevVal = resultRow[j];\n if (prevVal !== undefined) {\n resultRow[j] = prevVal + (aVal * bVal);\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Inflation step: element-wise powering and column normalization\n */\nfunction inflate(matrix: number[][], inflation: number): number[][] {\n const n = matrix.length;\n const result: number[][] = Array.from({length: n}, () => Array(n).fill(0) as number[]);\n\n // Element-wise powering\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n const val = matrix[i]?.[j];\n if (val !== undefined) {\n const resultRow = result[i];\n if (resultRow) {\n resultRow[j] = Math.pow(val, inflation);\n }\n }\n }\n }\n\n // Column normalization\n for (let j = 0; j < n; j++) {\n let colSum = 0;\n for (let i = 0; i < n; i++) {\n const val = result[i]?.[j];\n if (val !== undefined) {\n colSum += val;\n }\n }\n\n if (colSum > 0) {\n for (let i = 0; i < n; i++) {\n const row = result[i];\n if (!row) {\n continue;\n }\n\n const val = row[j];\n if (val !== undefined) {\n row[j] = val / colSum;\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Pruning step: remove small values\n */\nfunction prune(matrix: number[][], threshold: number): number[][] {\n const n = matrix.length;\n const result: number[][] = Array.from({length: n}, () => Array(n).fill(0) as number[]);\n\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n const matrixRow = matrix[i];\n if (!matrixRow) {\n continue;\n }\n\n const matrixVal = matrixRow[j];\n if (matrixVal !== undefined && matrixVal >= threshold) {\n const resultRow = result[i];\n if (resultRow) {\n resultRow[j] = matrixVal;\n }\n }\n }\n }\n\n // Re-normalize columns after pruning\n for (let j = 0; j < n; j++) {\n let colSum = 0;\n for (let i = 0; i < n; i++) {\n const resultRow = result[i];\n if (!resultRow) {\n continue;\n }\n\n const val = resultRow[j];\n if (val !== undefined) {\n colSum += val;\n }\n }\n\n if (colSum > 0) {\n for (let i = 0; i < n; i++) {\n const resultRow = result[i];\n if (!resultRow) {\n continue;\n }\n\n const val = resultRow[j];\n if (val !== undefined) {\n resultRow[j] = val / colSum;\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Check if the algorithm has converged\n */\nfunction hasConverged(oldMatrix: number[][], newMatrix: number[][], tolerance: number): boolean {\n const n = oldMatrix.length;\n\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n const oldRow = oldMatrix[i];\n const newRow = newMatrix[i];\n if (!oldRow || !newRow) {\n continue;\n }\n\n const oldVal = oldRow[j];\n const newVal = newRow[j];\n if (oldVal !== undefined && newVal !== undefined && Math.abs(oldVal - newVal) > tolerance) {\n return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Extract clusters from the final matrix\n */\nfunction extractClusters(matrix: number[][], nodeIds: NodeId[]): {\n communities: NodeId[][];\n attractors: Set<NodeId>;\n} {\n const n = matrix.length;\n const attractors = new Set<NodeId>();\n const communities: NodeId[][] = [];\n const nodeToCluster = new Map<number, number>();\n\n // Find attractors (columns with non-zero diagonal elements)\n for (let i = 0; i < n; i++) {\n const matrixRow = matrix[i];\n if (!matrixRow) {\n continue;\n }\n\n const diagonalVal = matrixRow[i];\n const nodeId = nodeIds[i];\n if (diagonalVal !== undefined && diagonalVal > 0 && nodeId !== undefined) {\n attractors.add(nodeId);\n }\n }\n\n // Assign nodes to clusters based on columns\n let clusterIndex = 0;\n for (let j = 0; j < n; j++) {\n // Find nodes that belong to this cluster (column)\n const clusterNodes: number[] = [];\n for (let i = 0; i < n; i++) {\n const matrixRow = matrix[i];\n if (!matrixRow) {\n continue;\n }\n\n const val = matrixRow[j];\n if (val !== undefined && val > 0 && !nodeToCluster.has(i)) {\n clusterNodes.push(i);\n nodeToCluster.set(i, clusterIndex);\n }\n }\n\n if (clusterNodes.length > 0) {\n communities.push(clusterNodes.map((idx) => {\n const nodeId = nodeIds[idx];\n return nodeId;\n }).filter((node): node is NodeId => node !== undefined));\n clusterIndex++;\n }\n }\n\n // Handle isolated nodes\n for (let i = 0; i < n; i++) {\n if (!nodeToCluster.has(i)) {\n const nodeId = nodeIds[i];\n if (nodeId !== undefined) {\n communities.push([nodeId]);\n }\n\n nodeToCluster.set(i, clusterIndex++);\n }\n }\n\n return {communities, attractors};\n}\n\n/**\n * Calculate modularity of MCL clustering result\n */\nexport function calculateMCLModularity(\n graph: Graph,\n communities: NodeId[][],\n): number {\n const m = graph.totalEdgeCount;\n if (m === 0) {\n return 0;\n }\n\n let modularity = 0;\n const communityMap = new Map<NodeId, number>();\n\n // Build community map\n communities.forEach((community, index) => {\n community.forEach((nodeId) => {\n communityMap.set(nodeId, index);\n });\n });\n\n // Calculate modularity\n for (const edge of graph.edges()) {\n const sourceCommunity = communityMap.get(edge.source);\n const targetCommunity = communityMap.get(edge.target);\n\n if (sourceCommunity !== undefined && targetCommunity !== undefined && sourceCommunity === targetCommunity) {\n modularity += 1;\n }\n\n const sourceDegree = graph.degree(edge.source);\n const targetDegree = graph.degree(edge.target);\n modularity -= (sourceDegree * targetDegree) / (2 * m);\n }\n\n return modularity / (2 * m);\n}\n","import type {Graph} from \"../core/graph.js\";\nimport type {NodeId} from \"../types/index.js\";\nimport {euclideanDistance} from \"../utils/math-utilities.js\";\n\n/**\n * Spectral Clustering implementation\n *\n * Uses eigenvalues and eigenvectors of the graph Laplacian matrix to perform clustering.\n * Particularly effective for finding non-convex clusters and communities in graphs.\n *\n * Time complexity: O(V³) for eigendecomposition\n * Space complexity: O(V²)\n */\n\nexport interface SpectralClusteringOptions {\n k: number; // Number of clusters to find\n laplacianType?: \"unnormalized\" | \"normalized\" | \"randomWalk\"; // Type of Laplacian\n maxIterations?: number; // Max iterations for k-means (default: 100)\n tolerance?: number; // Convergence tolerance (default: 1e-4)\n}\n\nexport interface SpectralClusteringResult {\n communities: NodeId[][];\n clusterAssignments: Map<NodeId, number>;\n eigenvalues?: number[];\n eigenvectors?: number[][];\n}\n\n/**\n * Perform spectral clustering on a graph\n *\n * @warning This implementation uses simplified power iteration for eigenvector\n * computation with approximate eigenvalues. For production use cases requiring\n * precise clustering, consider using a proper linear algebra library like ml-matrix.\n *\n * The approximate eigenvalues (0.1, 0.2 for second and third eigenvectors) work\n * well for most graph structures but may produce suboptimal results for graphs\n * with unusual spectral properties.\n */\nexport function spectralClustering(\n graph: Graph,\n options: SpectralClusteringOptions,\n): SpectralClusteringResult {\n const {\n k,\n laplacianType = \"normalized\",\n maxIterations = 100,\n tolerance = 1e-4,\n } = options;\n\n // Input validation\n if (k < 1 || !Number.isInteger(k)) {\n throw new Error(\"k must be a positive integer\");\n }\n\n const nodes = Array.from(graph.nodes());\n const nodeIds = nodes.map((node) => node.id);\n const n = nodeIds.length;\n\n if (k >= n) {\n // Return each node as its own cluster\n const communities: NodeId[][] = nodeIds.map((id) => [id]);\n const clusterAssignments = new Map<NodeId, number>();\n nodeIds.forEach((id, index) => clusterAssignments.set(id, index));\n return {communities, clusterAssignments};\n }\n\n // Build adjacency matrix\n const adjacencyMatrix = buildAdjacencyMatrix(graph, nodeIds);\n\n // Build Laplacian matrix\n const laplacianMatrix = buildLaplacianMatrix(adjacencyMatrix, laplacianType);\n\n // Find k smallest eigenvectors\n const eigenResult = findSmallestEigenvectors(laplacianMatrix, k);\n\n // Perform k-means clustering on the eigenvectors\n // For spectral clustering, we need to transpose the eigenvector matrix\n // Each row should be a data point (node) with features from the eigenvectors\n const dataPoints: number[][] = [];\n for (let i = 0; i < nodeIds.length; i++) {\n const point: number[] = [];\n for (let j = 0; j < k; j++) {\n const eigenvector = eigenResult.eigenvectors[j];\n if (eigenvector) {\n point.push(eigenvector[i] ?? 0);\n }\n }\n dataPoints.push(point);\n }\n\n // Normalize the data points row-wise (for normalized spectral clustering)\n if (laplacianType === \"normalized\") {\n normalizeRows(dataPoints);\n }\n\n const kmeans = kMeansClustering(dataPoints, k, maxIterations, tolerance);\n\n // Build communities\n const communities: NodeId[][] = Array.from({length: k}, () => []);\n const clusterAssignments = new Map<NodeId, number>();\n\n for (let i = 0; i < nodeIds.length; i++) {\n const clusterId = kmeans.assignments[i] ?? 0;\n const nodeId = nodeIds[i];\n if (!nodeId) {\n continue;\n }\n\n // Ensure clusterId is valid\n if (clusterId >= 0 && clusterId < k) {\n const community = communities[clusterId];\n if (community) {\n community.push(nodeId);\n }\n\n clusterAssignments.set(nodeId, clusterId);\n } else {\n // Assign to first cluster if invalid\n const firstCommunity = communities[0];\n if (firstCommunity) {\n firstCommunity.push(nodeId);\n }\n\n clusterAssignments.set(nodeId, 0);\n }\n }\n\n // Filter out empty communities\n const nonEmptyCommunities = communities.filter((community) => community.length > 0);\n\n return {\n communities: nonEmptyCommunities,\n clusterAssignments,\n eigenvalues: eigenResult.eigenvalues,\n eigenvectors: eigenResult.eigenvectors,\n };\n}\n\n/**\n * Build adjacency matrix from graph\n */\nfunction buildAdjacencyMatrix(graph: Graph, nodeIds: NodeId[]): number[][] {\n const n = nodeIds.length;\n const matrix: number[][] = Array.from({length: n}, () => Array(n).fill(0) as number[]);\n const nodeToIndex = new Map<NodeId, number>();\n\n nodeIds.forEach((id, index) => nodeToIndex.set(id, index));\n\n for (let i = 0; i < n; i++) {\n const nodeId = nodeIds[i];\n if (!nodeId) {\n continue;\n }\n\n const neighbors = graph.neighbors(nodeId);\n\n for (const neighbor of neighbors) {\n const j = nodeToIndex.get(neighbor);\n if (j !== undefined) {\n const edge = graph.getEdge(nodeId, neighbor);\n const weight = edge?.weight ?? 1;\n const matrixRow = matrix[i];\n if (matrixRow) {\n matrixRow[j] = weight;\n }\n\n if (!graph.isDirected) {\n const matrixRowJ = matrix[j];\n if (matrixRowJ) {\n matrixRowJ[i] = weight;\n }\n }\n }\n }\n }\n\n return matrix;\n}\n\n/**\n * Build Laplacian matrix from adjacency matrix\n */\nfunction buildLaplacianMatrix(adjacency: number[][], type: string): number[][] {\n const n = adjacency.length;\n const laplacian: number[][] = Array.from({length: n}, () => Array(n).fill(0) as number[]);\n\n // Calculate degree matrix\n const degrees = Array(n).fill(0) as number[];\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n const adjacencyRow = adjacency[i];\n const adjacencyVal = adjacencyRow ? adjacencyRow[j] : 0;\n if (adjacencyVal !== undefined) {\n const degreeVal = degrees[i];\n if (degreeVal !== undefined) {\n degrees[i] = degreeVal + adjacencyVal;\n }\n }\n }\n }\n\n if (type === \"unnormalized\") {\n // L = D - A\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n if (i === j) {\n const laplacianRow = laplacian[i];\n const degreeVal = degrees[i];\n if (laplacianRow && degreeVal !== undefined) {\n laplacianRow[j] = degreeVal;\n }\n } else {\n const adjacencyRow = adjacency[i];\n const laplacianRow = laplacian[i];\n if (adjacencyRow && laplacianRow) {\n const adjacencyVal = adjacencyRow[j];\n laplacianRow[j] = adjacencyVal !== undefined ? -adjacencyVal : 0;\n }\n }\n }\n }\n } else if (type === \"normalized\") {\n // L_sym = D^(-1/2) * L * D^(-1/2)\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n if (i === j) {\n const di = degrees[i];\n const laplacianRow = laplacian[i];\n if (laplacianRow) {\n laplacianRow[j] = di !== undefined && di > 0 ? 1 : 0;\n }\n } else {\n const adjacencyRow = adjacency[i];\n if (!adjacencyRow) {\n continue;\n }\n\n const adjacencyVal = adjacencyRow[j];\n const di = degrees[i];\n const dj = degrees[j];\n if (adjacencyVal !== undefined && adjacencyVal > 0 && di !== undefined && dj !== undefined && di > 0 && dj > 0) {\n const laplacianRow = laplacian[i];\n if (laplacianRow) {\n laplacianRow[j] = -adjacencyVal / Math.sqrt(di * dj);\n }\n }\n }\n }\n }\n } else if (type === \"randomWalk\") {\n // L_rw = D^(-1) * L\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n if (i === j) {\n const di = degrees[i];\n const laplacianRow = laplacian[i];\n if (laplacianRow) {\n laplacianRow[j] = di !== undefined && di > 0 ? 1 : 0;\n }\n } else {\n const adjacencyRow = adjacency[i];\n if (!adjacencyRow) {\n continue;\n }\n\n const adjacencyVal = adjacencyRow[j];\n const di = degrees[i];\n if (adjacencyVal !== undefined && adjacencyVal > 0 && di !== undefined && di > 0) {\n const laplacianRow = laplacian[i];\n if (laplacianRow) {\n laplacianRow[j] = -adjacencyVal / di;\n }\n }\n }\n }\n }\n }\n\n return laplacian;\n}\n\n/**\n * Find k smallest eigenvectors using simplified eigendecomposition\n * This is a simplified implementation - in practice, you'd use LAPACK or similar\n */\nfunction findSmallestEigenvectors(matrix: number[][], k: number): {\n eigenvalues: number[];\n eigenvectors: number[][];\n} {\n const n = matrix.length;\n\n if (n === 0 || k === 0) {\n return {eigenvalues: [], eigenvectors: []};\n }\n\n // For very small matrices, use the full power iteration approach\n // Remove the simplified approach that was causing issues\n if (k >= n) {\n // If k >= n, we still need proper eigenvectors, not identity\n // Fall through to the power iteration below\n }\n\n // For spectral clustering, we need proper eigenvectors\n // Special handling for small k values which are common in clustering\n if (k <= 3 && n > k) {\n return computeSmallestEigenvectorsSimple(matrix, k, n);\n }\n\n // For larger k, use power iteration\n const eigenvectors: number[][] = [];\n const eigenvalues: number[] = [];\n const maxIterations = 100;\n\n for (let eigIdx = 0; eigIdx < k; eigIdx++) {\n // Initialize random vector\n let vector = Array(n).fill(0).map(() => Math.random() - 0.5);\n\n // Normalize initial vector\n const initNorm = Math.sqrt(vector.reduce((sum, val) => sum + (val * val), 0));\n if (initNorm > 0) {\n vector = vector.map((val) => val / initNorm);\n }\n\n // Orthogonalize against previous eigenvectors\n for (let j = 0; j < eigIdx; j++) {\n const ejVector = eigenvectors[j];\n if (!ejVector) {\n continue;\n }\n\n const dot = vector.reduce((sum, val, idx) => sum + (val * (ejVector[idx] ?? 0)), 0);\n vector = vector.map((val, idx) => val - (dot * (ejVector[idx] ?? 0)));\n }\n\n // Power iteration\n for (let iter = 0; iter < maxIterations; iter++) {\n // Multiply by matrix\n const newVector = Array(n).fill(0) as number[];\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n const matrixRow = matrix[i];\n const vecVal = vector[j];\n const matrixVal = matrixRow?.[j];\n if (matrixVal !== undefined && vecVal !== undefined) {\n const nvVal = newVector[i];\n if (nvVal !== undefined) {\n newVector[i] = nvVal + (matrixVal * vecVal);\n }\n }\n }\n }\n\n // Orthogonalize against previous eigenvectors\n for (let j = 0; j < eigIdx; j++) {\n const ejVector = eigenvectors[j];\n if (!ejVector) {\n continue;\n }\n\n const dot = newVector.reduce((sum, val, idx) => sum + (val * (ejVector[idx] ?? 0)), 0);\n for (let i = 0; i < n; i++) {\n const ejVal = ejVector[i];\n if (ejVal !== undefined) {\n const nvVal = newVector[i];\n if (nvVal !== undefined) {\n newVector[i] = nvVal - (dot * ejVal);\n }\n }\n }\n }\n\n // Normalize\n const norm = Math.sqrt(newVector.reduce((sum, val) => sum + ((val * val)), 0));\n if (norm > 1e-10) {\n vector = newVector.map((val) => val / norm);\n } else {\n break;\n }\n }\n\n // Calculate eigenvalue (Rayleigh quotient)\n let eigenvalue = 0;\n const Av = Array(n).fill(0) as number[];\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n const matrixRow = matrix[i];\n const vecVal = vector[j];\n const matrixVal = matrixRow?.[j];\n if (matrixVal !== undefined && vecVal !== undefined) {\n const avVal = Av[i];\n if (avVal !== undefined) {\n Av[i] = avVal + (matrixVal * vecVal);\n }\n }\n }\n }\n eigenvalue = vector.reduce((sum, val, idx) => {\n const avVal = Av[idx];\n return sum + (val * (avVal ?? 0));\n }, 0);\n\n eigenvectors.push(vector);\n eigenvalues.push(eigenvalue);\n }\n\n return {eigenvalues, eigenvectors};\n}\n\n/**\n * Normalize matrix rows to unit length\n */\nfunction normalizeRows(matrix: number[][]): void {\n for (const row of matrix) {\n const norm = Math.sqrt(row.reduce((sum, val) => sum + (val * val), 0));\n if (norm > 0) {\n for (let j = 0; j < row.length; j++) {\n const val = row[j];\n if (val !== undefined) {\n row[j] = val / norm;\n }\n }\n }\n }\n}\n\n/**\n * K-means clustering algorithm\n */\nfunction kMeansClustering(\n data: number[][],\n k: number,\n maxIterations: number,\n tolerance = 1e-4,\n): {assignments: number[], centroids: number[][]} {\n const n = data.length;\n const d = data[0]?.length ?? 0;\n\n // Handle edge cases\n if (n === 0 || k === 0) {\n return {assignments: [], centroids: []};\n }\n\n if (k >= n) {\n // Each point is its own cluster\n return {\n assignments: Array.from({length: n}, (_, i) => i),\n centroids: data.slice(0, n),\n };\n }\n\n // Initialize centroids by selecting random data points\n const centroids: number[][] = [];\n const selectedIndices = new Set<number>();\n\n while (centroids.length < k && selectedIndices.size < n) {\n const idx = Math.floor(Math.random() * n);\n if (!selectedIndices.has(idx) && data[idx]) {\n selectedIndices.add(idx);\n centroids.push([... data[idx]]);\n }\n }\n\n // Fill remaining centroids with random values if needed\n while (centroids.length < k) {\n const centroid = Array(d).fill(0) as number[];\n for (let j = 0; j < d; j++) {\n centroid[j] = Math.random() - 0.5;\n }\n centroids.push(centroid);\n }\n\n const assignments = Array(n).fill(0) as number[];\n let oldAssignments = Array(n).fill(-1) as number[];\n\n for (let iteration = 0; iteration < maxIterations; iteration++) {\n // Assign points to closest centroids\n for (let i = 0; i < n; i++) {\n let minDistance = Number.POSITIVE_INFINITY;\n let bestCluster = 0;\n\n for (let j = 0; j < k; j++) {\n const dataPoint = data[i];\n const centroid = centroids[j];\n if (!dataPoint || !centroid) {\n continue;\n }\n\n const distance = euclideanDistance(dataPoint, centroid);\n if (distance < minDistance) {\n minDistance = distance;\n bestCluster = j;\n }\n }\n\n assignments[i] = bestCluster;\n }\n\n // Check for convergence based on assignment changes\n let assignmentsChanged = false;\n for (let i = 0; i < n; i++) {\n if (assignments[i] !== oldAssignments[i]) {\n assignmentsChanged = true;\n break;\n }\n }\n\n if (!assignmentsChanged) {\n break;\n }\n\n oldAssignments = [... assignments];\n\n // Store old centroids for tolerance-based convergence check\n const oldCentroids = centroids.map((c) => [... c]);\n\n // Update centroids\n const counts = Array(k).fill(0) as number[];\n const sums: number[][] = Array.from({length: k}, () => Array(d).fill(0) as number[]);\n\n for (let i = 0; i < n; i++) {\n const cluster = assignments[i] ?? 0;\n const dataPoint = data[i];\n if (!dataPoint) {\n continue;\n }\n\n const sumsCluster = sums[cluster];\n if (sumsCluster !== undefined) {\n const countVal = counts[cluster];\n if (countVal !== undefined) {\n counts[cluster] = countVal + 1;\n }\n\n for (let j = 0; j < d; j++) {\n const dpVal = dataPoint[j];\n if (dpVal !== undefined) {\n const sumVal = sumsCluster[j];\n if (sumVal !== undefined) {\n sumsCluster[j] = sumVal + dpVal;\n }\n }\n }\n }\n }\n\n for (let i = 0; i < k; i++) {\n const countVal = counts[i];\n if (countVal !== undefined && countVal > 0) {\n const sumsRow = sums[i];\n const centroidsRow = centroids[i];\n if (sumsRow !== undefined && centroidsRow !== undefined) {\n for (let j = 0; j < d; j++) {\n const sumVal = sumsRow[j];\n if (sumVal !== undefined) {\n const countValInner = counts[i];\n if (countValInner !== undefined) {\n centroidsRow[j] = sumVal / countValInner;\n }\n }\n }\n }\n }\n }\n\n // Check for tolerance-based convergence (centroid movement)\n let maxCentroidShift = 0;\n for (let i = 0; i < k; i++) {\n const oldCentroid = oldCentroids[i];\n const newCentroid = centroids[i];\n if (oldCentroid && newCentroid) {\n const shift = euclideanDistance(oldCentroid, newCentroid);\n if (shift > maxCentroidShift) {\n maxCentroidShift = shift;\n }\n }\n }\n\n if (maxCentroidShift < tolerance) {\n break;\n }\n }\n\n return {assignments, centroids};\n}\n\n/**\n * Compute smallest eigenvectors for small k (optimized for k=2, k=3)\n */\nfunction computeSmallestEigenvectorsSimple(matrix: number[][], k: number, n: number): {\n eigenvalues: number[];\n eigenvectors: number[][];\n} {\n const eigenvectors: number[][] = [];\n const eigenvalues: number[] = [];\n\n // First eigenvector is constant (corresponds to eigenvalue 0 for connected graph)\n const firstVector = Array(n).fill(1 / Math.sqrt(n)) as number[];\n eigenvectors.push(firstVector);\n eigenvalues.push(0);\n\n // For k >= 2, compute the Fiedler vector (second smallest eigenvector)\n if (k >= 2) {\n // Use power iteration on I - L/lambda_max to find second smallest\n const maxEig = 2; // For normalized Laplacian, max eigenvalue <= 2\n let vector = Array(n).fill(0).map(() => Math.random() - 0.5);\n\n // Make orthogonal to first eigenvector\n const dot1 = vector.reduce((sum, val) => sum + (val / Math.sqrt(n)), 0);\n vector = vector.map((val) => val - (dot1 / Math.sqrt(n)));\n\n // Power iteration on shifted matrix\n for (let iter = 0; iter < 100; iter++) {\n // Compute (I - L/maxEig) * v\n const newVector = Array(n).fill(0) as number[];\n\n // Identity part\n for (let i = 0; i < n; i++) {\n newVector[i] = vector[i] ?? 0;\n }\n\n // Subtract L * v / maxEig\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n const matrixVal = matrix[i]?.[j] ?? 0;\n const vecVal = vector[j] ?? 0;\n newVector[i] = (newVector[i] ?? 0) - ((matrixVal * vecVal) / maxEig);\n }\n }\n\n // Orthogonalize against first eigenvector\n const dot = newVector.reduce((sum, val) => sum + (val / Math.sqrt(n)), 0);\n for (let i = 0; i < n; i++) {\n newVector[i] = (newVector[i] ?? 0) - (dot / Math.sqrt(n));\n }\n\n // Normalize\n const norm = Math.sqrt(newVector.reduce((sum, val) => sum + (val * val), 0));\n if (norm > 1e-10) {\n vector = newVector.map((val) => val / norm);\n }\n }\n\n eigenvectors.push(vector);\n eigenvalues.push(0.1); // Approximate\n }\n\n // For k = 3, add another eigenvector\n if (k >= 3) {\n let vector = Array(n).fill(0).map(() => Math.random() - 0.5);\n\n // Orthogonalize against previous eigenvectors\n for (const prev of eigenvectors) {\n const dot = vector.reduce((sum, val, idx) => sum + (val * (prev[idx] ?? 0)), 0);\n vector = vector.map((val, idx) => val - (dot * (prev[idx] ?? 0)));\n }\n\n // Similar power iteration\n for (let iter = 0; iter < 50; iter++) {\n const newVector = Array(n).fill(0) as number[];\n\n // Identity part\n for (let i = 0; i < n; i++) {\n newVector[i] = vector[i] ?? 0;\n }\n\n // Subtract L * v / 2\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n const matrixVal = matrix[i]?.[j] ?? 0;\n const vecVal = vector[j] ?? 0;\n newVector[i] = (newVector[i] ?? 0) - ((matrixVal * vecVal) / 2);\n }\n }\n\n // Orthogonalize\n for (const prev of eigenvectors) {\n const dot = newVector.reduce((sum, val, idx) => sum + (val * (prev[idx] ?? 0)), 0);\n for (let i = 0; i < n; i++) {\n newVector[i] = (newVector[i] ?? 0) - (dot * (prev[i] ?? 0));\n }\n }\n\n // Normalize\n const norm = Math.sqrt(newVector.reduce((sum, val) => sum + (val * val), 0));\n if (norm > 1e-10) {\n vector = newVector.map((val) => val / norm);\n }\n }\n\n eigenvectors.push(vector);\n eigenvalues.push(0.2); // Approximate\n }\n\n return {eigenvalues: eigenvalues.slice(0, k), eigenvectors: eigenvectors.slice(0, k)};\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport type {NodeId} from \"../../types/index.js\";\nimport {bfsColoringWithPartitions} from \"../traversal/bfs-variants.js\";\n\n/**\n * Maximum Bipartite Matching implementation using Hopcroft-Karp algorithm\n *\n * Finds the maximum matching in a bipartite graph. A matching is a set of edges\n * without common vertices. Maximum matching has the largest possible number of edges.\n *\n * Time complexity: O(√V × E)\n * Space complexity: O(V)\n */\n\nexport interface BipartiteMatchingResult {\n matching: Map<NodeId, NodeId>; // Maps left nodes to right nodes\n size: number; // Number of matched pairs\n}\n\nexport interface BipartiteMatchingOptions {\n leftNodes?: Set<NodeId>; // Optional: specify left partition\n rightNodes?: Set<NodeId>; // Optional: specify right partition\n}\n\n/**\n * Find maximum matching in a bipartite graph using augmenting path algorithm\n * (simplified implementation that's more reliable than Hopcroft-Karp for this context)\n */\nexport function maximumBipartiteMatching(\n graph: Graph,\n options: BipartiteMatchingOptions = {},\n): BipartiteMatchingResult {\n // If partitions not provided, try to infer them\n let {leftNodes, rightNodes} = options;\n\n if (!leftNodes || !rightNodes) {\n const partition = bipartitePartition(graph);\n if (!partition) {\n throw new Error(\"Graph is not bipartite\");\n }\n\n leftNodes = partition.left;\n rightNodes = partition.right;\n }\n\n const matching = new Map<NodeId, NodeId>();\n const matchRight = new Map<NodeId, NodeId>(); // Right to left matching\n\n // Find augmenting paths using DFS\n const visited = new Set<NodeId>();\n\n const dfs = (u: NodeId): boolean => {\n const neighbors = Array.from(graph.neighbors(u));\n\n for (const v of neighbors) {\n if (!rightNodes.has(v) || visited.has(v)) {\n continue;\n }\n\n visited.add(v);\n\n // If v is unmatched or we can find augmenting path from match of v\n const matchedNode = matchRight.get(v);\n if (!matchRight.has(v) || (matchedNode !== undefined && dfs(matchedNode))) {\n matching.set(u, v);\n matchRight.set(v, u);\n return true;\n }\n }\n return false;\n };\n\n // Try to find augmenting path for each left node\n let matchingSize = 0;\n for (const u of leftNodes) {\n visited.clear();\n if (dfs(u)) {\n matchingSize++;\n }\n }\n\n return {\n matching,\n size: matchingSize,\n };\n}\n\n/**\n * Check if graph is bipartite and return the partition\n */\nexport function bipartitePartition(graph: Graph): {left: Set<NodeId>, right: Set<NodeId>} | null {\n const result = bfsColoringWithPartitions(graph);\n\n if (!result.isBipartite || !result.partitions) {\n return null;\n }\n\n return {\n left: result.partitions[0],\n right: result.partitions[1],\n };\n}\n\n/**\n * Simple greedy bipartite matching algorithm\n * Useful for comparison or when Hopcroft-Karp is overkill\n */\nexport function greedyBipartiteMatching(\n graph: Graph,\n options: BipartiteMatchingOptions = {},\n): BipartiteMatchingResult {\n let {leftNodes, rightNodes} = options;\n\n if (!leftNodes || !rightNodes) {\n const partition = bipartitePartition(graph);\n if (!partition) {\n throw new Error(\"Graph is not bipartite\");\n }\n\n leftNodes = partition.left;\n rightNodes = partition.right;\n }\n\n const matching = new Map<NodeId, NodeId>();\n const matched = new Set<NodeId>();\n\n for (const u of leftNodes) {\n const neighbors = Array.from(graph.neighbors(u));\n\n for (const v of neighbors) {\n if (rightNodes.has(v) && !matched.has(v)) {\n matching.set(u, v);\n matched.add(v);\n break;\n }\n }\n }\n\n return {\n matching,\n size: matching.size,\n };\n}\n","import type {Graph} from \"../../core/graph.js\";\nimport type {NodeId} from \"../../types/index.js\";\n\n/**\n * Graph Isomorphism (VF2) algorithm implementation\n *\n * Determines if two graphs are isomorphic (structurally identical).\n * Two graphs are isomorphic if there exists a bijection between their vertices\n * that preserves adjacency.\n *\n * Based on the VF2 algorithm by Cordella et al. (2004)\n *\n * Time complexity: O(n! × n) worst case, but typically much faster\n * Space complexity: O(n)\n */\n\nexport interface IsomorphismResult {\n isIsomorphic: boolean;\n mapping?: Map<NodeId, NodeId>; // Maps nodes from graph1 to graph2\n}\n\nexport interface IsomorphismOptions {\n nodeMatch?: (node1: NodeId, node2: NodeId, g1: Graph, g2: Graph) => boolean;\n edgeMatch?: (edge1: [NodeId, NodeId], edge2: [NodeId, NodeId], g1: Graph, g2: Graph) => boolean;\n findAllMappings?: boolean; // Find all possible isomorphisms\n}\n\ninterface VF2State {\n core1: Map<NodeId, NodeId>; // Mapping from G1 to G2\n core2: Map<NodeId, NodeId>; // Mapping from G2 to G1\n in1: Map<NodeId, number>; // Terminal set in G1\n in2: Map<NodeId, number>; // Terminal set in G2\n out1: Map<NodeId, number>; // Terminal set out G1\n out2: Map<NodeId, number>; // Terminal set out G2\n depth: number; // Current depth of search\n}\n\n/**\n * Check if two graphs are isomorphic using VF2 algorithm\n */\nexport function isGraphIsomorphic(\n graph1: Graph,\n graph2: Graph,\n options: IsomorphismOptions = {},\n): IsomorphismResult {\n // Quick checks\n if (graph1.nodeCount !== graph2.nodeCount || graph1.totalEdgeCount !== graph2.totalEdgeCount) {\n return {isIsomorphic: false};\n }\n\n if (graph1.isDirected !== graph2.isDirected) {\n return {isIsomorphic: false};\n }\n\n const nodes1 = Array.from(graph1.nodes()).map((n) => n.id);\n const nodes2 = Array.from(graph2.nodes()).map((n) => n.id);\n\n // Check degree sequences\n const degrees1 = nodes1.map((n) => graph1.degree(n)).sort((a, b) => a - b);\n const degrees2 = nodes2.map((n) => graph2.degree(n)).sort((a, b) => a - b);\n\n for (let i = 0; i < degrees1.length; i++) {\n if (degrees1[i] !== degrees2[i]) {\n return {isIsomorphic: false};\n }\n }\n\n // Initialize VF2 state\n const state: VF2State = {\n core1: new Map(),\n core2: new Map(),\n in1: new Map(),\n in2: new Map(),\n out1: new Map(),\n out2: new Map(),\n depth: 0,\n };\n\n // Find isomorphism\n const mappings: Map<NodeId, NodeId>[] = [];\n const found = vf2Recurse(graph1, graph2, state, nodes1, nodes2, options, mappings);\n\n if (found && mappings.length > 0) {\n return {\n isIsomorphic: true,\n mapping: mappings[0] ?? new Map<NodeId, NodeId>(),\n };\n }\n\n return {isIsomorphic: false};\n}\n\n/**\n * VF2 recursive search\n */\nfunction vf2Recurse(\n g1: Graph,\n g2: Graph,\n state: VF2State,\n nodes1: NodeId[],\n nodes2: NodeId[],\n options: IsomorphismOptions,\n mappings: Map<NodeId, NodeId>[],\n): boolean {\n // Check if we've found a complete mapping\n if (state.core1.size === nodes1.length) {\n mappings.push(new Map(state.core1));\n return !options.findAllMappings; // Continue if we want all mappings\n }\n\n // Get candidate pairs\n const candidates = getCandidatePairs(g1, g2, state, nodes1, nodes2);\n\n for (const [node1, node2] of candidates) {\n if (isFeasible(g1, g2, state, node1, node2, options)) {\n // Add pair to mapping\n const newState = addPair(g1, g2, state, node1, node2);\n\n if (vf2Recurse(g1, g2, newState, nodes1, nodes2, options, mappings)) {\n return true;\n }\n }\n }\n\n return false;\n}\n\n/**\n * Get candidate pairs for the next mapping\n */\nfunction getCandidatePairs(\n g1: Graph,\n g2: Graph,\n state: VF2State,\n nodes1: NodeId[],\n nodes2: NodeId[],\n): [NodeId, NodeId][] {\n const pairs: [NodeId, NodeId][] = [];\n\n // Try to pick from terminal sets first\n let node1: NodeId | null = null;\n\n // Pick from out1\n for (const [n] of state.out1) {\n if (!state.core1.has(n)) {\n node1 = n;\n break;\n }\n }\n\n // If not found, pick from in1\n if (!node1) {\n for (const [n] of state.in1) {\n if (!state.core1.has(n)) {\n node1 = n;\n break;\n }\n }\n }\n\n // If still not found, pick any unmapped node\n if (!node1) {\n for (const n of nodes1) {\n if (!state.core1.has(n)) {\n node1 = n;\n break;\n }\n }\n }\n\n if (!node1) {\n return pairs;\n }\n\n // Find compatible nodes in G2\n for (const node2 of nodes2) {\n if (!state.core2.has(node2)) {\n // Basic compatibility check\n if (g1.degree(node1) === g2.degree(node2)) {\n pairs.push([node1, node2]);\n }\n }\n }\n\n return pairs;\n}\n\n/**\n * Check if a pair is feasible\n */\nfunction isFeasible(\n g1: Graph,\n g2: Graph,\n state: VF2State,\n node1: NodeId,\n node2: NodeId,\n options: IsomorphismOptions,\n): boolean {\n // Node match predicate\n if (options.nodeMatch && !options.nodeMatch(node1, node2, g1, g2)) {\n return false;\n }\n\n // Check syntactic feasibility\n const neighbors1 = new Set(g1.neighbors(node1));\n const neighbors2 = new Set(g2.neighbors(node2));\n\n // Check that mapped neighbors correspond\n for (const [n1, n2] of state.core1) {\n if (neighbors1.has(n1)) {\n if (!neighbors2.has(n2)) {\n return false;\n }\n\n // Edge match predicate\n if (options.edgeMatch && !options.edgeMatch([node1, n1], [node2, n2], g1, g2)) {\n return false;\n }\n } else if (neighbors2.has(n2)) {\n return false;\n }\n }\n\n // Check terminal set sizes\n let new1In = 0; let new1Out = 0; let term1In = 0; let term1Out = 0;\n let new2In = 0; let new2Out = 0; let term2In = 0; let term2Out = 0;\n\n for (const neighbor of neighbors1) {\n if (state.core1.has(neighbor)) {\n // Already mapped\n } else if (state.in1.has(neighbor)) {\n term1In++;\n } else if (state.out1.has(neighbor)) {\n term1Out++;\n } else {\n if (g1.isDirected) {\n if (g1.hasEdge(neighbor, node1)) {\n new1In++;\n }\n\n if (g1.hasEdge(node1, neighbor)) {\n new1Out++;\n }\n } else {\n new1In++;\n new1Out++;\n }\n }\n }\n\n for (const neighbor of neighbors2) {\n if (state.core2.has(neighbor)) {\n // Already mapped\n } else if (state.in2.has(neighbor)) {\n term2In++;\n } else if (state.out2.has(neighbor)) {\n term2Out++;\n } else {\n if (g2.isDirected) {\n if (g2.hasEdge(neighbor, node2)) {\n new2In++;\n }\n\n if (g2.hasEdge(node2, neighbor)) {\n new2Out++;\n }\n } else {\n new2In++;\n new2Out++;\n }\n }\n }\n\n return term1In === term2In && term1Out === term2Out &&\n new1In === new2In && new1Out === new2Out;\n}\n\n/**\n * Add a pair to the mapping and update terminal sets\n */\nfunction addPair(\n g1: Graph,\n g2: Graph,\n state: VF2State,\n node1: NodeId,\n node2: NodeId,\n): VF2State {\n const newState: VF2State = {\n core1: new Map(state.core1),\n core2: new Map(state.core2),\n in1: new Map(state.in1),\n in2: new Map(state.in2),\n out1: new Map(state.out1),\n out2: new Map(state.out2),\n depth: state.depth + 1,\n };\n\n newState.core1.set(node1, node2);\n newState.core2.set(node2, node1);\n\n // Update terminal sets\n const neighbors1 = g1.neighbors(node1);\n for (const neighbor of neighbors1) {\n if (!newState.core1.has(neighbor) && !newState.in1.has(neighbor) && !newState.out1.has(neighbor)) {\n if (g1.isDirected) {\n if (g1.hasEdge(neighbor, node1)) {\n newState.in1.set(neighbor, newState.depth);\n }\n\n if (g1.hasEdge(node1, neighbor)) {\n newState.out1.set(neighbor, newState.depth);\n }\n } else {\n newState.in1.set(neighbor, newState.depth);\n newState.out1.set(neighbor, newState.depth);\n }\n }\n }\n\n const neighbors2 = g2.neighbors(node2);\n for (const neighbor of neighbors2) {\n if (!newState.core2.has(neighbor) && !newState.in2.has(neighbor) && !newState.out2.has(neighbor)) {\n if (g2.isDirected) {\n if (g2.hasEdge(neighbor, node2)) {\n newState.in2.set(neighbor, newState.depth);\n }\n\n if (g2.hasEdge(node2, neighbor)) {\n newState.out2.set(neighbor, newState.depth);\n }\n } else {\n newState.in2.set(neighbor, newState.depth);\n newState.out2.set(neighbor, newState.depth);\n }\n }\n }\n\n return newState;\n}\n\n/**\n * Find all isomorphisms between two graphs\n */\nexport function findAllIsomorphisms(\n graph1: Graph,\n graph2: Graph,\n options: IsomorphismOptions = {},\n): Map<NodeId, NodeId>[] {\n // Quick checks\n if (graph1.nodeCount !== graph2.nodeCount || graph1.totalEdgeCount !== graph2.totalEdgeCount) {\n return [];\n }\n\n if (graph1.isDirected !== graph2.isDirected) {\n return [];\n }\n\n const nodes1 = Array.from(graph1.nodes()).map((n) => n.id);\n const nodes2 = Array.from(graph2.nodes()).map((n) => n.id);\n\n // Check degree sequences\n const degrees1 = nodes1.map((n) => graph1.degree(n)).sort((a, b) => a - b);\n const degrees2 = nodes2.map((n) => graph2.degree(n)).sort((a, b) => a - b);\n\n for (let i = 0; i < degrees1.length; i++) {\n if (degrees1[i] !== degrees2[i]) {\n return [];\n }\n }\n\n // Handle empty graphs\n if (nodes1.length === 0) {\n return [new Map<NodeId, NodeId>()];\n }\n\n // Initialize VF2 state\n const state: VF2State = {\n core1: new Map(),\n core2: new Map(),\n in1: new Map(),\n in2: new Map(),\n out1: new Map(),\n out2: new Map(),\n depth: 0,\n };\n\n // Find all isomorphisms\n const mappings: Map<NodeId, NodeId>[] = [];\n vf2Recurse(graph1, graph2, state, nodes1, nodes2, {... options, findAllMappings: true}, mappings);\n\n return mappings;\n}\n","import type {Graph} from \"../core/graph.js\";\nimport type {NodeId} from \"../types/index.js\";\nimport {getCommonNeighbors, getIntermediateNodes} from \"../utils/graph-utilities.js\";\nimport type {LinkPredictionOptions, LinkPredictionScore} from \"./common-neighbors.js\";\n\n/**\n * Adamic-Adar Index link prediction implementation\n *\n * Predicts the likelihood of a link between two nodes based on their common\n * neighbors, weighted by the inverse logarithm of the neighbors' degrees.\n * This gives higher weight to rare common neighbors.\n *\n * Formula: AA(x,y) = Σ (1 / log(|Γ(z)|)) for all z ∈ Γ(x) ∩ Γ(y)\n * where Γ(z) is the set of neighbors of node z\n *\n * Time complexity: O(k²) where k is the average degree\n * Space complexity: O(k)\n */\n\n/**\n * Calculate Adamic-Adar index for a pair of nodes\n */\nexport function adamicAdarScore(\n graph: Graph,\n source: NodeId,\n target: NodeId,\n options: LinkPredictionOptions = {},\n): number {\n if (!graph.hasNode(source) || !graph.hasNode(target)) {\n return 0;\n }\n\n const {directed = false} = options;\n\n // Use utility function to get common neighbors\n // For directed graphs, we want intermediate nodes that form paths source->X->target\n const commonNeighborsSet = directed ?\n getIntermediateNodes(graph, source, target) :\n getCommonNeighbors(graph, source, target, false);\n\n // Calculate Adamic-Adar score\n let score = 0;\n for (const neighbor of commonNeighborsSet) {\n const degree = directed ?\n graph.outDegree(neighbor) : // Use out-degree for directed graphs\n graph.degree(neighbor); // Use total degree for undirected graphs\n\n if (degree > 1) {\n score += 1 / Math.log(degree);\n } else if (degree === 1) {\n // For degree 1, we can't use log(1) = 0, so use a small constant\n score += 1; // or some other reasonable value\n }\n }\n\n return score;\n}\n\n/**\n * Calculate Adamic-Adar scores for all possible node pairs\n */\nexport function adamicAdarPrediction(\n graph: Graph,\n options: LinkPredictionOptions = {},\n): LinkPredictionScore[] {\n const {\n directed = false,\n includeExisting = false,\n topK,\n } = options;\n\n const scores: LinkPredictionScore[] = [];\n const nodes = Array.from(graph.nodes()).map((n) => n.id);\n\n for (let i = 0; i < nodes.length; i++) {\n for (let j = i + 1; j < nodes.length; j++) {\n const source = nodes[i];\n const target = nodes[j];\n\n if (!source || !target) {\n continue;\n }\n\n // Skip existing edges unless requested\n if (!includeExisting && graph.hasEdge(source, target)) {\n continue;\n }\n\n const score = adamicAdarScore(graph, source, target, {directed});\n\n if (score > 0) {\n scores.push({source, target, score});\n\n // For undirected graphs, also add the reverse pair\n if (!directed && source !== target) {\n scores.push({source: target, target: source, score});\n }\n }\n }\n }\n\n // Sort by score in descending order\n scores.sort((a, b) => b.score - a.score);\n\n // Return top K if specified\n if (topK && topK > 0) {\n return scores.slice(0, topK);\n }\n\n return scores;\n}\n\n/**\n * Calculate Adamic-Adar scores for specific node pairs\n */\nexport function adamicAdarForPairs(\n graph: Graph,\n pairs: [NodeId, NodeId][],\n options: LinkPredictionOptions = {},\n): LinkPredictionScore[] {\n return pairs.map(([source, target]) => ({\n source,\n target,\n score: adamicAdarScore(graph, source, target, options),\n }));\n}\n\n/**\n * Get top Adamic-Adar candidates for link prediction for a specific node\n */\nexport function getTopAdamicAdarCandidatesForNode(\n graph: Graph,\n node: NodeId,\n options: LinkPredictionOptions & {candidates?: NodeId[]} = {},\n): LinkPredictionScore[] {\n if (!graph.hasNode(node)) {\n return [];\n }\n\n const {\n directed = false,\n includeExisting = false,\n topK = 10,\n candidates,\n } = options;\n\n const scores: LinkPredictionScore[] = [];\n const targetNodes = candidates ?? Array.from(graph.nodes()).map((n) => n.id);\n\n for (const target of targetNodes) {\n if (target === node) {\n continue;\n }\n\n // Skip existing edges unless requested\n if (!includeExisting && graph.hasEdge(node, target)) {\n continue;\n }\n\n const score = adamicAdarScore(graph, node, target, {directed});\n\n if (score > 0) {\n scores.push({source: node, target, score});\n }\n }\n\n // Sort by score in descending order\n scores.sort((a, b) => b.score - a.score);\n\n return scores.slice(0, topK);\n}\n\n/**\n * Calculate precision and recall for Adamic-Adar link prediction evaluation\n */\nexport function evaluateAdamicAdar(\n trainingGraph: Graph,\n testEdges: [NodeId, NodeId][],\n nonEdges: [NodeId, NodeId][],\n options: LinkPredictionOptions = {},\n): {\n precision: number;\n recall: number;\n f1Score: number;\n auc: number;\n } {\n // Get scores for test edges and non-edges\n const testScores = adamicAdarForPairs(trainingGraph, testEdges, options);\n const nonEdgeScores = adamicAdarForPairs(trainingGraph, nonEdges, options);\n\n // Combine and sort all scores\n const allScores = [\n ... testScores.map((s) => ({... s, isActualEdge: true})),\n ... nonEdgeScores.map((s) => ({... s, isActualEdge: false})),\n ].sort((a, b) => b.score - a.score);\n\n // Calculate precision and recall at different thresholds\n let truePositives = 0;\n let falsePositives = 0;\n let bestF1 = 0;\n let bestPrecision = 0;\n let bestRecall = 0;\n\n const totalPositives = testEdges.length;\n\n for (const scoreItem of allScores) {\n if (scoreItem.isActualEdge) {\n truePositives++;\n } else {\n falsePositives++;\n }\n\n const precision = truePositives / (truePositives + falsePositives);\n const recall = truePositives / totalPositives;\n const f1 = precision + recall > 0 ? 2 * (precision * recall) / (precision + recall) : 0;\n\n if (f1 > bestF1) {\n bestF1 = f1;\n bestPrecision = precision;\n bestRecall = recall;\n }\n }\n\n // Calculate AUC (Area Under Curve)\n let auc = 0;\n let tpCount = 0;\n let fpCount = 0;\n\n for (const item of allScores) {\n if (item.isActualEdge) {\n tpCount++;\n } else {\n auc += tpCount;\n fpCount++;\n }\n }\n\n if (tpCount > 0 && fpCount > 0) {\n auc = auc / (tpCount * fpCount);\n } else {\n auc = 0.5; // Random performance\n }\n\n return {\n precision: bestPrecision,\n recall: bestRecall,\n f1Score: bestF1,\n auc,\n };\n}\n\n/**\n * Compare Adamic-Adar with Common Neighbors for the same dataset\n */\nexport function compareAdamicAdarWithCommonNeighbors(\n graph: Graph,\n testEdges: [NodeId, NodeId][],\n nonEdges: [NodeId, NodeId][],\n options: LinkPredictionOptions = {},\n): {\n adamicAdar: ReturnType<typeof evaluateAdamicAdar>;\n commonNeighbors: {\n precision: number;\n recall: number;\n f1Score: number;\n auc: number;\n };\n } {\n // Import common neighbors evaluation function\n // Since we're using ES modules, we can't use require. Instead, we'll implement a simple version here\n const commonNeighborsPairs = (pairs: [NodeId, NodeId][]): LinkPredictionScore[] =>\n pairs.map(([source, target]) => ({\n source,\n target,\n score: getCommonNeighbors(graph, source, target, options.directed).size,\n }));\n\n const testScores = commonNeighborsPairs(testEdges);\n const nonEdgeScores = commonNeighborsPairs(nonEdges);\n\n const allScores = [\n ... testScores.map((s) => ({... s, isActualEdge: true})),\n ... nonEdgeScores.map((s) => ({... s, isActualEdge: false})),\n ].sort((a, b) => b.score - a.score);\n\n let truePositives = 0;\n let falsePositives = 0;\n let bestF1 = 0;\n let bestPrecision = 0;\n let bestRecall = 0;\n const totalPositives = testEdges.length;\n\n for (const scoreItem of allScores) {\n if (scoreItem.isActualEdge) {\n truePositives++;\n } else {\n falsePositives++;\n }\n\n const precision = truePositives / (truePositives + falsePositives);\n const recall = truePositives / totalPositives;\n const f1 = precision + recall > 0 ? 2 * (precision * recall) / (precision + recall) : 0;\n if (f1 > bestF1) {\n bestF1 = f1;\n bestPrecision = precision;\n bestRecall = recall;\n }\n }\n\n let auc = 0;\n let tpCount = 0;\n let fpCount = 0;\n for (const item of allScores) {\n if (item.isActualEdge) {\n tpCount++;\n } else {\n auc += tpCount;\n fpCount++;\n }\n }\n if (tpCount > 0 && fpCount > 0) {\n auc = auc / (tpCount * fpCount);\n } else {\n auc = 0.5;\n }\n\n const commonNeighborsResults = {\n precision: bestPrecision,\n recall: bestRecall,\n f1Score: bestF1,\n auc,\n };\n\n const adamicAdarResults = evaluateAdamicAdar(graph, testEdges, nonEdges, options);\n\n return {\n adamicAdar: adamicAdarResults,\n commonNeighbors: commonNeighborsResults,\n };\n}\n","import type {Graph} from \"../core/graph.js\";\nimport type {NodeId} from \"../types/index.js\";\nimport {getCommonNeighbors, getIntermediateNodes} from \"../utils/graph-utilities.js\";\n\n/**\n * Common Neighbors link prediction implementation\n *\n * Predicts the likelihood of a link between two nodes based on the number\n * of common neighbors they share. The intuition is that nodes with many\n * common neighbors are more likely to be connected.\n *\n * Time complexity: O(k²) where k is the average degree\n * Space complexity: O(k)\n */\n\nexport interface LinkPredictionScore {\n source: NodeId;\n target: NodeId;\n score: number;\n}\n\nexport interface LinkPredictionOptions {\n directed?: boolean; // Consider direction (default: false)\n includeExisting?: boolean; // Include existing edges (default: false)\n topK?: number; // Return only top K predictions\n}\n\n/**\n * Calculate common neighbors score for a pair of nodes\n */\nexport function commonNeighborsScore(\n graph: Graph,\n source: NodeId,\n target: NodeId,\n options: LinkPredictionOptions = {},\n): number {\n if (!graph.hasNode(source) || !graph.hasNode(target)) {\n return 0;\n }\n\n const {directed = false} = options;\n\n // Use utility function to get common neighbors\n // For directed graphs, we want intermediate nodes that form paths source->X->target\n const commonNeighborsSet = directed ?\n getIntermediateNodes(graph, source, target) :\n getCommonNeighbors(graph, source, target, false);\n\n return commonNeighborsSet.size;\n}\n\n/**\n * Calculate common neighbors scores for all possible node pairs\n */\nexport function commonNeighborsPrediction(\n graph: Graph,\n options: LinkPredictionOptions = {},\n): LinkPredictionScore[] {\n const {\n directed = false,\n includeExisting = false,\n topK,\n } = options;\n\n const scores: LinkPredictionScore[] = [];\n const nodes = Array.from(graph.nodes()).map((n) => n.id);\n\n for (let i = 0; i < nodes.length; i++) {\n for (let j = i + 1; j < nodes.length; j++) {\n const source = nodes[i];\n const target = nodes[j];\n\n if (!source || !target) {\n continue;\n }\n\n // Skip existing edges unless requested\n if (!includeExisting && graph.hasEdge(source, target)) {\n continue;\n }\n\n const score = commonNeighborsScore(graph, source, target, {directed});\n\n if (score > 0) {\n scores.push({source, target, score});\n\n // For undirected graphs, also add the reverse pair\n if (!directed && source !== target) {\n scores.push({source: target, target: source, score});\n }\n }\n }\n }\n\n // Sort by score in descending order\n scores.sort((a, b) => b.score - a.score);\n\n // Return top K if specified\n if (topK && topK > 0) {\n return scores.slice(0, topK);\n }\n\n return scores;\n}\n\n/**\n * Calculate common neighbors scores for specific node pairs\n */\nexport function commonNeighborsForPairs(\n graph: Graph,\n pairs: [NodeId, NodeId][],\n options: LinkPredictionOptions = {},\n): LinkPredictionScore[] {\n return pairs.map(([source, target]) => ({\n source,\n target,\n score: commonNeighborsScore(graph, source, target, options),\n }));\n}\n\n/**\n * Get top candidates for link prediction for a specific node\n */\nexport function getTopCandidatesForNode(\n graph: Graph,\n node: NodeId,\n options: LinkPredictionOptions & {candidates?: NodeId[]} = {},\n): LinkPredictionScore[] {\n if (!graph.hasNode(node)) {\n return [];\n }\n\n const {\n directed = false,\n includeExisting = false,\n topK = 10,\n candidates,\n } = options;\n\n const scores: LinkPredictionScore[] = [];\n const targetNodes = candidates ?? Array.from(graph.nodes()).map((n) => n.id);\n\n for (const target of targetNodes) {\n if (target === node) {\n continue;\n }\n\n // Skip existing edges unless requested\n if (!includeExisting && graph.hasEdge(node, target)) {\n continue;\n }\n\n const score = commonNeighborsScore(graph, node, target, {directed});\n\n if (score > 0) {\n scores.push({source: node, target, score});\n }\n }\n\n // Sort by score in descending order\n scores.sort((a, b) => b.score - a.score);\n\n return scores.slice(0, topK);\n}\n\n/**\n * Calculate precision and recall for link prediction evaluation\n */\nexport function evaluateCommonNeighbors(\n trainingGraph: Graph,\n testEdges: [NodeId, NodeId][],\n nonEdges: [NodeId, NodeId][],\n options: LinkPredictionOptions = {},\n): {\n precision: number;\n recall: number;\n f1Score: number;\n auc: number;\n } {\n // Get scores for test edges and non-edges\n const testScores = commonNeighborsForPairs(trainingGraph, testEdges, options);\n const nonEdgeScores = commonNeighborsForPairs(trainingGraph, nonEdges, options);\n\n // Combine and sort all scores\n const allScores = [\n ... testScores.map((s) => ({... s, isActualEdge: true})),\n ... nonEdgeScores.map((s) => ({... s, isActualEdge: false})),\n ].sort((a, b) => b.score - a.score);\n\n // Calculate precision and recall at different thresholds\n let truePositives = 0;\n let falsePositives = 0;\n let bestF1 = 0;\n let bestPrecision = 0;\n let bestRecall = 0;\n\n const totalPositives = testEdges.length;\n\n for (const scoreItem of allScores) {\n if (scoreItem.isActualEdge) {\n truePositives++;\n } else {\n falsePositives++;\n }\n\n const precision = truePositives / (truePositives + falsePositives);\n const recall = truePositives / totalPositives;\n const f1 = precision + recall > 0 ? 2 * (precision * recall) / (precision + recall) : 0;\n\n if (f1 > bestF1) {\n bestF1 = f1;\n bestPrecision = precision;\n bestRecall = recall;\n }\n }\n\n // Calculate AUC (Area Under Curve)\n let auc = 0;\n let tpCount = 0;\n let fpCount = 0;\n\n for (const item of allScores) {\n if (item.isActualEdge) {\n tpCount++;\n } else {\n auc += tpCount;\n fpCount++;\n }\n }\n\n if (tpCount > 0 && fpCount > 0) {\n auc = auc / (tpCount * fpCount);\n } else {\n auc = 0.5; // Random performance\n }\n\n return {\n precision: bestPrecision,\n recall: bestRecall,\n f1Score: bestF1,\n auc,\n };\n}\n","import type {Graph} from \"../core/graph.js\";\nimport type {NodeId} from \"../types/index.js\";\nimport {euclideanDistance, SeededRandom} from \"../utils/math-utilities.js\";\n\n/**\n * Configuration options for the SynC (Synergistic Deep Graph Clustering) algorithm\n */\nexport interface SynCConfig {\n /** Number of clusters to find */\n numClusters: number;\n /** Maximum number of iterations for convergence */\n maxIterations?: number;\n /** Convergence tolerance */\n tolerance?: number;\n /** Random seed for reproducibility */\n seed?: number;\n /** Learning rate for optimization */\n learningRate?: number;\n /** Regularization parameter */\n lambda?: number;\n}\n\n/**\n * Result of the SynC clustering algorithm\n */\nexport interface SynCResult {\n /** Cluster assignments for each node */\n clusters: Map<NodeId, number>;\n /** Final loss value */\n loss: number;\n /** Number of iterations performed */\n iterations: number;\n /** Node embeddings learned by the algorithm */\n embeddings: Map<NodeId, number[]>;\n /** Whether the algorithm converged */\n converged: boolean;\n}\n\n/**\n * Synergistic Deep Graph Clustering (SynC) Algorithm\n *\n * This algorithm combines representation learning with structure augmentation\n * for improved clustering performance on graphs. It jointly optimizes node\n * embeddings and cluster assignments while preserving graph structure.\n *\n * Based on: \"Synergistic Deep Graph Clustering\" (arXiv:2406.15797, June 2024)\n *\n * @param graph - Input graph to cluster\n * @param config - Configuration options\n * @returns Clustering result with assignments and embeddings\n */\nexport function syncClustering(graph: Graph, config: SynCConfig): SynCResult {\n const {\n numClusters,\n maxIterations = 100,\n tolerance = 1e-6,\n seed = 42,\n learningRate = 0.01,\n lambda = 0.1,\n } = config;\n\n // Set random seed for reproducibility (save original)\n const originalRandom = Math.random;\n const rng = SeededRandom.createGenerator(seed);\n Math.random = rng;\n\n const nodes = Array.from(graph.nodes());\n const nodeCount = nodes.length;\n\n if (nodeCount === 0) {\n return {\n clusters: new Map(),\n loss: 0,\n iterations: 0,\n embeddings: new Map(),\n converged: true,\n };\n }\n\n if (numClusters <= 0 || numClusters > nodeCount) {\n throw new Error(`Invalid number of clusters: ${String(numClusters)}. Must be between 1 and ${String(nodeCount)}`);\n }\n\n // Initialize node embeddings (simplified version using graph features)\n const embeddingDim = Math.min(64, nodeCount);\n const embeddings = new Map<NodeId, number[]>();\n\n // Initialize embeddings based on node features\n for (const node of nodes) {\n const embedding = initializeNodeEmbedding(graph, node.id, embeddingDim);\n embeddings.set(node.id, embedding);\n }\n\n // Initialize cluster centers\n const clusterCenters = initializeClusterCenters(embeddings, numClusters);\n\n let previousLoss = Infinity;\n let iterations = 0;\n let converged = false;\n\n for (iterations = 0; iterations < maxIterations; iterations++) {\n // E-step: Assign nodes to clusters\n const clusters = new Map<NodeId, number>();\n\n for (const node of nodes) {\n const nodeEmbedding = embeddings.get(node.id);\n if (!nodeEmbedding) {\n continue;\n }\n\n let bestCluster = 0;\n let minDistance = Infinity;\n\n for (let k = 0; k < numClusters; k++) {\n const center = clusterCenters[k];\n if (!center) {\n continue;\n }\n\n const distance = euclideanDistance(nodeEmbedding, center);\n if (distance < minDistance) {\n minDistance = distance;\n bestCluster = k;\n }\n }\n\n clusters.set(node.id, bestCluster);\n }\n\n // M-step: Update embeddings and cluster centers\n updateEmbeddings(graph, embeddings, clusters, learningRate, lambda);\n updateClusterCenters(embeddings, clusters, clusterCenters, numClusters);\n\n // Calculate current loss\n const currentLoss = calculateLoss(graph, embeddings, clusters, clusterCenters, lambda);\n\n // Check for convergence\n if (Math.abs(previousLoss - currentLoss) < tolerance) {\n converged = true;\n break;\n }\n\n previousLoss = currentLoss;\n }\n\n // Final cluster assignment\n const finalClusters = new Map<NodeId, number>();\n for (const node of nodes) {\n const nodeEmbedding = embeddings.get(node.id);\n if (!nodeEmbedding) {\n continue;\n }\n\n let bestCluster = 0;\n let minDistance = Infinity;\n\n for (let k = 0; k < numClusters; k++) {\n const center = clusterCenters[k];\n if (!center) {\n continue;\n }\n\n const distance = euclideanDistance(nodeEmbedding, center);\n if (distance < minDistance) {\n minDistance = distance;\n bestCluster = k;\n }\n }\n\n finalClusters.set(node.id, bestCluster);\n }\n\n // Restore original random function\n Math.random = originalRandom;\n\n return {\n clusters: finalClusters,\n loss: previousLoss,\n iterations: iterations + 1,\n embeddings,\n converged,\n };\n}\n\n/**\n * Initialize node embedding based on graph structure and features\n */\nfunction initializeNodeEmbedding(graph: Graph, nodeId: NodeId, dim: number): number[] {\n const embedding = new Array<number>(dim).fill(0);\n\n // Use node degree as a base feature\n const degree = graph.degree(nodeId);\n const normalizedDegree = degree / Math.max(1, graph.nodeCount - 1);\n\n // Initialize with small random values influenced by graph structure\n for (let i = 0; i < dim; i++) {\n embedding[i] = ((Math.random() - 0.5) * 0.1) + (normalizedDegree * 0.1);\n }\n\n return embedding;\n}\n\n/**\n * Initialize cluster centers using k-means++ style initialization\n */\nfunction initializeClusterCenters(embeddings: Map<NodeId, number[]>, numClusters: number): number[][] {\n const embeddingArray = Array.from(embeddings.values());\n const centers: number[][] = [];\n\n // Choose first center randomly\n const firstCenter = embeddingArray[Math.floor(Math.random() * embeddingArray.length)];\n if (firstCenter) {\n centers.push([... firstCenter] as number[]);\n }\n\n // Choose remaining centers using k-means++ initialization\n for (let k = 1; k < numClusters; k++) {\n const distances: number[] = [];\n let totalDistance = 0;\n\n for (const embedding of embeddingArray) {\n let minDistance = Infinity;\n for (const center of centers) {\n const distance = euclideanDistance(embedding, center);\n minDistance = Math.min(minDistance, distance);\n }\n distances.push(minDistance * minDistance);\n totalDistance += minDistance * minDistance;\n }\n\n // Choose next center with probability proportional to squared distance\n let randomValue = Math.random() * totalDistance;\n for (let i = 0; i < embeddingArray.length; i++) {\n const distanceValue = distances[i];\n if (distanceValue !== undefined) {\n randomValue -= distanceValue;\n }\n\n if (randomValue <= 0) {\n const newCenter = embeddingArray[i];\n if (newCenter) {\n centers.push([... newCenter] as number[]);\n }\n\n break;\n }\n }\n }\n\n return centers;\n}\n\n/**\n * Update node embeddings using gradient descent\n */\nfunction updateEmbeddings(\n graph: Graph,\n embeddings: Map<NodeId, number[]>,\n clusters: Map<NodeId, number>,\n learningRate: number,\n lambda: number,\n): void {\n const gradients = new Map<NodeId, number[]>();\n\n // Initialize gradients\n for (const [nodeId, embedding] of embeddings) {\n gradients.set(nodeId, new Array<number>(embedding.length).fill(0));\n }\n\n // Calculate gradients based on graph structure (simplified)\n for (const node of graph.nodes()) {\n const nodeId = node.id;\n const nodeEmbedding = embeddings.get(nodeId);\n if (!nodeEmbedding) {\n continue;\n }\n\n const gradient = gradients.get(nodeId);\n if (!gradient) {\n continue;\n }\n\n // Neighbor reconstruction loss gradient\n for (const neighborId of graph.neighbors(nodeId)) {\n const neighborEmbedding = embeddings.get(neighborId);\n if (!neighborEmbedding) {\n continue;\n }\n\n const diff = nodeEmbedding.map((val: number, i: number) => val - (neighborEmbedding[i] ?? 0));\n\n for (let i = 0; i < gradient.length; i++) {\n const gradVal = gradient[i];\n const diffVal = diff[i];\n if (gradVal !== undefined && diffVal !== undefined) {\n gradient[i] = gradVal + (lambda * diffVal);\n }\n }\n }\n\n // Regularization gradient\n for (let i = 0; i < gradient.length; i++) {\n const gradVal = gradient[i];\n const nodeVal = nodeEmbedding[i];\n if (gradVal !== undefined && nodeVal !== undefined) {\n gradient[i] = gradVal + (lambda * nodeVal);\n }\n }\n }\n\n // Update embeddings\n for (const [nodeId, embedding] of embeddings) {\n const gradient = gradients.get(nodeId);\n if (!gradient) {\n continue;\n }\n\n for (let i = 0; i < embedding.length; i++) {\n const embVal = embedding[i];\n const gradVal = gradient[i];\n if (embVal !== undefined && gradVal !== undefined) {\n embedding[i] = embVal - (learningRate * gradVal);\n }\n }\n }\n}\n\n/**\n * Update cluster centers based on current assignments\n */\nfunction updateClusterCenters(\n embeddings: Map<NodeId, number[]>,\n clusters: Map<NodeId, number>,\n clusterCenters: number[][],\n numClusters: number,\n): void {\n const dimensions = clusterCenters[0]?.length ?? 0;\n const clusterSums: number[][] = Array.from({length: numClusters}, () =>\n new Array(dimensions).fill(0) as number[],\n );\n const clusterCounts = new Array<number>(numClusters).fill(0);\n\n // Sum embeddings for each cluster\n for (const [nodeId, clusterIdx] of clusters) {\n const embedding = embeddings.get(nodeId);\n if (!embedding) {\n continue;\n }\n\n for (let i = 0; i < embedding.length; i++) {\n const clusterSum = clusterSums[clusterIdx];\n if (!clusterSum) {\n continue;\n }\n\n const sumVal = clusterSum[i];\n const embVal = embedding[i];\n if (sumVal !== undefined && embVal !== undefined) {\n clusterSum[i] = sumVal + embVal;\n }\n }\n if (clusterCounts[clusterIdx] !== undefined) {\n clusterCounts[clusterIdx]++;\n }\n }\n\n // Update cluster centers (average of assigned embeddings)\n for (let k = 0; k < numClusters; k++) {\n const count = clusterCounts[k];\n const center = clusterCenters[k];\n const sum = clusterSums[k];\n if (count !== undefined && count > 0 && center && sum) {\n for (let i = 0; i < center.length; i++) {\n const sumVal = sum[i];\n if (sumVal !== undefined) {\n center[i] = sumVal / count;\n }\n }\n }\n }\n}\n\n/**\n * Calculate the total loss function\n */\nfunction calculateLoss(\n graph: Graph,\n embeddings: Map<NodeId, number[]>,\n clusters: Map<NodeId, number>,\n clusterCenters: number[][],\n lambda: number,\n): number {\n let clusteringLoss = 0;\n let reconstructionLoss = 0;\n let regularizationLoss = 0;\n\n // Clustering loss (distance to cluster centers)\n for (const [nodeId, clusterIdx] of clusters) {\n const embedding = embeddings.get(nodeId);\n if (!embedding) {\n continue;\n }\n\n const center = clusterCenters[clusterIdx];\n if (!center) {\n continue;\n }\n\n clusteringLoss += euclideanDistance(embedding, center) ** 2;\n }\n\n // Graph reconstruction loss\n for (const node of graph.nodes()) {\n const nodeId = node.id;\n const nodeEmbedding = embeddings.get(nodeId);\n if (!nodeEmbedding) {\n continue;\n }\n\n for (const neighborId of graph.neighbors(nodeId)) {\n const neighborEmbedding = embeddings.get(neighborId);\n if (!neighborEmbedding) {\n continue;\n }\n\n const distance = euclideanDistance(nodeEmbedding, neighborEmbedding);\n reconstructionLoss += distance ** 2;\n }\n }\n\n // Regularization loss\n for (const embedding of embeddings.values()) {\n for (const value of embedding) {\n regularizationLoss += value ** 2;\n }\n }\n\n return clusteringLoss + (lambda * reconstructionLoss) + (lambda * regularizationLoss);\n}\n\n","import type {Graph} from \"../core/graph.js\";\nimport type {NodeId} from \"../types/index.js\";\n\n/**\n * Configuration options for the TeraHAC (Hierarchical Agglomerative Clustering) algorithm\n */\nexport interface TeraHACConfig {\n /** Linkage criterion: 'single', 'complete', 'average', 'ward' */\n linkage?: \"single\" | \"complete\" | \"average\" | \"ward\";\n /** Number of clusters to stop at (optional) */\n numClusters?: number;\n /** Distance threshold to stop clustering */\n distanceThreshold?: number;\n /** Maximum number of nodes to process efficiently */\n maxNodes?: number;\n /** Use graph structure for distance calculation */\n useGraphDistance?: boolean;\n /** Custom warning handler (default: console.warn) */\n onWarning?: (message: string) => void;\n}\n\n/**\n * Represents a node in the dendrogram/cluster hierarchy\n */\nexport interface ClusterNode {\n /** Unique identifier for this cluster */\n id: string;\n /** Node IDs in this cluster */\n members: Set<NodeId>;\n /** Left child cluster (if internal node) */\n left?: ClusterNode;\n /** Right child cluster (if internal node) */\n right?: ClusterNode;\n /** Distance at which this cluster was formed */\n distance: number;\n /** Size of the cluster */\n size: number;\n}\n\n/**\n * Result of the TeraHAC clustering algorithm\n */\nexport interface TeraHACResult {\n /** Root of the dendrogram */\n dendrogram: ClusterNode;\n /** Flat clustering at specified level */\n clusters: Map<NodeId, number>;\n /** All merge distances in order */\n distances: number[];\n /** Number of clusters in final result */\n numClusters: number;\n}\n\n/**\n * TeraHAC - Hierarchical Agglomerative Clustering for Large Graphs\n *\n * This algorithm performs hierarchical clustering on graphs by iteratively\n * merging the closest clusters. Optimized for scalability to handle large\n * graphs efficiently.\n *\n * Based on: \"Scaling Hierarchical Agglomerative Clustering to Trillion-Edge Graphs\"\n * Google Research 2024\n *\n * @param graph - Input graph to cluster\n * @param config - Configuration options\n * @returns Hierarchical clustering result\n */\nexport function teraHAC(graph: Graph, config: TeraHACConfig = {}): TeraHACResult {\n const {\n linkage = \"average\",\n numClusters,\n distanceThreshold,\n maxNodes = 10000,\n useGraphDistance = true,\n onWarning = console.warn,\n } = config;\n\n // Input validation\n if (numClusters !== undefined && (numClusters < 1 || !Number.isInteger(numClusters))) {\n throw new Error(\"numClusters must be a positive integer\");\n }\n\n const nodes = Array.from(graph.nodes());\n const nodeCount = nodes.length;\n\n if (nodeCount === 0) {\n throw new Error(\"Cannot cluster empty graph\");\n }\n\n if (nodeCount > maxNodes) {\n onWarning(`Graph has ${String(nodeCount)} nodes, which exceeds maxNodes (${String(maxNodes)}). Performance may be degraded.`);\n }\n\n // Initialize each node as its own cluster\n const clusters = new Map<string, ClusterNode>();\n let nextClusterId = nodeCount;\n\n for (let i = 0; i < nodeCount; i++) {\n const node = nodes[i];\n if (!node) {\n continue;\n }\n\n const clusterId = i.toString();\n clusters.set(clusterId, {\n id: clusterId,\n members: new Set([node.id]),\n distance: 0,\n size: 1,\n });\n }\n\n // Calculate initial distance matrix\n const distanceMatrix = calculateDistanceMatrix(graph, nodes, useGraphDistance);\n const mergeDistances: number[] = [];\n\n // Priority queue for efficient nearest neighbor finding\n const mergeCandidates = initializeMergeCandidates(clusters, distanceMatrix);\n\n let dendrogram: ClusterNode | undefined;\n\n // Perform agglomerative clustering\n while (clusters.size > 1 && mergeCandidates.length > 0) {\n // Find closest pair of clusters\n const {cluster1Id, cluster2Id, distance} = findClosestPair(mergeCandidates);\n\n // Check stopping criteria\n if (numClusters && clusters.size <= numClusters) {\n break;\n }\n\n if (distanceThreshold && distance > distanceThreshold) {\n break;\n }\n\n // Get the two clusters to merge\n const cluster1 = clusters.get(cluster1Id);\n const cluster2 = clusters.get(cluster2Id);\n if (!cluster1 || !cluster2) {\n continue;\n }\n\n // Create new merged cluster\n const newClusterId = (nextClusterId++).toString();\n const mergedMembers = new Set([... cluster1.members, ... cluster2.members]);\n\n const newCluster: ClusterNode = {\n id: newClusterId,\n members: mergedMembers,\n left: cluster1,\n right: cluster2,\n distance,\n size: cluster1.size + cluster2.size,\n };\n\n // Remove old clusters\n clusters.delete(cluster1Id);\n clusters.delete(cluster2Id);\n\n // Add new cluster\n clusters.set(newClusterId, newCluster);\n mergeDistances.push(distance);\n\n // Update merge candidates\n updateMergeCandidates(mergeCandidates, cluster1Id, cluster2Id, newClusterId, clusters, distanceMatrix, linkage);\n\n dendrogram = newCluster;\n }\n\n // If we have multiple remaining clusters, create a virtual root\n if (clusters.size > 1) {\n const remainingClusters = Array.from(clusters.values());\n let root = remainingClusters[0];\n if (!root) {\n dendrogram = undefined;\n } else {\n for (let i = 1; i < remainingClusters.length; i++) {\n const currentCluster = remainingClusters[i];\n if (!currentCluster) {\n continue;\n }\n\n const newRoot: ClusterNode = {\n id: (nextClusterId++).toString(),\n members: new Set([... root.members, ... currentCluster.members]),\n left: root,\n right: currentCluster,\n distance: Infinity,\n size: root.size + currentCluster.size,\n };\n root = newRoot;\n }\n dendrogram = root;\n }\n\n dendrogram = root;\n }\n\n dendrogram ??= Array.from(clusters.values())[0];\n\n // Extract flat clustering\n const finalNumClusters = numClusters ?? clusters.size;\n const flatClusters = dendrogram ? extractFlatClustering(dendrogram, finalNumClusters) : new Map<NodeId, number>();\n\n if (!dendrogram) {\n throw new Error(\"Failed to create dendrogram\");\n }\n\n return {\n dendrogram,\n clusters: flatClusters,\n distances: mergeDistances,\n numClusters: finalNumClusters,\n };\n}\n\n/**\n * Calculate distance matrix between all pairs of nodes\n */\nfunction calculateDistanceMatrix(graph: Graph, nodes: {id: NodeId}[], useGraphDistance: boolean): number[][] {\n const n = nodes.length;\n const matrix: number[][] = Array.from({length: n}, () => new Array(n).fill(Infinity) as number[]);\n\n if (useGraphDistance) {\n // Use graph-based distances (shortest path)\n for (let i = 0; i < n; i++) {\n const node = nodes[i];\n if (!node) {\n continue;\n }\n\n const distances = bfsShortestPaths(graph, node.id);\n for (let j = 0; j < n; j++) {\n if (i !== j) {\n const targetNode = nodes[j];\n if (targetNode && i < matrix.length && j < n) {\n const row = matrix[i];\n if (row && j < row.length) {\n const distance = distances.get(targetNode.id);\n row[j] = distance ?? Infinity;\n }\n }\n } else if (i < matrix.length) {\n const row = matrix[i];\n if (row && j < row.length) {\n row[j] = 0;\n }\n }\n }\n }\n } else {\n // Use simple edge-based distances\n for (let i = 0; i < n; i++) {\n for (let j = i + 1; j < n; j++) {\n const node1 = nodes[i];\n const node2 = nodes[j];\n if (node1 && node2) {\n const hasEdge = graph.hasEdge(node1.id, node2.id);\n const distance = hasEdge ? 1 : 2; // Connected: 1, not connected: 2\n if (i < matrix.length) {\n const rowI = matrix[i];\n if (rowI && j < rowI.length) {\n rowI[j] = distance;\n }\n }\n\n if (j < matrix.length) {\n const rowJ = matrix[j];\n if (rowJ && i < rowJ.length) {\n rowJ[i] = distance;\n }\n }\n }\n }\n if (i < matrix.length) {\n const row = matrix[i];\n if (row && i < row.length) {\n row[i] = 0;\n }\n }\n }\n }\n\n return matrix;\n}\n\n/**\n * BFS-based shortest path calculation from a source node\n */\nfunction bfsShortestPaths(graph: Graph, source: NodeId): Map<NodeId, number> {\n const distances = new Map<NodeId, number>();\n const queue: [NodeId, number][] = [[source, 0]];\n const visited = new Set<NodeId>();\n\n visited.add(source);\n distances.set(source, 0);\n\n while (queue.length > 0) {\n const item = queue.shift();\n if (!item) {\n break;\n }\n\n const [current, distance] = item;\n\n for (const neighbor of graph.neighbors(current)) {\n if (!visited.has(neighbor)) {\n visited.add(neighbor);\n distances.set(neighbor, distance + 1);\n queue.push([neighbor, distance + 1]);\n }\n }\n }\n\n return distances;\n}\n\n/**\n * Initialize merge candidates priority queue\n */\nfunction initializeMergeCandidates(\n clusters: Map<string, ClusterNode>,\n distanceMatrix: number[][],\n): {cluster1Id: string, cluster2Id: string, distance: number}[] {\n const candidates: {cluster1Id: string, cluster2Id: string, distance: number}[] = [];\n const clusterIds = Array.from(clusters.keys());\n\n for (let i = 0; i < clusterIds.length; i++) {\n for (let j = i + 1; j < clusterIds.length; j++) {\n const id1 = clusterIds[i];\n const id2 = clusterIds[j];\n if (!id1 || !id2) {\n continue;\n }\n\n const row = distanceMatrix[parseInt(id1)];\n if (!row) {\n continue;\n }\n\n const distance = row[parseInt(id2)] ?? Infinity;\n // Include all candidates, even disconnected ones (with finite but large distance)\n candidates.push({\n cluster1Id: id1,\n cluster2Id: id2,\n distance: distance === Infinity ? 100 : distance,\n });\n }\n }\n\n // Sort by distance (ascending)\n candidates.sort((a, b) => a.distance - b.distance);\n return candidates;\n}\n\n/**\n * Find the closest pair of clusters\n */\nfunction findClosestPair(\n mergeCandidates: {cluster1Id: string, cluster2Id: string, distance: number}[],\n): {cluster1Id: string, cluster2Id: string, distance: number} {\n // Return the first (closest) valid candidate\n const candidate = mergeCandidates.shift();\n if (!candidate) {\n throw new Error(\"No merge candidates available\");\n }\n\n return candidate;\n}\n\n/**\n * Update merge candidates after a merge operation\n */\nfunction updateMergeCandidates(\n mergeCandidates: {cluster1Id: string, cluster2Id: string, distance: number}[],\n oldCluster1Id: string,\n oldCluster2Id: string,\n newClusterId: string,\n clusters: Map<string, ClusterNode>,\n distanceMatrix: number[][],\n linkage: string,\n): void {\n // Remove candidates involving the merged clusters\n for (let i = mergeCandidates.length - 1; i >= 0; i--) {\n const candidate = mergeCandidates[i];\n if (!candidate) {\n continue;\n }\n\n if (candidate.cluster1Id === oldCluster1Id || candidate.cluster1Id === oldCluster2Id ||\n candidate.cluster2Id === oldCluster1Id || candidate.cluster2Id === oldCluster2Id) {\n mergeCandidates.splice(i, 1);\n }\n }\n\n // Add new candidates for the merged cluster\n const newCluster = clusters.get(newClusterId);\n if (!newCluster) {\n return;\n }\n\n for (const [clusterId, cluster] of clusters) {\n if (clusterId !== newClusterId) {\n const distance = calculateClusterDistance(newCluster, cluster, distanceMatrix, linkage);\n mergeCandidates.push({\n cluster1Id: newClusterId,\n cluster2Id: clusterId,\n distance: distance === Infinity ? 100 : distance,\n });\n }\n }\n\n // Re-sort candidates\n mergeCandidates.sort((a, b) => a.distance - b.distance);\n}\n\n/**\n * Calculate distance between two clusters based on linkage criterion\n */\nfunction calculateClusterDistance(\n cluster1: ClusterNode,\n cluster2: ClusterNode,\n distanceMatrix: number[][],\n linkage: string,\n): number {\n const members1 = Array.from(cluster1.members);\n const members2 = Array.from(cluster2.members);\n const distances: number[] = [];\n\n // Calculate all pairwise distances between cluster members\n for (const member1 of members1) {\n for (const member2 of members2) {\n const idx1 = parseInt(member1.toString());\n const idx2 = parseInt(member2.toString());\n if (idx1 < distanceMatrix.length && idx2 < distanceMatrix.length) {\n const row = distanceMatrix[idx1];\n if (row) {\n const distance = row[idx2];\n if (distance !== undefined) {\n distances.push(distance);\n }\n }\n }\n }\n }\n\n if (distances.length === 0) {\n return Infinity;\n }\n\n // Apply linkage criterion\n switch (linkage) {\n case \"single\":\n return Math.min(... distances);\n case \"complete\":\n return Math.max(... distances);\n case \"average\":\n return distances.reduce((sum, d) => sum + d, 0) / distances.length;\n case \"ward\":\n // Simplified Ward linkage (would need cluster centroids for full implementation)\n return distances.reduce((sum, d) => sum + (d * d), 0) / distances.length;\n default:\n return distances.reduce((sum, d) => sum + d, 0) / distances.length;\n }\n}\n\n/**\n * Extract flat clustering from dendrogram\n */\nfunction extractFlatClustering(dendrogram: ClusterNode, numClusters: number): Map<NodeId, number> {\n const clusters = new Map<NodeId, number>();\n\n if (numClusters === 1) {\n // Single cluster\n const clusterId = 0;\n for (const member of dendrogram.members) {\n clusters.set(member, clusterId);\n }\n return clusters;\n }\n\n // Find clusters at the specified level\n const clusterNodes: ClusterNode[] = [];\n const queue: ClusterNode[] = [dendrogram];\n\n while (queue.length > 0 && clusterNodes.length < numClusters) {\n const current = queue.shift();\n if (!current) {\n break;\n }\n\n if (!current.left || !current.right || clusterNodes.length + queue.length + 1 >= numClusters) {\n // This is a leaf or we need to keep this level\n clusterNodes.push(current);\n } else {\n // Continue decomposing\n queue.push(current.left, current.right);\n }\n }\n\n // Assign cluster IDs\n for (let i = 0; i < clusterNodes.length; i++) {\n const cluster = clusterNodes[i];\n if (!cluster) {\n continue;\n }\n\n for (const member of cluster.members) {\n clusters.set(member, i);\n }\n }\n\n return clusters;\n}\n","import type {Graph} from \"../core/graph.js\";\nimport type {NodeId} from \"../types/index.js\";\nimport {SeededRandom} from \"../utils/math-utilities.js\";\n\n/**\n * Configuration options for the GRSBM (Greedy Recursive Spectral Bisection) algorithm\n */\nexport interface GRSBMConfig {\n /** Maximum depth of recursive bisection */\n maxDepth?: number;\n /** Minimum cluster size to continue splitting */\n minClusterSize?: number;\n /** Number of eigenvectors to use for spectral embedding */\n numEigenvectors?: number;\n /** Convergence tolerance for eigenvalue computation */\n tolerance?: number;\n /** Maximum number of power iterations for eigenvalue computation */\n maxIterations?: number;\n /** Random seed for reproducibility */\n seed?: number;\n}\n\n/**\n * Represents a cluster in the hierarchical structure\n */\nexport interface GRSBMCluster {\n /** Unique identifier for this cluster */\n id: string;\n /** Node IDs in this cluster */\n members: Set<NodeId>;\n /** Left child cluster (if split) */\n left?: GRSBMCluster;\n /** Right child cluster (if split) */\n right?: GRSBMCluster;\n /** Modularity score of this cluster */\n modularity: number;\n /** Depth in the hierarchy */\n depth: number;\n /** Spectral embedding quality score */\n spectralScore: number;\n}\n\n/**\n * Result of the GRSBM clustering algorithm\n */\nexport interface GRSBMResult {\n /** Root of the cluster hierarchy */\n root: GRSBMCluster;\n /** Flat clustering at leaf level */\n clusters: Map<NodeId, number>;\n /** Number of final clusters */\n numClusters: number;\n /** Modularity scores for each level */\n modularityScores: number[];\n /** Explanation of the clustering structure */\n explanation: ClusterExplanation[];\n}\n\n/**\n * Explanation for a cluster split decision\n */\nexport interface ClusterExplanation {\n /** Cluster that was split */\n clusterId: string;\n /** Reason for the split */\n reason: string;\n /** Modularity improvement from the split */\n modularityImprovement: number;\n /** Key nodes that influenced the split */\n keyNodes: NodeId[];\n /** Spectral embedding values */\n spectralValues: number[];\n}\n\n/**\n * GRSBM - Greedy Recursive Spectral Bisection with Modularity\n *\n * This algorithm performs hierarchical community detection using spectral\n * bisection guided by modularity optimization. It provides explainable\n * community structure by tracking the reasoning behind each split.\n *\n * Based on: \"Explainable Community Detection via Hierarchical Spectral Clustering\" (2024)\n *\n * @param graph - Input graph to cluster\n * @param config - Configuration options\n * @returns Hierarchical clustering result with explanations\n */\nexport function grsbm(graph: Graph, config: GRSBMConfig = {}): GRSBMResult {\n const {\n maxDepth = 10,\n minClusterSize = 2, // Reduced default to allow more splits\n numEigenvectors = 2,\n tolerance = 1e-6,\n maxIterations = 100,\n seed = 42,\n } = config;\n\n // Set random seed for reproducibility\n const rng = SeededRandom.createGenerator(seed);\n const originalRandom = Math.random;\n Math.random = rng;\n\n const nodes = Array.from(graph.nodes());\n const nodeCount = nodes.length;\n\n if (nodeCount === 0) {\n throw new Error(\"Cannot cluster empty graph\");\n }\n\n // Initialize root cluster with all nodes\n const rootMembers = new Set(nodes.map((node) => node.id));\n const initialModularity = calculateModularity(graph, new Map([... rootMembers].map((id) => [id, 0])));\n\n const root: GRSBMCluster = {\n id: \"root\",\n members: rootMembers,\n modularity: initialModularity,\n depth: 0,\n spectralScore: 0,\n };\n\n const explanations: ClusterExplanation[] = [];\n const modularityScores: number[] = [initialModularity];\n\n // Perform recursive bisection\n const clusterQueue: GRSBMCluster[] = [root];\n let nextClusterId = 1;\n\n while (clusterQueue.length > 0) {\n const currentCluster = clusterQueue.shift();\n if (!currentCluster) {\n continue;\n }\n\n // Check stopping criteria\n if (currentCluster.depth >= maxDepth ||\n currentCluster.members.size < minClusterSize * 2) {\n continue;\n }\n\n // Attempt spectral bisection\n const bisectionResult = spectralBisection(\n graph,\n currentCluster,\n numEigenvectors,\n tolerance,\n maxIterations,\n );\n\n if (!bisectionResult) {\n continue; // Could not split this cluster\n }\n\n const {leftMembers, rightMembers, spectralScore, keyNodes, spectralValues, reason} = bisectionResult;\n\n // Create child clusters\n const leftCluster: GRSBMCluster = {\n id: `cluster_${String(nextClusterId++)}`,\n members: leftMembers,\n modularity: 0, // Will be calculated below\n depth: currentCluster.depth + 1,\n spectralScore,\n };\n\n const rightCluster: GRSBMCluster = {\n id: `cluster_${String(nextClusterId++)}`,\n members: rightMembers,\n modularity: 0, // Will be calculated below\n depth: currentCluster.depth + 1,\n spectralScore,\n };\n\n // Calculate modularity improvement\n const newAssignment = new Map<NodeId, number>();\n for (const nodeId of leftMembers) {\n newAssignment.set(nodeId, 0);\n }\n for (const nodeId of rightMembers) {\n newAssignment.set(nodeId, 1);\n }\n\n const newModularity = calculateModularity(graph, newAssignment);\n const modularityImprovement = newModularity - currentCluster.modularity;\n\n // Only split if modularity improves or is neutral (allow small splits)\n if (modularityImprovement >= -0.01) { // Small tolerance for neutral splits\n leftCluster.modularity = newModularity;\n rightCluster.modularity = newModularity;\n\n currentCluster.left = leftCluster;\n currentCluster.right = rightCluster;\n\n // Add explanation\n explanations.push({\n clusterId: currentCluster.id,\n reason,\n modularityImprovement,\n keyNodes,\n spectralValues,\n });\n\n modularityScores.push(newModularity);\n\n // Add children to queue for further processing\n clusterQueue.push(leftCluster, rightCluster);\n }\n }\n\n // Extract flat clustering from leaf nodes\n const clusters = new Map<NodeId, number>();\n let clusterId = 0;\n\n function assignClusterIds(cluster: GRSBMCluster): void {\n if (!cluster.left && !cluster.right) {\n // Leaf node\n for (const nodeId of cluster.members) {\n clusters.set(nodeId, clusterId);\n }\n clusterId++;\n } else {\n // Internal node - traverse children\n if (cluster.left) {\n assignClusterIds(cluster.left);\n }\n\n if (cluster.right) {\n assignClusterIds(cluster.right);\n }\n }\n }\n\n assignClusterIds(root);\n\n // Restore original random function\n Math.random = originalRandom;\n\n return {\n root,\n clusters,\n numClusters: clusterId,\n modularityScores,\n explanation: explanations,\n };\n}\n\n/**\n * Perform spectral bisection on a cluster\n */\nfunction spectralBisection(\n graph: Graph,\n cluster: GRSBMCluster,\n numEigenvectors: number,\n tolerance: number,\n maxIterations: number,\n): {\n leftMembers: Set<NodeId>;\n rightMembers: Set<NodeId>;\n spectralScore: number;\n keyNodes: NodeId[];\n spectralValues: number[];\n reason: string;\n} | null {\n const members = Array.from(cluster.members);\n const n = members.length;\n\n if (n < 4) {\n return null; // Too small to split meaningfully\n }\n\n // Create subgraph Laplacian matrix\n const laplacian = createLaplacianMatrix(graph, members);\n\n // Compute the second smallest eigenvector (Fiedler vector)\n const eigenvector = computeFiedlerVector(laplacian, tolerance, maxIterations);\n\n if (!eigenvector) {\n return null; // Could not compute eigenvector\n }\n\n // Find optimal split point\n const sortedIndices = eigenvector\n .map((value, index) => ({value, index}))\n .sort((a, b) => a.value - b.value);\n\n let bestSplitIndex = Math.floor(n / 2);\n let bestModularity = -Infinity;\n\n // Try different split points\n for (let splitIndex = Math.floor(n * 0.2); splitIndex <= Math.floor(n * 0.8); splitIndex++) {\n const leftIndices = sortedIndices.slice(0, splitIndex).map((item) => item.index);\n const rightIndices = sortedIndices.slice(splitIndex).map((item) => item.index);\n\n const assignment = new Map<NodeId, number>();\n for (const idx of leftIndices) {\n const nodeId = members[idx];\n if (nodeId !== undefined) {\n assignment.set(nodeId, 0);\n }\n }\n for (const idx of rightIndices) {\n const nodeId = members[idx];\n if (nodeId !== undefined) {\n assignment.set(nodeId, 1);\n }\n }\n\n const modularity = calculateModularity(graph, assignment);\n\n if (modularity > bestModularity) {\n bestModularity = modularity;\n bestSplitIndex = splitIndex;\n }\n }\n\n // Create final split\n const leftIndices = sortedIndices.slice(0, bestSplitIndex).map((item) => item.index);\n const rightIndices = sortedIndices.slice(bestSplitIndex).map((item) => item.index);\n\n const leftMembers = new Set<NodeId>();\n const rightMembers = new Set<NodeId>();\n\n for (const idx of leftIndices) {\n const nodeId = members[idx];\n if (nodeId !== undefined) {\n leftMembers.add(nodeId);\n }\n }\n\n for (const idx of rightIndices) {\n const nodeId = members[idx];\n if (nodeId !== undefined) {\n rightMembers.add(nodeId);\n }\n }\n\n // Identify key nodes (those with extreme spectral values)\n const extremeThreshold = 0.1;\n const sortedValues = [... eigenvector].sort((a, b) => Math.abs(b) - Math.abs(a));\n const threshold = sortedValues[Math.floor(sortedValues.length * extremeThreshold)] ?? 0;\n\n const keyNodes: NodeId[] = [];\n for (let i = 0; i < eigenvector.length; i++) {\n const eigenValue = eigenvector[i];\n if (eigenValue !== undefined && Math.abs(eigenValue) >= Math.abs(threshold)) {\n const nodeId = members[i];\n if (nodeId !== undefined) {\n keyNodes.push(nodeId);\n }\n }\n }\n\n // Calculate spectral score (based on eigenvalue gap)\n const firstValue = sortedValues[0] ?? 0;\n const lastValue = sortedValues[sortedValues.length - 1] ?? 0;\n const spectralScore = Math.abs(firstValue - lastValue);\n\n // Generate explanation\n const reason = `Spectral bisection based on Fiedler vector with modularity ${bestModularity.toFixed(3)}. Split creates clusters of sizes ${String(leftMembers.size)} and ${String(rightMembers.size)}.`;\n\n return {\n leftMembers,\n rightMembers,\n spectralScore,\n keyNodes: keyNodes.slice(0, 5), // Top 5 key nodes\n spectralValues: eigenvector,\n reason,\n };\n}\n\n/**\n * Create Laplacian matrix for a subgraph\n */\nfunction createLaplacianMatrix(graph: Graph, nodes: NodeId[]): number[][] {\n const n = nodes.length;\n const nodeIndex = new Map<NodeId, number>();\n\n // Create node index mapping\n for (let i = 0; i < n; i++) {\n const node = nodes[i];\n if (node !== undefined) {\n nodeIndex.set(node, i);\n }\n }\n\n // Initialize Laplacian matrix\n const laplacian = Array.from({length: n}, () => new Array<number>(n).fill(0));\n\n // Fill adjacency part and calculate degrees\n const degrees = new Array<number>(n).fill(0);\n\n for (let i = 0; i < n; i++) {\n const nodeId = nodes[i];\n if (nodeId === undefined) {\n continue;\n }\n\n for (const neighbor of graph.neighbors(nodeId)) {\n const neighborIdx = nodeIndex.get(neighbor);\n if (neighborIdx !== undefined && i < laplacian.length && i < degrees.length) {\n const row = laplacian[i];\n if (row) {\n row[neighborIdx] = -1;\n degrees[i] = (degrees[i] ?? 0) + 1;\n }\n }\n }\n }\n\n // Set diagonal (degree) values\n for (let i = 0; i < n; i++) {\n const row = laplacian[i];\n const degree = degrees[i];\n if (row && degree !== undefined) {\n row[i] = degree;\n }\n }\n\n return laplacian;\n}\n\n/**\n * Compute the Fiedler vector (second smallest eigenvector) using power iteration\n */\nfunction computeFiedlerVector(laplacian: number[][], tolerance: number, maxIterations: number): number[] | null {\n const n = laplacian.length;\n if (n < 2) {\n return null;\n }\n\n // Initialize random vector orthogonal to the all-ones vector\n let vector = new Array<number>(n).fill(0);\n for (let i = 0; i < n; i++) {\n vector[i] = Math.random() - 0.5;\n }\n\n // Make orthogonal to all-ones vector\n const mean = vector.reduce((sum: number, val: number) => sum + val, 0) / n;\n for (let i = 0; i < n; i++) {\n const val = vector[i];\n if (val !== undefined) {\n vector[i] = val - mean;\n }\n }\n\n // Normalize\n const norm = Math.sqrt(vector.reduce((sum: number, val: number) => sum + (val * val), 0));\n if (norm > 0) {\n for (let i = 0; i < n; i++) {\n const val = vector[i];\n if (val !== undefined) {\n vector[i] = val / norm;\n }\n }\n }\n\n // Power iteration with deflation for second smallest eigenvalue\n for (let iter = 0; iter < maxIterations; iter++) {\n const newVector = new Array<number>(n).fill(0);\n\n // Matrix-vector multiplication: newVector = L * vector\n for (let i = 0; i < n; i++) {\n let sum = 0;\n const row = laplacian[i];\n if (row) {\n for (let j = 0; j < n; j++) {\n const matrixVal = row[j];\n const vectorVal = vector[j];\n if (matrixVal !== undefined && vectorVal !== undefined) {\n sum += matrixVal * vectorVal;\n }\n }\n }\n\n newVector[i] = sum;\n }\n\n // For smallest eigenvalue, we actually want inverse iteration\n // This is simplified - in practice would solve (L - shift*I)x = vector\n // For now, use power iteration on -L (approximately)\n for (let i = 0; i < n; i++) {\n const val = newVector[i];\n if (val !== undefined) {\n newVector[i] = -val;\n }\n }\n\n // Orthogonalize against all-ones vector\n const newMean = newVector.reduce((sum, val) => sum + val, 0) / n;\n for (let i = 0; i < n; i++) {\n const val = newVector[i];\n if (val !== undefined) {\n newVector[i] = val - newMean;\n }\n }\n\n // Normalize\n const newNorm = Math.sqrt(newVector.reduce((sum, val) => sum + (val * val), 0));\n if (newNorm < tolerance) {\n break; // Converged to zero vector\n }\n\n for (let i = 0; i < n; i++) {\n const val = newVector[i];\n if (val !== undefined) {\n newVector[i] = val / newNorm;\n }\n }\n\n // Check convergence\n let diff = 0;\n for (let i = 0; i < n; i++) {\n const newVal = newVector[i];\n const oldVal = vector[i];\n if (newVal !== undefined && oldVal !== undefined) {\n diff += Math.abs(newVal - oldVal);\n }\n }\n\n vector = newVector;\n\n if (diff < tolerance) {\n break;\n }\n }\n\n return vector;\n}\n\n/**\n * Calculate modularity of a graph partitioning\n */\nfunction calculateModularity(graph: Graph, assignment: Map<NodeId, number>): number {\n const totalEdges = graph.uniqueEdgeCount;\n if (totalEdges === 0) {\n return 0;\n }\n\n let modularity = 0;\n const communities = new Map<number, Set<NodeId>>();\n\n // Group nodes by community\n for (const [nodeId, communityId] of assignment) {\n if (!communities.has(communityId)) {\n communities.set(communityId, new Set());\n }\n\n const community = communities.get(communityId);\n if (community) {\n community.add(nodeId);\n }\n }\n\n // Calculate modularity for each community\n for (const [, members] of communities) {\n let internalEdges = 0;\n let totalDegree = 0;\n\n for (const nodeId of members) {\n const nodeDegree = graph.degree(nodeId);\n totalDegree += nodeDegree;\n\n // Count internal edges\n for (const neighbor of graph.neighbors(nodeId)) {\n if (members.has(neighbor)) {\n internalEdges++;\n }\n }\n }\n\n // Each edge is counted twice in undirected graphs\n internalEdges /= 2;\n\n // Modularity contribution for this community\n const expectedEdges = (totalDegree * totalDegree) / (4 * totalEdges);\n modularity += (internalEdges - expectedEdges) / totalEdges;\n }\n\n return modularity;\n}\n\n"],"names":["this","SparseTypedFastBitSet_1","require$$0","Type","SparseTypedFastBitSet","TypedFastBitSet_1","TypedFastBitSet","exports","require$$1","nodeId","hasNegativeCycle","element","result","calculateModularity","getTotalEdgeWeight","getNodeDegree","nodeLabel","getNeighborCommunities","u","v","graphToAdjacencySet","degreeV","communities","clusterAssignments","leftIndices","rightIndices"],"mappings":"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","x_google_ignoreList":[1,2,3,4]}
|