@graphty/algorithms 2.0.6 → 2.1.0
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 +9 -11
- package/dist/algorithms.js +499 -30
- package/dist/algorithms.js.map +1 -1
- package/dist/algorithms.standalone.js +500 -31
- package/dist/algorithms.standalone.js.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.js +2 -2
- package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
- package/dist/src/algorithms/community/girvan-newman.js +1 -1
- package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
- package/dist/src/algorithms/matching/isomorphism.js +3 -3
- package/dist/src/algorithms/matching/isomorphism.js.map +1 -1
- package/dist/src/algorithms/mst/prim.js +1 -1
- package/dist/src/algorithms/mst/prim.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.js +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.js +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs-unified.js +2 -2
- package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -1
- package/dist/src/algorithms/traversal/dfs.js +2 -2
- package/dist/src/algorithms/traversal/dfs.js.map +1 -1
- package/dist/src/clustering/spectral.js +2 -2
- package/dist/src/clustering/spectral.js.map +1 -1
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/indexed/accelerator.d.ts +14 -2
- package/dist/src/indexed/accelerator.d.ts.map +1 -1
- package/dist/src/indexed/accelerator.js +8 -0
- package/dist/src/indexed/accelerator.js.map +1 -1
- package/dist/src/indexed/components.d.ts +8 -0
- package/dist/src/indexed/components.d.ts.map +1 -1
- package/dist/src/indexed/components.js +8 -1
- package/dist/src/indexed/components.js.map +1 -1
- package/dist/src/indexed/hits.d.ts +39 -0
- package/dist/src/indexed/hits.d.ts.map +1 -0
- package/dist/src/indexed/hits.js +95 -0
- package/dist/src/indexed/hits.js.map +1 -0
- package/dist/src/indexed/index.d.ts +5 -1
- package/dist/src/indexed/index.d.ts.map +1 -1
- package/dist/src/indexed/index.js +5 -1
- package/dist/src/indexed/index.js.map +1 -1
- package/dist/src/indexed/k-core.d.ts +32 -0
- package/dist/src/indexed/k-core.d.ts.map +1 -0
- package/dist/src/indexed/k-core.js +118 -0
- package/dist/src/indexed/k-core.js.map +1 -0
- package/dist/src/indexed/katz.d.ts +38 -0
- package/dist/src/indexed/katz.d.ts.map +1 -0
- package/dist/src/indexed/katz.js +61 -0
- package/dist/src/indexed/katz.js.map +1 -0
- package/dist/src/indexed/louvain.d.ts +33 -0
- package/dist/src/indexed/louvain.d.ts.map +1 -0
- package/dist/src/indexed/louvain.js +301 -0
- package/dist/src/indexed/louvain.js.map +1 -0
- package/package.json +5 -5
- package/src/algorithms/centrality/betweenness.ts +2 -2
- package/src/algorithms/community/girvan-newman.ts +1 -1
- package/src/algorithms/matching/isomorphism.ts +3 -3
- package/src/algorithms/mst/prim.ts +1 -1
- package/src/algorithms/shortest-path/bellman-ford.ts +3 -3
- package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +1 -1
- package/src/algorithms/shortest-path/dijkstra.ts +1 -1
- package/src/algorithms/traversal/bfs-unified.ts +2 -2
- package/src/algorithms/traversal/dfs.ts +2 -2
- package/src/clustering/spectral.ts +2 -2
- package/src/index.ts +10 -0
- package/src/indexed/accelerator.ts +26 -2
- package/src/indexed/components.ts +8 -1
- package/src/indexed/hits.ts +126 -0
- package/src/indexed/index.ts +5 -7
- package/src/indexed/k-core.ts +138 -0
- package/src/indexed/katz.ts +88 -0
- package/src/indexed/louvain.ts +345 -0
package/dist/algorithms.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"algorithms.js","sources":["../src/core/graph.ts","../src/errors.ts","../../node_modules/.pnpm/typedfastbitset@0.6.1/node_modules/typedfastbitset/lib/utils.js","../../node_modules/.pnpm/typedfastbitset@0.6.1/node_modules/typedfastbitset/lib/SparseTypedFastBitSet.js","../../node_modules/.pnpm/typedfastbitset@0.6.1/node_modules/typedfastbitset/lib/TypedFastBitSet.js","../../node_modules/.pnpm/typedfastbitset@0.6.1/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","../src/indexed/bfs.ts","../src/indexed/common-neighbors.ts","../src/indexed/structures/union-find.ts","../src/indexed/components.ts","../src/indexed/structures/arc-source.ts","../src/indexed/structures/min-heap.ts","../src/indexed/dijkstra.ts","../src/indexed/mst.ts","../src/indexed/pagerank.ts","../src/indexed/to-snapshot.ts","../src/indexed/accelerator.ts"],"sourcesContent":["import type { Edge, GraphConfig, Node, NodeId } from \"../types/index.js\";\n\n/**\n * True when an undirected edge seen from `source` is the mirror of one already yielded from\n * `target`: ids of one type compare by value, ids of different types by their type name.\n * @param source - The node the edge is read from\n * @param target - The node the edge points to\n * @returns True when this side of the edge is the duplicate\n */\nfunction isMirror(source: NodeId, target: NodeId): boolean {\n return typeof source === typeof target ? source > target : typeof source > typeof target;\n}\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 private mutations: number;\n\n /**\n * Creates a new Graph instance.\n * @param config - Configuration options for the graph\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 this.mutations = 0;\n }\n\n /**\n * Add a node to the graph\n * @param id - The unique identifier for the node\n * @param data - Optional key-value data to attach to the node\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 this.mutations++;\n }\n }\n\n /**\n * Remove a node from the graph\n * @param id - The unique identifier of the node to remove\n * @returns True if the node was removed, false if it did not exist\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 this.mutations++;\n return true;\n }\n\n /**\n * Add an edge to the graph\n * @param source - The source node identifier\n * @param target - The target node identifier\n * @param weight - The weight of the edge (defaults to 1)\n * @param data - Optional key-value data to attach to the edge\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. With allowParallelEdges the adjacency still holds one edge per\n // pair, so a repeated pair replaces the earlier edge and must not be counted again.\n const replacing = this.hasEdge(source, target);\n if (!this.config.allowParallelEdges && replacing) {\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 if (!replacing) {\n this.edgeCount++;\n }\n\n this.mutations++;\n }\n\n /**\n * Remove an edge from the graph\n * @param source - The source node identifier\n * @param target - The target node identifier\n * @returns True if the edge was removed, false if it did not exist\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 this.mutations++;\n return true;\n }\n\n /**\n * Check if a node exists in the graph\n * @param id - The unique identifier of the node to check\n * @returns True if the node exists, false otherwise\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 * @param source - The source node identifier\n * @param target - The target node identifier\n * @returns True if the edge exists, false otherwise\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 * @param id - The unique identifier of the node to retrieve\n * @returns The node if found, undefined otherwise\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 * @param source - The source node identifier\n * @param target - The target node identifier\n * @returns The edge if found, undefined otherwise\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 * @returns The total count of nodes\n */\n get nodeCount(): number {\n return this.nodeMap.size;\n }\n\n /**\n * A counter that increases on every topology change (`addNode` of a new id, `removeNode`,\n * `addEdge`, `removeEdge`, `clear`) and never on a read. Callers memoise derived structures on\n * `(graph, mutationCount)`; graph-format design 14.1 rule 4 names this counter, and `toSnapshot`\n * is its first consumer. It is monotone and is NOT reset by `clear()`: a reset could hand a\n * stale cache entry a matching key.\n * @returns The number of topology changes made to this graph\n */\n get mutationCount(): number {\n return this.mutations;\n }\n\n /**\n * Get the number of edges in the graph\n * @returns The total count of edges\n */\n get totalEdgeCount(): number {\n return this.edgeCount;\n }\n\n /**\n * Check if the graph is directed\n * @returns True if the graph is directed, false otherwise\n */\n get isDirected(): boolean {\n return this.config.directed;\n }\n\n /**\n * Get all nodes in the graph\n * @returns An iterator over all nodes\n */\n nodes(): IterableIterator<Node> {\n return this.nodeMap.values();\n }\n\n /**\n * Get all edges in the graph\n * @yields Each unique edge 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. A string never compares\n // greater than a number (both `<` and `>` are false), so mixed-type ids are\n // ordered by their type name first; the mirror is then skipped on exactly one side.\n if (!this.config.directed && isMirror(source, edge.target)) {\n continue;\n }\n\n yield edge;\n }\n }\n }\n\n /**\n * Get neighbors of a node (outgoing edges)\n * @param nodeId - The node identifier to get neighbors for\n * @returns An iterator over the neighbor node identifiers\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 * @param nodeId - The node identifier to get incoming neighbors for\n * @returns An iterator over the incoming neighbor node identifiers\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 * @param nodeId - The node identifier to get outgoing neighbors for\n * @returns An iterator over the outgoing neighbor node identifiers\n */\n outNeighbors(nodeId: NodeId): IterableIterator<NodeId> {\n return this.neighbors(nodeId);\n }\n\n /**\n * Get the degree of a node\n * @param nodeId - The node identifier to get the degree for\n * @returns The total degree of the 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 * @param nodeId - The node identifier to get the in-degree for\n * @returns The number of incoming edges to the 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 * @param nodeId - The node identifier to get the out-degree for\n * @returns The number of outgoing edges from the 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 * @returns A new Graph instance with the same nodes and edges\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(edge.source, edge.target, edge.weight, edge.data ? { ...edge.data } : undefined);\n }\n\n return cloned;\n }\n\n /**\n * Get graph configuration\n * @returns A copy of the graph configuration object\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 this.mutations++;\n }\n\n /**\n * Get the number of unique edges in the graph\n * For undirected graphs, each edge is counted once\n * @returns The count of unique edges\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 \n for (const _edge of this.edges()) {\n count++;\n }\n return count;\n }\n}\n","/**\n * Thrown when an iterative algorithm reaches its iteration cap before meeting its tolerance.\n *\n * The scores it had reached are not returned: an unconverged vector is not the answer, and\n * returning it in silence would pass it off as one. networkx makes the same choice with\n * `PowerIterationFailedConvergence`. Raise `maxIterations`, or loosen `tolerance`, and call again.\n */\nexport class ConvergenceError extends Error {\n override readonly name = \"ConvergenceError\";\n\n /**\n * Builds the error and its message.\n * @param algorithm - The function that gave up, e.g. `\"eigenvectorCentrality\"`\n * @param iterations - The passes it ran, which is its `maxIterations`\n * @param tolerance - The tolerance it did not meet\n */\n constructor(\n readonly algorithm: string,\n readonly iterations: number,\n readonly tolerance: number,\n ) {\n super(\n `${algorithm} did not converge in ${String(iterations)} iterations (tolerance ${String(tolerance)}); raise maxIterations or tolerance`,\n );\n }\n}\n\n/**\n * Thrown when a shortest path cannot be walked back from its predecessor array: the walk met a\n * missing or out-of-range predecessor before the source (`\"gap\"`), or took more than\n * `nodeCount - 1` steps without reaching it (`\"cycle\"`).\n *\n * A CPU search never produces such an array; an accelerator's result can (a kernel bug, a lost\n * device, a buffer read too early). The error surfaces it instead of hanging or returning a wrong\n * path, and nothing recomputes the path on the CPU.\n */\nexport class PathWalkError extends Error {\n override readonly name = \"PathWalkError\";\n\n /**\n * Builds the error and its message.\n * @param source - The search's source node index\n * @param target - The node index the walk started from\n * @param reason - `\"gap\"` or `\"cycle\"`, as above\n */\n constructor(\n readonly source: number,\n readonly target: number,\n readonly reason: \"cycle\" | \"gap\",\n ) {\n super(\n `cannot walk the shortest path from node ${String(source)} to node ${String(target)}: the predecessor array has a ${reason}`,\n );\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 /**\n * Creates a new GraphBitSet with optional pre-allocated capacity.\n * @param capacity - The initial capacity to pre-allocate for the bitset\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 to the set.\n * @param index - The element index to add\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 from the set.\n * @param index - The element index to remove\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 an element exists in the set.\n * @param index - The element index to check\n * @returns True if the element exists, false otherwise\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 the set is empty.\n * @returns True if the set contains no elements, false otherwise\n */\n isEmpty(): boolean {\n return this._cardinality === 0;\n }\n\n /**\n * Optimized for graph algorithms - add a range of indices.\n * @param start - The starting index (inclusive)\n * @param end - The ending index (exclusive)\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 - get the number of elements in the set.\n * @returns The number of elements in the set\n */\n size(): number {\n return this._cardinality;\n }\n\n /**\n * Batch operations for frontier management - swap contents with another GraphBitSet.\n * @param other - The GraphBitSet to swap contents with\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 over all elements in the set.\n * @yields The indices of elements in the set\n */\n *[Symbol.iterator](): Generator<number> {\n // Use TypedFastBitSet's optimized iteration\n yield* this.bitset;\n }\n\n /**\n * Perform union operation with another GraphBitSet, updating this set in place.\n * @param other - The GraphBitSet to union with\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 /**\n * Perform intersection operation with another GraphBitSet, updating this set in place.\n * @param other - The GraphBitSet to intersect with\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 /**\n * Perform difference operation with another GraphBitSet, updating this set in place.\n * @param other - The GraphBitSet to subtract from this set\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 * @returns A new GraphBitSet with the same elements\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 /**\n * Creates a new VisitedBitArray with the specified size.\n * @param size - The number of bits to allocate\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 the specified index.\n * @param index - The bit index to set\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 value at the specified index.\n * @param index - The bit index to get\n * @returns True if the bit is set, false otherwise\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 the specified index.\n * @param index - The bit index to toggle\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 - count the number of set bits.\n * @returns The number of bits set to 1\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 * @param n - The 32-bit word to count\n * @returns The number of bits set to 1 in the word\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 * @returns The total number of bits in the array\n */\n size(): number {\n return this._size;\n }\n\n /**\n * Check if all bits are zero.\n * @returns True if no bits are set, false otherwise\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 an array of indices.\n * @param indices - Array of bit indices to set\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 * @returns Array containing the indices of all bits that are set to 1\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 /**\n * Creates a new CompactDistanceArray with the specified size.\n * @param size - The number of distance values to store\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 the specified index.\n * @param index - The node index to set the distance for\n * @param distance - The distance value to set\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 the specified index.\n * @param index - The node index to get the distance for\n * @returns The distance value, or INFINITY if not set\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 a node has been visited (has a valid distance).\n * @param index - The node index to check\n * @returns True if the node has been visited, false otherwise\n */\n isVisited(index: number): boolean {\n return this.data[index] !== CompactDistanceArray.INFINITY;\n }\n\n /**\n * Reset all distances to unvisited state.\n */\n clear(): void {\n this.data.fill(CompactDistanceArray.INFINITY);\n }\n\n /**\n * Get the size of the distance array.\n * @returns The number of elements in the array\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 */\ninterface 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 */\ninterface 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 /**\n * Creates a new DirectionOptimizedBFS instance.\n * @param graph - The CSR graph to perform BFS on\n * @param options - Optional configuration for switching thresholds\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 node.\n * @param source - The source node ID to start the BFS from\n * @returns The BFS result containing distances and parent pointers\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 || 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 * @returns The scout count (total degree of newly discovered nodes)\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 for frontier neighbors.\n * @returns The number of newly discovered 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 * @returns The total number of outgoing edges from frontier nodes\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 * @returns The BFS result containing distances and parent pointers\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 from multiple source nodes.\n * @param sources - Array of source node IDs to start the BFS from\n * @returns The BFS result containing distances and parent pointers\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 || 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 * @param graph - The CSR graph to perform BFS on\n * @param source - The source node ID to start the BFS from\n * @param options - Optional configuration for switching thresholds\n * @returns The BFS result containing distances and parent pointers\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","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 /**\n * Creates a new CSRGraph from an adjacency list representation.\n * @param adjacencyList - Map of node IDs to arrays of neighbor node IDs\n * @param weights - Optional map of edge weights keyed by \"source-target\" strings\n * @param buildReverse - Whether to build reverse edges for bottom-up BFS (default true)\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 * @param adjacencyList - Map of node IDs to arrays of neighbor node IDs\n * @param weights - Optional map of edge weights keyed by \"source-target\" strings\n * @param buildReverse - Whether to build reverse edges for bottom-up BFS\n * @returns The constructed CSR graph data structure\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 /**\n * Get the total number of nodes in the graph.\n * @returns The number of nodes\n */\n nodeCount(): number {\n return this.data.indexToNodeId.length;\n }\n\n /**\n * Get the total number of edges in the graph.\n * @returns The number of edges\n */\n edgeCount(): number {\n return this.data.columnIndices.length;\n }\n\n /**\n * Check if a node exists in the graph.\n * @param nodeId - The node ID to check\n * @returns True if the node exists, false otherwise\n */\n hasNode(nodeId: TNodeId): boolean {\n return this.data.nodeIdToIndex.has(nodeId);\n }\n\n /**\n * Check if an edge exists between two nodes.\n * @param source - The source node ID\n * @param target - The target node ID\n * @returns True if the edge exists, false otherwise\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 of a node as node IDs.\n * @param nodeId - The node ID to get neighbors for\n * @returns An iterator over neighbor 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 in the graph.\n * @returns An iterator over all node IDs\n */\n nodes(): IterableIterator<TNodeId> {\n return this.data.indexToNodeId.values();\n }\n\n /**\n * Get neighbors as indices (internal use).\n * @param nodeIndex - The internal index of the node\n * @returns Array of neighbor indices\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 /**\n * Get the out-degree (number of outgoing edges) of a node.\n * @param nodeId - The node ID to get the out-degree for\n * @returns The number of outgoing edges from the node\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 * @param nodeIndex - The internal index of the node\n * @returns The number of outgoing edges from the node\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 * @param nodeIndex - The internal index of the node\n * @yields The indices of neighboring nodes\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 * @param nodeIndex - The internal index of the node\n * @yields The indices of nodes with edges pointing to this node\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 internal index.\n * @param nodeId - The node ID to convert\n * @returns The internal index for the node\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 internal index to node ID.\n * @param index - The internal index to convert\n * @returns The node ID for the given index\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 between two nodes.\n * @param source - The source node ID\n * @param target - The target node ID\n * @returns The edge weight, or undefined if the edge doesn't exist or has no 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 * @param arr - The typed array to search in\n * @param target - The value to search for\n * @param start - The starting index (inclusive)\n * @param end - The ending index (exclusive)\n * @returns The index of the target, or -1 if not found\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 interface.\n * @param graph - The graph object to convert, must implement nodes, neighbors, hasNode, and optionally getEdge\n * @param graph.nodes - Function that returns an iterator over node objects with id property\n * @param graph.neighbors - Function that returns an iterator over neighbor node IDs\n * @param graph.hasNode - Function that checks if a node exists in the graph\n * @param graph.getEdge - Optional function that returns edge data including weight\n * @returns A new CSRGraph instance\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 /**\n * Creates a new GraphAdapter that wraps or converts a graph to CSR format.\n * @param graph - The graph to adapt (either standard Graph or ReadonlyGraph)\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 * @param graph - The graph to convert\n * @returns A new CSRGraph instance\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 /**\n * Get the total number of nodes in the graph.\n * @returns The number of nodes\n */\n nodeCount(): number {\n return this.csrGraph.nodeCount();\n }\n\n /**\n * Get the total number of edges in the graph.\n * @returns The number of edges\n */\n edgeCount(): number {\n return this.csrGraph.edgeCount();\n }\n\n /**\n * Check if a node exists in the graph.\n * @param nodeId - The node ID to check\n * @returns True if the node exists, false otherwise\n */\n hasNode(nodeId: TNodeId): boolean {\n return this.csrGraph.hasNode(nodeId);\n }\n\n /**\n * Check if an edge exists between two nodes.\n * @param source - The source node ID\n * @param target - The target node ID\n * @returns True if the edge exists, false otherwise\n */\n hasEdge(source: TNodeId, target: TNodeId): boolean {\n return this.csrGraph.hasEdge(source, target);\n }\n\n /**\n * Get neighbors of a node as node IDs.\n * @param nodeId - The node ID to get neighbors for\n * @returns An iterator over neighbor node IDs\n */\n neighbors(nodeId: TNodeId): IterableIterator<TNodeId> {\n return this.csrGraph.neighbors(nodeId);\n }\n\n /**\n * Get the out-degree (number of outgoing edges) of a node.\n * @param nodeId - The node ID to get the out-degree for\n * @returns The number of outgoing edges from the node\n */\n outDegree(nodeId: TNodeId): number {\n return this.csrGraph.outDegree(nodeId);\n }\n\n /**\n * Get all nodes in the graph.\n * @returns An iterator over all node IDs\n */\n nodes(): IterableIterator<TNodeId> {\n return this.csrGraph.nodes();\n }\n\n /**\n * Get the underlying CSR graph.\n * @returns The CSRGraph instance used internally\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 * @param _config - The configuration object (ignored)\n */\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 * @returns An empty configuration object\n */\nexport function getOptimizationConfig(): GraphAlgorithmConfig {\n return {};\n}\n\n/**\n * Check if a graph is already in CSR format.\n * @param graph - The graph to check\n * @returns True if the graph is a CSRGraph instance\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 * @param graph - The graph to convert\n * @returns A CSRGraph instance (either the original if already CSR, or a new converted one)\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 * @param nodes - Array of node IDs\n * @param edges - Array of edge tuples [source, target, weight?]\n * @returns A new CSRGraph instance\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>(target: T, predecessor: Map<T, T | null>): 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(graph: Graph, source: NodeId, target: NodeId, directed = false): Set<NodeId> {\n const sourceNeighbors = new Set(directed ? graph.outNeighbors(source) : graph.neighbors(source));\n const targetNeighbors = new Set(directed ? graph.outNeighbors(target) : graph.neighbors(target));\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(graph: Graph, source: NodeId, target: NodeId): 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(source: NodeId, target: NodeId, isDirected: boolean): 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(graph: Graph, nodeId: NodeId, mode: \"in\" | \"out\" | \"total\" = \"total\"): 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>(communities: Map<T, number>): 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 * @param graph - The input graph to convert\n * @returns CSR graph representation (cached for efficiency)\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 * @param graph - The input graph to traverse\n * @param startNode - The node to start the BFS from\n * @param options - Traversal options (callbacks, target node, etc.)\n * @returns Traversal result with visited nodes, order, and tree structure\n */\nexport function breadthFirstSearch(graph: Graph, startNode: NodeId, options: TraversalOptions = {}): 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 * @param graph - The input graph to traverse\n * @param startNode - The node to start the BFS from\n * @param options - Traversal options (callbacks, target node, etc.)\n * @returns Traversal result with visited nodes, order, and tree structure\n */\nfunction breadthFirstSearchStandard(graph: Graph, startNode: NodeId, options: TraversalOptions = {}): 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 * @param graph - The input graph to traverse\n * @param startNode - The node to start the BFS from\n * @param options - Traversal options (callbacks, target node, etc.)\n * @returns Traversal result with visited nodes, order, and tree structure\n */\nfunction breadthFirstSearchOptimized(graph: Graph, startNode: NodeId, options: TraversalOptions = {}): 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 * @param graph - The input graph to search\n * @param source - The source node ID\n * @param target - The target node ID\n * @returns Shortest path result or null if no path exists\n */\nexport function shortestPathBFS(graph: Graph, source: NodeId, target: NodeId): 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 * @param graph - The input graph to search\n * @param source - The source node ID\n * @param target - The target node ID\n * @returns Shortest path result or null if no path exists\n */\nfunction shortestPathBFSStandard(graph: Graph, source: NodeId, target: NodeId): 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 * @param graph - The input graph to search\n * @param source - The source node ID\n * @param target - The target node ID\n * @returns Shortest path result or null if no path exists\n */\nfunction shortestPathBFSOptimized(graph: Graph, source: NodeId, target: NodeId): 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 * @param graph - The input graph to search\n * @param source - The source node ID to compute shortest paths from\n * @returns Map of node IDs to their shortest path results\n */\nexport function singleSourceShortestPathBFS(graph: Graph, source: NodeId): 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 * @param graph - The input graph to search\n * @param source - The source node ID to compute shortest paths from\n * @returns Map of node IDs to their shortest path results\n */\nfunction singleSourceShortestPathBFSStandard(graph: Graph, source: NodeId): 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 * @param graph - The input graph to search\n * @param source - The source node ID to compute shortest paths from\n * @returns Map of node IDs to their shortest path results\n */\nfunction singleSourceShortestPathBFSOptimized(graph: Graph, source: NodeId): 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 * @param graph - The undirected graph to check\n * @returns True if the graph is bipartite, false otherwise\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 * @param graph - The input graph to traverse\n * @param startNode - The node to start the DFS from\n * @param options - DFS options (recursive mode, pre/post order, etc.)\n * @returns Traversal result with visited nodes, order, and tree structure\n */\nexport function depthFirstSearch(graph: Graph, startNode: NodeId, options: DFSOptions = {}): 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 * @param graph - The input graph to traverse\n * @param startNode - The node to start the DFS from\n * @param visited - Set to track visited nodes\n * @param order - Array to store traversal order\n * @param tree - Map to store parent relationships\n * @param options - DFS options (recursive mode, pre/post order, etc.)\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 * @param graph - The input graph to traverse\n * @param node - Current node being visited\n * @param visited - Set to track visited nodes\n * @param order - Array to store traversal order\n * @param tree - Map to store parent relationships\n * @param options - DFS options (recursive mode, pre/post order, etc.)\n * @param depth - Current depth in the traversal tree\n * @param parent - Parent node of the current node\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 * @param graph - The input graph to check for cycles\n * @returns True if the graph contains a cycle, false otherwise\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 * @param graph - The directed graph to check\n * @param node - Current node being visited\n * @param visited - Set of all visited nodes\n * @param recursionStack - Set of nodes in the current recursion path\n * @returns True if a cycle is found, false otherwise\n */\nfunction hasCycleUtilDirected(graph: Graph, node: NodeId, visited: Set<NodeId>, recursionStack: Set<NodeId>): 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 * @param graph - The undirected graph to check\n * @param node - Current node being visited\n * @param visited - Set of all visited nodes\n * @param parent - Parent node of the current node\n * @returns True if a cycle is found, false otherwise\n */\nfunction hasCycleUtilUndirected(graph: Graph, node: NodeId, visited: Set<NodeId>, parent: NodeId | null): 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 * @param graph - The directed acyclic graph to sort\n * @returns Array of node IDs in topological order, or null if graph has cycles\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 * @param graph - The directed graph being sorted\n * @param node - Current node being visited\n * @param visited - Set of visited nodes\n * @param stack - Stack to store nodes in reverse topological order\n */\nfunction topologicalSortUtil(graph: Graph, node: NodeId, visited: Set<NodeId>, stack: NodeId[]): 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 * @param graph - The directed graph to analyze\n * @returns Array of strongly connected components (each is an array of node IDs)\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 * @param graph - The graph being traversed\n * @param node - Current node being visited\n * @param visited - Set of visited nodes\n * @param finishOrder - Array to store nodes in order of completion\n */\nfunction dfsFinishOrder(graph: Graph, node: NodeId, visited: Set<NodeId>, finishOrder: NodeId[]): 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 * @param graph - The graph being traversed\n * @param node - Current node being visited\n * @param visited - Set of visited nodes\n * @param component - Array to collect nodes in the current component\n */\nfunction dfsCollectComponent(graph: Graph, node: NodeId, visited: Set<NodeId>, component: NodeId[]): 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 * @param graph - The directed graph to transpose\n * @returns A new graph with all edges reversed\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 * One relaxable arc: a direction an edge can actually be traversed in.\n */\ninterface Arc {\n from: NodeId;\n to: NodeId;\n weight: number;\n}\n\n/**\n * Expand the graph's edges into the arcs Bellman-Ford may relax.\n *\n * A directed graph yields one arc per edge. An UNDIRECTED graph yields two, because\n * `graph.edges()` reports each undirected edge once, arbitrarily oriented from one of its\n * endpoints. Relaxing only that orientation makes every edge one-way and leaves most of an\n * undirected graph unreachable from the source -- the distances come back as Infinity for\n * nodes that are plainly connected.\n *\n * Note that expanding is not merely a convenience: on an undirected graph a single\n * negative-weight edge IS a negative cycle, since it can be traversed back and forth forever.\n * Producing both arcs is what lets the cycle check below report that correctly.\n * @param graph - The graph whose edges are being expanded.\n * @returns Every arc that may be relaxed, in edge order.\n */\nfunction relaxableArcs(graph: Graph): Arc[] {\n const arcs: Arc[] = [];\n for (const edge of graph.edges()) {\n const weight = edge.weight ?? 1;\n arcs.push({ from: edge.source, to: edge.target, weight });\n if (!graph.isDirected) {\n arcs.push({ from: edge.target, to: edge.source, weight });\n }\n }\n\n return arcs;\n}\n\n/**\n * Find shortest paths from source using Bellman-Ford algorithm\n * @param graph - The graph to search\n * @param source - The starting node for the search\n * @param options - Algorithm options including optional target for early termination\n * @returns The distances, predecessors, and negative cycle information\n */\nexport function bellmanFord(graph: Graph, source: NodeId, options: BellmanFordOptions = {}): 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 const arcs = relaxableArcs(graph);\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 arc of arcs) {\n const u = arc.from;\n const v = arc.to;\n const {weight} = arc;\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 arc of arcs) {\n const u = arc.from;\n const v = arc.to;\n const {weight} = arc;\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 * @param graph - The graph to search\n * @param source - The starting node for the path\n * @param target - The destination node for the path\n * @returns The shortest path result or null if no path exists\n */\nexport function bellmanFordPath(graph: Graph, source: NodeId, target: NodeId): 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 * @param graph - The graph to check for negative cycles\n * @returns True if the graph contains a negative cycle\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 * 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 /**\n * Creates a new PriorityQueue instance.\n * @param compareFn - Custom comparison function for priorities. Returns negative if a has higher priority than b.\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 * @param item - The item to add to the queue\n * @param priority - The priority value for the item (lower values have higher priority in min-heap)\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 * @returns The item with the highest priority, or undefined if the queue is empty\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 * @returns The item with the highest priority, or undefined if the queue is empty\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 * @returns True if the queue has no items, false otherwise\n */\n isEmpty(): boolean {\n return this.heap.length === 0;\n }\n\n /**\n * Get the number of items in the queue\n * @returns The number of items currently 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 * @param item - The item whose priority should be updated\n * @param newPriority - The new priority value for the item\n * @returns True if the item was found and updated, false otherwise\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 * @returns An array of all items with their priorities\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 * @param index - The index of the element to heapify up\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 * @param index - The index of the element to heapify down\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 (\n leftChildIndex < this.heap.length &&\n leftChild &&\n target &&\n this.compareFn(leftChild.priority, target.priority) < 0\n ) {\n targetIndex = leftChildIndex;\n }\n\n const rightChild = this.heap[rightChildIndex];\n const newTarget = this.heap[targetIndex];\n\n if (\n rightChildIndex < this.heap.length &&\n rightChild &&\n newTarget &&\n this.compareFn(rightChild.priority, newTarget.priority) < 0\n ) {\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 * @param i - Index of the first element\n * @param j - Index of the second element\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 /**\n * Creates a new BidirectionalDijkstra instance\n * @param graph - The graph to search for shortest paths\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 * @param source - The starting node for the path\n * @param target - The destination node for the path\n * @returns The shortest path result or null if no path exists\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() || !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 (\n !this.forwardSearch.frontier.isEmpty() &&\n (this.backwardSearch.frontier.isEmpty() ||\n this.forwardSearch.frontier.size() <= this.backwardSearch.frontier.size())\n ) {\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() && 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(search: SearchState, oppositeSearch: SearchState, isForward: boolean): 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 ? this.graph.getEdge(current, neighbor) : 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) || 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 * @param graph - The graph to search\n * @param source - The starting node for the search\n * @param options - Algorithm options including optional target for early termination\n * @returns A map of node IDs to their shortest path results\n */\nexport function dijkstra(graph: Graph, source: NodeId, options: DijkstraOptions = {}): 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 * @param graph - The graph to search\n * @param source - The starting node for the path\n * @param target - The destination node for the path\n * @param options - Algorithm options including bidirectional search toggle\n * @returns The shortest path result or null if no path exists\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 * @param graph - The graph to search\n * @param source - The starting node for the search\n * @param cutoff - Optional maximum distance to search\n * @returns A map of node IDs to their distances from the source\n */\nexport function singleSourceShortestPath(graph: Graph, source: NodeId, cutoff?: number): 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 * @param graph - The graph to compute all-pairs shortest paths for\n * @returns A nested map of source to target to distance\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","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\n/**\n * Computes all-pairs shortest paths using the Floyd-Warshall algorithm\n * @param graph - The graph to compute shortest paths for\n * @returns The distances, predecessors, and negative cycle detection result\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\n/**\n * Finds the shortest path between two nodes using Floyd-Warshall\n * @param graph - The graph to search\n * @param source - The starting node for the path\n * @param target - The destination node for the path\n * @returns The path and distance or null if no path exists\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\n/**\n * Computes the transitive closure of a graph using Floyd-Warshall\n * @param graph - The graph to compute transitive closure for\n * @returns A map of each node to the set of nodes reachable from it\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 * @param graph - The input graph to traverse\n * @param source - The source node to start BFS from\n * @param options - Configuration options\n * @param options.optimized - Whether to use CSR-optimized implementation for large graphs\n * @returns Object containing distances, predecessors, path counts (sigma), and traversal stack\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 * @param graph - The input graph to traverse\n * @param source - The source node to start BFS from\n * @param cutoff - Maximum distance to explore (optional)\n * @param options - Configuration options\n * @param options.optimized - Whether to use CSR-optimized implementation for large graphs\n * @returns Map of node IDs to their shortest distances from the source\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 * @param graph - The input graph to check for bipartiteness\n * @returns Object with bipartite status and optional partition sets\n */\nexport function bfsColoringWithPartitions(graph: Graph): {\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 * @param residualGraph - Map representing the residual graph with capacities\n * @param source - The source node ID\n * @param sink - The sink node ID\n * @returns Object with path and capacity, or null if no path exists\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 * @param graph - The input weighted graph to traverse\n * @param source - The source node to start BFS from\n * @param cutoff - Maximum distance to explore (optional)\n * @param options - Configuration options\n * @param options.optimized - Whether to use CSR-optimized implementation for large graphs\n * @returns Map of node IDs to their shortest weighted distances from the source\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 * @param graph - The CSR graph representation\n * @param source - The source node to start BFS from\n * @returns Object containing distances, predecessors, path counts (sigma), and traversal stack\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 * @param graph - The CSR graph representation\n * @param source - The source node to start BFS from\n * @param cutoff - Maximum distance to explore (optional)\n * @returns Map of node IDs to their shortest distances from the source\n */\nfunction bfsDistancesOnlyCSR(graph: CSRGraph, source: NodeId, cutoff?: number): 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 * @param graph - The CSR graph representation\n * @param source - The source node to start BFS from\n * @param cutoff - Maximum distance to explore (optional)\n * @returns Map of node IDs to their shortest weighted distances from the source\n */\nfunction bfsWeightedDistancesCSR(graph: CSRGraph, source: NodeId, cutoff?: number): 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 *\n * Every member is `readonly` and carries `| undefined`: the GPU package compiles this declaration\n * a second time under `exactOptionalPropertyTypes`, where `sources?: readonly number[]` and\n * `sources?: readonly number[] | undefined` are different types (plan decision PD-6).\n */\nexport interface BetweennessCentralityOptions {\n /** Whether to normalize the centrality values (default: false) */\n readonly normalized?: boolean | undefined;\n /** Whether to use endpoints in path counting (default: false) */\n readonly endpoints?: boolean | undefined;\n /** Whether to use optimized BFS implementation for large graphs */\n readonly optimized?: boolean | undefined;\n /**\n * Sampled betweenness: the source NODE INDICES to run from. Indices are meaningful only against\n * a `GraphSnapshot`, so the legacy `Graph`-taking entry points below THROW when this is set.\n */\n readonly sources?: readonly number[] | undefined;\n /** Sampled betweenness: how many sources to draw when `sources` is not given. */\n readonly k?: number | undefined;\n}\n\n/**\n * Refuse the index-space options on a path that has no index space.\n *\n * Ignoring them would be the expensive silence: a caller asking for a 128-source sample would get\n * an exact all-sources run, correct and a thousand times too slow, with no signal at all.\n * @param options - The caller's options\n * @param fn - The entry point's name, for the message\n */\nfunction rejectIndexOptions(options: BetweennessCentralityOptions, fn: string): void {\n if (options.sources !== undefined || options.k !== undefined) {\n throw new Error(\n `${fn}: 'sources' and 'k' are node INDICES and are meaningful only against a GraphSnapshot; ` +\n \"call accelerated(accelerator).betweennessCentrality(snapshot, options) instead\",\n );\n }\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 * @param graph - The input graph to analyze\n * @param source - The source node for shortest path computation\n * @param optimized - Whether to use optimized BFS implementation\n * @returns The BFS result containing stack, predecessors, sigma, and distances\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 * @param result - The BFS result from brandesSingleSource\n * @param source - The source node used in BFS\n * @param centrality - The centrality map to update\n * @param options - Algorithm configuration options\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 * @param result - The BFS result from brandesSingleSource\n * @param source - The source node used in BFS\n * @param edgeCentrality - The edge centrality map to update\n * @param options - Algorithm configuration options\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 * @param centrality - The centrality map to normalize in place\n * @param nodeCount - Total number of nodes in the graph\n * @param isDirected - Whether the graph is directed\n */\nfunction normalizeCentrality(centrality: Record<string, number>, nodeCount: number, isDirected: boolean): void {\n const n = nodeCount;\n const normalizationFactor = isDirected ? (n - 1) * (n - 2) : ((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 * @param graph - The input graph to analyze\n * @param options - Algorithm configuration options\n * @returns Centrality scores for each node keyed by node ID\n */\nexport function betweennessCentrality(\n graph: Graph,\n options: BetweennessCentralityOptions = {},\n): Record<string, number> {\n rejectIndexOptions(options, \"betweennessCentrality\");\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 * @param graph - The input graph to analyze\n * @param targetNode - The node to calculate centrality for\n * @param options - Algorithm configuration options\n * @returns The betweenness centrality score for the target node\n */\nexport function nodeBetweennessCentrality(\n graph: Graph,\n targetNode: NodeId,\n options: BetweennessCentralityOptions = {},\n): number {\n rejectIndexOptions(options, \"nodeBetweennessCentrality\");\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 * @param graph - The input graph to analyze\n * @param options - Algorithm configuration options\n * @returns Edge centrality scores keyed by edge string representation\n */\nexport function edgeBetweennessCentrality(\n graph: Graph,\n options: BetweennessCentralityOptions = {},\n): Map<string, number> {\n rejectIndexOptions(options, \"edgeBetweennessCentrality\");\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 - 1) * (n - 2) : ((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 * @param distances - Map of node IDs to their distances from source\n * @param sourceNode - The source node for distance calculations\n * @param totalNodes - Total number of nodes in the graph\n * @param options - Algorithm configuration options\n * @returns The closeness centrality score for the source node\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 * @param graph - The input graph\n * @param options - Algorithm options\n * @returns Centrality scores for each node\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(graph: Graph, options: ClosenessCentralityOptions = {}): 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 * @param graph - The input graph to analyze\n * @param node - The node to calculate centrality for\n * @param options - Algorithm configuration options\n * @returns The closeness centrality score for the node\n */\nexport function nodeClosenessCentrality(graph: Graph, node: NodeId, options: ClosenessCentralityOptions = {}): 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(\n graph,\n node,\n options.cutoff,\n options.optimized !== undefined ? { optimized: options.optimized } : {},\n );\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 * @param graph - The input graph to analyze\n * @param options - Algorithm configuration options\n * @returns Centrality scores for each node keyed by node ID\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 * @param graph - The input graph to analyze\n * @param node - The node to calculate centrality for\n * @param options - Algorithm configuration options\n * @returns The weighted closeness centrality score for the node\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(\n graph,\n node,\n options.cutoff,\n options.optimized !== undefined ? { optimized: options.optimized } : {},\n );\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 * @param graph - The input graph to analyze\n * @param options - Algorithm configuration options\n * @returns Centrality scores for each node keyed by node ID\n */\nexport function degreeCentrality(graph: Graph, options: CentralityOptions = {}): 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 ? degree / maxPossibleDegree : 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 * @param graph - The input graph to analyze\n * @param nodeId - The node to calculate centrality for\n * @param options - Algorithm configuration options\n * @returns The degree centrality score for the node\n */\nexport function nodeDegreeCentrality(graph: Graph, nodeId: string | number, options: CentralityOptions = {}): 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 ? degree / maxPossibleDegree : 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\n/**\n * Delta-based PageRank class that tracks changes between iterations\n * and only processes nodes with significant changes for improved performance.\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 /**\n * Creates a new DeltaPageRank instance for the given graph.\n * @param graph - The directed graph to compute PageRank on\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 /**\n * Computes PageRank scores using delta-based iteration for faster convergence.\n * @param options - Configuration options for PageRank computation\n * @returns Map of node IDs to their PageRank scores\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 * @param modifiedNodes - Set of nodes that were modified (edges added/removed)\n * @param options - Configuration options for PageRank computation\n * @returns Updated PageRank scores\n */\n public update(modifiedNodes: Set<NodeId>, options: DeltaPageRankOptions = {}): 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 /**\n * Creates a new PriorityDeltaPageRank instance for the given graph.\n * @param graph - The directed graph to compute PageRank on\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 /**\n * Computes PageRank scores using priority queue-based delta iteration.\n * Processes nodes in order of their delta magnitude for optimal convergence.\n * @param options - Configuration options for PageRank computation\n * @returns Map of node IDs to their PageRank scores\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 { ConvergenceError } from \"../../errors.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 + E)\n */\n\nexport interface EigenvectorCentralityOptions extends CentralityOptions {\n maxIterations?: number; // Maximum iterations (default: 100)\n tolerance?: number; // Convergence tolerance per node (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 *\n * Iterates x <- (A + I) x, as networkx does. Shifting by the identity raises every eigenvalue by\n * one and leaves the eigenvectors alone, so the largest eigenvalue becomes the only one of largest\n * magnitude -- even on a bipartite graph, whose spectrum holds both +lambda and -lambda and makes\n * unshifted power iteration oscillate forever. The run stops when the L1 change summed over all\n * nodes falls below `n * tolerance`, networkx's test.\n *\n * On a directed graph `mode` picks the edges that feed a node: `\"in\"` (the default, as networkx)\n * scores a node by the nodes pointing AT it, `\"out\"` by the nodes it points at (networkx on\n * `G.reverse()`), and `\"total\"` by both (networkx on `G.to_undirected()`). An undirected graph\n * ignores `mode`. When the graph has no cycle along that relation (no edges, or a directed\n * acyclic graph) the adjacency matrix is nilpotent, its only eigenvalue is 0, and every score is\n * exactly 0.\n * @param graph - The graph to compute eigenvector centrality on\n * @param options - Configuration options for the computation\n * @returns Object mapping node IDs to their eigenvector centrality scores\n * @throws {ConvergenceError} When `maxIterations` passes do not meet `tolerance`, as networkx\n * raises `PowerIterationFailedConvergence`. Raise `maxIterations` or `tolerance` and call again.\n */\nexport function eigenvectorCentrality(graph: Graph, options: EigenvectorCentralityOptions = {}): CentralityResult {\n const { maxIterations = 100, tolerance = 1e-6, normalized = true, startVector, mode = \"in\" } = options;\n\n const nodeIds = Array.from(graph.nodes(), (node) => node.id);\n const keys = nodeIds.map((id) => id.toString());\n const n = keys.length;\n const centrality: CentralityResult = {};\n\n if (n === 0) {\n return centrality;\n }\n\n const index = new Map(keys.map((key, i) => [key, i]));\n const feeders = (id: (typeof nodeIds)[number]): Iterable<(typeof nodeIds)[number]> => {\n if (!graph.isDirected || mode === \"out\") {\n return graph.neighbors(id);\n }\n return mode === \"in\" ? graph.inNeighbors(id) : new Set([...graph.inNeighbors(id), ...graph.neighbors(id)]);\n };\n const adjacency = nodeIds.map((id) => Array.from(feeders(id), (m) => index.get(m.toString()) ?? 0));\n\n if (isNilpotent(adjacency)) {\n for (const key of keys) {\n centrality[key] = 0;\n }\n return centrality;\n }\n\n // A node with nothing feeding it scores exactly 0 once the largest eigenvalue is positive,\n // so it starts there and (A + I) keeps it there.\n let x = new Float64Array(n);\n for (let i = 0; i < n; i++) {\n x[i] = adjacency[i]?.length ? (startVector?.get(keys[i] ?? \"\") ?? 1) : 0;\n }\n scaleToUnitLength(x);\n\n let next = new Float64Array(n);\n let converged = false;\n for (let iteration = 0; iteration < maxIterations && !converged; iteration++) {\n for (let i = 0; i < n; i++) {\n let sum = x[i] ?? 0;\n for (const j of adjacency[i] ?? []) {\n sum += x[j] ?? 0;\n }\n next[i] = sum;\n }\n scaleToUnitLength(next);\n\n let change = 0;\n for (let i = 0; i < n; i++) {\n change += Math.abs((next[i] ?? 0) - (x[i] ?? 0));\n }\n [x, next] = [next, x];\n converged = change < n * tolerance;\n }\n if (!converged) {\n throw new ConvergenceError(\"eigenvectorCentrality\", maxIterations, tolerance);\n }\n\n for (let i = 0; i < n; i++) {\n centrality[keys[i] ?? \"\"] = x[i] ?? 0;\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 for (const value of x) {\n maxValue = Math.max(maxValue, value);\n minValue = Math.min(minValue, value);\n }\n const range = maxValue - minValue;\n // All scores equal: 1 each, or 0 each when there is nothing to score.\n const flat = maxValue > 0 ? 1 : 0;\n for (const key of keys) {\n centrality[key] = range > 0 ? ((centrality[key] ?? 0) - minValue) / range : flat;\n }\n }\n\n return centrality;\n}\n\n/**\n * Whether the relation has no cycle (Kahn's algorithm), which makes its adjacency matrix nilpotent.\n * @param adjacency - Each node's neighbour indices\n * @returns True when every node can be peeled off in topological order\n */\nfunction isNilpotent(adjacency: number[][]): boolean {\n const inDegree = new Int32Array(adjacency.length);\n for (const targets of adjacency) {\n for (const j of targets) {\n inDegree[j] = (inDegree[j] ?? 0) + 1;\n }\n }\n const queue: number[] = [];\n inDegree.forEach((degree, i) => {\n if (degree === 0) {\n queue.push(i);\n }\n });\n for (let head = 0; head < queue.length; head++) {\n for (const j of adjacency[queue[head] ?? 0] ?? []) {\n inDegree[j] = (inDegree[j] ?? 0) - 1;\n if (inDegree[j] === 0) {\n queue.push(j);\n }\n }\n }\n return queue.length === adjacency.length;\n}\n\n/**\n * Scale a vector in place to unit Euclidean length (a zero vector is left alone).\n * @param v - The vector to scale\n */\nfunction scaleToUnitLength(v: Float64Array): void {\n let norm = 0;\n for (const value of v) {\n norm += value * value;\n }\n norm = Math.sqrt(norm);\n if (norm > 0) {\n for (let i = 0; i < v.length; i++) {\n v[i] = (v[i] ?? 0) / norm;\n }\n }\n}\n\n/**\n * Calculate eigenvector centrality for a specific node.\n * @param graph - The graph to compute eigenvector centrality on\n * @param nodeId - The ID of the node to calculate centrality for\n * @param options - Configuration options for the computation\n * @returns The eigenvector centrality score for the specified 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 * @param graph - The graph to compute HITS scores on\n * @param options - Configuration options for the computation\n * @returns Object containing hub and authority scores for all nodes\n */\nexport function hits(graph: Graph, options: HITSOptions = {}): HITSResult {\n const { maxIterations = 100, tolerance = 1e-6, normalized = true } = 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 * @param graph - The graph to compute HITS scores on\n * @param nodeId - The ID of the node to calculate scores for\n * @param options - Configuration options for the computation\n * @returns Object containing hub and authority scores for the specified 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 * @param graph - The graph to compute Katz centrality on\n * @param options - Configuration options for the computation\n * @returns Object mapping node IDs to their Katz centrality scores\n */\nexport function katzCentrality(graph: Graph, options: KatzCentralityOptions = {}): CentralityResult {\n const { alpha = 0.1, beta = 1.0, maxIterations = 100, tolerance = 1e-6, normalized = true } = 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 ? Array.from(graph.inNeighbors(nodeId)) : 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 * @param graph - The graph to compute Katz centrality on\n * @param nodeId - The ID of the node to calculate centrality for\n * @param options - Configuration options for the computation\n * @returns The Katz centrality score for the specified node\n */\nexport function nodeKatzCentrality(graph: Graph, nodeId: string | number, options: KatzCentralityOptions = {}): 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. compute() runs the same power iteration as the standard\n * algorithm; update() restarts it from the previous scores after a graph change.\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 /** Iterations the last compute() or update() actually ran. */\n public iterations = 0;\n\n /** Whether the last compute() or update() met its tolerance before maxIterations. */\n public converged = false;\n\n /**\n * Creates a new SimpleDeltaPageRank instance for the given graph.\n * @param graph - The directed graph to compute PageRank on\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 /**\n * Computes PageRank scores for all nodes in the graph using power iteration.\n * @param options - Configuration options for PageRank computation\n * @param options.dampingFactor - Probability of following a link (default: 0.85)\n * @param options.tolerance - Convergence tolerance threshold (default: 1e-6)\n * @param options.maxIterations - Maximum number of iterations (default: 100)\n * @param options.initialRanks - Starting scores (missing nodes start at 1/n; normalized to sum 1)\n * @param options.personalization - Personalization vector for Personalized PageRank\n * @param options.weight - Edge attribute name for weighted PageRank\n * @returns Map of node IDs to their PageRank scores; `iterations` and `converged` describe the run\n */\n public compute(\n options: {\n dampingFactor?: number;\n tolerance?: number;\n maxIterations?: number;\n initialRanks?: Map<NodeId, number>;\n personalization?: Map<NodeId, number>;\n weight?: string;\n } = {},\n ): Map<NodeId, number> {\n const {\n dampingFactor = 0.85,\n tolerance = 1e-6,\n maxIterations = 100,\n initialRanks,\n personalization,\n weight,\n } = options;\n\n this.iterations = 0;\n this.converged = false;\n\n if (this.nodeCount === 0) {\n this.converged = true;\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, initialRanks?.get(node.id) ?? 1.0 / this.nodeCount);\n }\n\n this.normalizeMap(scores);\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 totalWeight += weight ? (this.graph.getEdge(node.id, neighbor)?.weight ?? 1) : 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. Every node propagates every iteration: skipping a node whose score has\n // settled drops its whole contribution from its neighbours, which leaks rank and stops the\n // run from ever converging.\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 every node\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\n let maxDiff = 0;\n\n for (const nodeId of scores.keys()) {\n maxDiff = Math.max(maxDiff, Math.abs((newScores.get(nodeId) ?? 0) - (scores.get(nodeId) ?? 0)));\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 if (maxDiff < tolerance) {\n this.converged = true;\n break;\n }\n }\n\n this.iterations = this.converged ? iteration + 1 : iteration;\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 * @param modifiedNodes - Set of nodes that were modified (edges added/removed)\n * @param options - Computation options\n * @param options.dampingFactor - Probability of following a link (default: 0.85)\n * @param options.tolerance - Convergence tolerance threshold (default: 1e-6)\n * @param options.maxIterations - Maximum number of iterations (default: 100)\n * @param options.personalization - Personalization vector for Personalized PageRank\n * @param options.weight - Edge attribute name for weighted PageRank\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 { dampingFactor = 0.85, tolerance = 1e-6, maxIterations = 100, personalization, weight } = options;\n\n this.iterations = 0;\n this.converged = false;\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 totalWeight += weight ? (this.graph.getEdge(node.id, neighbor)?.weight ?? 1) : 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 this.converged = true;\n break;\n }\n }\n\n this.iterations = this.converged ? iteration + 1 : iteration;\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 * @param graph - The directed input graph to analyze\n * @param options - Algorithm configuration options\n * @returns PageRank result containing ranks, iteration count, and convergence status\n */\nexport function pageRank(graph: Graph, options: PageRankOptions = {}): 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 initialRanks?: Map<NodeId, number>;\n personalization?: Map<NodeId, number>;\n weight?: string;\n } = {\n dampingFactor,\n tolerance,\n maxIterations,\n };\n\n if (initialRanks) {\n deltaOptions.initialRanks = initialRanks;\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: deltaPageRank.iterations,\n converged: deltaPageRank.converged,\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 // The loop breaks before incrementing on convergence, and leaves at maxIterations otherwise.\n iterations: converged ? iteration + 1 : iteration,\n converged,\n };\n}\n\n/**\n * Calculate Personalized PageRank for a specific set of source nodes\n * @param graph - The directed input graph to analyze\n * @param personalNodes - Nodes to personalize the PageRank towards\n * @param options - Algorithm configuration options\n * @returns PageRank result containing ranks, iteration count, and convergence status\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 * @param graph - The directed input graph to analyze\n * @param options - Algorithm configuration options\n * @returns PageRank scores for each node keyed by node ID\n */\nexport function pageRankCentrality(graph: Graph, options: PageRankOptions = {}): 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 * @param graph - The directed input graph to analyze\n * @param k - Number of top nodes to return\n * @param options - Algorithm configuration options\n * @returns Array of top-k nodes with their PageRank scores, sorted descending\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 * @param ranks - The ranks map to normalize in place\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 /**\n * Creates a new UnionFind data structure with the given elements.\n * @param elements - Array of elements to initialize the data structure with\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 * @param element - The element to find the root for\n * @returns The root element of the set containing the given element\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 * @param elementA - The first element whose set should be merged\n * @param elementB - The second element whose set should be merged\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 * @param elementA - The first element to check\n * @param elementB - The second element to check\n * @returns True if both elements are in the same component, false otherwise\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 * @returns The current count of disjoint 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 * @param element - The element whose component should be retrieved\n * @returns Array of all elements in the same component\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 * @returns Array of arrays, where each inner array contains elements of one component\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 * @param element - The element whose component size should be retrieved\n * @returns The number of elements in 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 * @param element - The element to add as a new singleton set\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 * @param element - The element to check for\n * @returns True if the element exists, false otherwise\n */\n hasElement(element: NodeId): boolean {\n return this.parent.has(element);\n }\n\n /**\n * Get the total number of elements\n * @returns The total count of all elements in the data structure\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 * @param graph - The input graph (must be undirected)\n * @returns Array of connected components, each containing an array of node IDs\n */\nexport function connectedComponents(graph: Graph): NodeId[][] {\n if (graph.isDirected) {\n throw new Error(\n \"Connected components algorithm requires an undirected graph. Use stronglyConnectedComponents for directed graphs.\",\n );\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 * @param graph - The input graph (must be undirected)\n * @returns Array of connected components, each containing an array of node IDs\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 * @param graph - The input graph\n * @param nodeId - The starting node ID\n * @param visited - Set of already visited node IDs\n * @param component - Array to accumulate component members\n */\nfunction dfsComponent(graph: Graph, nodeId: NodeId, visited: Set<NodeId>, component: NodeId[]): 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 * @param graph - The input graph (must be undirected)\n * @returns The number of connected components in the graph\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 * @param graph - The input graph (must be undirected)\n * @returns True if the graph is connected, false otherwise\n */\nexport function isConnected(graph: Graph): boolean {\n return numberOfConnectedComponents(graph) <= 1;\n}\n\n/**\n * Find the largest connected component\n * @param graph - The input graph (must be undirected)\n * @returns Array of node IDs in 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) => (current.length > largest.length ? current : largest));\n}\n\n/**\n * Get the connected component containing a specific node\n * @param graph - The input graph (must be undirected)\n * @param nodeId - The node ID to find the component for\n * @returns Array of node IDs in the same component as the specified 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 * @param graph - The input graph (must be directed)\n * @returns Array of strongly connected components, each containing an array of node IDs\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 * @param graph - The input graph (must be directed)\n * @returns True if the graph is strongly connected, false otherwise\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 * @param graph - The input graph (must be directed)\n * @returns Array of weakly connected components, each containing an array of node IDs\n */\nexport function weaklyConnectedComponents(graph: Graph): NodeId[][] {\n if (!graph.isDirected) {\n throw new Error(\n \"Weakly connected components are for directed graphs. Use connectedComponents for undirected graphs.\",\n );\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 * @param graph - The input graph (must be directed)\n * @returns True if the graph is weakly connected, false otherwise\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 * @param graph - The input graph (must be directed)\n * @returns Object containing the condensed graph, component map, and component arrays\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 && 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\n/**\n * Computes the minimum spanning tree of an undirected graph using Kruskal's algorithm.\n * The algorithm sorts edges by weight and greedily adds edges that don't create cycles,\n * using a union-find data structure to efficiently detect cycles.\n * @param graph - The undirected graph to compute the MST for\n * @returns The minimum spanning tree as a set of edges and the total weight\n * @throws Error if the graph is directed or not connected\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 =\n 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\n/**\n * Alias for kruskalMST. Computes the minimum spanning tree of an undirected graph.\n * @param graph - The undirected graph to compute the MST for\n * @returns The minimum spanning tree as a set of edges and the total weight\n * @throws Error if the graph is directed or not connected\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\n/**\n * Computes the minimum spanning tree of an undirected graph using Prim's algorithm.\n * The algorithm grows the MST from a starting node by repeatedly adding the minimum\n * weight edge that connects a node in the tree to a node outside the tree.\n * @param graph - The undirected graph to compute the MST for\n * @param startNode - Optional starting node; if not provided, uses the first node in the graph\n * @returns The minimum spanning tree as a set of edges and the total weight\n * @throws Error if the graph is directed, the start node is not found, or the graph is not connected\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 * @param graph - The input graph\n * @param options - Algorithm options\n * @returns Array of community detection results representing the dendrogram\n */\nexport function girvanNewman(graph: Graph, options: GirvanNewmanOptions = {}): 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 { betweenness: edgeBetweenness, edgeEndpoints } = 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 // Use original edge endpoints to preserve node ID types (number vs string)\n const endpoints = edgeEndpoints.get(edgeKey);\n if (endpoints) {\n edgesToRemove.push(endpoints);\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((community) => community.length >= minCommunitySize);\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 * Edge betweenness result containing centrality values and original edge endpoints\n */\ninterface EdgeBetweennessResult {\n betweenness: Map<string, number>;\n edgeEndpoints: Map<string, { source: NodeId; target: NodeId }>;\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 * @param graph - The input graph to analyze\n * @returns Object with betweenness map and edge endpoints map (preserving original ID types)\n */\nfunction calculateEdgeBetweenness(graph: Graph): EdgeBetweennessResult {\n const edgeBetweenness = new Map<string, number>();\n const edgeEndpoints = new Map<string, { source: NodeId; target: NodeId }>();\n\n // Initialize all edges with 0 betweenness and store original endpoints\n for (const edge of graph.edges()) {\n const edgeKey = getEdgeKey(edge.source, edge.target);\n edgeBetweenness.set(edgeKey, 0);\n edgeEndpoints.set(edgeKey, { source: edge.source, target: edge.target });\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 { betweenness: edgeBetweenness, edgeEndpoints };\n}\n\n/**\n * Find all shortest paths from a source node using optimized BFS\n * @param graph - The input graph to search\n * @param source - The source node to compute shortest paths from\n * @returns Object containing distances, predecessors, and path counts\n */\nfunction findAllShortestPaths(\n graph: Graph,\n source: NodeId,\n): {\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 * @param source - The source node ID\n * @param target - The target node ID\n * @returns A consistent string key for the edge (ordered alphabetically)\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\n *\n * Newman's Q, written per community:\n *\n * Q = sum over communities c of [ w_in(c) / m - ( K_c / (2m) )^2 ]\n *\n * where m is the total edge weight with each undirected edge counted once, w_in(c) is the summed\n * weight of the edges with both endpoints inside c, and K_c is the summed weighted degree of c's\n * nodes.\n *\n * WHY NOT A SUM OVER EDGES. The textbook double sum runs over every ordered PAIR of nodes inside\n * a community, not only over the pairs an edge happens to join. Collecting the null-model term\n * only where an edge exists leaves the penalty far too small, and the shortfall grows with\n * community size -- so the uncut whole graph, whose modularity is 0 by definition, outscores\n * every real cut and a caller reading the dendrogram the standard way is handed one community\n * containing everything. The per-community form above counts every pair exactly once and still\n * costs one pass over the edges rather than a pass over every pair.\n * @param graph - The original graph\n * @param communityMap - Map from node IDs to community indices\n * @returns The modularity score of the partition\n */\nfunction calculateModularity(graph: Graph, communityMap: Map<NodeId, number>): number {\n const totalEdgeWeight = getTotalEdgeWeight(graph);\n if (totalEdgeWeight === 0) {\n return 0;\n }\n\n // Summed weighted degree of each community's nodes.\n const degreeSum = new Map<number, number>();\n for (const node of graph.nodes()) {\n const community = communityMap.get(node.id);\n if (community === undefined) {\n continue;\n }\n\n degreeSum.set(community, (degreeSum.get(community) ?? 0) + getNodeDegree(graph, node.id));\n }\n\n // Summed weight of the edges that stay inside a community.\n const internalWeight = new Map<number, number>();\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 === undefined || communityI !== communityJ) {\n continue;\n }\n\n internalWeight.set(communityI, (internalWeight.get(communityI) ?? 0) + (edge.weight ?? 1));\n }\n\n let modularity = 0;\n for (const [community, degrees] of degreeSum) {\n const share = degrees / (2 * totalEdgeWeight);\n modularity += (internalWeight.get(community) ?? 0) / totalEdgeWeight - share * share;\n }\n\n return modularity;\n}\n\n/**\n * Calculate total edge weight in the graph\n * @param graph - The input graph\n * @returns Total sum of all edge weights\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 * @param graph - The input graph\n * @param nodeId - The node ID to compute degree for\n * @returns The weighted degree of the 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 * @param graph - The input graph\n * @returns Object containing components array and node-to-component map\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","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 * @param graph - The Graph instance to convert\n * @returns A nested Map where outer keys are source nodes and inner maps contain target nodes with edge weights\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 * @param map - The nested Map representation of the graph\n * @param isDirected - Whether the resulting graph should be directed (defaults to true)\n * @returns A new Graph instance with nodes and edges from the map\n */\nexport function mapToGraph(map: Map<string, Map<string, number>>, isDirected = true): 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 /**\n * Creates a new GraphAdapter instance wrapping a Map representation.\n * @param map - The nested Map representation of the graph\n * @param isDirected - Whether the graph should be treated as directed (defaults to true)\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 * @returns Array of node objects with their ids\n */\n nodes(): { id: NodeId }[] {\n return Array.from(this.map.keys()).map((id) => ({ id }));\n }\n\n /**\n * Get node count\n * @returns The total number of nodes in the graph\n */\n get nodeCount(): number {\n return this.map.size;\n }\n\n /**\n * Check if node exists\n * @param nodeId - The id of the node to check\n * @returns True if the node exists, false otherwise\n */\n hasNode(nodeId: NodeId): boolean {\n return this.map.has(String(nodeId));\n }\n\n /**\n * Get neighbors of a node\n * @param nodeId - The id of the node to get neighbors for\n * @returns Array of neighbor node ids\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 * @param source - The source node id\n * @param target - The target node id\n * @returns The edge object with source, target and weight, or null if no edge exists\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 * @param source - The source node id\n * @param target - The target node id\n * @returns True if an edge exists between source and target, false otherwise\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 * @returns Array of edge objects with source, target and optional weight\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 * @returns The total number of edges in the graph\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 * @param nodeId - The id of the node to get degree for\n * @returns The number of edges connected to the node\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 * @param nodeId - The id of the node to get in-degree for\n * @returns The number of incoming edges to the node\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 * @param nodeId - The id of the node to get out-degree for\n * @returns The number of outgoing edges from the node\n */\n outDegree(nodeId: NodeId): number {\n return this.degree(nodeId);\n }\n\n /**\n * Get underlying map representation\n * @returns The internal Map representation of the graph\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 /**\n * Creates a new SeededRandom instance with the given seed.\n * @param seed - The seed value for reproducible random number generation\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 * @returns A pseudo-random number in the range [0, 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 * @param seed - The seed value for reproducible random number generation\n * @returns A function that returns the next random number when called\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 * @param values - Map of values to normalize in place\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 * @param values - Map of values to normalize in place\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 * @param values - Map of values to normalize in place\n */\n l2Norm(values: Map<string, number>): void {\n const sumSquares = Array.from(values.values()).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 * @param values - Map of values to normalize in place\n */\n sumToOne(values: Map<string, number>): void {\n const sum = Array.from(values.values()).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 * @param graph - Map representation of the graph (node to neighbors with weights)\n * @param options - Algorithm configuration options\n * @returns Community assignments, iteration count, and convergence status\n */\nfunction labelPropagationImpl(\n graph: Map<string, Map<string, number>>,\n options: LabelPropagationOptions = {},\n): LabelPropagationResult {\n const { maxIterations = 100, randomSeed = 42 } = 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 * @param graph - Map representation of the graph (node to neighbors with weights)\n * @param options - Algorithm configuration options\n * @returns Community assignments, iteration count, and convergence status\n */\nfunction labelPropagationAsyncImpl(\n graph: Map<string, Map<string, number>>,\n options: LabelPropagationOptions = {},\n): LabelPropagationResult {\n const { maxIterations = 100 } = 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 * @param graph - Map representation of the graph (node to neighbors with weights)\n * @param seedLabels - Map of node IDs to their fixed community labels\n * @param options - Algorithm configuration options\n * @returns Community assignments, iteration count, and convergence status\n */\nfunction labelPropagationSemiSupervisedImpl(\n graph: Map<string, Map<string, number>>,\n seedLabels: Map<string, number>,\n options: LabelPropagationOptions = {},\n): LabelPropagationResult {\n const { maxIterations = 100, randomSeed = 42 } = 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 * @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(graph: Graph, options: LabelPropagationOptions = {}): 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 * @param graph - Undirected graph (can be weighted)\n * @param options - Algorithm options\n * @returns Community assignments\n */\nexport function labelPropagationAsync(graph: Graph, options: LabelPropagationOptions = {}): 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 * @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 * 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/** How many local-moving sweeps one level may take before it is declared settled. */\nconst LOCAL_MOVE_PASSES = 50;\n\n/**\n * Internal implementation of Leiden algorithm for community detection\n * Improves upon Louvain by ensuring well-connected communities\n * @param inputGraph - Map representation of the graph (node to neighbors with weights)\n * @param options - Algorithm configuration options\n * @returns Community assignments, modularity score, and iteration count\n */\nfunction leidenImpl(inputGraph: Map<string, Map<string, number>>, options: LeidenOptions = {}): LeidenResult {\n const { resolution = 1.0, randomSeed = 42, maxIterations = 100, threshold = 1e-7 } = 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 const random = SeededRandom.createGenerator(randomSeed);\n const base = weighLevel(inputGraph);\n\n // Which node of the CURRENT level holds each original node. Every partition is scored against\n // the original graph through this map, so an aggregation can never leave the answer keyed by\n // the super-node names a caller has never heard of -- which is what it used to do.\n const placement = new Map<string, string>();\n for (const node of inputGraph.keys()) {\n placement.set(node, node);\n }\n\n let bestCommunities = singletonCommunities(inputGraph);\n let bestModularity = calculateModularity(inputGraph, bestCommunities, base.degrees, base.totalWeight, resolution);\n let levelGraph = inputGraph;\n let iterations = 0;\n\n // Whether this level is the ORIGINAL graph, started from the best partition so far rather than\n // from singletons. Local moving on aggregated levels can only move whole super-nodes, so a node\n // merged into the wrong community early could never leave it, and the answer could be beaten by\n // moving one node. The paper (Traag et al. 2019) iterates until a pass over the original nodes\n // changes nothing; returning to them once the levels settle is that pass.\n let polishing = false;\n\n while (iterations < maxIterations) {\n iterations++;\n\n const weights = weighLevel(levelGraph);\n const communities = polishing ? new Map(bestCommunities) : singletonCommunities(levelGraph);\n const moved = moveNodesLocally(levelGraph, weights, communities, random, resolution, LOCAL_MOVE_PASSES);\n\n // Leiden's guarantee over Louvain: a community whose members are not connected to each\n // other inside this level's graph is split into the pieces that are.\n for (const [node, piece] of refinePartition(levelGraph, communities)) {\n communities.set(node, piece);\n }\n\n const candidate = new Map<string, number>();\n for (const [original, levelNode] of placement) {\n const community = communities.get(levelNode);\n if (community !== undefined) {\n candidate.set(original, community);\n }\n }\n\n const modularity = calculateModularity(inputGraph, candidate, base.degrees, base.totalWeight, resolution);\n const improved = modularity > bestModularity + threshold;\n\n if (modularity > bestModularity) {\n bestModularity = modularity;\n bestCommunities = candidate;\n }\n\n const distinct = new Set(communities.values()).size;\n const settled = polishing ? !improved : !improved || !moved || distinct === levelGraph.size;\n\n if (settled) {\n if (polishing) {\n break;\n }\n\n // The levels have settled: go back to the original nodes, starting from the answer.\n polishing = true;\n levelGraph = inputGraph;\n for (const node of inputGraph.keys()) {\n placement.set(node, node);\n }\n\n continue;\n }\n\n polishing = false;\n\n const aggregated = aggregateLevel(levelGraph, communities);\n for (const [original, levelNode] of placement) {\n const superNode = aggregated.mapping.get(levelNode);\n if (superNode !== undefined) {\n placement.set(original, superNode);\n }\n }\n\n levelGraph = aggregated.graph;\n }\n\n // Renumber communities consecutively, in the order they are first met, so the ids a caller\n // reads are 0..k-1 whatever the levels handed out along the way.\n const renumbered = new Map<number, number>();\n const finalCommunities = new Map<string, number>();\n for (const [node, community] of bestCommunities) {\n let id = renumbered.get(community);\n if (id === undefined) {\n id = renumbered.size;\n renumbered.set(community, id);\n }\n\n finalCommunities.set(node, id);\n }\n\n return {\n communities: finalCommunities,\n modularity: bestModularity,\n iterations,\n };\n}\n\n/**\n * Calculate modularity of a partition\n * @param graph - Map representation of the graph\n * @param communities - Map of node IDs to community IDs\n * @param degrees - Map of node IDs to their weighted degrees\n * @param totalWeight - Total weight of all edges in the graph\n * @param resolution - Resolution parameter for modularity calculation\n * @returns The modularity score of the 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 * @param node - The node ID to get neighbor communities for\n * @param graph - Map representation of the graph\n * @param communities - Map of node IDs to community IDs\n * @returns Map of community IDs to total edge weight connecting to that community\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 * Refine partition (Leiden-specific improvement)\n * Ensures well-connected communities by considering subsets\n * @param originalGraph - Map representation of the original graph\n * @param communities - Map of node IDs to community IDs\n * @returns Refined community assignments with well-connected communities\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 * @param graph - Map representation of the graph (node to set of neighbors)\n * @returns Array of connected components (each is a set of node IDs)\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 * What one level of the algorithm knows about its own graph.\n *\n * RECOMPUTED PER LEVEL, which is the half that used to be missing. After the first aggregation\n * every node is a super-node, and scoring the new graph with the old graph's degrees made the\n * second level's modularity a number about a graph that no longer existed. It came out at zero,\n * the loop read that as \"no improvement\", and the algorithm stopped after one pass.\n */\ninterface LevelWeights {\n /** The weighted degree of each node at this level, self-loops included. */\n degrees: Map<string, number>;\n /** Half the summed degree: the total edge weight m, each undirected edge counted once. */\n totalWeight: number;\n}\n\n/**\n * Weigh one level's graph.\n * @param graph - The level's graph, stored with both directions of every edge.\n * @returns The degrees and the total edge weight.\n */\nfunction weighLevel(graph: Map<string, Map<string, number>>): LevelWeights {\n const degrees = new Map<string, number>();\n let summed = 0;\n\n for (const [node, neighbors] of graph) {\n let degree = 0;\n for (const weight of neighbors.values()) {\n degree += weight;\n }\n\n degrees.set(node, degree);\n summed += degree;\n }\n\n return { degrees, totalWeight: summed / 2 };\n}\n\n/**\n * One node per community, numbered from zero in the order the graph lists its nodes.\n * @param graph - The level's graph.\n * @returns The partition every level starts from.\n */\nfunction singletonCommunities(graph: Map<string, Map<string, number>>): Map<string, number> {\n const communities = new Map<string, number>();\n let next = 0;\n\n for (const node of graph.keys()) {\n communities.set(node, next++);\n }\n\n return communities;\n}\n\n/**\n * The summed degree of each community's members, which local moving keeps in step with every move.\n * @param communities - The partition.\n * @param degrees - The weighted degree of each node at this level.\n * @returns The summed degree per community.\n */\nfunction communityDegrees(communities: Map<string, number>, degrees: Map<string, number>): Map<number, number> {\n const totals = new Map<number, number>();\n\n for (const [node, community] of communities) {\n totals.set(community, (totals.get(community) ?? 0) + (degrees.get(node) ?? 0));\n }\n\n return totals;\n}\n\n/**\n * Move nodes to neighbouring communities until a whole sweep changes nothing.\n *\n * ONE SWEEP IS NOT CONVERGENCE, and treating it as such is what left this algorithm returning\n * partitions it could beat with six single-node moves. A move changes the communities its\n * neighbours are weighed against, so the node visited first is judged against a partition that no\n * longer exists by the time the sweep ends. Repeating until a sweep moves nobody is what makes\n * the answer a local optimum of the objective rather than an artefact of the visiting order.\n * @param graph - The level's graph.\n * @param weights - Its degrees and total edge weight.\n * @param communities - The partition, moved in place.\n * @param random - The seeded generator the visiting order is shuffled with.\n * @param resolution - Higher values favour smaller communities.\n * @param maxPasses - A ceiling on the sweeps, so a pathological graph cannot spin for ever.\n * @returns Whether anything moved at all.\n */\nfunction moveNodesLocally(\n graph: Map<string, Map<string, number>>,\n weights: LevelWeights,\n communities: Map<string, number>,\n random: () => number,\n resolution: number,\n maxPasses: number,\n): boolean {\n const { degrees, totalWeight } = weights;\n\n if (totalWeight === 0) {\n return false;\n }\n\n const totals = communityDegrees(communities, degrees);\n const nodes = [...graph.keys()];\n let movedEver = false;\n // A fresh id for a node that does better on its own, the empty community the paper also offers.\n let nextEmpty = 0;\n for (const community of communities.values()) {\n nextEmpty = Math.max(nextEmpty, community + 1);\n }\n\n for (let pass = 0; pass < maxPasses; pass++) {\n const order = [...nodes];\n shuffle(order, random);\n let movedThisPass = false;\n\n for (const node of order) {\n const current = communities.get(node);\n const degree = degrees.get(node);\n if (current === undefined || degree === undefined) {\n continue;\n }\n\n const neighborCommunities = getNeighborCommunities(node, graph, communities);\n const selfLoop = graph.get(node)?.get(node) ?? 0;\n const weightToCurrent = (neighborCommunities.get(current) ?? 0) - selfLoop;\n const degreeOfCurrent = (totals.get(current) ?? 0) - degree;\n\n let bestCommunity = current;\n let bestGain = 0;\n\n // Leaving for an empty community: the target has no weight and no degree.\n if (degreeOfCurrent > 0) {\n const alone =\n -weightToCurrent / totalWeight +\n (resolution * degree * degreeOfCurrent) / (2 * totalWeight * totalWeight);\n if (alone > bestGain) {\n bestGain = alone;\n bestCommunity = nextEmpty;\n }\n }\n\n for (const [community, weightToTarget] of neighborCommunities) {\n if (community === current) {\n continue;\n }\n\n // The standard modularity gain for moving one node out of its community and into\n // another: what the move adds to the edges inside a community, less what it adds\n // to what a random graph of the same degrees would have had there.\n const gain =\n (weightToTarget - weightToCurrent) / totalWeight -\n (resolution * degree * ((totals.get(community) ?? 0) - degreeOfCurrent)) /\n (2 * totalWeight * totalWeight);\n\n if (gain > bestGain) {\n bestGain = gain;\n bestCommunity = community;\n }\n }\n\n if (bestCommunity !== current) {\n if (bestCommunity === nextEmpty) {\n nextEmpty++;\n }\n\n communities.set(node, bestCommunity);\n totals.set(current, (totals.get(current) ?? 0) - degree);\n totals.set(bestCommunity, (totals.get(bestCommunity) ?? 0) + degree);\n movedThisPass = true;\n movedEver = true;\n }\n }\n\n if (!movedThisPass) {\n break;\n }\n }\n\n return movedEver;\n}\n\n/**\n * Collapse each community into one node, carrying its internal weight as a self-loop.\n *\n * THE SELF-LOOP IS THE POINT. Without it the aggregated graph forgets every edge inside a\n * community, so the next level scores a graph with no internal weight anywhere and every\n * partition of it looks equally bad. Both directions of every internal edge land in the same\n * entry, which is exactly the doubled internal weight the modularity sum wants.\n * @param graph - The level's graph.\n * @param communities - The partition to collapse.\n * @returns The next level's graph, and where each node of this one went.\n */\nfunction aggregateLevel(\n graph: Map<string, Map<string, number>>,\n communities: Map<string, number>,\n): { graph: Map<string, Map<string, number>>; mapping: Map<string, string> } {\n const aggregated = new Map<string, Map<string, number>>();\n const mapping = new Map<string, string>();\n\n for (const [node, community] of communities) {\n const superNode = `c${String(community)}`;\n mapping.set(node, superNode);\n if (!aggregated.has(superNode)) {\n aggregated.set(superNode, new Map());\n }\n }\n\n for (const [node, neighbors] of graph) {\n const source = mapping.get(node);\n const row = source === undefined ? undefined : aggregated.get(source);\n if (row === undefined) {\n continue;\n }\n\n for (const [neighbor, weight] of neighbors) {\n const target = mapping.get(neighbor);\n if (target === undefined) {\n continue;\n }\n\n row.set(target, (row.get(target) ?? 0) + weight);\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 * @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(graph: Graph, options: LeidenOptions = {}): LeidenResult {\n // Convert Graph to Map representation\n const graphMap = graphToMap(graph);\n return leidenImpl(graphMap, options);\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 * Runs the full multilevel method of Blondel et al. (local moving, then aggregating each community\n * into one node, repeated until nothing moves) over typed arrays indexed 0..n-1.\n *\n * Key optimizations:\n * - Typed-array adjacency (CSR) instead of per-edge map lookups\n * - Leaf node pruning: skip a degree-1 node already in its neighbour's community\n * - Importance ordering: Process high-impact nodes first\n * - Threshold cycling: Adaptive move thresholds, relative to each node's largest possible gain\n * - Early termination: Stop when changes become insignificant\n *\n * The graph is treated as undirected: a directed edge counts as an undirected edge of its weight.\n * A self-loop of weight w adds 2w to its node's degree, the standard convention (NetworkX too).\n */\n\ninterface OptimizedLouvainOptions {\n /**\n * Resolution parameter (default: 1.0)\n */\n resolution?: number;\n /**\n * Maximum local-moving sweeps per level (default: 100)\n */\n maxIterations?: number;\n /**\n * Convergence tolerance on a sweep's modularity gain (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 move threshold, as a fraction of a node's largest possible modularity gain (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\n/** One level of the multilevel method: an undirected weighted graph in CSR form. */\ninterface Level {\n n: number;\n /** Row offsets into `targets` / `weights`, length n + 1. Each edge appears in both rows. */\n offsets: Int32Array;\n targets: Int32Array;\n weights: Float64Array;\n /** Weight of the edges inside each node (self-loops), each edge counted once. */\n self: Float64Array;\n /** Weighted degree of each node (a self-loop counts twice). */\n degree: Float64Array;\n}\n\ninterface LocalMovingOptions {\n resolution: number;\n maxIterations: number;\n tolerance: number;\n pruneLeaves: boolean;\n importanceOrdering: boolean;\n pruningThreshold: number;\n thresholdCycling: boolean;\n}\n\n/**\n * Optimized Louvain implementation with early pruning and threshold cycling\n */\nexport class OptimizedLouvain {\n private graph: Graph;\n private pruningStats: PruningStats;\n\n /**\n * Create an optimized Louvain detector for the given graph\n * @param graph - The input graph to detect communities in\n */\n constructor(graph: Graph) {\n this.graph = graph;\n this.pruningStats = {\n leafNodesPruned: 0,\n lowDegreeNodesPruned: 0,\n stableNodesPruned: 0,\n };\n }\n\n /**\n * Run optimized Louvain algorithm\n * @param options - Algorithm configuration options\n * @returns Community detection result with communities, modularity, and iterations (levels)\n */\n public detectCommunities(options: OptimizedLouvainOptions = {}): CommunityResult {\n const settings: LocalMovingOptions = {\n resolution: options.resolution ?? 1.0,\n maxIterations: options.maxIterations ?? 100,\n tolerance: options.tolerance ?? 1e-6,\n pruneLeaves: options.pruneLeaves ?? true,\n importanceOrdering: options.importanceOrdering ?? true,\n pruningThreshold: options.pruningThreshold ?? 0.01,\n thresholdCycling: options.thresholdCycling ?? true,\n };\n\n const { level: base, ids } = this.buildLevel();\n // membership[i] = the current level's node that original node i has been folded into\n const membership = new Int32Array(base.n);\n for (let i = 0; i < base.n; i++) {\n membership[i] = i;\n }\n\n let level = base;\n let iterations = 0;\n while (level.n > 1) {\n const { community, count, moved } = this.localMoving(level, settings);\n if (!moved) {\n break;\n }\n\n iterations++;\n for (let i = 0; i < membership.length; i++) {\n membership[i] = community[membership[i]];\n }\n\n level = aggregate(level, community, count);\n }\n\n const groups: NodeId[][] = Array.from({ length: level.n }, () => []);\n for (let i = 0; i < membership.length; i++) {\n groups[membership[i]].push(ids[i]);\n }\n\n return {\n communities: groups.filter((group) => group.length > 0),\n modularity: levelModularity(level, settings.resolution),\n iterations,\n };\n }\n\n /**\n * Get pruning statistics\n * @returns Statistics about nodes pruned during optimization\n */\n public getPruningStats(): PruningStats {\n return { ...this.pruningStats };\n }\n\n /**\n * Index the graph's nodes 0..n-1 and build the level-0 CSR adjacency\n * @returns The level-0 graph and the node id at each index\n */\n private buildLevel(): { level: Level; ids: NodeId[] } {\n const ids: NodeId[] = [];\n const index = new Map<NodeId, number>();\n for (const node of this.graph.nodes()) {\n index.set(node.id, ids.length);\n ids.push(node.id);\n }\n\n const n = ids.length;\n const edges: [number, number, number][] = [];\n const counts = new Int32Array(n + 1);\n const self = new Float64Array(n);\n const degree = new Float64Array(n);\n\n for (const edge of this.graph.edges()) {\n const s = index.get(edge.source);\n const t = index.get(edge.target);\n if (s === undefined || t === undefined) {\n continue;\n }\n\n const w = edge.weight ?? 1;\n degree[s] += w;\n degree[t] += w;\n if (s === t) {\n self[s] += w;\n continue;\n }\n\n edges.push([s, t, w]);\n counts[s + 1]++;\n counts[t + 1]++;\n }\n\n return { level: buildCsr(n, counts, edges, self, degree), ids };\n }\n\n /**\n * Move each node to the neighbouring community with the best modularity gain, until no move\n * improves modularity\n * @param level - The graph at this level\n * @param options - Local moving options\n * @returns Each node's community (numbered 0..count-1), the count, and whether any node moved\n */\n private localMoving(\n level: Level,\n options: LocalMovingOptions,\n ): { community: Int32Array; count: number; moved: boolean } {\n const { n, offsets, targets, weights, degree } = level;\n const { resolution, maxIterations, tolerance, pruneLeaves } = options;\n\n const twoM = degree.reduce((sum, d) => sum + d, 0);\n const community = new Int32Array(n);\n const total = new Float64Array(n);\n for (let i = 0; i < n; i++) {\n community[i] = i;\n total[i] = degree[i];\n }\n\n if (twoM === 0) {\n return { community, count: n, moved: false };\n }\n\n const order = this.nodeOrder(level, options.importanceOrdering);\n // Scratch: weight from the current node to each community, and the communities touched\n const toCommunity = new Float64Array(n);\n const touched = new Int32Array(n);\n\n let moved = false;\n let useThreshold = options.thresholdCycling;\n for (let sweep = 0; sweep < maxIterations; sweep++) {\n // The threshold is a fraction of the most node i could gain from any move (all of its\n // weight landing inside the target, k_i), so it scales with the graph\n const threshold = useThreshold ? options.pruningThreshold * Math.pow(0.5, sweep / 10) : 0;\n let sweepMoved = false;\n let sweepGain = 0;\n\n for (const i of order) {\n const start = offsets[i];\n const end = offsets[i + 1];\n if (pruneLeaves && end - start === 1 && community[targets[start]] === community[i]) {\n // A leaf's only move is to its one neighbour's community, and it is there\n this.pruningStats.leafNodesPruned++;\n continue;\n }\n\n if (end === start) {\n continue;\n }\n\n const current = community[i];\n let touchedCount = 0;\n for (let e = start; e < end; e++) {\n const c = community[targets[e]];\n if (toCommunity[c] === 0) {\n touched[touchedCount++] = c;\n }\n\n toCommunity[c] += weights[e];\n }\n\n // Gains are in units of m * dQ: w(i, c) - resolution * tot(c) * k_i / 2m\n const k = degree[i];\n total[current] -= k;\n const stayGain = toCommunity[current] - (resolution * total[current] * k) / twoM;\n let best = current;\n let bestGain = stayGain;\n const minImprovement = threshold * k;\n\n for (let t = 0; t < touchedCount; t++) {\n const c = touched[t];\n if (c !== current) {\n const gain = toCommunity[c] - (resolution * total[c] * k) / twoM;\n if (gain > bestGain + minImprovement) {\n bestGain = gain;\n best = c;\n }\n }\n\n toCommunity[c] = 0;\n }\n\n total[best] += k;\n if (best !== current) {\n community[i] = best;\n sweepMoved = true;\n sweepGain += (bestGain - stayGain) / (twoM / 2);\n }\n }\n\n moved ||= sweepMoved;\n if (!sweepMoved || sweepGain < tolerance) {\n // A threshold can stall moves that are still worth making: finish without one\n if (useThreshold) {\n useThreshold = false;\n continue;\n }\n\n break;\n }\n }\n\n // Renumber the communities 0..count-1\n const renumber = new Int32Array(n).fill(-1);\n let count = 0;\n for (let i = 0; i < n; i++) {\n const c = community[i];\n if (renumber[c] === -1) {\n renumber[c] = count++;\n }\n\n community[i] = renumber[c];\n }\n\n return { community, count, moved };\n }\n\n /**\n * Order nodes for local moving, by importance (degree * log(1 + weighted degree)) if asked\n * @param level - The graph at this level\n * @param importanceOrdering - Whether to sort by importance\n * @returns Node indices in processing order\n */\n private nodeOrder(level: Level, importanceOrdering: boolean): Int32Array {\n const order = new Int32Array(level.n);\n for (let i = 0; i < level.n; i++) {\n order[i] = i;\n }\n\n if (!importanceOrdering) {\n return order;\n }\n\n const importance = new Float64Array(level.n);\n for (let i = 0; i < level.n; i++) {\n importance[i] = (level.offsets[i + 1] - level.offsets[i]) * Math.log(1 + level.degree[i]);\n }\n\n return order.sort((a, b) => importance[b] - importance[a]);\n }\n}\n\n/**\n * Build a CSR level from an undirected edge list (each edge listed once, no self-loops)\n * @param n - Node count\n * @param counts - counts[i + 1] = number of edges incident to node i\n * @param edges - The edges as [source, target, weight]\n * @param self - Self-loop weight of each node\n * @param degree - Weighted degree of each node\n * @returns The level\n */\nfunction buildCsr(\n n: number,\n counts: Int32Array,\n edges: [number, number, number][],\n self: Float64Array,\n degree: Float64Array,\n): Level {\n const offsets = counts;\n for (let i = 0; i < n; i++) {\n offsets[i + 1] += offsets[i];\n }\n\n const targets = new Int32Array(offsets[n]);\n const weights = new Float64Array(offsets[n]);\n const fill = offsets.slice(0, n);\n for (const [s, t, w] of edges) {\n targets[fill[s]] = t;\n weights[fill[s]++] = w;\n targets[fill[t]] = s;\n weights[fill[t]++] = w;\n }\n\n return { n, offsets, targets, weights, self, degree };\n}\n\n/**\n * Fold each community into one node: edges between communities are summed, edges inside a\n * community become its self-loop\n * @param level - The graph at this level\n * @param community - Each node's community, numbered 0..count-1\n * @param count - Number of communities\n * @returns The next level\n */\nfunction aggregate(level: Level, community: Int32Array, count: number): Level {\n const self = new Float64Array(count);\n const degree = new Float64Array(count);\n const members: number[][] = Array.from({ length: count }, () => []);\n for (let i = 0; i < level.n; i++) {\n const c = community[i];\n members[c].push(i);\n self[c] += level.self[i];\n degree[c] += level.degree[i];\n }\n\n const edges: [number, number, number][] = [];\n const counts = new Int32Array(count + 1);\n const toCommunity = new Float64Array(count);\n const touched: number[] = [];\n for (let c = 0; c < count; c++) {\n for (const i of members[c]) {\n for (let e = level.offsets[i]; e < level.offsets[i + 1]; e++) {\n const d = community[level.targets[e]];\n if (d === c) {\n // Seen once from each endpoint\n self[c] += level.weights[e] / 2;\n } else if (d > c) {\n // Keep each inter-community edge once, from its lower-numbered side\n if (toCommunity[d] === 0) {\n touched.push(d);\n }\n\n toCommunity[d] += level.weights[e];\n }\n }\n }\n\n for (const d of touched) {\n edges.push([c, d, toCommunity[d]]);\n counts[c + 1]++;\n counts[d + 1]++;\n toCommunity[d] = 0;\n }\n\n touched.length = 0;\n }\n\n return buildCsr(count, counts, edges, self, degree);\n}\n\n/**\n * Modularity of the partition that puts each node of `level` in its own community\n * @param level - The graph at this level\n * @param resolution - Resolution parameter\n * @returns Q = sum over nodes c of [ self(c) / m - resolution * (k_c / 2m)^2 ]\n */\nfunction levelModularity(level: Level, resolution: number): number {\n const twoM = level.degree.reduce((sum, d) => sum + d, 0);\n if (twoM === 0) {\n return 0;\n }\n\n let modularity = 0;\n for (let c = 0; c < level.n; c++) {\n const share = level.degree[c] / twoM;\n modularity += (2 * level.self[c]) / twoM - resolution * share * share;\n }\n\n return modularity;\n}\n\n/**\n * Optimized Louvain algorithm with automatic optimization selection\n * @param graph - The input graph to detect communities in\n * @param options - Algorithm configuration options\n * @returns Community detection result with communities, modularity, and iterations\n */\nexport function louvainOptimized(graph: Graph, options: OptimizedLouvainOptions = {}): 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 * @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 * @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 * @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(graph: Graph, nodeId: NodeId, communities: Map<NodeId, number>): 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 * weight of the edges inside communities to what would be expected in a random graph\n * with the same degrees.\n *\n * Formula: Q = sum over communities c of [ w_in(c)/m - gamma * (K_c / 2m)^2 ]\n * where:\n * - m = total edge weight, each undirected edge counted once\n * - w_in(c) = summed weight of the edges with both endpoints inside community c\n * - K_c = summed weighted degree of community c's nodes\n * - gamma = resolution parameter (higher values favor smaller communities)\n *\n * This is the per-community form of Q = (1/2m) * sum_ij [A_ij - gamma * k_i * k_j / (2m)] over the\n * pairs in the same community.\n * The double sum runs over every PAIR of nodes inside a community, so collecting the null-model\n * term only where an edge exists leaves the penalty far too small and rewards coarseness: the\n * single-community partition, whose modularity is 0 by definition, would otherwise outscore every\n * real split. The form below visits each community once and each edge once, so it counts every\n * pair exactly once without a pass over the whole adjacency matrix.\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(graph: Graph, communities: Map<NodeId, number>, resolution = 1.0): number {\n const totalEdgeWeight = getTotalEdgeWeight(graph);\n if (totalEdgeWeight === 0) {\n return 0;\n }\n\n // Summed weighted degree of each community's nodes.\n const degreeSum = new Map<number, number>();\n for (const node of graph.nodes()) {\n const community = communities.get(node.id);\n if (community === undefined) {\n continue;\n }\n\n degreeSum.set(community, (degreeSum.get(community) ?? 0) + getNodeDegree(graph, node.id));\n }\n\n // Summed weight of the edges that stay inside a community.\n const internalWeight = new Map<number, number>();\n for (const edge of graph.edges()) {\n const communityI = communities.get(edge.source);\n const communityJ = communities.get(edge.target);\n\n if (communityI === undefined || communityI !== communityJ) {\n continue;\n }\n\n internalWeight.set(communityI, (internalWeight.get(communityI) ?? 0) + (edge.weight ?? 1));\n }\n\n let modularity = 0;\n for (const [community, degrees] of degreeSum) {\n const share = degrees / (2 * totalEdgeWeight);\n modularity += (internalWeight.get(community) ?? 0) / totalEdgeWeight - resolution * share * share;\n }\n\n return modularity;\n}\n","import { Graph } from \"../../core/graph.js\";\nimport type { CommunityResult, LouvainOptions, NodeId } from \"../../types/index.js\";\nimport { louvainOptimized } from \"./louvain-optimized.js\";\nimport { calculateModularity, getNeighborCommunities, getNodeDegree, getTotalEdgeWeight } 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 * @param graph - The input graph\n * @param options - Algorithm options\n * @returns Community detection result with communities, modularity, and iterations\n */\nexport function louvain(graph: Graph, options: LouvainOptions = {}): 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 * @param graph - The input graph\n * @returns Map of node IDs to their initial community IDs\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 * @param graph - The input graph\n * @param communities - Map of node IDs to community IDs\n * @param resolution - Resolution parameter for modularity calculation\n * @returns True if any improvement was made, false otherwise\n */\nfunction louvainPhase1(graph: Graph, communities: Map<NodeId, number>, resolution: number): 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,\n nodeId,\n currentCommunity,\n communities,\n 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,\n nodeId,\n neighborCommunity,\n communities,\n 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 * @param graph - The input graph\n * @param nodeId - The node ID to evaluate\n * @param community - The community to measure contribution to\n * @param communities - Map of all node IDs to community IDs\n * @param resolution - Resolution parameter for modularity calculation\n * @returns The modularity contribution of the node to the specified 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 =\n (internalLinks - (resolution * nodeDegree * communityDegree) / (2 * totalEdgeWeight)) / totalEdgeWeight;\n\n return modularityIncrease;\n}\n\n/**\n * Extract final community structure\n * @param communities - Map of node IDs to community IDs\n * @returns Array of communities (each is an array of node IDs)\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 /**\n * Creates a new MinPriorityQueue instance.\n * @param compareFunction - Custom comparison function. Returns negative if a has higher priority than b.\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 (\n left < this.heap.length &&\n leftItem !== undefined &&\n minItem !== undefined &&\n this.compare(leftItem, minItem) < 0\n ) {\n minIndex = left;\n }\n\n const rightItem = this.heap[right];\n const newMinItem = this.heap[minIndex];\n if (\n right < this.heap.length &&\n rightItem !== undefined &&\n newMinItem !== undefined &&\n this.compare(rightItem, newMinItem) < 0\n ) {\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 /**\n * Insert a value into the priority queue.\n * @param value - The value to insert\n */\n insert(value: T): void {\n this.heap.push(value);\n this.heapifyUp(this.heap.length - 1);\n }\n\n /**\n * Remove and return the minimum value from the priority queue.\n * @returns The minimum value, or undefined if the queue is empty\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 /**\n * View the minimum value without removing it.\n * @returns The minimum value, or undefined if the queue is empty\n */\n peek(): T | undefined {\n return this.heap[0];\n }\n\n /**\n * Check if the priority queue is empty.\n * @returns True if the queue has no items, false otherwise\n */\n isEmpty(): boolean {\n return this.heap.length === 0;\n }\n\n /**\n * Get the number of items in the priority queue.\n * @returns The number of items currently in the queue\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 * @param cameFrom - Map of each node to its predecessor on the path\n * @param goal - The goal node to reconstruct the path to\n * @returns An array of nodes representing the path from start to goal\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 * @param width - The width of the grid\n * @param height - The height of the grid\n * @param obstacles - Set of obstacle coordinates as \"x,y\" strings\n * @returns A grid graph with 4-directional movement\n */\n createGridGraph(width: number, height: number, obstacles = new Set<string>()): 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],\n [1, 0],\n [0, -1],\n [-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 * @param coord - The coordinate string in \"x,y\" format\n * @returns A tuple of [x, y] coordinates\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","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 * @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 * @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 Detailed result including path, cost, visited nodes, and score maps\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 * @param a - First coordinate as [x, y] tuple\n * @param b - Second coordinate as [x, y] tuple\n * @returns The Manhattan distance between the two points\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 * @param a - First coordinate as [x, y] tuple\n * @param b - Second coordinate as [x, y] tuple\n * @returns The Euclidean distance between the two points\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 * @param a - First coordinate as [x, y] tuple\n * @param b - Second coordinate as [x, y] tuple\n * @returns The Chebyshev distance between the two points\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 * @param _a - First node (unused)\n * @param _b - Second node (unused)\n * @returns Always returns 0\n */\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 * @param graph - The original graph with capacity values\n * @returns A residual graph initialized with the original capacities\n */\nfunction createResidualGraph(graph: Map<string, Map<string, number>>): 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 * @param residualGraph - The residual graph with remaining capacities\n * @param source - The source node\n * @param sink - The sink node\n * @returns An array of nodes forming the path, or null if no path exists\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 * @param residualGraph - The residual graph to update\n * @param flowGraph - The flow graph to update with new flow values\n * @param originalGraph - The original graph for edge direction reference\n * @param path - The augmenting path to update flow along\n * @param pathFlow - The amount of flow to push through the 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 * @param residualGraph - The residual graph after max flow computation\n * @param source - The source node\n * @returns The minimum cut partition with source and sink sets and cut edges\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 * @param graph - The graph with capacity values\n * @param source - The source node\n * @param sink - The sink node\n * @param findPath - Function to find an augmenting path in the residual graph\n * @returns The maximum flow result including flow value, flow graph, and minimum cut\n */\nfunction maxFlowCore(\n graph: Map<string, Map<string, number>>,\n source: string,\n sink: string,\n findPath: (\n residual: Map<string, Map<string, number>>,\n src: string,\n snk: string,\n ) => { 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 * @param graph - The graph with capacity values\n * @param source - The source node\n * @param sink - The sink node\n * @returns The maximum flow result\n */\nfunction fordFulkersonImpl(graph: Map<string, Map<string, number>>, source: string, sink: string): MaxFlowResult {\n // Adapter function for DFS path finding\n const findPathDFS = (\n residual: Map<string, Map<string, number>>,\n src: string,\n snk: string,\n ): { 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 * @param graph - The graph with capacity values\n * @param source - The source node\n * @param sink - The sink node\n * @returns The maximum flow result\n */\nfunction edmondsKarpImpl(graph: Map<string, Map<string, number>>, source: string, sink: string): MaxFlowResult {\n // Use BFS variant for path finding\n const findPathBFS = (\n residual: Map<string, Map<string, number>>,\n src: string,\n snk: string,\n ): { 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 * @param leftNodes - Array of left partition node identifiers\n * @param rightNodes - Array of right partition node identifiers\n * @param edges - Array of edges connecting left nodes to right nodes\n * @returns The flow network graph with source and sink nodes\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 * @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(graph: Graph, source: string, sink: string): 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 * @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 * @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(graph: Graph, source: string, sink: string): 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 * @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(graph: Graph | Map<string, Map<string, number>>): 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 * @param graph - The undirected weighted graph\n * @param nodes - Array of remaining nodes in the graph\n * @returns The cut result with last two nodes, cut value, and partition\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 * @param graph - The graph to modify by contracting nodes\n * @param nodes - Array of nodes to update after contraction\n * @param s - The node to keep after contraction\n * @param t - The node to merge into s\n */\nfunction contractNodes(graph: Map<string, Map<string, number>>, nodes: string[], s: string, t: string): 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 * @param graph - The directed graph to convert\n * @returns An undirected graph with edges in both directions\n */\nfunction makeUndirected(graph: Map<string, Map<string, number>>): 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 * @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(graph: Graph | Map<string, Map<string, number>>, iterations = 100): 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 * @param graph - The undirected weighted graph\n * @returns The cut result with cut value and two partitions\n */\nfunction kargerSingleRun(graph: Map<string, Map<string, number>>): {\n cutValue: number;\n partition1: Set<string>;\n partition2: Set<string>;\n} {\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) {\n // 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 * @param graph - The working graph to modify\n * @param superNodes - Map tracking which original nodes are in each super node\n * @param u - First endpoint of the edge to contract\n * @param v - Second endpoint of the edge to contract (merged into u)\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 * 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 * @param graph - The input graph to convert\n * @returns Map of node IDs to sets of neighbor node IDs\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 * @param graph - Adjacency map representation of the graph\n * @param distances - Map to store computed distances between nodes\n */\nfunction computeGraphDistance<T>(graph: Map<T, Set<T>>, distances: Map<T, Map<T, number>>): 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 * @param cluster1 - First cluster node\n * @param cluster2 - Second cluster node\n * @param distances - Precomputed distance matrix between nodes\n * @param linkage - Linkage method to use for computing cluster distance\n * @returns The distance between the two clusters\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 * @param graph - Adjacency map representation of the graph\n * @param linkage - Linkage method for cluster distance computation\n * @returns Hierarchical clustering result with dendrogram and cluster assignments\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 =\n distMap.get(cluster2.id) ?? clusterDistances.get(cluster2.id)?.get(cluster1.id) ?? 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 * @param root - Root node of the dendrogram\n * @param height - Height at which to cut the dendrogram\n * @returns Array of sets representing clusters at the specified height\n */\nexport function cutDendrogram<T>(root: ClusterNode<T>, height: number): 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 * @param root - Root node of the dendrogram\n * @param k - Target number of clusters\n * @returns Array of sets representing exactly k clusters\n */\nexport function cutDendrogramKClusters<T>(root: ClusterNode<T>, k: number): 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 * @param graph - The input graph to cluster\n * @returns Hierarchical clustering result with dendrogram and cluster assignments\n */\nexport function modularityHierarchicalClustering(graph: Graph): 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 - 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 * @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 * @param graph - The input graph to convert\n * @returns Map of node IDs to sets of neighbor node IDs\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 * @param graph - Adjacency map representation of the graph\n * @returns K-core decomposition result with cores, coreness values, and maximum core number\n */\nfunction kCoreDecompositionImpl<T>(graph: Map<T, Set<T>>): 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 * @param graph - Undirected graph\n * @param k - Core number\n * @returns Set of nodes in k-core or higher\n */\nexport function getKCore(graph: Graph, k: number): 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 * @param graph - Original graph\n * @param k - Core number\n * @returns K-core subgraph\n */\nexport function getKCoreSubgraph(graph: Graph, k: number): 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 * @param graph - Undirected graph\n * @returns Array of nodes ordered by degeneracy\n */\nexport function degeneracyOrdering(graph: Graph): 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 * @param graph - Undirected graph\n * @param k - Truss number (k >= 2)\n * @returns Edges in k-truss\n */\nexport function kTruss(graph: Graph, k: number): 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) {\n // Avoid duplicates\n const edge = `${u},${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 = `${u},${v}`;\n const edge2 = `${u},${w}`;\n const edge3 = `${v},${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 ? `${u},${w}` : `${w},${u}`;\n const edge2 = v < w ? `${v},${w}` : `${w},${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 * @param directedGraph - Directed graph represented as adjacency map with edge weights\n * @returns Undirected graph represented as adjacency map with neighbor sets\n */\nexport function toUndirected<T>(directedGraph: Map<T, Map<T, number>>): 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 * @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(graph: Graph): KCoreResult<string> {\n // Convert Graph to adjacency set representation\n const adjacencySet = graphToAdjacencySet(graph);\n return kCoreDecompositionImpl(adjacencySet);\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 * @param graph - The input graph to cluster\n * @param options - MCL algorithm options (expansion, inflation, iterations, etc.)\n * @returns MCL clustering result with communities, attractors, and convergence info\n */\nexport function markovClustering(graph: Graph, options: MCLOptions = {}): 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 * @param graph - The input graph\n * @param nodeIds - Array of node IDs in the graph\n * @param selfLoops - Whether to add self-loops to the matrix\n * @returns Column-normalized transition matrix\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 === undefined) {\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 * @param matrix - Input square matrix\n * @param power - Power to raise the matrix to\n * @returns Matrix raised to the specified power\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 * @param a - First matrix\n * @param b - Second matrix\n * @returns Product matrix a * b\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 * @param matrix - Input matrix to inflate\n * @param inflation - Inflation parameter for element-wise powering\n * @returns Inflated and column-normalized matrix\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 * @param matrix - Input matrix to prune\n * @param threshold - Values below this threshold are set to zero\n * @returns Pruned and re-normalized matrix\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 * @param oldMatrix - Matrix from previous iteration\n * @param newMatrix - Matrix from current iteration\n * @param tolerance - Convergence tolerance threshold\n * @returns True if the maximum difference between matrices is below tolerance\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 * @param matrix - Final converged MCL matrix\n * @param nodeIds - Array of node IDs corresponding to matrix indices\n * @returns Object containing communities and attractor nodes\n */\nfunction extractClusters(\n matrix: number[][],\n nodeIds: NodeId[],\n): {\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 (columns) to clusters based on which attractor (row) they flow to\n // After MCL convergence, matrix[i][j] > 0 means node j belongs to attractor i's cluster\n const attractorToCommunity = new Map<number, number[]>();\n\n for (let j = 0; j < n; j++) {\n // Find the attractor for this column (node j)\n // Look for the row with the highest non-zero value in column j\n let maxVal = 0;\n let attractorRow = -1;\n\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 > maxVal) {\n maxVal = val;\n attractorRow = i;\n }\n }\n\n if (attractorRow >= 0) {\n // Node j belongs to the cluster of attractor at row attractorRow\n let community = attractorToCommunity.get(attractorRow);\n if (!community) {\n community = [];\n attractorToCommunity.set(attractorRow, community);\n }\n community.push(j);\n nodeToCluster.set(j, attractorRow);\n }\n }\n\n // Convert attractor communities to node ID arrays\n for (const [, memberIndices] of attractorToCommunity) {\n communities.push(\n memberIndices\n .map((idx) => {\n const nodeId = nodeIds[idx];\n return nodeId;\n })\n .filter((node): node is NodeId => node !== undefined),\n );\n }\n\n // Handle isolated nodes (nodes with all-zero columns)\n for (let j = 0; j < n; j++) {\n if (!nodeToCluster.has(j)) {\n const nodeId = nodeIds[j];\n if (nodeId !== undefined) {\n communities.push([nodeId]);\n }\n }\n }\n\n return { communities, attractors };\n}\n\n/**\n * Calculate modularity of MCL clustering result\n * @param graph - The original graph that was clustered\n * @param communities - Array of communities (each community is an array of node IDs)\n * @returns Modularity score between -0.5 and 1.0\n */\nexport function calculateMCLModularity(graph: Graph, communities: NodeId[][]): 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, SeededRandom } 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 seed?: number; // Random seed for reproducible results\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 * Note: 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 * @param graph - The input graph to cluster\n * @param options - Spectral clustering options (k, laplacianType, etc.)\n * @returns Spectral clustering result with communities and cluster assignments\n */\nexport function spectralClustering(graph: Graph, options: SpectralClusteringOptions): SpectralClusteringResult {\n const { k, laplacianType = \"normalized\", maxIterations = 100, tolerance = 1e-4, seed } = options;\n\n // Create random function - use seeded PRNG if seed provided, otherwise Math.random\n const random = seed !== undefined ? SeededRandom.createGenerator(seed) : Math.random;\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, random);\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, random);\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 * @param graph - The input graph\n * @param nodeIds - Array of node IDs defining matrix index order\n * @returns Square adjacency matrix with edge weights\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 * @param adjacency - Square adjacency matrix\n * @param type - Type of Laplacian (unnormalized, normalized, or randomWalk)\n * @returns The computed Laplacian 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 (\n adjacencyVal !== undefined &&\n adjacencyVal > 0 &&\n di !== undefined &&\n dj !== undefined &&\n di > 0 &&\n dj > 0\n ) {\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 * @param matrix - The Laplacian matrix for eigendecomposition\n * @param k - Number of smallest eigenvectors to find\n * @param random - Random number generator function\n * @returns Object containing eigenvalues and corresponding eigenvectors\n */\nfunction findSmallestEigenvectors(\n matrix: number[][],\n k: number,\n random: () => number,\n): {\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, random);\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)\n .fill(0)\n .map(() => 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 * @param matrix - Matrix to normalize in place\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 * @param data - Array of data points, each point is an array of coordinates\n * @param k - Number of clusters to form\n * @param maxIterations - Maximum number of iterations\n * @param tolerance - Convergence tolerance for centroid movement\n * @param random - Random number generator function\n * @returns Object containing cluster assignments and final centroids\n */\nfunction kMeansClustering(\n data: number[][],\n k: number,\n maxIterations: number,\n tolerance = 1e-4,\n random: () => number = Math.random,\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(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] = 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 * @param matrix - The Laplacian matrix\n * @param k - Number of eigenvectors to compute (1-3)\n * @param n - Size of the matrix\n * @param random - Random number generator function\n * @returns Object containing eigenvalues and eigenvectors\n */\nfunction computeSmallestEigenvectorsSimple(\n matrix: number[][],\n k: number,\n n: number,\n random: () => number,\n): {\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)\n .fill(0)\n .map(() => 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)\n .fill(0)\n .map(() => 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 * @param graph - The bipartite graph to find maximum matching for\n * @param options - Optional configuration including left and right node partitions\n * @returns The maximum matching as a map from left nodes to right nodes and the matching size\n * @throws Error if the graph is not bipartite\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 * @param graph - The graph to check for bipartiteness\n * @returns An object with left and right node sets if bipartite, or null if not bipartite\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 * @param graph - The bipartite graph to find matching for\n * @param options - Optional configuration including left and right node partitions\n * @returns The matching as a map from left nodes to right nodes and the matching size\n * @throws Error if the graph is not bipartite\n */\nexport function greedyBipartiteMatching(graph: Graph, options: BipartiteMatchingOptions = {}): 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 * @param graph1 - The first graph to compare\n * @param graph2 - The second graph to compare\n * @param options - Optional configuration for node and edge matching predicates\n * @returns An object indicating if the graphs are isomorphic and an optional mapping between nodes\n */\nexport function isGraphIsomorphic(graph1: Graph, graph2: Graph, options: IsomorphismOptions = {}): 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 * @param g1 - The first graph being compared\n * @param g2 - The second graph being compared\n * @param state - The current VF2 algorithm state containing mappings and terminal sets\n * @param nodes1 - Array of node IDs from the first graph\n * @param nodes2 - Array of node IDs from the second graph\n * @param options - Configuration options for matching predicates\n * @param mappings - Array to collect found isomorphism mappings\n * @returns True if an isomorphism was found and search should stop, false otherwise\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 * @param g1 - The first graph being compared\n * @param g2 - The second graph being compared\n * @param state - The current VF2 algorithm state containing mappings and terminal sets\n * @param nodes1 - Array of node IDs from the first graph\n * @param nodes2 - Array of node IDs from the second graph\n * @returns Array of candidate node pairs to try matching\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 * @param g1 - The first graph being compared\n * @param g2 - The second graph being compared\n * @param state - The current VF2 algorithm state containing mappings and terminal sets\n * @param node1 - The candidate node from the first graph\n * @param node2 - The candidate node from the second graph\n * @param options - Configuration options for matching predicates\n * @returns True if the node pair can be feasibly matched, false otherwise\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;\n let new1Out = 0;\n let term1In = 0;\n let term1Out = 0;\n let new2In = 0;\n let new2Out = 0;\n let term2In = 0;\n 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 && new1In === new2In && new1Out === new2Out;\n}\n\n/**\n * Add a pair to the mapping and update terminal sets\n * @param g1 - The first graph being compared\n * @param g2 - The second graph being compared\n * @param state - The current VF2 algorithm state containing mappings and terminal sets\n * @param node1 - The node from the first graph to add to the mapping\n * @param node2 - The node from the second graph to add to the mapping\n * @returns A new VF2 state with the pair added and terminal sets updated\n */\nfunction addPair(g1: Graph, g2: Graph, state: VF2State, node1: NodeId, node2: NodeId): 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 * @param graph1 - The first graph to compare\n * @param graph2 - The second graph to compare\n * @param options - Optional configuration for node and edge matching predicates\n * @returns An array of all possible node mappings between the 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 * @param graph - The input graph\n * @param source - The source node ID\n * @param target - The target node ID\n * @param options - Link prediction options\n * @returns The Adamic-Adar score for the node pair\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 * @param graph - The input graph\n * @param options - Link prediction options\n * @returns Array of link prediction scores sorted by score descending\n */\nexport function adamicAdarPrediction(graph: Graph, options: LinkPredictionOptions = {}): LinkPredictionScore[] {\n const { directed = false, includeExisting = false, topK } = 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 === undefined || target === undefined) {\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 * @param graph - The input graph\n * @param pairs - Array of node ID pairs to calculate scores for\n * @param options - Link prediction options\n * @returns Array of link prediction scores for the specified 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 * @param graph - The input graph\n * @param node - The node ID to get candidates for\n * @param options - Link prediction options with optional candidate list\n * @returns Array of top link prediction candidates sorted by score descending\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 { directed = false, includeExisting = false, topK = 10, candidates } = 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 * @param trainingGraph - The training graph without test edges\n * @param testEdges - Array of node pairs that are actual edges\n * @param nonEdges - Array of node pairs that are not edges\n * @param options - Link prediction options\n * @returns Evaluation metrics including precision, recall, F1 score, and AUC\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 * @param graph - The input graph\n * @param testEdges - Array of node pairs that are actual edges\n * @param nonEdges - Array of node pairs that are not edges\n * @param options - Link prediction options\n * @returns Comparison of evaluation metrics for both algorithms\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 * @param graph - The input graph\n * @param source - The source node ID\n * @param target - The target node ID\n * @param options - Link prediction options\n * @returns The number of common neighbors\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 * @param graph - The input graph\n * @param options - Link prediction options\n * @returns Array of link prediction scores sorted by score descending\n */\nexport function commonNeighborsPrediction(graph: Graph, options: LinkPredictionOptions = {}): LinkPredictionScore[] {\n const { directed = false, includeExisting = false, topK } = 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 === undefined || target === undefined) {\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 * @param graph - The input graph\n * @param pairs - Array of node ID pairs to calculate scores for\n * @param options - Link prediction options\n * @returns Array of link prediction scores for the specified 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 * @param graph - The input graph\n * @param node - The node ID to get candidates for\n * @param options - Link prediction options with optional candidate list\n * @returns Array of top link prediction candidates sorted by score descending\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 { directed = false, includeExisting = false, topK = 10, candidates } = 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 * @param trainingGraph - The training graph without test edges\n * @param testEdges - Array of node pairs that are actual edges\n * @param nonEdges - Array of node pairs that are not edges\n * @param options - Link prediction options\n * @returns Evaluation metrics including precision, recall, F1 score, and AUC\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 * @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 { numClusters, maxIterations = 100, tolerance = 1e-6, seed = 42, learningRate = 0.01, lambda = 0.1 } = 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(\n `Invalid number of clusters: ${String(numClusters)}. Must be between 1 and ${String(nodeCount)}`,\n );\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 * @param graph - The input graph\n * @param nodeId - The node ID to initialize embedding for\n * @param dim - The embedding dimension\n * @returns The initialized embedding vector\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 * @param embeddings - Map of node IDs to embedding vectors\n * @param numClusters - Number of cluster centers to initialize\n * @returns Array of initialized cluster center vectors\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 * @param graph - The input graph\n * @param embeddings - Map of node IDs to embedding vectors\n * @param _clusters - Map of node IDs to cluster assignments (reserved for future use)\n * @param learningRate - Learning rate for gradient descent\n * @param lambda - Regularization parameter\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 * @param embeddings - Map of node IDs to embedding vectors\n * @param clusters - Map of node IDs to cluster assignments\n * @param clusterCenters - Array of cluster center vectors to update\n * @param numClusters - Number of clusters\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(\n { 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 * @param graph - The input graph\n * @param embeddings - Map of node IDs to embedding vectors\n * @param clusters - Map of node IDs to cluster assignments\n * @param clusterCenters - Array of cluster center vectors\n * @param lambda - Regularization parameter\n * @returns The total loss value\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","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 * @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(\n `Graph has ${String(nodeCount)} nodes, which exceeds maxNodes (${String(maxNodes)}). Performance may be degraded.`,\n );\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 * @param graph - The input graph\n * @param nodes - Array of nodes to calculate distances between\n * @param useGraphDistance - Whether to use graph-based shortest path distances\n * @returns 2D distance matrix\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 * @param graph - The input graph\n * @param source - The source node ID\n * @returns Map of node IDs to their distances from the source\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 * @param clusters - Map of cluster IDs to cluster nodes\n * @param distanceMatrix - 2D distance matrix between nodes\n * @returns Array of merge candidates sorted by distance\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 * @param mergeCandidates - Array of merge candidates\n * @returns The closest cluster pair with their distance\n */\nfunction findClosestPair(mergeCandidates: { cluster1Id: string; cluster2Id: string; distance: number }[]): {\n cluster1Id: string;\n cluster2Id: string;\n distance: number;\n} {\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 * @param mergeCandidates - Array of merge candidates to update\n * @param oldCluster1Id - ID of first merged cluster\n * @param oldCluster2Id - ID of second merged cluster\n * @param newClusterId - ID of the newly created cluster\n * @param clusters - Map of cluster IDs to cluster nodes\n * @param distanceMatrix - 2D distance matrix between nodes\n * @param linkage - Linkage criterion to use\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 (\n candidate.cluster1Id === oldCluster1Id ||\n candidate.cluster1Id === oldCluster2Id ||\n candidate.cluster2Id === oldCluster1Id ||\n candidate.cluster2Id === oldCluster2Id\n ) {\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 * @param cluster1 - First cluster\n * @param cluster2 - Second cluster\n * @param distanceMatrix - 2D distance matrix between nodes\n * @param linkage - Linkage criterion (single, complete, average, ward)\n * @returns The distance between the two clusters\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 * @param dendrogram - The root of the dendrogram tree\n * @param numClusters - The target number of clusters\n * @returns Map of node IDs to cluster assignments\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 * @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 || currentCluster.members.size < minClusterSize * 2) {\n continue;\n }\n\n // Attempt spectral bisection\n const bisectionResult = spectralBisection(graph, currentCluster, numEigenvectors, tolerance, maxIterations);\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) {\n // 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 * @param graph - The input graph\n * @param cluster - The cluster to bisect\n * @param _numEigenvectors - Number of eigenvectors to compute (reserved for future use)\n * @param tolerance - Convergence tolerance\n * @param maxIterations - Maximum number of iterations\n * @returns Bisection result with left/right members, scores, and explanation, or null if bisection failed\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.map((value, index) => ({ value, index })).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 * @param graph - The input graph\n * @param nodes - The nodes to include in the subgraph\n * @returns The Laplacian matrix as a 2D array\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 * @param laplacian - The Laplacian matrix\n * @param tolerance - Convergence tolerance\n * @param maxIterations - Maximum number of iterations\n * @returns The Fiedler vector, or null if computation failed\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 * @param graph - The input graph\n * @param assignment - Map from node ID to community ID\n * @returns The modularity score\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","import { type AdjacencyView, INVALID_INDEX, type U32 } from \"@graphty/graph-format\";\n\n/** Result of the index-based BFS (graph-format design 14.2 Port 1). @public */\nexport interface BfsResult {\n /** Visit order, one entry per visited node; a subarray of length `visitedCount`. */\n readonly order: U32;\n /** Parent of every node, INVALID_INDEX for the start node and for unvisited nodes. */\n readonly parent: U32;\n /** Hop depth of every node, INVALID_INDEX for unvisited nodes. */\n readonly depth: U32;\n /** How many nodes were visited. */\n readonly visitedCount: number;\n}\n\n/** Options of the index-based BFS. @public */\nexport interface BfsOptions {\n /** Stop expanding at this depth; unbounded when omitted. */\n readonly maxDepth?: number | undefined;\n}\n\n/**\n * Breadth-first search over out-neighbours. Takes any `AdjacencyView`, so `s.reverse()` gives an\n * in-neighbour BFS with no extra code.\n * @param g - The adjacency to traverse\n * @param start - The node index to start from\n * @param options - Traversal options\n * @returns The visit order, the parent array, the depth array and the visited count\n * @public\n */\nexport function breadthFirstSearch(g: AdjacencyView, start: number, options: BfsOptions = {}): BfsResult {\n const { nodeCount, rowPtr, colIdx } = g;\n const parent = new Uint32Array(nodeCount).fill(INVALID_INDEX);\n const depth = new Uint32Array(nodeCount).fill(INVALID_INDEX);\n const order = new Uint32Array(nodeCount);\n const maxDepth = options.maxDepth ?? INVALID_INDEX;\n let head = 0;\n let tail = 0;\n order[tail++] = start;\n depth[start] = 0;\n while (head < tail) {\n const u = order[head++];\n const d = depth[u];\n if (d >= maxDepth) {\n continue;\n }\n const end = rowPtr[u + 1];\n for (let a = rowPtr[u]; a < end; a++) {\n const v = colIdx[a];\n if (depth[v] === INVALID_INDEX) {\n depth[v] = d + 1;\n parent[v] = u;\n order[tail++] = v;\n }\n }\n }\n return { order: order.subarray(0, tail), parent, depth, visitedCount: tail };\n}\n","import type { AdjacencyView, GraphSnapshot } from \"@graphty/graph-format\";\n\n/** Options of the index-based common-neighbour score. @public */\nexport interface CommonNeighborsOptions {\n /** Intersect out(u) with in(v) instead of the two undirected rows. */\n readonly directed?: boolean | undefined;\n}\n\n/**\n * The number of distinct common neighbours of two nodes, by a merge of their sorted rows.\n * @param s - The snapshot\n * @param u - A node index\n * @param v - A node index\n * @param o - Options\n * @returns The count of distinct common neighbours\n * @public\n */\nexport function commonNeighborsScore(s: GraphSnapshot, u: number, v: number, o: CommonNeighborsOptions = {}): number {\n const fwd: AdjacencyView = s;\n const bwd: AdjacencyView = o.directed === true ? s.reverse() : s;\n let i = fwd.rowPtr[u];\n const iEnd = fwd.rowPtr[u + 1];\n let j = bwd.rowPtr[v];\n const jEnd = bwd.rowPtr[v + 1];\n let count = 0;\n while (i < iEnd && j < jEnd) {\n const a = fwd.colIdx[i];\n const b = bwd.colIdx[j];\n if (a === b) {\n count++;\n i++;\n j++;\n while (i < iEnd && fwd.colIdx[i] === a) {\n i++;\n }\n while (j < jEnd && bwd.colIdx[j] === b) {\n j++;\n }\n } else if (a < b) {\n i++;\n } else {\n j++;\n }\n }\n return count;\n}\n","import { renumberPartition, type U32 } from \"@graphty/graph-format\";\n\n/**\n * Index-keyed union-find over `[0, size)` with union by rank and path halving. The legacy\n * `UnionFind` (`src/data-structures/union-find.ts`) is NodeId-keyed and stays where it is.\n * @public\n */\nexport class IntUnionFind {\n private readonly parent: U32;\n private readonly rank: U32;\n\n /**\n * Create a union-find whose every element is a singleton set.\n * @param size - The number of elements, each initially its own singleton set\n */\n constructor(size: number) {\n this.parent = new Uint32Array(size);\n this.rank = new Uint32Array(size);\n for (let i = 0; i < size; i++) {\n this.parent[i] = i;\n }\n }\n\n /**\n * Find the representative of an element's set, halving the path on the way up.\n * @param x - An element index\n * @returns The representative of x's set\n */\n find(x: number): number {\n let node = x;\n while (this.parent[node] !== node) {\n this.parent[node] = this.parent[this.parent[node]]; // path halving\n node = this.parent[node];\n }\n return node;\n }\n\n /**\n * Merge the sets of two elements, attaching the shallower tree under the deeper one.\n * @param a - An element index\n * @param b - An element index\n * @returns True when the two sets were distinct and have now been merged\n */\n union(a: number, b: number): boolean {\n const ra = this.find(a);\n const rb = this.find(b);\n if (ra === rb) {\n return false;\n }\n if (this.rank[ra] < this.rank[rb]) {\n this.parent[ra] = rb;\n } else if (this.rank[ra] > this.rank[rb]) {\n this.parent[rb] = ra;\n } else {\n this.parent[rb] = ra;\n this.rank[ra]++;\n }\n return true;\n }\n\n /**\n * Dense labels in FIRST-SEEN order, which is what makes `groups()` identical to the legacy\n * iteration order and identical to the GPU's after its own `renumberPartition` readback\n * (design 9.7's connectedComponents row).\n * @returns The labels and the number of distinct sets\n */\n toLabels(): { readonly labels: U32; readonly count: number } {\n const roots = new Uint32Array(this.parent.length);\n for (let i = 0; i < roots.length; i++) {\n roots[i] = this.find(i);\n }\n return renumberPartition(roots);\n }\n}\n","import { type GraphSnapshot, type U32 } from \"@graphty/graph-format\";\n\nimport { IntUnionFind } from \"./structures/union-find.js\";\n\n/** A partition of the node set (graph-format design 14.2's result table, line 3738). @public */\nexport interface LabelResult {\n /** Dense label per node index, in first-seen order. */\n readonly labels: U32;\n /** Number of distinct labels. */\n readonly count: number;\n /**\n * Node indices grouped by label, computed once and cached.\n * @returns One array per label\n */\n groups(): U32[];\n}\n\nfunction withGroups(labels: U32, count: number): LabelResult {\n let cached: U32[] | null = null;\n return {\n labels,\n count,\n groups(): U32[] {\n if (cached === null) {\n const sizes = new Uint32Array(count);\n for (let i = 0; i < labels.length; i++) {\n sizes[labels[i]]++;\n }\n const out: U32[] = [];\n for (let c = 0; c < count; c++) {\n out.push(new Uint32Array(sizes[c]));\n }\n const fill = new Uint32Array(count);\n for (let i = 0; i < labels.length; i++) {\n const c = labels[i];\n out[c][fill[c]++] = i;\n }\n cached = out;\n }\n return cached;\n },\n };\n}\n\nfunction unionEdges(s: GraphSnapshot): LabelResult {\n const uf = new IntUnionFind(s.nodeCount);\n const el = s.edgeList();\n for (let e = 0; e < s.edgeCount; e++) {\n uf.union(el.src[e], el.dst[e]);\n }\n const { labels, count } = uf.toLabels();\n return withGroups(labels, count);\n}\n\n/**\n * Connected components of an UNDIRECTED snapshot.\n * @param s - An undirected snapshot\n * @returns The partition\n * @public\n */\nexport function connectedComponents(s: GraphSnapshot): LabelResult {\n if (s.directed) {\n throw new Error(\n \"Connected components requires an undirected graph. Use weaklyConnectedComponents, or pass s.toUndirected().snapshot.\",\n );\n }\n return unionEdges(s);\n}\n\n/**\n * Weakly connected components: the same union-find pass with the direction check dropped.\n * @param s - Any snapshot\n * @returns The partition\n * @public\n */\nexport function weaklyConnectedComponents(s: GraphSnapshot): LabelResult {\n return unionEdges(s);\n}\n","import type { U32 } from \"@graphty/graph-format\";\n\n/**\n * The source node of an arc, by binary search on `rowPtr`. `GraphSnapshot` exposes `arcSource(a)`\n * (`graph-format/src/snapshot/graph-snapshot.ts:544`), but an `AdjacencyView` -- which is what the\n * Port 1 and Port 2 signatures take, so that `reverse()` works as an input for free -- does not,\n * so the predecessor walk carries its own.\n * @param rowPtr - The view's nodeCount + 1 row offsets\n * @param arc - An arc index in `[0, arcCount)`\n * @returns The node index whose row contains the arc\n * @public\n */\nexport function arcSourceIn(rowPtr: U32, arc: number): number {\n let lo = 0;\n let hi = rowPtr.length - 1; // nodeCount\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (rowPtr[mid + 1] <= arc) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n return lo;\n}\n","import { type F64, INVALID_INDEX, type U32 } from \"@graphty/graph-format\";\n\n/**\n * A binary min-heap over node indices with O(log n) decrease-key, keyed by `Float64Array` values\n * (graph-format design 14.2, `graph-format-design.md:3771`). `pushOrDecrease` is the only operation\n * Dijkstra's inner loop needs: it inserts an absent node and decreases a present one, so the heap\n * never holds a stale duplicate and `pop()` needs no \"is this entry current\" check.\n * @public\n */\nexport class IndexedMinHeap {\n private readonly heap: U32; // slot -> node\n private readonly slot: U32; // node -> slot, INVALID_INDEX when absent\n private readonly key: F64; // node -> key\n private size = 0;\n\n /**\n * Create an empty heap over node indices in `[0, capacity)`.\n * @param capacity - The number of distinct node indices the heap may hold\n */\n constructor(capacity: number) {\n this.heap = new Uint32Array(capacity);\n this.slot = new Uint32Array(capacity).fill(INVALID_INDEX);\n this.key = new Float64Array(capacity);\n }\n\n /**\n * Whether the heap holds no entries.\n * @returns True when the heap holds no entries\n */\n isEmpty(): boolean {\n return this.size === 0;\n }\n\n /**\n * Insert a node that is not in the heap.\n * @param node - The node index\n * @param key - Its key\n */\n push(node: number, key: number): void {\n this.key[node] = key;\n this.heap[this.size] = node;\n this.slot[node] = this.size;\n this.size++;\n this.siftUp(this.size - 1);\n }\n\n /**\n * Insert the node, or lower its key if it is already present and the new key is smaller.\n * @param node - The node index\n * @param key - Its candidate key\n */\n pushOrDecrease(node: number, key: number): void {\n const at = this.slot[node];\n if (at === INVALID_INDEX) {\n this.push(node, key);\n return;\n }\n if (key < this.key[node]) {\n this.key[node] = key;\n this.siftUp(at);\n }\n }\n\n /**\n * Remove and return the node with the smallest key. Undefined behaviour on an empty heap;\n * callers guard with `isEmpty()`.\n * @returns The node index\n */\n pop(): number {\n const top = this.heap[0];\n this.slot[top] = INVALID_INDEX;\n this.size--;\n if (this.size > 0) {\n const moved = this.heap[this.size];\n this.heap[0] = moved;\n this.slot[moved] = 0;\n this.siftDown(0);\n }\n return top;\n }\n\n private siftUp(from: number): void {\n let at = from;\n const node = this.heap[at];\n const key = this.key[node];\n while (at > 0) {\n const parent = (at - 1) >> 1;\n const parentNode = this.heap[parent];\n if (this.key[parentNode] <= key) {\n break;\n }\n this.heap[at] = parentNode;\n this.slot[parentNode] = at;\n at = parent;\n }\n this.heap[at] = node;\n this.slot[node] = at;\n }\n\n private siftDown(from: number): void {\n let at = from;\n const node = this.heap[at];\n const key = this.key[node];\n for (;;) {\n const left = 2 * at + 1;\n if (left >= this.size) {\n break;\n }\n const right = left + 1;\n const child = right < this.size && this.key[this.heap[right]] < this.key[this.heap[left]] ? right : left;\n const childNode = this.heap[child];\n if (key <= this.key[childNode]) {\n break;\n }\n this.heap[at] = childNode;\n this.slot[childNode] = at;\n at = child;\n }\n this.heap[at] = node;\n this.slot[node] = at;\n }\n}\n","import { type AdjacencyView, INVALID_INDEX, type NumericVector, type U32 } from \"@graphty/graph-format\";\n\nimport { PathWalkError } from \"../errors.js\";\nimport { arcSourceIn } from \"./structures/arc-source.js\";\nimport { IndexedMinHeap } from \"./structures/min-heap.js\";\n\n/**\n * Single-source shortest paths, index-based (graph-format design 14.2 Port 2, line 3860).\n * `dist` is a `NumericVector` rather than the design's `F64` because ONE declaration serves both\n * the CPU port (which produces a `Float64Array`) and the dispatcher's decoration of an\n * accelerator's f32 result (plan decision PD-3, departure DEP-8A-C).\n * @public\n */\nexport interface SsspResult {\n /** Distance per node; +Infinity for unreached nodes. */\n readonly dist: NumericVector;\n /** The ARC that relaxed each node; INVALID_INDEX for the source and for unreached nodes. */\n readonly predArc: U32;\n /**\n * Node indices from the source to `target` inclusive; empty when `target` is unreached.\n * @param target - The node index to walk back from\n */\n pathTo(target: number): U32;\n /**\n * LOGICAL EDGE indices along that path, one fewer than `pathTo`; this is what graphty-element's\n * `isInPath` writes through. Empty when `target` is unreached.\n * @param target - The node index to walk back from\n */\n pathEdges(target: number): U32;\n}\n\n/** Options of the index-based SSSP. @public */\nexport interface SsspOptions {\n /** Stop relaxing beyond this distance. */\n readonly cutoff?: number | undefined;\n /** Per-arc weight override, arcCount long -- the facade passes `expandEdges(s, shadow.data)`. */\n readonly weights?: NumericVector | undefined;\n}\n\n/**\n * The arcs from `target` back to `source`, target end first. `predArc` may come from an\n * accelerator, so it is not trusted: a missing or out-of-range arc, or more than nodeCount - 1\n * steps, throws rather than walking off the array or looping.\n * @param g - The adjacency the search ran on\n * @param predArc - The search's predecessor-arc array\n * @param source - The search's source node index\n * @param target - The node to walk back from (reached, and not the source)\n * @returns Arc indices, target end first\n */\nfunction walkBack(g: AdjacencyView, predArc: U32, source: number, target: number): number[] {\n const arcs: number[] = [];\n let node = target;\n while (node !== source) {\n if (arcs.length >= g.nodeCount - 1) {\n throw new PathWalkError(source, target, \"cycle\");\n }\n const arc = predArc[node];\n if (!(arc < g.arcCount)) {\n throw new PathWalkError(source, target, \"gap\"); // INVALID_INDEX is past arcCount too\n }\n arcs.push(arc);\n node = arcSourceIn(g.rowPtr, arc);\n }\n return arcs;\n}\n\n/**\n * Walk the predecessor arcs back from `target` and return the node path, source first.\n * @param g - The adjacency the search ran on\n * @param predArc - The search's predecessor-arc array\n * @param source - The search's source node index\n * @param target - The node to walk back from\n * @returns Node indices from source to target inclusive, or an empty array when unreached\n * @throws PathWalkError when `predArc` has a gap or a cycle between `target` and `source`\n * @public\n */\nexport function walkPredArcs(g: AdjacencyView, predArc: U32, source: number, target: number): U32 {\n if (target === source) {\n return Uint32Array.of(source);\n }\n if (predArc[target] === INVALID_INDEX) {\n return new Uint32Array(0);\n }\n const reversed = [target, ...walkBack(g, predArc, source, target).map((arc) => arcSourceIn(g.rowPtr, arc))];\n const out = new Uint32Array(reversed.length);\n for (let i = 0; i < reversed.length; i++) {\n out[i] = reversed[reversed.length - 1 - i];\n }\n return out;\n}\n\n/**\n * Walk the predecessor arcs back from `target` and return the logical edges on the path.\n * @param g - The adjacency the search ran on\n * @param predArc - The search's predecessor-arc array\n * @param source - The search's source node index\n * @param target - The node to walk back from\n * @returns Logical edge indices from source to target, or an empty array when unreached\n * @throws PathWalkError when `predArc` has a gap or a cycle between `target` and `source`\n * @public\n */\nexport function walkPredEdges(g: AdjacencyView, predArc: U32, source: number, target: number): U32 {\n if (target === source || predArc[target] === INVALID_INDEX) {\n return new Uint32Array(0);\n }\n // the EXACT parallel edge, not a (u, v) lookup\n const reversed = walkBack(g, predArc, source, target).map((arc) => g.arcToEdge[arc]);\n const out = new Uint32Array(reversed.length);\n for (let i = 0; i < reversed.length; i++) {\n out[i] = reversed[reversed.length - 1 - i];\n }\n return out;\n}\n\n/**\n * Dijkstra over an adjacency view, with the predecessor recorded as the relaxing ARC so a parallel\n * edge on the path is identified exactly.\n * @param g - The adjacency to search\n * @param source - The node index to start from\n * @param options - Cutoff and per-arc weight override\n * @returns The distances, the predecessor arcs, and the two path accessors\n * @public\n */\nexport function dijkstra(g: AdjacencyView, source: number, options: SsspOptions = {}): SsspResult {\n const { nodeCount, rowPtr, colIdx } = g;\n const weights: NumericVector | null = options.weights ?? g.weights;\n const dist = new Float64Array(nodeCount).fill(Infinity);\n const predArc = new Uint32Array(nodeCount).fill(INVALID_INDEX);\n const heap = new IndexedMinHeap(nodeCount);\n const cutoff = options.cutoff ?? Infinity;\n dist[source] = 0;\n heap.push(source, 0);\n while (!heap.isEmpty()) {\n const u = heap.pop();\n const du = dist[u];\n const end = rowPtr[u + 1];\n for (let a = rowPtr[u]; a < end; a++) {\n const w = weights === null ? 1 : weights[a];\n const v = colIdx[a];\n const dv = du + w;\n if (dv < dist[v] && dv <= cutoff) {\n dist[v] = dv;\n predArc[v] = a;\n heap.pushOrDecrease(v, dv);\n }\n }\n }\n return {\n dist,\n predArc,\n pathTo: (target: number): U32 => walkPredArcs(g, predArc, source, target),\n pathEdges: (target: number): U32 => walkPredEdges(g, predArc, source, target),\n };\n}\n","import type { GraphSnapshot, NumericVector, U32 } from \"@graphty/graph-format\";\n\nimport { IntUnionFind } from \"./structures/union-find.js\";\n\n/** Options of the index-based MST. @public */\nexport interface MstOptions {\n /** Per-arc weight override, arcCount long; gathered back to per-edge through `edgeToArc`. */\n readonly weights?: NumericVector | undefined;\n}\n\n/** Result of the index-based MST (graph-format design 14.2's result table, line 3745). @public */\nexport interface MstResult {\n /** Logical edge indices of the spanning forest, in the order they were accepted. */\n readonly edges: U32;\n /** Sum of the accepted edges' weights. */\n readonly totalWeight: number;\n}\n\n/**\n * Kruskal's minimum spanning forest over logical edges.\n *\n * The sort is a comparator over an f64 key array, tie-broken by edge index, rather than the\n * design's radix sort on the f32 bit pattern (plan departure DEP-8A-D): the tie-break makes it\n * stable by construction and it has to serve both the f32 arc array and an f64 override.\n * @param s - The snapshot\n * @param o - The optional per-arc weight override\n * @returns The accepted edge indices and their total weight\n * @public\n */\nexport function kruskalMST(s: GraphSnapshot, o: MstOptions = {}): MstResult {\n const el = s.edgeList();\n const m = s.edgeCount;\n const keys = new Float64Array(m);\n if (o.weights !== undefined) {\n // The override is per ARC; edgeList().arc holds the arc of each edge's declared orientation.\n for (let e = 0; e < m; e++) {\n keys[e] = o.weights[el.arc[e]];\n }\n } else if (el.weights !== null) {\n for (let e = 0; e < m; e++) {\n keys[e] = el.weights[e];\n }\n } else {\n keys.fill(1);\n }\n const order: number[] = new Array<number>(m);\n for (let e = 0; e < m; e++) {\n order[e] = e;\n }\n order.sort((a, b) => keys[a] - keys[b] || a - b);\n const uf = new IntUnionFind(s.nodeCount);\n const accepted = new Uint32Array(Math.max(s.nodeCount - 1, 0));\n let taken = 0;\n let totalWeight = 0;\n for (const e of order) {\n if (uf.union(el.src[e], el.dst[e])) {\n accepted[taken++] = e;\n totalWeight += keys[e];\n }\n }\n return { edges: accepted.subarray(0, taken), totalWeight };\n}\n","import type { F64, GraphSnapshot, NumericVector } from \"@graphty/graph-format\";\n\n/** Options of the index-based PageRank (graph-format design 14.2 Port 3, line 3892). @public */\nexport interface PageRankOptions {\n /** Probability of following a link; default 0.85. */\n readonly dampingFactor?: number | undefined;\n /** Iteration cap; default 100. */\n readonly maxIterations?: number | undefined;\n /** L1 convergence tolerance; default 1e-6. */\n readonly tolerance?: number | undefined;\n /** Use the snapshot's arc weights; default false. */\n readonly weighted?: boolean | undefined;\n}\n\n/** Result of the index-based PageRank. @public */\nexport interface PageRankResult {\n /** Score per node index. */\n readonly scores: F64;\n /** Iterations actually run. */\n readonly iterations: number;\n /** Whether the L1 delta fell below the tolerance. */\n readonly converged: boolean;\n}\n\n/**\n * PageRank by pull over `reverse()`, with the dangling mass redistributed uniformly.\n * @param s - A DIRECTED snapshot\n * @param o - Algorithm options\n * @returns The scores, the iteration count and the convergence flag\n * @public\n */\nexport function pageRank(s: GraphSnapshot, o: PageRankOptions = {}): PageRankResult {\n if (!s.directed) {\n throw new Error(\"PageRank requires a directed graph\");\n }\n const n = s.nodeCount;\n const d = o.dampingFactor ?? 0.85;\n const maxIter = o.maxIterations ?? 100;\n const tol = o.tolerance ?? 1e-6;\n const rev = s.reverse();\n const weighted = o.weighted === true && rev.weights !== null;\n const outW: NumericVector = weighted ? s.weightedOutDegree() : s.outDegree();\n let rank = new Float64Array(n).fill(1 / n);\n let next = new Float64Array(n);\n let it = 0;\n let converged = false;\n for (; it < maxIter && !converged; it++) {\n let dangling = 0;\n for (let u = 0; u < n; u++) {\n if (outW[u] === 0) {\n dangling += rank[u];\n }\n }\n const base = (1 - d) / n + (d * dangling) / n;\n let delta = 0;\n for (let v = 0; v < n; v++) {\n let acc = 0;\n const end = rev.rowPtr[v + 1];\n for (let a = rev.rowPtr[v]; a < end; a++) {\n const u = rev.colIdx[a];\n const ow = outW[u];\n if (ow > 0) {\n acc += (rank[u] * (weighted && rev.weights !== null ? rev.weights[a] : 1)) / ow;\n }\n }\n next[v] = base + d * acc;\n delta += Math.abs(next[v] - rank[v]);\n }\n [rank, next] = [next, rank];\n converged = delta < tol;\n }\n return { scores: rank, iterations: it, converged };\n}\n","/**\n * Conversion from the legacy `Graph` class to a frozen graph-format snapshot\n * (graph-format design 14.1 rule 4, 14.6 row A1). This is the ONLY bridge between the legacy\n * Map-of-Maps surface and `indexed.*`; nothing under `src/indexed/` other than this file imports\n * `../core/graph.js`.\n * @module\n */\n\nimport { GraphBuilder, type GraphSnapshot } from \"@graphty/graph-format\";\n\nimport type { Graph } from \"../core/graph.js\";\n\n/** Options of {@link toSnapshot}. @public */\nexport interface ToSnapshotOptions {\n /**\n * Record FNV-1a checksums at freeze so a caller can assert `snapshot.validate({ checksum: true })`\n * (graph-format design 14.2's first port rule: views are shared, so a port that writes into one\n * has to fail a test rather than corrupt the next call). Default false; the test suites set it.\n */\n readonly checksum?: boolean | undefined;\n}\n\ninterface CacheEntry {\n readonly mutationCount: number;\n readonly checksum: boolean;\n readonly snapshot: GraphSnapshot;\n}\n\n/**\n * One entry per graph, REPLACED rather than appended to on a mutation. The entry holds the\n * mutationCount it was built at, which is what makes a stale hit impossible -- the bug the old\n * `WeakMap<Graph, CSRGraph>` cache had (graph-format design 14.1 rule 4).\n */\nconst SNAPSHOT_CACHE = new WeakMap<Graph, CacheEntry>();\n\n/**\n * Freeze a legacy `Graph` into a `GraphSnapshot`, memoised on the graph's `mutationCount`.\n *\n * The builder is created with `weightDtype: \"f64\"` so a legacy graph's double weights survive\n * exactly: at freeze, graph-format keeps the original values in an f64 edge column with role\n * `weight` (the \"shadow\") whenever at least one of them is not f32-exact, and costs nothing when\n * they all are (graph-format design section 3.7, `graph-format/src/builder/freeze.ts:332-360`).\n * A weighted `indexed.*` port reproduces legacy f64 results by passing\n * `expandEdges(s, shadow.data)` as its per-arc `weights` override.\n *\n * Every legacy edge carries a weight (`Graph.addEdge` defaults it to 1), so the builder's\n * `weighted: \"auto\"` always allocates the arc weight array -- 4 bytes per arc. That is truthful\n * rather than wasteful: the legacy graph really does store the value.\n * @param graph - The legacy graph to convert\n * @param options - Conversion options\n * @returns A frozen snapshot of the graph's current topology and weights\n * @public\n */\nexport function toSnapshot(graph: Graph, options: ToSnapshotOptions = {}): GraphSnapshot {\n const checksum = options.checksum === true;\n const cached = SNAPSHOT_CACHE.get(graph);\n // A checksummed snapshot answers a plain request; a plain one cannot answer a checksummed\n // request -- validate({ checksum: true }) throws E_INVALID_SNAPSHOT (\"no-checksum\") when none\n // were recorded (graph-format/src/types/snapshot.ts:401-405).\n if (cached !== undefined && cached.mutationCount === graph.mutationCount && (cached.checksum || !checksum)) {\n return cached.snapshot;\n }\n const builder = new GraphBuilder({\n directed: graph.isDirected,\n weightDtype: \"f64\",\n expectedNodes: graph.nodeCount,\n expectedEdges: graph.totalEdgeCount,\n });\n for (const node of graph.nodes()) {\n builder.addNode(node.id);\n }\n for (const edge of graph.edges()) {\n builder.addEdge(edge.source, edge.target, edge.weight);\n }\n const snapshot = builder.freeze({ label: \"algorithms.toSnapshot\", checksum });\n SNAPSHOT_CACHE.set(graph, { mutationCount: graph.mutationCount, checksum, snapshot });\n return snapshot;\n}\n","/**\n * The accelerator seam of `@graphty/algorithms` (WebGPU design section 9.2). It contains NO\n * WebGPU types: an accelerator is anything that satisfies `AlgorithmAccelerator` structurally,\n * and this package never imports the GPU package (design section 9.1, the dependency direction).\n *\n * `accelerated(acc)` is the ONE dispatcher object (design section 9.2, the dispatcher rule); the\n * spelling is `accelerated(acc).pageRank(s, options)`, never\n * `runAlgorithm(snapshot, { accelerator })`. There is no try/catch anywhere below: an accelerator\n * method that throws propagates its throw unchanged, because a silent CPU fallback would hide a\n * broken device behind a slow answer.\n * @module\n */\n\nimport type { F32, F64, GraphSnapshot, NumericVector, U32 } from \"@graphty/graph-format\";\n\nimport type { BfsOptions } from \"./bfs.js\";\nimport { type SsspOptions, type SsspResult, walkPredArcs, walkPredEdges } from \"./dijkstra.js\";\nimport * as indexed from \"./index.js\";\nimport type { MstOptions } from \"./mst.js\";\nimport type { PageRankOptions } from \"./pagerank.js\";\n\n// ============================================================ result shapes (design 9.2 lines 2909-2922)\n// Scores may be f32 (an accelerator) or f64 (the CPU ports), so every score field is NumericVector.\n\n/** A score vector with its convergence report. @public */\nexport interface ScoresResultLike {\n readonly scores: NumericVector;\n readonly iterations: number;\n readonly converged: boolean;\n}\n/** ScoresResultLike plus the mass held by dangling nodes. @public */\nexport interface PageRankResultLike extends ScoresResultLike {\n readonly danglingMass?: number | undefined;\n}\n/** The two HITS vectors with their convergence report. @public */\nexport interface HitsResultLike {\n readonly hubs: NumericVector;\n readonly authorities: NumericVector;\n readonly iterations: number;\n readonly converged: boolean;\n}\n/** A partition: dense labels, a count, and the grouped node indices. @public */\nexport interface LabelResultLike {\n readonly labels: U32;\n readonly count: number;\n groups(): U32[];\n}\n/** A breadth-first traversal. @public */\nexport interface BfsResultLike {\n readonly depth: U32;\n readonly parent: U32;\n readonly order: U32;\n readonly visitedCount: number;\n}\n/** Single-source distances plus the relaxing arc per node. @public */\nexport interface SsspResultLike {\n readonly dist: NumericVector;\n readonly predArc: U32;\n}\n/** SsspResultLike plus the negative-cycle flag. @public */\nexport interface BellmanFordResultLike extends SsspResultLike {\n readonly hasNegativeCycle: boolean;\n}\n/** A per-logical-edge score vector. @public */\nexport interface EdgeScoresResultLike {\n readonly scores: NumericVector;\n}\n/** An all-pairs distance matrix, row-major, n by n. @public */\nexport interface ApspResultLike {\n readonly dist: NumericVector;\n readonly n: number;\n}\n/** Per-node coreness. @public */\nexport interface CorenessResultLike {\n readonly coreness: U32;\n}\n/** A spanning forest as logical edge indices. @public */\nexport interface MstResultLike {\n readonly edges: U32;\n readonly totalWeight: number;\n}\n/** A partition with its modularity. @public */\nexport interface CommunityResultLike extends LabelResultLike {\n readonly modularity: number;\n}\n\n// ============================================================ the injected object (design 9.2 lines 2925-2948)\n\n/**\n * The structural contract an injected accelerator satisfies. EVERY member except `kind` is\n * optional: an accelerator declares only what it implements, and the dispatcher runs the CPU port\n * for everything else. The list is the design's, in full, so that an accelerator written against\n * it needs no change as the ports land.\n * @public\n */\nexport interface AlgorithmAccelerator {\n readonly kind: string;\n pageRank?(s: GraphSnapshot, options?: PageRankOptions): Promise<PageRankResultLike>;\n personalizedPageRank?(\n s: GraphSnapshot,\n personalization: F32 | F64,\n options?: PageRankOptions,\n ): Promise<PageRankResultLike>;\n hits?(s: GraphSnapshot, options?: HitsOptionsLike): Promise<HitsResultLike>;\n eigenvectorCentrality?(s: GraphSnapshot, options?: HitsOptionsLike): Promise<ScoresResultLike>;\n katzCentrality?(s: GraphSnapshot, options?: HitsOptionsLike): Promise<ScoresResultLike>;\n connectedComponents?(s: GraphSnapshot): Promise<LabelResultLike>;\n weaklyConnectedComponents?(s: GraphSnapshot): Promise<LabelResultLike>;\n breadthFirstSearch?(s: GraphSnapshot, source: number, options?: BfsOptions): Promise<BfsResultLike>;\n sssp?(s: GraphSnapshot, source: number, options?: SsspOptions): Promise<SsspResultLike>;\n bellmanFord?(s: GraphSnapshot, source: number, options?: SsspOptions): Promise<BellmanFordResultLike>;\n closenessCentrality?(s: GraphSnapshot, options?: HitsOptionsLike): Promise<ScoresResultLike>;\n betweennessCentrality?(s: GraphSnapshot, options?: BetweennessAcceleratorOptions): Promise<ScoresResultLike>;\n edgeBetweennessCentrality?(\n s: GraphSnapshot,\n options?: BetweennessAcceleratorOptions,\n ): Promise<EdgeScoresResultLike>;\n allPairsShortestPath?(s: GraphSnapshot, options?: SsspOptions): Promise<ApspResultLike>;\n kCoreDecomposition?(s: GraphSnapshot): Promise<CorenessResultLike>;\n triangleCount?(s: GraphSnapshot): Promise<{ readonly perNode: U32; readonly total: number }>;\n labelPropagation?(s: GraphSnapshot, options?: HitsOptionsLike): Promise<LabelResultLike>;\n minimumSpanningTree?(s: GraphSnapshot, options?: MstOptions): Promise<MstResultLike>;\n louvain?(s: GraphSnapshot, options?: HitsOptionsLike): Promise<CommunityResultLike>;\n release?(s: GraphSnapshot): void;\n dispose?(): void;\n}\n\n/**\n * The option shape of the power-iteration family until each one's `indexed.*` port lands and\n * brings its real option type (plan decision PD-2's \"NOT TOUCHED\" rows). It is DELIBERATELY not\n * `Record<string, unknown>`: these three are the members every one of those algorithms takes, so\n * an accelerator can honour them today and the type narrows rather than widens as ports arrive.\n * @public\n */\nexport interface HitsOptionsLike {\n readonly maxIterations?: number | undefined;\n readonly tolerance?: number | undefined;\n readonly weighted?: boolean | undefined;\n}\n\n/**\n * Betweenness options as the accelerator sees them: node INDICES, which is the only form that\n * means anything on a snapshot (plan decision PD-5).\n * @public\n */\nexport interface BetweennessAcceleratorOptions {\n readonly normalized?: boolean | undefined;\n readonly endpoints?: boolean | undefined;\n readonly sources?: readonly number[] | undefined;\n readonly k?: number | undefined;\n}\n\n// ============================================================ the dispatcher (design 9.2 lines 2950-2957)\n\n/**\n * The async dispatcher: one method per accelerable `indexed.*` function. Each delegates to the\n * accelerator when it has the method and runs the CPU port otherwise, wrapped in `Promise.resolve`\n * so both paths are async and graphty-element's `async run()` adapters treat them alike.\n *\n * The list GROWS with the A2 ports -- each port PR adds its method. Today it carries the six whose\n * ports exist (plan departure DEP-8A-E).\n * @public\n */\nexport interface AcceleratedAlgorithms {\n readonly accelerator: AlgorithmAccelerator | null;\n pageRank(s: GraphSnapshot, options?: PageRankOptions): Promise<PageRankResultLike>;\n sssp(s: GraphSnapshot, source: number, options?: SsspOptions): Promise<SsspResult>;\n breadthFirstSearch(s: GraphSnapshot, source: number, options?: BfsOptions): Promise<BfsResultLike>;\n connectedComponents(s: GraphSnapshot): Promise<LabelResultLike>;\n weaklyConnectedComponents(s: GraphSnapshot): Promise<LabelResultLike>;\n minimumSpanningTree(s: GraphSnapshot, options?: MstOptions): Promise<MstResultLike>;\n}\n\n/**\n * Attach `pathTo` / `pathEdges` to an accelerator's bare `{ dist, predArc }`, so both paths return\n * the design's `SsspResult` and the element keeps ONE result-writing loop. The GPU package cannot\n * attach them itself: it must not depend on the CPU package at runtime (design 9.2 line 2971, D3).\n * @param s - The snapshot the search ran on\n * @param source - The search's source node index\n * @param like - The accelerator's result\n * @returns The decorated result\n */\nfunction decorateSssp(s: GraphSnapshot, source: number, like: SsspResultLike): SsspResult {\n const { predArc } = like;\n return {\n dist: like.dist,\n predArc,\n pathTo: (target: number): U32 => walkPredArcs(s, predArc, source, target),\n pathEdges: (target: number): U32 => walkPredEdges(s, predArc, source, target),\n };\n}\n\n/**\n * Build the dispatcher for an accelerator, or for none.\n * @param acc - The injected accelerator, or `null` / `undefined` for the CPU path\n * @returns A dispatcher whose methods delegate where they can and run the CPU port otherwise\n * @public\n */\nexport function accelerated(acc: AlgorithmAccelerator | null | undefined): AcceleratedAlgorithms {\n return {\n accelerator: acc ?? null,\n pageRank: (s, options) =>\n acc?.pageRank !== undefined ? acc.pageRank(s, options) : Promise.resolve(indexed.pageRank(s, options)),\n sssp: (s, source, options) =>\n acc?.sssp !== undefined\n ? acc.sssp(s, source, options).then((like) => decorateSssp(s, source, like))\n : Promise.resolve(indexed.dijkstra(s, source, options)),\n breadthFirstSearch: (s, source, options) =>\n acc?.breadthFirstSearch !== undefined\n ? acc.breadthFirstSearch(s, source, options)\n : Promise.resolve(indexed.breadthFirstSearch(s, source, options)),\n connectedComponents: (s) =>\n acc?.connectedComponents !== undefined\n ? acc.connectedComponents(s)\n : Promise.resolve(indexed.connectedComponents(s)),\n weaklyConnectedComponents: (s) =>\n acc?.weaklyConnectedComponents !== undefined\n ? acc.weaklyConnectedComponents(s)\n : Promise.resolve(indexed.weaklyConnectedComponents(s)),\n minimumSpanningTree: (s, options) =>\n acc?.minimumSpanningTree !== undefined\n ? acc.minimumSpanningTree(s, options)\n : Promise.resolve(indexed.kruskalMST(s, options)),\n };\n}\n"],"names":["this","SparseTypedFastBitSet_1","require$$0","Type","SparseTypedFastBitSet","index","TypedFastBitSet_1","TypedFastBitSet","exports","require$$1","nodeId","breadthFirstSearch","hasNegativeCycle","element","dijkstra","pageRank","result","connectedComponents","weaklyConnectedComponents","kruskalMST","calculateModularity","getTotalEdgeWeight","getNodeDegree","nodeLabel","getNeighborCommunities","u","v","graphToAdjacencySet","degreeV","communities","clusterAssignments","commonNeighborsScore","leftIndices","rightIndices","indexed.pageRank","indexed.dijkstra","indexed.breadthFirstSearch","indexed.connectedComponents","indexed.weaklyConnectedComponents","indexed.kruskalMST"],"mappings":"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","x_google_ignoreList":[2,3,4,5]}
|
|
1
|
+
{"version":3,"file":"algorithms.js","sources":["../src/core/graph.ts","../src/errors.ts","../../node_modules/.pnpm/typedfastbitset@0.6.1/node_modules/typedfastbitset/lib/utils.js","../../node_modules/.pnpm/typedfastbitset@0.6.1/node_modules/typedfastbitset/lib/SparseTypedFastBitSet.js","../../node_modules/.pnpm/typedfastbitset@0.6.1/node_modules/typedfastbitset/lib/TypedFastBitSet.js","../../node_modules/.pnpm/typedfastbitset@0.6.1/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","../src/indexed/bfs.ts","../src/indexed/common-neighbors.ts","../src/indexed/structures/union-find.ts","../src/indexed/components.ts","../src/indexed/structures/arc-source.ts","../src/indexed/structures/min-heap.ts","../src/indexed/dijkstra.ts","../src/indexed/hits.ts","../src/indexed/k-core.ts","../src/indexed/katz.ts","../src/indexed/louvain.ts","../src/indexed/mst.ts","../src/indexed/pagerank.ts","../src/indexed/to-snapshot.ts","../src/indexed/accelerator.ts"],"sourcesContent":["import type { Edge, GraphConfig, Node, NodeId } from \"../types/index.js\";\n\n/**\n * True when an undirected edge seen from `source` is the mirror of one already yielded from\n * `target`: ids of one type compare by value, ids of different types by their type name.\n * @param source - The node the edge is read from\n * @param target - The node the edge points to\n * @returns True when this side of the edge is the duplicate\n */\nfunction isMirror(source: NodeId, target: NodeId): boolean {\n return typeof source === typeof target ? source > target : typeof source > typeof target;\n}\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 private mutations: number;\n\n /**\n * Creates a new Graph instance.\n * @param config - Configuration options for the graph\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 this.mutations = 0;\n }\n\n /**\n * Add a node to the graph\n * @param id - The unique identifier for the node\n * @param data - Optional key-value data to attach to the node\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 this.mutations++;\n }\n }\n\n /**\n * Remove a node from the graph\n * @param id - The unique identifier of the node to remove\n * @returns True if the node was removed, false if it did not exist\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 this.mutations++;\n return true;\n }\n\n /**\n * Add an edge to the graph\n * @param source - The source node identifier\n * @param target - The target node identifier\n * @param weight - The weight of the edge (defaults to 1)\n * @param data - Optional key-value data to attach to the edge\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. With allowParallelEdges the adjacency still holds one edge per\n // pair, so a repeated pair replaces the earlier edge and must not be counted again.\n const replacing = this.hasEdge(source, target);\n if (!this.config.allowParallelEdges && replacing) {\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 if (!replacing) {\n this.edgeCount++;\n }\n\n this.mutations++;\n }\n\n /**\n * Remove an edge from the graph\n * @param source - The source node identifier\n * @param target - The target node identifier\n * @returns True if the edge was removed, false if it did not exist\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 this.mutations++;\n return true;\n }\n\n /**\n * Check if a node exists in the graph\n * @param id - The unique identifier of the node to check\n * @returns True if the node exists, false otherwise\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 * @param source - The source node identifier\n * @param target - The target node identifier\n * @returns True if the edge exists, false otherwise\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 * @param id - The unique identifier of the node to retrieve\n * @returns The node if found, undefined otherwise\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 * @param source - The source node identifier\n * @param target - The target node identifier\n * @returns The edge if found, undefined otherwise\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 * @returns The total count of nodes\n */\n get nodeCount(): number {\n return this.nodeMap.size;\n }\n\n /**\n * A counter that increases on every topology change (`addNode` of a new id, `removeNode`,\n * `addEdge`, `removeEdge`, `clear`) and never on a read. Callers memoise derived structures on\n * `(graph, mutationCount)`; graph-format design 14.1 rule 4 names this counter, and `toSnapshot`\n * is its first consumer. It is monotone and is NOT reset by `clear()`: a reset could hand a\n * stale cache entry a matching key.\n * @returns The number of topology changes made to this graph\n */\n get mutationCount(): number {\n return this.mutations;\n }\n\n /**\n * Get the number of edges in the graph\n * @returns The total count of edges\n */\n get totalEdgeCount(): number {\n return this.edgeCount;\n }\n\n /**\n * Check if the graph is directed\n * @returns True if the graph is directed, false otherwise\n */\n get isDirected(): boolean {\n return this.config.directed;\n }\n\n /**\n * Get all nodes in the graph\n * @returns An iterator over all nodes\n */\n nodes(): IterableIterator<Node> {\n return this.nodeMap.values();\n }\n\n /**\n * Get all edges in the graph\n * @yields Each unique edge 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. A string never compares\n // greater than a number (both `<` and `>` are false), so mixed-type ids are\n // ordered by their type name first; the mirror is then skipped on exactly one side.\n if (!this.config.directed && isMirror(source, edge.target)) {\n continue;\n }\n\n yield edge;\n }\n }\n }\n\n /**\n * Get neighbors of a node (outgoing edges)\n * @param nodeId - The node identifier to get neighbors for\n * @returns An iterator over the neighbor node identifiers\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 * @param nodeId - The node identifier to get incoming neighbors for\n * @returns An iterator over the incoming neighbor node identifiers\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 * @param nodeId - The node identifier to get outgoing neighbors for\n * @returns An iterator over the outgoing neighbor node identifiers\n */\n outNeighbors(nodeId: NodeId): IterableIterator<NodeId> {\n return this.neighbors(nodeId);\n }\n\n /**\n * Get the degree of a node\n * @param nodeId - The node identifier to get the degree for\n * @returns The total degree of the 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 * @param nodeId - The node identifier to get the in-degree for\n * @returns The number of incoming edges to the 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 * @param nodeId - The node identifier to get the out-degree for\n * @returns The number of outgoing edges from the 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 * @returns A new Graph instance with the same nodes and edges\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(edge.source, edge.target, edge.weight, edge.data ? { ...edge.data } : undefined);\n }\n\n return cloned;\n }\n\n /**\n * Get graph configuration\n * @returns A copy of the graph configuration object\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 this.mutations++;\n }\n\n /**\n * Get the number of unique edges in the graph\n * For undirected graphs, each edge is counted once\n * @returns The count of unique edges\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 \n for (const _edge of this.edges()) {\n count++;\n }\n return count;\n }\n}\n","/**\n * Thrown when an iterative algorithm reaches its iteration cap before meeting its tolerance.\n *\n * The scores it had reached are not returned: an unconverged vector is not the answer, and\n * returning it in silence would pass it off as one. networkx makes the same choice with\n * `PowerIterationFailedConvergence`. Raise `maxIterations`, or loosen `tolerance`, and call again.\n */\nexport class ConvergenceError extends Error {\n override readonly name = \"ConvergenceError\";\n\n /**\n * Builds the error and its message.\n * @param algorithm - The function that gave up, e.g. `\"eigenvectorCentrality\"`\n * @param iterations - The passes it ran, which is its `maxIterations`\n * @param tolerance - The tolerance it did not meet\n */\n constructor(\n readonly algorithm: string,\n readonly iterations: number,\n readonly tolerance: number,\n ) {\n super(\n `${algorithm} did not converge in ${String(iterations)} iterations (tolerance ${String(tolerance)}); raise maxIterations or tolerance`,\n );\n }\n}\n\n/**\n * Thrown when a shortest path cannot be walked back from its predecessor array: the walk met a\n * missing or out-of-range predecessor before the source (`\"gap\"`), or took more than\n * `nodeCount - 1` steps without reaching it (`\"cycle\"`).\n *\n * A CPU search never produces such an array; an accelerator's result can (a kernel bug, a lost\n * device, a buffer read too early). The error surfaces it instead of hanging or returning a wrong\n * path, and nothing recomputes the path on the CPU.\n */\nexport class PathWalkError extends Error {\n override readonly name = \"PathWalkError\";\n\n /**\n * Builds the error and its message.\n * @param source - The search's source node index\n * @param target - The node index the walk started from\n * @param reason - `\"gap\"` or `\"cycle\"`, as above\n */\n constructor(\n readonly source: number,\n readonly target: number,\n readonly reason: \"cycle\" | \"gap\",\n ) {\n super(\n `cannot walk the shortest path from node ${String(source)} to node ${String(target)}: the predecessor array has a ${reason}`,\n );\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 /**\n * Creates a new GraphBitSet with optional pre-allocated capacity.\n * @param capacity - The initial capacity to pre-allocate for the bitset\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 to the set.\n * @param index - The element index to add\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 from the set.\n * @param index - The element index to remove\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 an element exists in the set.\n * @param index - The element index to check\n * @returns True if the element exists, false otherwise\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 the set is empty.\n * @returns True if the set contains no elements, false otherwise\n */\n isEmpty(): boolean {\n return this._cardinality === 0;\n }\n\n /**\n * Optimized for graph algorithms - add a range of indices.\n * @param start - The starting index (inclusive)\n * @param end - The ending index (exclusive)\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 - get the number of elements in the set.\n * @returns The number of elements in the set\n */\n size(): number {\n return this._cardinality;\n }\n\n /**\n * Batch operations for frontier management - swap contents with another GraphBitSet.\n * @param other - The GraphBitSet to swap contents with\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 over all elements in the set.\n * @yields The indices of elements in the set\n */\n *[Symbol.iterator](): Generator<number> {\n // Use TypedFastBitSet's optimized iteration\n yield* this.bitset;\n }\n\n /**\n * Perform union operation with another GraphBitSet, updating this set in place.\n * @param other - The GraphBitSet to union with\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 /**\n * Perform intersection operation with another GraphBitSet, updating this set in place.\n * @param other - The GraphBitSet to intersect with\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 /**\n * Perform difference operation with another GraphBitSet, updating this set in place.\n * @param other - The GraphBitSet to subtract from this set\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 * @returns A new GraphBitSet with the same elements\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 /**\n * Creates a new VisitedBitArray with the specified size.\n * @param size - The number of bits to allocate\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 the specified index.\n * @param index - The bit index to set\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 value at the specified index.\n * @param index - The bit index to get\n * @returns True if the bit is set, false otherwise\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 the specified index.\n * @param index - The bit index to toggle\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 - count the number of set bits.\n * @returns The number of bits set to 1\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 * @param n - The 32-bit word to count\n * @returns The number of bits set to 1 in the word\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 * @returns The total number of bits in the array\n */\n size(): number {\n return this._size;\n }\n\n /**\n * Check if all bits are zero.\n * @returns True if no bits are set, false otherwise\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 an array of indices.\n * @param indices - Array of bit indices to set\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 * @returns Array containing the indices of all bits that are set to 1\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 /**\n * Creates a new CompactDistanceArray with the specified size.\n * @param size - The number of distance values to store\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 the specified index.\n * @param index - The node index to set the distance for\n * @param distance - The distance value to set\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 the specified index.\n * @param index - The node index to get the distance for\n * @returns The distance value, or INFINITY if not set\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 a node has been visited (has a valid distance).\n * @param index - The node index to check\n * @returns True if the node has been visited, false otherwise\n */\n isVisited(index: number): boolean {\n return this.data[index] !== CompactDistanceArray.INFINITY;\n }\n\n /**\n * Reset all distances to unvisited state.\n */\n clear(): void {\n this.data.fill(CompactDistanceArray.INFINITY);\n }\n\n /**\n * Get the size of the distance array.\n * @returns The number of elements in the array\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 */\ninterface 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 */\ninterface 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 /**\n * Creates a new DirectionOptimizedBFS instance.\n * @param graph - The CSR graph to perform BFS on\n * @param options - Optional configuration for switching thresholds\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 node.\n * @param source - The source node ID to start the BFS from\n * @returns The BFS result containing distances and parent pointers\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 || 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 * @returns The scout count (total degree of newly discovered nodes)\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 for frontier neighbors.\n * @returns The number of newly discovered 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 * @returns The total number of outgoing edges from frontier nodes\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 * @returns The BFS result containing distances and parent pointers\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 from multiple source nodes.\n * @param sources - Array of source node IDs to start the BFS from\n * @returns The BFS result containing distances and parent pointers\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 || 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 * @param graph - The CSR graph to perform BFS on\n * @param source - The source node ID to start the BFS from\n * @param options - Optional configuration for switching thresholds\n * @returns The BFS result containing distances and parent pointers\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","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 /**\n * Creates a new CSRGraph from an adjacency list representation.\n * @param adjacencyList - Map of node IDs to arrays of neighbor node IDs\n * @param weights - Optional map of edge weights keyed by \"source-target\" strings\n * @param buildReverse - Whether to build reverse edges for bottom-up BFS (default true)\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 * @param adjacencyList - Map of node IDs to arrays of neighbor node IDs\n * @param weights - Optional map of edge weights keyed by \"source-target\" strings\n * @param buildReverse - Whether to build reverse edges for bottom-up BFS\n * @returns The constructed CSR graph data structure\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 /**\n * Get the total number of nodes in the graph.\n * @returns The number of nodes\n */\n nodeCount(): number {\n return this.data.indexToNodeId.length;\n }\n\n /**\n * Get the total number of edges in the graph.\n * @returns The number of edges\n */\n edgeCount(): number {\n return this.data.columnIndices.length;\n }\n\n /**\n * Check if a node exists in the graph.\n * @param nodeId - The node ID to check\n * @returns True if the node exists, false otherwise\n */\n hasNode(nodeId: TNodeId): boolean {\n return this.data.nodeIdToIndex.has(nodeId);\n }\n\n /**\n * Check if an edge exists between two nodes.\n * @param source - The source node ID\n * @param target - The target node ID\n * @returns True if the edge exists, false otherwise\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 of a node as node IDs.\n * @param nodeId - The node ID to get neighbors for\n * @returns An iterator over neighbor 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 in the graph.\n * @returns An iterator over all node IDs\n */\n nodes(): IterableIterator<TNodeId> {\n return this.data.indexToNodeId.values();\n }\n\n /**\n * Get neighbors as indices (internal use).\n * @param nodeIndex - The internal index of the node\n * @returns Array of neighbor indices\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 /**\n * Get the out-degree (number of outgoing edges) of a node.\n * @param nodeId - The node ID to get the out-degree for\n * @returns The number of outgoing edges from the node\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 * @param nodeIndex - The internal index of the node\n * @returns The number of outgoing edges from the node\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 * @param nodeIndex - The internal index of the node\n * @yields The indices of neighboring nodes\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 * @param nodeIndex - The internal index of the node\n * @yields The indices of nodes with edges pointing to this node\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 internal index.\n * @param nodeId - The node ID to convert\n * @returns The internal index for the node\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 internal index to node ID.\n * @param index - The internal index to convert\n * @returns The node ID for the given index\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 between two nodes.\n * @param source - The source node ID\n * @param target - The target node ID\n * @returns The edge weight, or undefined if the edge doesn't exist or has no 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 * @param arr - The typed array to search in\n * @param target - The value to search for\n * @param start - The starting index (inclusive)\n * @param end - The ending index (exclusive)\n * @returns The index of the target, or -1 if not found\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 interface.\n * @param graph - The graph object to convert, must implement nodes, neighbors, hasNode, and optionally getEdge\n * @param graph.nodes - Function that returns an iterator over node objects with id property\n * @param graph.neighbors - Function that returns an iterator over neighbor node IDs\n * @param graph.hasNode - Function that checks if a node exists in the graph\n * @param graph.getEdge - Optional function that returns edge data including weight\n * @returns A new CSRGraph instance\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 /**\n * Creates a new GraphAdapter that wraps or converts a graph to CSR format.\n * @param graph - The graph to adapt (either standard Graph or ReadonlyGraph)\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 * @param graph - The graph to convert\n * @returns A new CSRGraph instance\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 /**\n * Get the total number of nodes in the graph.\n * @returns The number of nodes\n */\n nodeCount(): number {\n return this.csrGraph.nodeCount();\n }\n\n /**\n * Get the total number of edges in the graph.\n * @returns The number of edges\n */\n edgeCount(): number {\n return this.csrGraph.edgeCount();\n }\n\n /**\n * Check if a node exists in the graph.\n * @param nodeId - The node ID to check\n * @returns True if the node exists, false otherwise\n */\n hasNode(nodeId: TNodeId): boolean {\n return this.csrGraph.hasNode(nodeId);\n }\n\n /**\n * Check if an edge exists between two nodes.\n * @param source - The source node ID\n * @param target - The target node ID\n * @returns True if the edge exists, false otherwise\n */\n hasEdge(source: TNodeId, target: TNodeId): boolean {\n return this.csrGraph.hasEdge(source, target);\n }\n\n /**\n * Get neighbors of a node as node IDs.\n * @param nodeId - The node ID to get neighbors for\n * @returns An iterator over neighbor node IDs\n */\n neighbors(nodeId: TNodeId): IterableIterator<TNodeId> {\n return this.csrGraph.neighbors(nodeId);\n }\n\n /**\n * Get the out-degree (number of outgoing edges) of a node.\n * @param nodeId - The node ID to get the out-degree for\n * @returns The number of outgoing edges from the node\n */\n outDegree(nodeId: TNodeId): number {\n return this.csrGraph.outDegree(nodeId);\n }\n\n /**\n * Get all nodes in the graph.\n * @returns An iterator over all node IDs\n */\n nodes(): IterableIterator<TNodeId> {\n return this.csrGraph.nodes();\n }\n\n /**\n * Get the underlying CSR graph.\n * @returns The CSRGraph instance used internally\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 * @param _config - The configuration object (ignored)\n */\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 * @returns An empty configuration object\n */\nexport function getOptimizationConfig(): GraphAlgorithmConfig {\n return {};\n}\n\n/**\n * Check if a graph is already in CSR format.\n * @param graph - The graph to check\n * @returns True if the graph is a CSRGraph instance\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 * @param graph - The graph to convert\n * @returns A CSRGraph instance (either the original if already CSR, or a new converted one)\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 * @param nodes - Array of node IDs\n * @param edges - Array of edge tuples [source, target, weight?]\n * @returns A new CSRGraph instance\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>(target: T, predecessor: Map<T, T | null>): 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(graph: Graph, source: NodeId, target: NodeId, directed = false): Set<NodeId> {\n const sourceNeighbors = new Set(directed ? graph.outNeighbors(source) : graph.neighbors(source));\n const targetNeighbors = new Set(directed ? graph.outNeighbors(target) : graph.neighbors(target));\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(graph: Graph, source: NodeId, target: NodeId): 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(source: NodeId, target: NodeId, isDirected: boolean): 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(graph: Graph, nodeId: NodeId, mode: \"in\" | \"out\" | \"total\" = \"total\"): 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>(communities: Map<T, number>): 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 * @param graph - The input graph to convert\n * @returns CSR graph representation (cached for efficiency)\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 * @param graph - The input graph to traverse\n * @param startNode - The node to start the BFS from\n * @param options - Traversal options (callbacks, target node, etc.)\n * @returns Traversal result with visited nodes, order, and tree structure\n */\nexport function breadthFirstSearch(graph: Graph, startNode: NodeId, options: TraversalOptions = {}): 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 * @param graph - The input graph to traverse\n * @param startNode - The node to start the BFS from\n * @param options - Traversal options (callbacks, target node, etc.)\n * @returns Traversal result with visited nodes, order, and tree structure\n */\nfunction breadthFirstSearchStandard(graph: Graph, startNode: NodeId, options: TraversalOptions = {}): 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 !== undefined && 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 * @param graph - The input graph to traverse\n * @param startNode - The node to start the BFS from\n * @param options - Traversal options (callbacks, target node, etc.)\n * @returns Traversal result with visited nodes, order, and tree structure\n */\nfunction breadthFirstSearchOptimized(graph: Graph, startNode: NodeId, options: TraversalOptions = {}): 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 * @param graph - The input graph to search\n * @param source - The source node ID\n * @param target - The target node ID\n * @returns Shortest path result or null if no path exists\n */\nexport function shortestPathBFS(graph: Graph, source: NodeId, target: NodeId): 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 * @param graph - The input graph to search\n * @param source - The source node ID\n * @param target - The target node ID\n * @returns Shortest path result or null if no path exists\n */\nfunction shortestPathBFSStandard(graph: Graph, source: NodeId, target: NodeId): 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 * @param graph - The input graph to search\n * @param source - The source node ID\n * @param target - The target node ID\n * @returns Shortest path result or null if no path exists\n */\nfunction shortestPathBFSOptimized(graph: Graph, source: NodeId, target: NodeId): 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 * @param graph - The input graph to search\n * @param source - The source node ID to compute shortest paths from\n * @returns Map of node IDs to their shortest path results\n */\nexport function singleSourceShortestPathBFS(graph: Graph, source: NodeId): 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 * @param graph - The input graph to search\n * @param source - The source node ID to compute shortest paths from\n * @returns Map of node IDs to their shortest path results\n */\nfunction singleSourceShortestPathBFSStandard(graph: Graph, source: NodeId): 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 * @param graph - The input graph to search\n * @param source - The source node ID to compute shortest paths from\n * @returns Map of node IDs to their shortest path results\n */\nfunction singleSourceShortestPathBFSOptimized(graph: Graph, source: NodeId): 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 * @param graph - The undirected graph to check\n * @returns True if the graph is bipartite, false otherwise\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 === undefined) {\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 * @param graph - The input graph to traverse\n * @param startNode - The node to start the DFS from\n * @param options - DFS options (recursive mode, pre/post order, etc.)\n * @returns Traversal result with visited nodes, order, and tree structure\n */\nexport function depthFirstSearch(graph: Graph, startNode: NodeId, options: DFSOptions = {}): 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 * @param graph - The input graph to traverse\n * @param startNode - The node to start the DFS from\n * @param visited - Set to track visited nodes\n * @param order - Array to store traversal order\n * @param tree - Map to store parent relationships\n * @param options - DFS options (recursive mode, pre/post order, etc.)\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 !== undefined && 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 * @param graph - The input graph to traverse\n * @param node - Current node being visited\n * @param visited - Set to track visited nodes\n * @param order - Array to store traversal order\n * @param tree - Map to store parent relationships\n * @param options - DFS options (recursive mode, pre/post order, etc.)\n * @param depth - Current depth in the traversal tree\n * @param parent - Parent node of the current node\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 !== undefined && 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 * @param graph - The input graph to check for cycles\n * @returns True if the graph contains a cycle, false otherwise\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 * @param graph - The directed graph to check\n * @param node - Current node being visited\n * @param visited - Set of all visited nodes\n * @param recursionStack - Set of nodes in the current recursion path\n * @returns True if a cycle is found, false otherwise\n */\nfunction hasCycleUtilDirected(graph: Graph, node: NodeId, visited: Set<NodeId>, recursionStack: Set<NodeId>): 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 * @param graph - The undirected graph to check\n * @param node - Current node being visited\n * @param visited - Set of all visited nodes\n * @param parent - Parent node of the current node\n * @returns True if a cycle is found, false otherwise\n */\nfunction hasCycleUtilUndirected(graph: Graph, node: NodeId, visited: Set<NodeId>, parent: NodeId | null): 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 * @param graph - The directed acyclic graph to sort\n * @returns Array of node IDs in topological order, or null if graph has cycles\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 * @param graph - The directed graph being sorted\n * @param node - Current node being visited\n * @param visited - Set of visited nodes\n * @param stack - Stack to store nodes in reverse topological order\n */\nfunction topologicalSortUtil(graph: Graph, node: NodeId, visited: Set<NodeId>, stack: NodeId[]): 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 * @param graph - The directed graph to analyze\n * @returns Array of strongly connected components (each is an array of node IDs)\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 * @param graph - The graph being traversed\n * @param node - Current node being visited\n * @param visited - Set of visited nodes\n * @param finishOrder - Array to store nodes in order of completion\n */\nfunction dfsFinishOrder(graph: Graph, node: NodeId, visited: Set<NodeId>, finishOrder: NodeId[]): 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 * @param graph - The graph being traversed\n * @param node - Current node being visited\n * @param visited - Set of visited nodes\n * @param component - Array to collect nodes in the current component\n */\nfunction dfsCollectComponent(graph: Graph, node: NodeId, visited: Set<NodeId>, component: NodeId[]): 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 * @param graph - The directed graph to transpose\n * @returns A new graph with all edges reversed\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 * One relaxable arc: a direction an edge can actually be traversed in.\n */\ninterface Arc {\n from: NodeId;\n to: NodeId;\n weight: number;\n}\n\n/**\n * Expand the graph's edges into the arcs Bellman-Ford may relax.\n *\n * A directed graph yields one arc per edge. An UNDIRECTED graph yields two, because\n * `graph.edges()` reports each undirected edge once, arbitrarily oriented from one of its\n * endpoints. Relaxing only that orientation makes every edge one-way and leaves most of an\n * undirected graph unreachable from the source -- the distances come back as Infinity for\n * nodes that are plainly connected.\n *\n * Note that expanding is not merely a convenience: on an undirected graph a single\n * negative-weight edge IS a negative cycle, since it can be traversed back and forth forever.\n * Producing both arcs is what lets the cycle check below report that correctly.\n * @param graph - The graph whose edges are being expanded.\n * @returns Every arc that may be relaxed, in edge order.\n */\nfunction relaxableArcs(graph: Graph): Arc[] {\n const arcs: Arc[] = [];\n for (const edge of graph.edges()) {\n const weight = edge.weight ?? 1;\n arcs.push({ from: edge.source, to: edge.target, weight });\n if (!graph.isDirected) {\n arcs.push({ from: edge.target, to: edge.source, weight });\n }\n }\n\n return arcs;\n}\n\n/**\n * Find shortest paths from source using Bellman-Ford algorithm\n * @param graph - The graph to search\n * @param source - The starting node for the search\n * @param options - Algorithm options including optional target for early termination\n * @returns The distances, predecessors, and negative cycle information\n */\nexport function bellmanFord(graph: Graph, source: NodeId, options: BellmanFordOptions = {}): 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 const arcs = relaxableArcs(graph);\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 arc of arcs) {\n const u = arc.from;\n const v = arc.to;\n const { weight } = arc;\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 !== undefined && 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 arc of arcs) {\n const u = arc.from;\n const v = arc.to;\n const { weight } = arc;\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 * @param graph - The graph to search\n * @param source - The starting node for the path\n * @param target - The destination node for the path\n * @returns The shortest path result or null if no path exists\n */\nexport function bellmanFordPath(graph: Graph, source: NodeId, target: NodeId): 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 * @param graph - The graph to check for negative cycles\n * @returns True if the graph contains a negative cycle\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 * 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 /**\n * Creates a new PriorityQueue instance.\n * @param compareFn - Custom comparison function for priorities. Returns negative if a has higher priority than b.\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 * @param item - The item to add to the queue\n * @param priority - The priority value for the item (lower values have higher priority in min-heap)\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 * @returns The item with the highest priority, or undefined if the queue is empty\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 * @returns The item with the highest priority, or undefined if the queue is empty\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 * @returns True if the queue has no items, false otherwise\n */\n isEmpty(): boolean {\n return this.heap.length === 0;\n }\n\n /**\n * Get the number of items in the queue\n * @returns The number of items currently 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 * @param item - The item whose priority should be updated\n * @param newPriority - The new priority value for the item\n * @returns True if the item was found and updated, false otherwise\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 * @returns An array of all items with their priorities\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 * @param index - The index of the element to heapify up\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 * @param index - The index of the element to heapify down\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 (\n leftChildIndex < this.heap.length &&\n leftChild &&\n target &&\n this.compareFn(leftChild.priority, target.priority) < 0\n ) {\n targetIndex = leftChildIndex;\n }\n\n const rightChild = this.heap[rightChildIndex];\n const newTarget = this.heap[targetIndex];\n\n if (\n rightChildIndex < this.heap.length &&\n rightChild &&\n newTarget &&\n this.compareFn(rightChild.priority, newTarget.priority) < 0\n ) {\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 * @param i - Index of the first element\n * @param j - Index of the second element\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 /**\n * Creates a new BidirectionalDijkstra instance\n * @param graph - The graph to search for shortest paths\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 * @param source - The starting node for the path\n * @param target - The destination node for the path\n * @returns The shortest path result or null if no path exists\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() || !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 (\n !this.forwardSearch.frontier.isEmpty() &&\n (this.backwardSearch.frontier.isEmpty() ||\n this.forwardSearch.frontier.size() <= this.backwardSearch.frontier.size())\n ) {\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() && 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(search: SearchState, oppositeSearch: SearchState, isForward: boolean): 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 ? this.graph.getEdge(current, neighbor) : 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) || 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 === null) {\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 * @param graph - The graph to search\n * @param source - The starting node for the search\n * @param options - Algorithm options including optional target for early termination\n * @returns A map of node IDs to their shortest path results\n */\nexport function dijkstra(graph: Graph, source: NodeId, options: DijkstraOptions = {}): 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 !== undefined && 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 * @param graph - The graph to search\n * @param source - The starting node for the path\n * @param target - The destination node for the path\n * @param options - Algorithm options including bidirectional search toggle\n * @returns The shortest path result or null if no path exists\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 * @param graph - The graph to search\n * @param source - The starting node for the search\n * @param cutoff - Optional maximum distance to search\n * @returns A map of node IDs to their distances from the source\n */\nexport function singleSourceShortestPath(graph: Graph, source: NodeId, cutoff?: number): 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 * @param graph - The graph to compute all-pairs shortest paths for\n * @returns A nested map of source to target to distance\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","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\n/**\n * Computes all-pairs shortest paths using the Floyd-Warshall algorithm\n * @param graph - The graph to compute shortest paths for\n * @returns The distances, predecessors, and negative cycle detection result\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\n/**\n * Finds the shortest path between two nodes using Floyd-Warshall\n * @param graph - The graph to search\n * @param source - The starting node for the path\n * @param target - The destination node for the path\n * @returns The path and distance or null if no path exists\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\n/**\n * Computes the transitive closure of a graph using Floyd-Warshall\n * @param graph - The graph to compute transitive closure for\n * @returns A map of each node to the set of nodes reachable from it\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 * @param graph - The input graph to traverse\n * @param source - The source node to start BFS from\n * @param options - Configuration options\n * @param options.optimized - Whether to use CSR-optimized implementation for large graphs\n * @returns Object containing distances, predecessors, path counts (sigma), and traversal stack\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 * @param graph - The input graph to traverse\n * @param source - The source node to start BFS from\n * @param cutoff - Maximum distance to explore (optional)\n * @param options - Configuration options\n * @param options.optimized - Whether to use CSR-optimized implementation for large graphs\n * @returns Map of node IDs to their shortest distances from the source\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 * @param graph - The input graph to check for bipartiteness\n * @returns Object with bipartite status and optional partition sets\n */\nexport function bfsColoringWithPartitions(graph: Graph): {\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 * @param residualGraph - Map representing the residual graph with capacities\n * @param source - The source node ID\n * @param sink - The sink node ID\n * @returns Object with path and capacity, or null if no path exists\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 * @param graph - The input weighted graph to traverse\n * @param source - The source node to start BFS from\n * @param cutoff - Maximum distance to explore (optional)\n * @param options - Configuration options\n * @param options.optimized - Whether to use CSR-optimized implementation for large graphs\n * @returns Map of node IDs to their shortest weighted distances from the source\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 * @param graph - The CSR graph representation\n * @param source - The source node to start BFS from\n * @returns Object containing distances, predecessors, path counts (sigma), and traversal stack\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 * @param graph - The CSR graph representation\n * @param source - The source node to start BFS from\n * @param cutoff - Maximum distance to explore (optional)\n * @returns Map of node IDs to their shortest distances from the source\n */\nfunction bfsDistancesOnlyCSR(graph: CSRGraph, source: NodeId, cutoff?: number): 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 * @param graph - The CSR graph representation\n * @param source - The source node to start BFS from\n * @param cutoff - Maximum distance to explore (optional)\n * @returns Map of node IDs to their shortest weighted distances from the source\n */\nfunction bfsWeightedDistancesCSR(graph: CSRGraph, source: NodeId, cutoff?: number): 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 *\n * Every member is `readonly` and carries `| undefined`: the GPU package compiles this declaration\n * a second time under `exactOptionalPropertyTypes`, where `sources?: readonly number[]` and\n * `sources?: readonly number[] | undefined` are different types (plan decision PD-6).\n */\nexport interface BetweennessCentralityOptions {\n /** Whether to normalize the centrality values (default: false) */\n readonly normalized?: boolean | undefined;\n /** Whether to use endpoints in path counting (default: false) */\n readonly endpoints?: boolean | undefined;\n /** Whether to use optimized BFS implementation for large graphs */\n readonly optimized?: boolean | undefined;\n /**\n * Sampled betweenness: the source NODE INDICES to run from. Indices are meaningful only against\n * a `GraphSnapshot`, so the legacy `Graph`-taking entry points below THROW when this is set.\n */\n readonly sources?: readonly number[] | undefined;\n /** Sampled betweenness: how many sources to draw when `sources` is not given. */\n readonly k?: number | undefined;\n}\n\n/**\n * Refuse the index-space options on a path that has no index space.\n *\n * Ignoring them would be the expensive silence: a caller asking for a 128-source sample would get\n * an exact all-sources run, correct and a thousand times too slow, with no signal at all.\n * @param options - The caller's options\n * @param fn - The entry point's name, for the message\n */\nfunction rejectIndexOptions(options: BetweennessCentralityOptions, fn: string): void {\n if (options.sources !== undefined || options.k !== undefined) {\n throw new Error(\n `${fn}: 'sources' and 'k' are node INDICES and are meaningful only against a GraphSnapshot; ` +\n \"call accelerated(accelerator).betweennessCentrality(snapshot, options) instead\",\n );\n }\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 * @param graph - The input graph to analyze\n * @param source - The source node for shortest path computation\n * @param optimized - Whether to use optimized BFS implementation\n * @returns The BFS result containing stack, predecessors, sigma, and distances\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 * @param result - The BFS result from brandesSingleSource\n * @param source - The source node used in BFS\n * @param centrality - The centrality map to update\n * @param options - Algorithm configuration options\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 === undefined) {\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 * @param result - The BFS result from brandesSingleSource\n * @param source - The source node used in BFS\n * @param edgeCentrality - The edge centrality map to update\n * @param options - Algorithm configuration options\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 === undefined) {\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 * @param centrality - The centrality map to normalize in place\n * @param nodeCount - Total number of nodes in the graph\n * @param isDirected - Whether the graph is directed\n */\nfunction normalizeCentrality(centrality: Record<string, number>, nodeCount: number, isDirected: boolean): void {\n const n = nodeCount;\n const normalizationFactor = isDirected ? (n - 1) * (n - 2) : ((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 * @param graph - The input graph to analyze\n * @param options - Algorithm configuration options\n * @returns Centrality scores for each node keyed by node ID\n */\nexport function betweennessCentrality(\n graph: Graph,\n options: BetweennessCentralityOptions = {},\n): Record<string, number> {\n rejectIndexOptions(options, \"betweennessCentrality\");\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 * @param graph - The input graph to analyze\n * @param targetNode - The node to calculate centrality for\n * @param options - Algorithm configuration options\n * @returns The betweenness centrality score for the target node\n */\nexport function nodeBetweennessCentrality(\n graph: Graph,\n targetNode: NodeId,\n options: BetweennessCentralityOptions = {},\n): number {\n rejectIndexOptions(options, \"nodeBetweennessCentrality\");\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 * @param graph - The input graph to analyze\n * @param options - Algorithm configuration options\n * @returns Edge centrality scores keyed by edge string representation\n */\nexport function edgeBetweennessCentrality(\n graph: Graph,\n options: BetweennessCentralityOptions = {},\n): Map<string, number> {\n rejectIndexOptions(options, \"edgeBetweennessCentrality\");\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 - 1) * (n - 2) : ((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 * @param distances - Map of node IDs to their distances from source\n * @param sourceNode - The source node for distance calculations\n * @param totalNodes - Total number of nodes in the graph\n * @param options - Algorithm configuration options\n * @returns The closeness centrality score for the source node\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 * @param graph - The input graph\n * @param options - Algorithm options\n * @returns Centrality scores for each node\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(graph: Graph, options: ClosenessCentralityOptions = {}): 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 * @param graph - The input graph to analyze\n * @param node - The node to calculate centrality for\n * @param options - Algorithm configuration options\n * @returns The closeness centrality score for the node\n */\nexport function nodeClosenessCentrality(graph: Graph, node: NodeId, options: ClosenessCentralityOptions = {}): 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(\n graph,\n node,\n options.cutoff,\n options.optimized !== undefined ? { optimized: options.optimized } : {},\n );\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 * @param graph - The input graph to analyze\n * @param options - Algorithm configuration options\n * @returns Centrality scores for each node keyed by node ID\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 * @param graph - The input graph to analyze\n * @param node - The node to calculate centrality for\n * @param options - Algorithm configuration options\n * @returns The weighted closeness centrality score for the node\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(\n graph,\n node,\n options.cutoff,\n options.optimized !== undefined ? { optimized: options.optimized } : {},\n );\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 * @param graph - The input graph to analyze\n * @param options - Algorithm configuration options\n * @returns Centrality scores for each node keyed by node ID\n */\nexport function degreeCentrality(graph: Graph, options: CentralityOptions = {}): 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 ? degree / maxPossibleDegree : 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 * @param graph - The input graph to analyze\n * @param nodeId - The node to calculate centrality for\n * @param options - Algorithm configuration options\n * @returns The degree centrality score for the node\n */\nexport function nodeDegreeCentrality(graph: Graph, nodeId: string | number, options: CentralityOptions = {}): 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 ? degree / maxPossibleDegree : 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\n/**\n * Delta-based PageRank class that tracks changes between iterations\n * and only processes nodes with significant changes for improved performance.\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 /**\n * Creates a new DeltaPageRank instance for the given graph.\n * @param graph - The directed graph to compute PageRank on\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 /**\n * Computes PageRank scores using delta-based iteration for faster convergence.\n * @param options - Configuration options for PageRank computation\n * @returns Map of node IDs to their PageRank scores\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 * @param modifiedNodes - Set of nodes that were modified (edges added/removed)\n * @param options - Configuration options for PageRank computation\n * @returns Updated PageRank scores\n */\n public update(modifiedNodes: Set<NodeId>, options: DeltaPageRankOptions = {}): 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 /**\n * Creates a new PriorityDeltaPageRank instance for the given graph.\n * @param graph - The directed graph to compute PageRank on\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 /**\n * Computes PageRank scores using priority queue-based delta iteration.\n * Processes nodes in order of their delta magnitude for optimal convergence.\n * @param options - Configuration options for PageRank computation\n * @returns Map of node IDs to their PageRank scores\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 { ConvergenceError } from \"../../errors.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 + E)\n */\n\nexport interface EigenvectorCentralityOptions extends CentralityOptions {\n maxIterations?: number; // Maximum iterations (default: 100)\n tolerance?: number; // Convergence tolerance per node (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 *\n * Iterates x <- (A + I) x, as networkx does. Shifting by the identity raises every eigenvalue by\n * one and leaves the eigenvectors alone, so the largest eigenvalue becomes the only one of largest\n * magnitude -- even on a bipartite graph, whose spectrum holds both +lambda and -lambda and makes\n * unshifted power iteration oscillate forever. The run stops when the L1 change summed over all\n * nodes falls below `n * tolerance`, networkx's test.\n *\n * On a directed graph `mode` picks the edges that feed a node: `\"in\"` (the default, as networkx)\n * scores a node by the nodes pointing AT it, `\"out\"` by the nodes it points at (networkx on\n * `G.reverse()`), and `\"total\"` by both (networkx on `G.to_undirected()`). An undirected graph\n * ignores `mode`. When the graph has no cycle along that relation (no edges, or a directed\n * acyclic graph) the adjacency matrix is nilpotent, its only eigenvalue is 0, and every score is\n * exactly 0.\n * @param graph - The graph to compute eigenvector centrality on\n * @param options - Configuration options for the computation\n * @returns Object mapping node IDs to their eigenvector centrality scores\n * @throws {ConvergenceError} When `maxIterations` passes do not meet `tolerance`, as networkx\n * raises `PowerIterationFailedConvergence`. Raise `maxIterations` or `tolerance` and call again.\n */\nexport function eigenvectorCentrality(graph: Graph, options: EigenvectorCentralityOptions = {}): CentralityResult {\n const { maxIterations = 100, tolerance = 1e-6, normalized = true, startVector, mode = \"in\" } = options;\n\n const nodeIds = Array.from(graph.nodes(), (node) => node.id);\n const keys = nodeIds.map((id) => id.toString());\n const n = keys.length;\n const centrality: CentralityResult = {};\n\n if (n === 0) {\n return centrality;\n }\n\n const index = new Map(keys.map((key, i) => [key, i]));\n const feeders = (id: (typeof nodeIds)[number]): Iterable<(typeof nodeIds)[number]> => {\n if (!graph.isDirected || mode === \"out\") {\n return graph.neighbors(id);\n }\n return mode === \"in\" ? graph.inNeighbors(id) : new Set([...graph.inNeighbors(id), ...graph.neighbors(id)]);\n };\n const adjacency = nodeIds.map((id) => Array.from(feeders(id), (m) => index.get(m.toString()) ?? 0));\n\n if (isNilpotent(adjacency)) {\n for (const key of keys) {\n centrality[key] = 0;\n }\n return centrality;\n }\n\n // A node with nothing feeding it scores exactly 0 once the largest eigenvalue is positive,\n // so it starts there and (A + I) keeps it there.\n let x = new Float64Array(n);\n for (let i = 0; i < n; i++) {\n x[i] = adjacency[i]?.length ? (startVector?.get(keys[i] ?? \"\") ?? 1) : 0;\n }\n scaleToUnitLength(x);\n\n let next = new Float64Array(n);\n let converged = false;\n for (let iteration = 0; iteration < maxIterations && !converged; iteration++) {\n for (let i = 0; i < n; i++) {\n let sum = x[i] ?? 0;\n for (const j of adjacency[i] ?? []) {\n sum += x[j] ?? 0;\n }\n next[i] = sum;\n }\n scaleToUnitLength(next);\n\n let change = 0;\n for (let i = 0; i < n; i++) {\n change += Math.abs((next[i] ?? 0) - (x[i] ?? 0));\n }\n [x, next] = [next, x];\n converged = change < n * tolerance;\n }\n if (!converged) {\n throw new ConvergenceError(\"eigenvectorCentrality\", maxIterations, tolerance);\n }\n\n for (let i = 0; i < n; i++) {\n centrality[keys[i] ?? \"\"] = x[i] ?? 0;\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 for (const value of x) {\n maxValue = Math.max(maxValue, value);\n minValue = Math.min(minValue, value);\n }\n const range = maxValue - minValue;\n // All scores equal: 1 each, or 0 each when there is nothing to score.\n const flat = maxValue > 0 ? 1 : 0;\n for (const key of keys) {\n centrality[key] = range > 0 ? ((centrality[key] ?? 0) - minValue) / range : flat;\n }\n }\n\n return centrality;\n}\n\n/**\n * Whether the relation has no cycle (Kahn's algorithm), which makes its adjacency matrix nilpotent.\n * @param adjacency - Each node's neighbour indices\n * @returns True when every node can be peeled off in topological order\n */\nfunction isNilpotent(adjacency: number[][]): boolean {\n const inDegree = new Int32Array(adjacency.length);\n for (const targets of adjacency) {\n for (const j of targets) {\n inDegree[j] = (inDegree[j] ?? 0) + 1;\n }\n }\n const queue: number[] = [];\n inDegree.forEach((degree, i) => {\n if (degree === 0) {\n queue.push(i);\n }\n });\n for (let head = 0; head < queue.length; head++) {\n for (const j of adjacency[queue[head] ?? 0] ?? []) {\n inDegree[j] = (inDegree[j] ?? 0) - 1;\n if (inDegree[j] === 0) {\n queue.push(j);\n }\n }\n }\n return queue.length === adjacency.length;\n}\n\n/**\n * Scale a vector in place to unit Euclidean length (a zero vector is left alone).\n * @param v - The vector to scale\n */\nfunction scaleToUnitLength(v: Float64Array): void {\n let norm = 0;\n for (const value of v) {\n norm += value * value;\n }\n norm = Math.sqrt(norm);\n if (norm > 0) {\n for (let i = 0; i < v.length; i++) {\n v[i] = (v[i] ?? 0) / norm;\n }\n }\n}\n\n/**\n * Calculate eigenvector centrality for a specific node.\n * @param graph - The graph to compute eigenvector centrality on\n * @param nodeId - The ID of the node to calculate centrality for\n * @param options - Configuration options for the computation\n * @returns The eigenvector centrality score for the specified 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 * @param graph - The graph to compute HITS scores on\n * @param options - Configuration options for the computation\n * @returns Object containing hub and authority scores for all nodes\n */\nexport function hits(graph: Graph, options: HITSOptions = {}): HITSResult {\n const { maxIterations = 100, tolerance = 1e-6, normalized = true } = 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 * @param graph - The graph to compute HITS scores on\n * @param nodeId - The ID of the node to calculate scores for\n * @param options - Configuration options for the computation\n * @returns Object containing hub and authority scores for the specified 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 * @param graph - The graph to compute Katz centrality on\n * @param options - Configuration options for the computation\n * @returns Object mapping node IDs to their Katz centrality scores\n */\nexport function katzCentrality(graph: Graph, options: KatzCentralityOptions = {}): CentralityResult {\n const { alpha = 0.1, beta = 1.0, maxIterations = 100, tolerance = 1e-6, normalized = true } = 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 ? Array.from(graph.inNeighbors(nodeId)) : 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 * @param graph - The graph to compute Katz centrality on\n * @param nodeId - The ID of the node to calculate centrality for\n * @param options - Configuration options for the computation\n * @returns The Katz centrality score for the specified node\n */\nexport function nodeKatzCentrality(graph: Graph, nodeId: string | number, options: KatzCentralityOptions = {}): 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. compute() runs the same power iteration as the standard\n * algorithm; update() restarts it from the previous scores after a graph change.\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 /** Iterations the last compute() or update() actually ran. */\n public iterations = 0;\n\n /** Whether the last compute() or update() met its tolerance before maxIterations. */\n public converged = false;\n\n /**\n * Creates a new SimpleDeltaPageRank instance for the given graph.\n * @param graph - The directed graph to compute PageRank on\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 /**\n * Computes PageRank scores for all nodes in the graph using power iteration.\n * @param options - Configuration options for PageRank computation\n * @param options.dampingFactor - Probability of following a link (default: 0.85)\n * @param options.tolerance - Convergence tolerance threshold (default: 1e-6)\n * @param options.maxIterations - Maximum number of iterations (default: 100)\n * @param options.initialRanks - Starting scores (missing nodes start at 1/n; normalized to sum 1)\n * @param options.personalization - Personalization vector for Personalized PageRank\n * @param options.weight - Edge attribute name for weighted PageRank\n * @returns Map of node IDs to their PageRank scores; `iterations` and `converged` describe the run\n */\n public compute(\n options: {\n dampingFactor?: number;\n tolerance?: number;\n maxIterations?: number;\n initialRanks?: Map<NodeId, number>;\n personalization?: Map<NodeId, number>;\n weight?: string;\n } = {},\n ): Map<NodeId, number> {\n const {\n dampingFactor = 0.85,\n tolerance = 1e-6,\n maxIterations = 100,\n initialRanks,\n personalization,\n weight,\n } = options;\n\n this.iterations = 0;\n this.converged = false;\n\n if (this.nodeCount === 0) {\n this.converged = true;\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, initialRanks?.get(node.id) ?? 1.0 / this.nodeCount);\n }\n\n this.normalizeMap(scores);\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 totalWeight += weight ? (this.graph.getEdge(node.id, neighbor)?.weight ?? 1) : 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. Every node propagates every iteration: skipping a node whose score has\n // settled drops its whole contribution from its neighbours, which leaks rank and stops the\n // run from ever converging.\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 every node\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\n let maxDiff = 0;\n\n for (const nodeId of scores.keys()) {\n maxDiff = Math.max(maxDiff, Math.abs((newScores.get(nodeId) ?? 0) - (scores.get(nodeId) ?? 0)));\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 if (maxDiff < tolerance) {\n this.converged = true;\n break;\n }\n }\n\n this.iterations = this.converged ? iteration + 1 : iteration;\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 * @param modifiedNodes - Set of nodes that were modified (edges added/removed)\n * @param options - Computation options\n * @param options.dampingFactor - Probability of following a link (default: 0.85)\n * @param options.tolerance - Convergence tolerance threshold (default: 1e-6)\n * @param options.maxIterations - Maximum number of iterations (default: 100)\n * @param options.personalization - Personalization vector for Personalized PageRank\n * @param options.weight - Edge attribute name for weighted PageRank\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 { dampingFactor = 0.85, tolerance = 1e-6, maxIterations = 100, personalization, weight } = options;\n\n this.iterations = 0;\n this.converged = false;\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 totalWeight += weight ? (this.graph.getEdge(node.id, neighbor)?.weight ?? 1) : 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 this.converged = true;\n break;\n }\n }\n\n this.iterations = this.converged ? iteration + 1 : iteration;\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 * @param graph - The directed input graph to analyze\n * @param options - Algorithm configuration options\n * @returns PageRank result containing ranks, iteration count, and convergence status\n */\nexport function pageRank(graph: Graph, options: PageRankOptions = {}): 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 initialRanks?: Map<NodeId, number>;\n personalization?: Map<NodeId, number>;\n weight?: string;\n } = {\n dampingFactor,\n tolerance,\n maxIterations,\n };\n\n if (initialRanks) {\n deltaOptions.initialRanks = initialRanks;\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: deltaPageRank.iterations,\n converged: deltaPageRank.converged,\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 // The loop breaks before incrementing on convergence, and leaves at maxIterations otherwise.\n iterations: converged ? iteration + 1 : iteration,\n converged,\n };\n}\n\n/**\n * Calculate Personalized PageRank for a specific set of source nodes\n * @param graph - The directed input graph to analyze\n * @param personalNodes - Nodes to personalize the PageRank towards\n * @param options - Algorithm configuration options\n * @returns PageRank result containing ranks, iteration count, and convergence status\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 * @param graph - The directed input graph to analyze\n * @param options - Algorithm configuration options\n * @returns PageRank scores for each node keyed by node ID\n */\nexport function pageRankCentrality(graph: Graph, options: PageRankOptions = {}): 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 * @param graph - The directed input graph to analyze\n * @param k - Number of top nodes to return\n * @param options - Algorithm configuration options\n * @returns Array of top-k nodes with their PageRank scores, sorted descending\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 * @param ranks - The ranks map to normalize in place\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 /**\n * Creates a new UnionFind data structure with the given elements.\n * @param elements - Array of elements to initialize the data structure with\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 * @param element - The element to find the root for\n * @returns The root element of the set containing the given element\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 * @param elementA - The first element whose set should be merged\n * @param elementB - The second element whose set should be merged\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 * @param elementA - The first element to check\n * @param elementB - The second element to check\n * @returns True if both elements are in the same component, false otherwise\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 * @returns The current count of disjoint 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 * @param element - The element whose component should be retrieved\n * @returns Array of all elements in the same component\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 * @returns Array of arrays, where each inner array contains elements of one component\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 * @param element - The element whose component size should be retrieved\n * @returns The number of elements in 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 * @param element - The element to add as a new singleton set\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 * @param element - The element to check for\n * @returns True if the element exists, false otherwise\n */\n hasElement(element: NodeId): boolean {\n return this.parent.has(element);\n }\n\n /**\n * Get the total number of elements\n * @returns The total count of all elements in the data structure\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 * @param graph - The input graph (must be undirected)\n * @returns Array of connected components, each containing an array of node IDs\n */\nexport function connectedComponents(graph: Graph): NodeId[][] {\n if (graph.isDirected) {\n throw new Error(\n \"Connected components algorithm requires an undirected graph. Use stronglyConnectedComponents for directed graphs.\",\n );\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 * @param graph - The input graph (must be undirected)\n * @returns Array of connected components, each containing an array of node IDs\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 * @param graph - The input graph\n * @param nodeId - The starting node ID\n * @param visited - Set of already visited node IDs\n * @param component - Array to accumulate component members\n */\nfunction dfsComponent(graph: Graph, nodeId: NodeId, visited: Set<NodeId>, component: NodeId[]): 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 * @param graph - The input graph (must be undirected)\n * @returns The number of connected components in the graph\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 * @param graph - The input graph (must be undirected)\n * @returns True if the graph is connected, false otherwise\n */\nexport function isConnected(graph: Graph): boolean {\n return numberOfConnectedComponents(graph) <= 1;\n}\n\n/**\n * Find the largest connected component\n * @param graph - The input graph (must be undirected)\n * @returns Array of node IDs in 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) => (current.length > largest.length ? current : largest));\n}\n\n/**\n * Get the connected component containing a specific node\n * @param graph - The input graph (must be undirected)\n * @param nodeId - The node ID to find the component for\n * @returns Array of node IDs in the same component as the specified 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 * @param graph - The input graph (must be directed)\n * @returns Array of strongly connected components, each containing an array of node IDs\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 * @param graph - The input graph (must be directed)\n * @returns True if the graph is strongly connected, false otherwise\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 * @param graph - The input graph (must be directed)\n * @returns Array of weakly connected components, each containing an array of node IDs\n */\nexport function weaklyConnectedComponents(graph: Graph): NodeId[][] {\n if (!graph.isDirected) {\n throw new Error(\n \"Weakly connected components are for directed graphs. Use connectedComponents for undirected graphs.\",\n );\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 * @param graph - The input graph (must be directed)\n * @returns True if the graph is weakly connected, false otherwise\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 * @param graph - The input graph (must be directed)\n * @returns Object containing the condensed graph, component map, and component arrays\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 && 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\n/**\n * Computes the minimum spanning tree of an undirected graph using Kruskal's algorithm.\n * The algorithm sorts edges by weight and greedily adds edges that don't create cycles,\n * using a union-find data structure to efficiently detect cycles.\n * @param graph - The undirected graph to compute the MST for\n * @returns The minimum spanning tree as a set of edges and the total weight\n * @throws Error if the graph is directed or not connected\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 =\n 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\n/**\n * Alias for kruskalMST. Computes the minimum spanning tree of an undirected graph.\n * @param graph - The undirected graph to compute the MST for\n * @returns The minimum spanning tree as a set of edges and the total weight\n * @throws Error if the graph is directed or not connected\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\n/**\n * Computes the minimum spanning tree of an undirected graph using Prim's algorithm.\n * The algorithm grows the MST from a starting node by repeatedly adding the minimum\n * weight edge that connects a node in the tree to a node outside the tree.\n * @param graph - The undirected graph to compute the MST for\n * @param startNode - Optional starting node; if not provided, uses the first node in the graph\n * @returns The minimum spanning tree as a set of edges and the total weight\n * @throws Error if the graph is directed, the start node is not found, or the graph is not connected\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 === undefined) {\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 * @param graph - The input graph\n * @param options - Algorithm options\n * @returns Array of community detection results representing the dendrogram\n */\nexport function girvanNewman(graph: Graph, options: GirvanNewmanOptions = {}): 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 { betweenness: edgeBetweenness, edgeEndpoints } = 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 // Use original edge endpoints to preserve node ID types (number vs string)\n const endpoints = edgeEndpoints.get(edgeKey);\n if (endpoints) {\n edgesToRemove.push(endpoints);\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((community) => community.length >= minCommunitySize);\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 * Edge betweenness result containing centrality values and original edge endpoints\n */\ninterface EdgeBetweennessResult {\n betweenness: Map<string, number>;\n edgeEndpoints: Map<string, { source: NodeId; target: NodeId }>;\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 * @param graph - The input graph to analyze\n * @returns Object with betweenness map and edge endpoints map (preserving original ID types)\n */\nfunction calculateEdgeBetweenness(graph: Graph): EdgeBetweennessResult {\n const edgeBetweenness = new Map<string, number>();\n const edgeEndpoints = new Map<string, { source: NodeId; target: NodeId }>();\n\n // Initialize all edges with 0 betweenness and store original endpoints\n for (const edge of graph.edges()) {\n const edgeKey = getEdgeKey(edge.source, edge.target);\n edgeBetweenness.set(edgeKey, 0);\n edgeEndpoints.set(edgeKey, { source: edge.source, target: edge.target });\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 { betweenness: edgeBetweenness, edgeEndpoints };\n}\n\n/**\n * Find all shortest paths from a source node using optimized BFS\n * @param graph - The input graph to search\n * @param source - The source node to compute shortest paths from\n * @returns Object containing distances, predecessors, and path counts\n */\nfunction findAllShortestPaths(\n graph: Graph,\n source: NodeId,\n): {\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 === undefined) {\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 * @param source - The source node ID\n * @param target - The target node ID\n * @returns A consistent string key for the edge (ordered alphabetically)\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\n *\n * Newman's Q, written per community:\n *\n * Q = sum over communities c of [ w_in(c) / m - ( K_c / (2m) )^2 ]\n *\n * where m is the total edge weight with each undirected edge counted once, w_in(c) is the summed\n * weight of the edges with both endpoints inside c, and K_c is the summed weighted degree of c's\n * nodes.\n *\n * WHY NOT A SUM OVER EDGES. The textbook double sum runs over every ordered PAIR of nodes inside\n * a community, not only over the pairs an edge happens to join. Collecting the null-model term\n * only where an edge exists leaves the penalty far too small, and the shortfall grows with\n * community size -- so the uncut whole graph, whose modularity is 0 by definition, outscores\n * every real cut and a caller reading the dendrogram the standard way is handed one community\n * containing everything. The per-community form above counts every pair exactly once and still\n * costs one pass over the edges rather than a pass over every pair.\n * @param graph - The original graph\n * @param communityMap - Map from node IDs to community indices\n * @returns The modularity score of the partition\n */\nfunction calculateModularity(graph: Graph, communityMap: Map<NodeId, number>): number {\n const totalEdgeWeight = getTotalEdgeWeight(graph);\n if (totalEdgeWeight === 0) {\n return 0;\n }\n\n // Summed weighted degree of each community's nodes.\n const degreeSum = new Map<number, number>();\n for (const node of graph.nodes()) {\n const community = communityMap.get(node.id);\n if (community === undefined) {\n continue;\n }\n\n degreeSum.set(community, (degreeSum.get(community) ?? 0) + getNodeDegree(graph, node.id));\n }\n\n // Summed weight of the edges that stay inside a community.\n const internalWeight = new Map<number, number>();\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 === undefined || communityI !== communityJ) {\n continue;\n }\n\n internalWeight.set(communityI, (internalWeight.get(communityI) ?? 0) + (edge.weight ?? 1));\n }\n\n let modularity = 0;\n for (const [community, degrees] of degreeSum) {\n const share = degrees / (2 * totalEdgeWeight);\n modularity += (internalWeight.get(community) ?? 0) / totalEdgeWeight - share * share;\n }\n\n return modularity;\n}\n\n/**\n * Calculate total edge weight in the graph\n * @param graph - The input graph\n * @returns Total sum of all edge weights\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 * @param graph - The input graph\n * @param nodeId - The node ID to compute degree for\n * @returns The weighted degree of the 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 * @param graph - The input graph\n * @returns Object containing components array and node-to-component map\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","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 * @param graph - The Graph instance to convert\n * @returns A nested Map where outer keys are source nodes and inner maps contain target nodes with edge weights\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 * @param map - The nested Map representation of the graph\n * @param isDirected - Whether the resulting graph should be directed (defaults to true)\n * @returns A new Graph instance with nodes and edges from the map\n */\nexport function mapToGraph(map: Map<string, Map<string, number>>, isDirected = true): 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 /**\n * Creates a new GraphAdapter instance wrapping a Map representation.\n * @param map - The nested Map representation of the graph\n * @param isDirected - Whether the graph should be treated as directed (defaults to true)\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 * @returns Array of node objects with their ids\n */\n nodes(): { id: NodeId }[] {\n return Array.from(this.map.keys()).map((id) => ({ id }));\n }\n\n /**\n * Get node count\n * @returns The total number of nodes in the graph\n */\n get nodeCount(): number {\n return this.map.size;\n }\n\n /**\n * Check if node exists\n * @param nodeId - The id of the node to check\n * @returns True if the node exists, false otherwise\n */\n hasNode(nodeId: NodeId): boolean {\n return this.map.has(String(nodeId));\n }\n\n /**\n * Get neighbors of a node\n * @param nodeId - The id of the node to get neighbors for\n * @returns Array of neighbor node ids\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 * @param source - The source node id\n * @param target - The target node id\n * @returns The edge object with source, target and weight, or null if no edge exists\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 * @param source - The source node id\n * @param target - The target node id\n * @returns True if an edge exists between source and target, false otherwise\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 * @returns Array of edge objects with source, target and optional weight\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 * @returns The total number of edges in the graph\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 * @param nodeId - The id of the node to get degree for\n * @returns The number of edges connected to the node\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 * @param nodeId - The id of the node to get in-degree for\n * @returns The number of incoming edges to the node\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 * @param nodeId - The id of the node to get out-degree for\n * @returns The number of outgoing edges from the node\n */\n outDegree(nodeId: NodeId): number {\n return this.degree(nodeId);\n }\n\n /**\n * Get underlying map representation\n * @returns The internal Map representation of the graph\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 /**\n * Creates a new SeededRandom instance with the given seed.\n * @param seed - The seed value for reproducible random number generation\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 * @returns A pseudo-random number in the range [0, 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 * @param seed - The seed value for reproducible random number generation\n * @returns A function that returns the next random number when called\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 * @param values - Map of values to normalize in place\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 * @param values - Map of values to normalize in place\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 * @param values - Map of values to normalize in place\n */\n l2Norm(values: Map<string, number>): void {\n const sumSquares = Array.from(values.values()).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 * @param values - Map of values to normalize in place\n */\n sumToOne(values: Map<string, number>): void {\n const sum = Array.from(values.values()).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 * @param graph - Map representation of the graph (node to neighbors with weights)\n * @param options - Algorithm configuration options\n * @returns Community assignments, iteration count, and convergence status\n */\nfunction labelPropagationImpl(\n graph: Map<string, Map<string, number>>,\n options: LabelPropagationOptions = {},\n): LabelPropagationResult {\n const { maxIterations = 100, randomSeed = 42 } = 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 * @param graph - Map representation of the graph (node to neighbors with weights)\n * @param options - Algorithm configuration options\n * @returns Community assignments, iteration count, and convergence status\n */\nfunction labelPropagationAsyncImpl(\n graph: Map<string, Map<string, number>>,\n options: LabelPropagationOptions = {},\n): LabelPropagationResult {\n const { maxIterations = 100 } = 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 * @param graph - Map representation of the graph (node to neighbors with weights)\n * @param seedLabels - Map of node IDs to their fixed community labels\n * @param options - Algorithm configuration options\n * @returns Community assignments, iteration count, and convergence status\n */\nfunction labelPropagationSemiSupervisedImpl(\n graph: Map<string, Map<string, number>>,\n seedLabels: Map<string, number>,\n options: LabelPropagationOptions = {},\n): LabelPropagationResult {\n const { maxIterations = 100, randomSeed = 42 } = 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 * @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(graph: Graph, options: LabelPropagationOptions = {}): 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 * @param graph - Undirected graph (can be weighted)\n * @param options - Algorithm options\n * @returns Community assignments\n */\nexport function labelPropagationAsync(graph: Graph, options: LabelPropagationOptions = {}): 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 * @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 * 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/** How many local-moving sweeps one level may take before it is declared settled. */\nconst LOCAL_MOVE_PASSES = 50;\n\n/**\n * Internal implementation of Leiden algorithm for community detection\n * Improves upon Louvain by ensuring well-connected communities\n * @param inputGraph - Map representation of the graph (node to neighbors with weights)\n * @param options - Algorithm configuration options\n * @returns Community assignments, modularity score, and iteration count\n */\nfunction leidenImpl(inputGraph: Map<string, Map<string, number>>, options: LeidenOptions = {}): LeidenResult {\n const { resolution = 1.0, randomSeed = 42, maxIterations = 100, threshold = 1e-7 } = 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 const random = SeededRandom.createGenerator(randomSeed);\n const base = weighLevel(inputGraph);\n\n // Which node of the CURRENT level holds each original node. Every partition is scored against\n // the original graph through this map, so an aggregation can never leave the answer keyed by\n // the super-node names a caller has never heard of -- which is what it used to do.\n const placement = new Map<string, string>();\n for (const node of inputGraph.keys()) {\n placement.set(node, node);\n }\n\n let bestCommunities = singletonCommunities(inputGraph);\n let bestModularity = calculateModularity(inputGraph, bestCommunities, base.degrees, base.totalWeight, resolution);\n let levelGraph = inputGraph;\n let iterations = 0;\n\n // Whether this level is the ORIGINAL graph, started from the best partition so far rather than\n // from singletons. Local moving on aggregated levels can only move whole super-nodes, so a node\n // merged into the wrong community early could never leave it, and the answer could be beaten by\n // moving one node. The paper (Traag et al. 2019) iterates until a pass over the original nodes\n // changes nothing; returning to them once the levels settle is that pass.\n let polishing = false;\n\n while (iterations < maxIterations) {\n iterations++;\n\n const weights = weighLevel(levelGraph);\n const communities = polishing ? new Map(bestCommunities) : singletonCommunities(levelGraph);\n const moved = moveNodesLocally(levelGraph, weights, communities, random, resolution, LOCAL_MOVE_PASSES);\n\n // Leiden's guarantee over Louvain: a community whose members are not connected to each\n // other inside this level's graph is split into the pieces that are.\n for (const [node, piece] of refinePartition(levelGraph, communities)) {\n communities.set(node, piece);\n }\n\n const candidate = new Map<string, number>();\n for (const [original, levelNode] of placement) {\n const community = communities.get(levelNode);\n if (community !== undefined) {\n candidate.set(original, community);\n }\n }\n\n const modularity = calculateModularity(inputGraph, candidate, base.degrees, base.totalWeight, resolution);\n const improved = modularity > bestModularity + threshold;\n\n if (modularity > bestModularity) {\n bestModularity = modularity;\n bestCommunities = candidate;\n }\n\n const distinct = new Set(communities.values()).size;\n const settled = polishing ? !improved : !improved || !moved || distinct === levelGraph.size;\n\n if (settled) {\n if (polishing) {\n break;\n }\n\n // The levels have settled: go back to the original nodes, starting from the answer.\n polishing = true;\n levelGraph = inputGraph;\n for (const node of inputGraph.keys()) {\n placement.set(node, node);\n }\n\n continue;\n }\n\n polishing = false;\n\n const aggregated = aggregateLevel(levelGraph, communities);\n for (const [original, levelNode] of placement) {\n const superNode = aggregated.mapping.get(levelNode);\n if (superNode !== undefined) {\n placement.set(original, superNode);\n }\n }\n\n levelGraph = aggregated.graph;\n }\n\n // Renumber communities consecutively, in the order they are first met, so the ids a caller\n // reads are 0..k-1 whatever the levels handed out along the way.\n const renumbered = new Map<number, number>();\n const finalCommunities = new Map<string, number>();\n for (const [node, community] of bestCommunities) {\n let id = renumbered.get(community);\n if (id === undefined) {\n id = renumbered.size;\n renumbered.set(community, id);\n }\n\n finalCommunities.set(node, id);\n }\n\n return {\n communities: finalCommunities,\n modularity: bestModularity,\n iterations,\n };\n}\n\n/**\n * Calculate modularity of a partition\n * @param graph - Map representation of the graph\n * @param communities - Map of node IDs to community IDs\n * @param degrees - Map of node IDs to their weighted degrees\n * @param totalWeight - Total weight of all edges in the graph\n * @param resolution - Resolution parameter for modularity calculation\n * @returns The modularity score of the 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 * @param node - The node ID to get neighbor communities for\n * @param graph - Map representation of the graph\n * @param communities - Map of node IDs to community IDs\n * @returns Map of community IDs to total edge weight connecting to that community\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 * Refine partition (Leiden-specific improvement)\n * Ensures well-connected communities by considering subsets\n * @param originalGraph - Map representation of the original graph\n * @param communities - Map of node IDs to community IDs\n * @returns Refined community assignments with well-connected communities\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 * @param graph - Map representation of the graph (node to set of neighbors)\n * @returns Array of connected components (each is a set of node IDs)\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 * What one level of the algorithm knows about its own graph.\n *\n * RECOMPUTED PER LEVEL, which is the half that used to be missing. After the first aggregation\n * every node is a super-node, and scoring the new graph with the old graph's degrees made the\n * second level's modularity a number about a graph that no longer existed. It came out at zero,\n * the loop read that as \"no improvement\", and the algorithm stopped after one pass.\n */\ninterface LevelWeights {\n /** The weighted degree of each node at this level, self-loops included. */\n degrees: Map<string, number>;\n /** Half the summed degree: the total edge weight m, each undirected edge counted once. */\n totalWeight: number;\n}\n\n/**\n * Weigh one level's graph.\n * @param graph - The level's graph, stored with both directions of every edge.\n * @returns The degrees and the total edge weight.\n */\nfunction weighLevel(graph: Map<string, Map<string, number>>): LevelWeights {\n const degrees = new Map<string, number>();\n let summed = 0;\n\n for (const [node, neighbors] of graph) {\n let degree = 0;\n for (const weight of neighbors.values()) {\n degree += weight;\n }\n\n degrees.set(node, degree);\n summed += degree;\n }\n\n return { degrees, totalWeight: summed / 2 };\n}\n\n/**\n * One node per community, numbered from zero in the order the graph lists its nodes.\n * @param graph - The level's graph.\n * @returns The partition every level starts from.\n */\nfunction singletonCommunities(graph: Map<string, Map<string, number>>): Map<string, number> {\n const communities = new Map<string, number>();\n let next = 0;\n\n for (const node of graph.keys()) {\n communities.set(node, next++);\n }\n\n return communities;\n}\n\n/**\n * The summed degree of each community's members, which local moving keeps in step with every move.\n * @param communities - The partition.\n * @param degrees - The weighted degree of each node at this level.\n * @returns The summed degree per community.\n */\nfunction communityDegrees(communities: Map<string, number>, degrees: Map<string, number>): Map<number, number> {\n const totals = new Map<number, number>();\n\n for (const [node, community] of communities) {\n totals.set(community, (totals.get(community) ?? 0) + (degrees.get(node) ?? 0));\n }\n\n return totals;\n}\n\n/**\n * Move nodes to neighbouring communities until a whole sweep changes nothing.\n *\n * ONE SWEEP IS NOT CONVERGENCE, and treating it as such is what left this algorithm returning\n * partitions it could beat with six single-node moves. A move changes the communities its\n * neighbours are weighed against, so the node visited first is judged against a partition that no\n * longer exists by the time the sweep ends. Repeating until a sweep moves nobody is what makes\n * the answer a local optimum of the objective rather than an artefact of the visiting order.\n * @param graph - The level's graph.\n * @param weights - Its degrees and total edge weight.\n * @param communities - The partition, moved in place.\n * @param random - The seeded generator the visiting order is shuffled with.\n * @param resolution - Higher values favour smaller communities.\n * @param maxPasses - A ceiling on the sweeps, so a pathological graph cannot spin for ever.\n * @returns Whether anything moved at all.\n */\nfunction moveNodesLocally(\n graph: Map<string, Map<string, number>>,\n weights: LevelWeights,\n communities: Map<string, number>,\n random: () => number,\n resolution: number,\n maxPasses: number,\n): boolean {\n const { degrees, totalWeight } = weights;\n\n if (totalWeight === 0) {\n return false;\n }\n\n const totals = communityDegrees(communities, degrees);\n const nodes = [...graph.keys()];\n let movedEver = false;\n // A fresh id for a node that does better on its own, the empty community the paper also offers.\n let nextEmpty = 0;\n for (const community of communities.values()) {\n nextEmpty = Math.max(nextEmpty, community + 1);\n }\n\n for (let pass = 0; pass < maxPasses; pass++) {\n const order = [...nodes];\n shuffle(order, random);\n let movedThisPass = false;\n\n for (const node of order) {\n const current = communities.get(node);\n const degree = degrees.get(node);\n if (current === undefined || degree === undefined) {\n continue;\n }\n\n const neighborCommunities = getNeighborCommunities(node, graph, communities);\n const selfLoop = graph.get(node)?.get(node) ?? 0;\n const weightToCurrent = (neighborCommunities.get(current) ?? 0) - selfLoop;\n const degreeOfCurrent = (totals.get(current) ?? 0) - degree;\n\n let bestCommunity = current;\n let bestGain = 0;\n\n // Leaving for an empty community: the target has no weight and no degree.\n if (degreeOfCurrent > 0) {\n const alone =\n -weightToCurrent / totalWeight +\n (resolution * degree * degreeOfCurrent) / (2 * totalWeight * totalWeight);\n if (alone > bestGain) {\n bestGain = alone;\n bestCommunity = nextEmpty;\n }\n }\n\n for (const [community, weightToTarget] of neighborCommunities) {\n if (community === current) {\n continue;\n }\n\n // The standard modularity gain for moving one node out of its community and into\n // another: what the move adds to the edges inside a community, less what it adds\n // to what a random graph of the same degrees would have had there.\n const gain =\n (weightToTarget - weightToCurrent) / totalWeight -\n (resolution * degree * ((totals.get(community) ?? 0) - degreeOfCurrent)) /\n (2 * totalWeight * totalWeight);\n\n if (gain > bestGain) {\n bestGain = gain;\n bestCommunity = community;\n }\n }\n\n if (bestCommunity !== current) {\n if (bestCommunity === nextEmpty) {\n nextEmpty++;\n }\n\n communities.set(node, bestCommunity);\n totals.set(current, (totals.get(current) ?? 0) - degree);\n totals.set(bestCommunity, (totals.get(bestCommunity) ?? 0) + degree);\n movedThisPass = true;\n movedEver = true;\n }\n }\n\n if (!movedThisPass) {\n break;\n }\n }\n\n return movedEver;\n}\n\n/**\n * Collapse each community into one node, carrying its internal weight as a self-loop.\n *\n * THE SELF-LOOP IS THE POINT. Without it the aggregated graph forgets every edge inside a\n * community, so the next level scores a graph with no internal weight anywhere and every\n * partition of it looks equally bad. Both directions of every internal edge land in the same\n * entry, which is exactly the doubled internal weight the modularity sum wants.\n * @param graph - The level's graph.\n * @param communities - The partition to collapse.\n * @returns The next level's graph, and where each node of this one went.\n */\nfunction aggregateLevel(\n graph: Map<string, Map<string, number>>,\n communities: Map<string, number>,\n): { graph: Map<string, Map<string, number>>; mapping: Map<string, string> } {\n const aggregated = new Map<string, Map<string, number>>();\n const mapping = new Map<string, string>();\n\n for (const [node, community] of communities) {\n const superNode = `c${String(community)}`;\n mapping.set(node, superNode);\n if (!aggregated.has(superNode)) {\n aggregated.set(superNode, new Map());\n }\n }\n\n for (const [node, neighbors] of graph) {\n const source = mapping.get(node);\n const row = source === undefined ? undefined : aggregated.get(source);\n if (row === undefined) {\n continue;\n }\n\n for (const [neighbor, weight] of neighbors) {\n const target = mapping.get(neighbor);\n if (target === undefined) {\n continue;\n }\n\n row.set(target, (row.get(target) ?? 0) + weight);\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 * @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(graph: Graph, options: LeidenOptions = {}): LeidenResult {\n // Convert Graph to Map representation\n const graphMap = graphToMap(graph);\n return leidenImpl(graphMap, options);\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 * Runs the full multilevel method of Blondel et al. (local moving, then aggregating each community\n * into one node, repeated until nothing moves) over typed arrays indexed 0..n-1.\n *\n * Key optimizations:\n * - Typed-array adjacency (CSR) instead of per-edge map lookups\n * - Leaf node pruning: skip a degree-1 node already in its neighbour's community\n * - Importance ordering: Process high-impact nodes first\n * - Threshold cycling: Adaptive move thresholds, relative to each node's largest possible gain\n * - Early termination: Stop when changes become insignificant\n *\n * The graph is treated as undirected: a directed edge counts as an undirected edge of its weight.\n * A self-loop of weight w adds 2w to its node's degree, the standard convention (NetworkX too).\n */\n\ninterface OptimizedLouvainOptions {\n /**\n * Resolution parameter (default: 1.0)\n */\n resolution?: number;\n /**\n * Maximum local-moving sweeps per level (default: 100)\n */\n maxIterations?: number;\n /**\n * Convergence tolerance on a sweep's modularity gain (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 move threshold, as a fraction of a node's largest possible modularity gain (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\n/** One level of the multilevel method: an undirected weighted graph in CSR form. */\ninterface Level {\n n: number;\n /** Row offsets into `targets` / `weights`, length n + 1. Each edge appears in both rows. */\n offsets: Int32Array;\n targets: Int32Array;\n weights: Float64Array;\n /** Weight of the edges inside each node (self-loops), each edge counted once. */\n self: Float64Array;\n /** Weighted degree of each node (a self-loop counts twice). */\n degree: Float64Array;\n}\n\ninterface LocalMovingOptions {\n resolution: number;\n maxIterations: number;\n tolerance: number;\n pruneLeaves: boolean;\n importanceOrdering: boolean;\n pruningThreshold: number;\n thresholdCycling: boolean;\n}\n\n/**\n * Optimized Louvain implementation with early pruning and threshold cycling\n */\nexport class OptimizedLouvain {\n private graph: Graph;\n private pruningStats: PruningStats;\n\n /**\n * Create an optimized Louvain detector for the given graph\n * @param graph - The input graph to detect communities in\n */\n constructor(graph: Graph) {\n this.graph = graph;\n this.pruningStats = {\n leafNodesPruned: 0,\n lowDegreeNodesPruned: 0,\n stableNodesPruned: 0,\n };\n }\n\n /**\n * Run optimized Louvain algorithm\n * @param options - Algorithm configuration options\n * @returns Community detection result with communities, modularity, and iterations (levels)\n */\n public detectCommunities(options: OptimizedLouvainOptions = {}): CommunityResult {\n const settings: LocalMovingOptions = {\n resolution: options.resolution ?? 1.0,\n maxIterations: options.maxIterations ?? 100,\n tolerance: options.tolerance ?? 1e-6,\n pruneLeaves: options.pruneLeaves ?? true,\n importanceOrdering: options.importanceOrdering ?? true,\n pruningThreshold: options.pruningThreshold ?? 0.01,\n thresholdCycling: options.thresholdCycling ?? true,\n };\n\n const { level: base, ids } = this.buildLevel();\n // membership[i] = the current level's node that original node i has been folded into\n const membership = new Int32Array(base.n);\n for (let i = 0; i < base.n; i++) {\n membership[i] = i;\n }\n\n let level = base;\n let iterations = 0;\n while (level.n > 1) {\n const { community, count, moved } = this.localMoving(level, settings);\n if (!moved) {\n break;\n }\n\n iterations++;\n for (let i = 0; i < membership.length; i++) {\n membership[i] = community[membership[i]];\n }\n\n level = aggregate(level, community, count);\n }\n\n const groups: NodeId[][] = Array.from({ length: level.n }, () => []);\n for (let i = 0; i < membership.length; i++) {\n groups[membership[i]].push(ids[i]);\n }\n\n return {\n communities: groups.filter((group) => group.length > 0),\n modularity: levelModularity(level, settings.resolution),\n iterations,\n };\n }\n\n /**\n * Get pruning statistics\n * @returns Statistics about nodes pruned during optimization\n */\n public getPruningStats(): PruningStats {\n return { ...this.pruningStats };\n }\n\n /**\n * Index the graph's nodes 0..n-1 and build the level-0 CSR adjacency\n * @returns The level-0 graph and the node id at each index\n */\n private buildLevel(): { level: Level; ids: NodeId[] } {\n const ids: NodeId[] = [];\n const index = new Map<NodeId, number>();\n for (const node of this.graph.nodes()) {\n index.set(node.id, ids.length);\n ids.push(node.id);\n }\n\n const n = ids.length;\n const edges: [number, number, number][] = [];\n const counts = new Int32Array(n + 1);\n const self = new Float64Array(n);\n const degree = new Float64Array(n);\n\n for (const edge of this.graph.edges()) {\n const s = index.get(edge.source);\n const t = index.get(edge.target);\n if (s === undefined || t === undefined) {\n continue;\n }\n\n const w = edge.weight ?? 1;\n degree[s] += w;\n degree[t] += w;\n if (s === t) {\n self[s] += w;\n continue;\n }\n\n edges.push([s, t, w]);\n counts[s + 1]++;\n counts[t + 1]++;\n }\n\n return { level: buildCsr(n, counts, edges, self, degree), ids };\n }\n\n /**\n * Move each node to the neighbouring community with the best modularity gain, until no move\n * improves modularity\n * @param level - The graph at this level\n * @param options - Local moving options\n * @returns Each node's community (numbered 0..count-1), the count, and whether any node moved\n */\n private localMoving(\n level: Level,\n options: LocalMovingOptions,\n ): { community: Int32Array; count: number; moved: boolean } {\n const { n, offsets, targets, weights, degree } = level;\n const { resolution, maxIterations, tolerance, pruneLeaves } = options;\n\n const twoM = degree.reduce((sum, d) => sum + d, 0);\n const community = new Int32Array(n);\n const total = new Float64Array(n);\n for (let i = 0; i < n; i++) {\n community[i] = i;\n total[i] = degree[i];\n }\n\n if (twoM === 0) {\n return { community, count: n, moved: false };\n }\n\n const order = this.nodeOrder(level, options.importanceOrdering);\n // Scratch: weight from the current node to each community, and the communities touched\n const toCommunity = new Float64Array(n);\n const touched = new Int32Array(n);\n\n let moved = false;\n let useThreshold = options.thresholdCycling;\n for (let sweep = 0; sweep < maxIterations; sweep++) {\n // The threshold is a fraction of the most node i could gain from any move (all of its\n // weight landing inside the target, k_i), so it scales with the graph\n const threshold = useThreshold ? options.pruningThreshold * Math.pow(0.5, sweep / 10) : 0;\n let sweepMoved = false;\n let sweepGain = 0;\n\n for (const i of order) {\n const start = offsets[i];\n const end = offsets[i + 1];\n if (pruneLeaves && end - start === 1 && community[targets[start]] === community[i]) {\n // A leaf's only move is to its one neighbour's community, and it is there\n this.pruningStats.leafNodesPruned++;\n continue;\n }\n\n if (end === start) {\n continue;\n }\n\n const current = community[i];\n let touchedCount = 0;\n for (let e = start; e < end; e++) {\n const c = community[targets[e]];\n if (toCommunity[c] === 0) {\n touched[touchedCount++] = c;\n }\n\n toCommunity[c] += weights[e];\n }\n\n // Gains are in units of m * dQ: w(i, c) - resolution * tot(c) * k_i / 2m\n const k = degree[i];\n total[current] -= k;\n const stayGain = toCommunity[current] - (resolution * total[current] * k) / twoM;\n let best = current;\n let bestGain = stayGain;\n const minImprovement = threshold * k;\n\n for (let t = 0; t < touchedCount; t++) {\n const c = touched[t];\n if (c !== current) {\n const gain = toCommunity[c] - (resolution * total[c] * k) / twoM;\n if (gain > bestGain + minImprovement) {\n bestGain = gain;\n best = c;\n }\n }\n\n toCommunity[c] = 0;\n }\n\n total[best] += k;\n if (best !== current) {\n community[i] = best;\n sweepMoved = true;\n sweepGain += (bestGain - stayGain) / (twoM / 2);\n }\n }\n\n moved ||= sweepMoved;\n if (!sweepMoved || sweepGain < tolerance) {\n // A threshold can stall moves that are still worth making: finish without one\n if (useThreshold) {\n useThreshold = false;\n continue;\n }\n\n break;\n }\n }\n\n // Renumber the communities 0..count-1\n const renumber = new Int32Array(n).fill(-1);\n let count = 0;\n for (let i = 0; i < n; i++) {\n const c = community[i];\n if (renumber[c] === -1) {\n renumber[c] = count++;\n }\n\n community[i] = renumber[c];\n }\n\n return { community, count, moved };\n }\n\n /**\n * Order nodes for local moving, by importance (degree * log(1 + weighted degree)) if asked\n * @param level - The graph at this level\n * @param importanceOrdering - Whether to sort by importance\n * @returns Node indices in processing order\n */\n private nodeOrder(level: Level, importanceOrdering: boolean): Int32Array {\n const order = new Int32Array(level.n);\n for (let i = 0; i < level.n; i++) {\n order[i] = i;\n }\n\n if (!importanceOrdering) {\n return order;\n }\n\n const importance = new Float64Array(level.n);\n for (let i = 0; i < level.n; i++) {\n importance[i] = (level.offsets[i + 1] - level.offsets[i]) * Math.log(1 + level.degree[i]);\n }\n\n return order.sort((a, b) => importance[b] - importance[a]);\n }\n}\n\n/**\n * Build a CSR level from an undirected edge list (each edge listed once, no self-loops)\n * @param n - Node count\n * @param counts - counts[i + 1] = number of edges incident to node i\n * @param edges - The edges as [source, target, weight]\n * @param self - Self-loop weight of each node\n * @param degree - Weighted degree of each node\n * @returns The level\n */\nfunction buildCsr(\n n: number,\n counts: Int32Array,\n edges: [number, number, number][],\n self: Float64Array,\n degree: Float64Array,\n): Level {\n const offsets = counts;\n for (let i = 0; i < n; i++) {\n offsets[i + 1] += offsets[i];\n }\n\n const targets = new Int32Array(offsets[n]);\n const weights = new Float64Array(offsets[n]);\n const fill = offsets.slice(0, n);\n for (const [s, t, w] of edges) {\n targets[fill[s]] = t;\n weights[fill[s]++] = w;\n targets[fill[t]] = s;\n weights[fill[t]++] = w;\n }\n\n return { n, offsets, targets, weights, self, degree };\n}\n\n/**\n * Fold each community into one node: edges between communities are summed, edges inside a\n * community become its self-loop\n * @param level - The graph at this level\n * @param community - Each node's community, numbered 0..count-1\n * @param count - Number of communities\n * @returns The next level\n */\nfunction aggregate(level: Level, community: Int32Array, count: number): Level {\n const self = new Float64Array(count);\n const degree = new Float64Array(count);\n const members: number[][] = Array.from({ length: count }, () => []);\n for (let i = 0; i < level.n; i++) {\n const c = community[i];\n members[c].push(i);\n self[c] += level.self[i];\n degree[c] += level.degree[i];\n }\n\n const edges: [number, number, number][] = [];\n const counts = new Int32Array(count + 1);\n const toCommunity = new Float64Array(count);\n const touched: number[] = [];\n for (let c = 0; c < count; c++) {\n for (const i of members[c]) {\n for (let e = level.offsets[i]; e < level.offsets[i + 1]; e++) {\n const d = community[level.targets[e]];\n if (d === c) {\n // Seen once from each endpoint\n self[c] += level.weights[e] / 2;\n } else if (d > c) {\n // Keep each inter-community edge once, from its lower-numbered side\n if (toCommunity[d] === 0) {\n touched.push(d);\n }\n\n toCommunity[d] += level.weights[e];\n }\n }\n }\n\n for (const d of touched) {\n edges.push([c, d, toCommunity[d]]);\n counts[c + 1]++;\n counts[d + 1]++;\n toCommunity[d] = 0;\n }\n\n touched.length = 0;\n }\n\n return buildCsr(count, counts, edges, self, degree);\n}\n\n/**\n * Modularity of the partition that puts each node of `level` in its own community\n * @param level - The graph at this level\n * @param resolution - Resolution parameter\n * @returns Q = sum over nodes c of [ self(c) / m - resolution * (k_c / 2m)^2 ]\n */\nfunction levelModularity(level: Level, resolution: number): number {\n const twoM = level.degree.reduce((sum, d) => sum + d, 0);\n if (twoM === 0) {\n return 0;\n }\n\n let modularity = 0;\n for (let c = 0; c < level.n; c++) {\n const share = level.degree[c] / twoM;\n modularity += (2 * level.self[c]) / twoM - resolution * share * share;\n }\n\n return modularity;\n}\n\n/**\n * Optimized Louvain algorithm with automatic optimization selection\n * @param graph - The input graph to detect communities in\n * @param options - Algorithm configuration options\n * @returns Community detection result with communities, modularity, and iterations\n */\nexport function louvainOptimized(graph: Graph, options: OptimizedLouvainOptions = {}): 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 * @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 * @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 * @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(graph: Graph, nodeId: NodeId, communities: Map<NodeId, number>): 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 * weight of the edges inside communities to what would be expected in a random graph\n * with the same degrees.\n *\n * Formula: Q = sum over communities c of [ w_in(c)/m - gamma * (K_c / 2m)^2 ]\n * where:\n * - m = total edge weight, each undirected edge counted once\n * - w_in(c) = summed weight of the edges with both endpoints inside community c\n * - K_c = summed weighted degree of community c's nodes\n * - gamma = resolution parameter (higher values favor smaller communities)\n *\n * This is the per-community form of Q = (1/2m) * sum_ij [A_ij - gamma * k_i * k_j / (2m)] over the\n * pairs in the same community.\n * The double sum runs over every PAIR of nodes inside a community, so collecting the null-model\n * term only where an edge exists leaves the penalty far too small and rewards coarseness: the\n * single-community partition, whose modularity is 0 by definition, would otherwise outscore every\n * real split. The form below visits each community once and each edge once, so it counts every\n * pair exactly once without a pass over the whole adjacency matrix.\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(graph: Graph, communities: Map<NodeId, number>, resolution = 1.0): number {\n const totalEdgeWeight = getTotalEdgeWeight(graph);\n if (totalEdgeWeight === 0) {\n return 0;\n }\n\n // Summed weighted degree of each community's nodes.\n const degreeSum = new Map<number, number>();\n for (const node of graph.nodes()) {\n const community = communities.get(node.id);\n if (community === undefined) {\n continue;\n }\n\n degreeSum.set(community, (degreeSum.get(community) ?? 0) + getNodeDegree(graph, node.id));\n }\n\n // Summed weight of the edges that stay inside a community.\n const internalWeight = new Map<number, number>();\n for (const edge of graph.edges()) {\n const communityI = communities.get(edge.source);\n const communityJ = communities.get(edge.target);\n\n if (communityI === undefined || communityI !== communityJ) {\n continue;\n }\n\n internalWeight.set(communityI, (internalWeight.get(communityI) ?? 0) + (edge.weight ?? 1));\n }\n\n let modularity = 0;\n for (const [community, degrees] of degreeSum) {\n const share = degrees / (2 * totalEdgeWeight);\n modularity += (internalWeight.get(community) ?? 0) / totalEdgeWeight - resolution * share * share;\n }\n\n return modularity;\n}\n","import { Graph } from \"../../core/graph.js\";\nimport type { CommunityResult, LouvainOptions, NodeId } from \"../../types/index.js\";\nimport { louvainOptimized } from \"./louvain-optimized.js\";\nimport { calculateModularity, getNeighborCommunities, getNodeDegree, getTotalEdgeWeight } 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 * @param graph - The input graph\n * @param options - Algorithm options\n * @returns Community detection result with communities, modularity, and iterations\n */\nexport function louvain(graph: Graph, options: LouvainOptions = {}): 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 * @param graph - The input graph\n * @returns Map of node IDs to their initial community IDs\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 * @param graph - The input graph\n * @param communities - Map of node IDs to community IDs\n * @param resolution - Resolution parameter for modularity calculation\n * @returns True if any improvement was made, false otherwise\n */\nfunction louvainPhase1(graph: Graph, communities: Map<NodeId, number>, resolution: number): 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,\n nodeId,\n currentCommunity,\n communities,\n 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,\n nodeId,\n neighborCommunity,\n communities,\n 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 * @param graph - The input graph\n * @param nodeId - The node ID to evaluate\n * @param community - The community to measure contribution to\n * @param communities - Map of all node IDs to community IDs\n * @param resolution - Resolution parameter for modularity calculation\n * @returns The modularity contribution of the node to the specified 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 =\n (internalLinks - (resolution * nodeDegree * communityDegree) / (2 * totalEdgeWeight)) / totalEdgeWeight;\n\n return modularityIncrease;\n}\n\n/**\n * Extract final community structure\n * @param communities - Map of node IDs to community IDs\n * @returns Array of communities (each is an array of node IDs)\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 /**\n * Creates a new MinPriorityQueue instance.\n * @param compareFunction - Custom comparison function. Returns negative if a has higher priority than b.\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 (\n left < this.heap.length &&\n leftItem !== undefined &&\n minItem !== undefined &&\n this.compare(leftItem, minItem) < 0\n ) {\n minIndex = left;\n }\n\n const rightItem = this.heap[right];\n const newMinItem = this.heap[minIndex];\n if (\n right < this.heap.length &&\n rightItem !== undefined &&\n newMinItem !== undefined &&\n this.compare(rightItem, newMinItem) < 0\n ) {\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 /**\n * Insert a value into the priority queue.\n * @param value - The value to insert\n */\n insert(value: T): void {\n this.heap.push(value);\n this.heapifyUp(this.heap.length - 1);\n }\n\n /**\n * Remove and return the minimum value from the priority queue.\n * @returns The minimum value, or undefined if the queue is empty\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 /**\n * View the minimum value without removing it.\n * @returns The minimum value, or undefined if the queue is empty\n */\n peek(): T | undefined {\n return this.heap[0];\n }\n\n /**\n * Check if the priority queue is empty.\n * @returns True if the queue has no items, false otherwise\n */\n isEmpty(): boolean {\n return this.heap.length === 0;\n }\n\n /**\n * Get the number of items in the priority queue.\n * @returns The number of items currently in the queue\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 * @param cameFrom - Map of each node to its predecessor on the path\n * @param goal - The goal node to reconstruct the path to\n * @returns An array of nodes representing the path from start to goal\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 * @param width - The width of the grid\n * @param height - The height of the grid\n * @param obstacles - Set of obstacle coordinates as \"x,y\" strings\n * @returns A grid graph with 4-directional movement\n */\n createGridGraph(width: number, height: number, obstacles = new Set<string>()): 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],\n [1, 0],\n [0, -1],\n [-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 * @param coord - The coordinate string in \"x,y\" format\n * @returns A tuple of [x, y] coordinates\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","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 * @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 * @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 Detailed result including path, cost, visited nodes, and score maps\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 * @param a - First coordinate as [x, y] tuple\n * @param b - Second coordinate as [x, y] tuple\n * @returns The Manhattan distance between the two points\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 * @param a - First coordinate as [x, y] tuple\n * @param b - Second coordinate as [x, y] tuple\n * @returns The Euclidean distance between the two points\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 * @param a - First coordinate as [x, y] tuple\n * @param b - Second coordinate as [x, y] tuple\n * @returns The Chebyshev distance between the two points\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 * @param _a - First node (unused)\n * @param _b - Second node (unused)\n * @returns Always returns 0\n */\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 * @param graph - The original graph with capacity values\n * @returns A residual graph initialized with the original capacities\n */\nfunction createResidualGraph(graph: Map<string, Map<string, number>>): 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 * @param residualGraph - The residual graph with remaining capacities\n * @param source - The source node\n * @param sink - The sink node\n * @returns An array of nodes forming the path, or null if no path exists\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 * @param residualGraph - The residual graph to update\n * @param flowGraph - The flow graph to update with new flow values\n * @param originalGraph - The original graph for edge direction reference\n * @param path - The augmenting path to update flow along\n * @param pathFlow - The amount of flow to push through the 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 * @param residualGraph - The residual graph after max flow computation\n * @param source - The source node\n * @returns The minimum cut partition with source and sink sets and cut edges\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 * @param graph - The graph with capacity values\n * @param source - The source node\n * @param sink - The sink node\n * @param findPath - Function to find an augmenting path in the residual graph\n * @returns The maximum flow result including flow value, flow graph, and minimum cut\n */\nfunction maxFlowCore(\n graph: Map<string, Map<string, number>>,\n source: string,\n sink: string,\n findPath: (\n residual: Map<string, Map<string, number>>,\n src: string,\n snk: string,\n ) => { 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 * @param graph - The graph with capacity values\n * @param source - The source node\n * @param sink - The sink node\n * @returns The maximum flow result\n */\nfunction fordFulkersonImpl(graph: Map<string, Map<string, number>>, source: string, sink: string): MaxFlowResult {\n // Adapter function for DFS path finding\n const findPathDFS = (\n residual: Map<string, Map<string, number>>,\n src: string,\n snk: string,\n ): { 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 * @param graph - The graph with capacity values\n * @param source - The source node\n * @param sink - The sink node\n * @returns The maximum flow result\n */\nfunction edmondsKarpImpl(graph: Map<string, Map<string, number>>, source: string, sink: string): MaxFlowResult {\n // Use BFS variant for path finding\n const findPathBFS = (\n residual: Map<string, Map<string, number>>,\n src: string,\n snk: string,\n ): { 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 * @param leftNodes - Array of left partition node identifiers\n * @param rightNodes - Array of right partition node identifiers\n * @param edges - Array of edges connecting left nodes to right nodes\n * @returns The flow network graph with source and sink nodes\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 * @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(graph: Graph, source: string, sink: string): 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 * @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 * @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(graph: Graph, source: string, sink: string): 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 * @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(graph: Graph | Map<string, Map<string, number>>): 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 * @param graph - The undirected weighted graph\n * @param nodes - Array of remaining nodes in the graph\n * @returns The cut result with last two nodes, cut value, and partition\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 * @param graph - The graph to modify by contracting nodes\n * @param nodes - Array of nodes to update after contraction\n * @param s - The node to keep after contraction\n * @param t - The node to merge into s\n */\nfunction contractNodes(graph: Map<string, Map<string, number>>, nodes: string[], s: string, t: string): 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 * @param graph - The directed graph to convert\n * @returns An undirected graph with edges in both directions\n */\nfunction makeUndirected(graph: Map<string, Map<string, number>>): 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 * @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(graph: Graph | Map<string, Map<string, number>>, iterations = 100): 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 * @param graph - The undirected weighted graph\n * @returns The cut result with cut value and two partitions\n */\nfunction kargerSingleRun(graph: Map<string, Map<string, number>>): {\n cutValue: number;\n partition1: Set<string>;\n partition2: Set<string>;\n} {\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) {\n // 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 * @param graph - The working graph to modify\n * @param superNodes - Map tracking which original nodes are in each super node\n * @param u - First endpoint of the edge to contract\n * @param v - Second endpoint of the edge to contract (merged into u)\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 * 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 * @param graph - The input graph to convert\n * @returns Map of node IDs to sets of neighbor node IDs\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 * @param graph - Adjacency map representation of the graph\n * @param distances - Map to store computed distances between nodes\n */\nfunction computeGraphDistance<T>(graph: Map<T, Set<T>>, distances: Map<T, Map<T, number>>): 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 * @param cluster1 - First cluster node\n * @param cluster2 - Second cluster node\n * @param distances - Precomputed distance matrix between nodes\n * @param linkage - Linkage method to use for computing cluster distance\n * @returns The distance between the two clusters\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 * @param graph - Adjacency map representation of the graph\n * @param linkage - Linkage method for cluster distance computation\n * @returns Hierarchical clustering result with dendrogram and cluster assignments\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 =\n distMap.get(cluster2.id) ?? clusterDistances.get(cluster2.id)?.get(cluster1.id) ?? 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 * @param root - Root node of the dendrogram\n * @param height - Height at which to cut the dendrogram\n * @returns Array of sets representing clusters at the specified height\n */\nexport function cutDendrogram<T>(root: ClusterNode<T>, height: number): 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 * @param root - Root node of the dendrogram\n * @param k - Target number of clusters\n * @returns Array of sets representing exactly k clusters\n */\nexport function cutDendrogramKClusters<T>(root: ClusterNode<T>, k: number): 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 * @param graph - The input graph to cluster\n * @returns Hierarchical clustering result with dendrogram and cluster assignments\n */\nexport function modularityHierarchicalClustering(graph: Graph): 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 - 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 * @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 * @param graph - The input graph to convert\n * @returns Map of node IDs to sets of neighbor node IDs\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 * @param graph - Adjacency map representation of the graph\n * @returns K-core decomposition result with cores, coreness values, and maximum core number\n */\nfunction kCoreDecompositionImpl<T>(graph: Map<T, Set<T>>): 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 * @param graph - Undirected graph\n * @param k - Core number\n * @returns Set of nodes in k-core or higher\n */\nexport function getKCore(graph: Graph, k: number): 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 * @param graph - Original graph\n * @param k - Core number\n * @returns K-core subgraph\n */\nexport function getKCoreSubgraph(graph: Graph, k: number): 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 * @param graph - Undirected graph\n * @returns Array of nodes ordered by degeneracy\n */\nexport function degeneracyOrdering(graph: Graph): 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 * @param graph - Undirected graph\n * @param k - Truss number (k >= 2)\n * @returns Edges in k-truss\n */\nexport function kTruss(graph: Graph, k: number): 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) {\n // Avoid duplicates\n const edge = `${u},${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 = `${u},${v}`;\n const edge2 = `${u},${w}`;\n const edge3 = `${v},${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 ? `${u},${w}` : `${w},${u}`;\n const edge2 = v < w ? `${v},${w}` : `${w},${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 * @param directedGraph - Directed graph represented as adjacency map with edge weights\n * @returns Undirected graph represented as adjacency map with neighbor sets\n */\nexport function toUndirected<T>(directedGraph: Map<T, Map<T, number>>): 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 * @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(graph: Graph): KCoreResult<string> {\n // Convert Graph to adjacency set representation\n const adjacencySet = graphToAdjacencySet(graph);\n return kCoreDecompositionImpl(adjacencySet);\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 * @param graph - The input graph to cluster\n * @param options - MCL algorithm options (expansion, inflation, iterations, etc.)\n * @returns MCL clustering result with communities, attractors, and convergence info\n */\nexport function markovClustering(graph: Graph, options: MCLOptions = {}): 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 * @param graph - The input graph\n * @param nodeIds - Array of node IDs in the graph\n * @param selfLoops - Whether to add self-loops to the matrix\n * @returns Column-normalized transition matrix\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 === undefined) {\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 * @param matrix - Input square matrix\n * @param power - Power to raise the matrix to\n * @returns Matrix raised to the specified power\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 * @param a - First matrix\n * @param b - Second matrix\n * @returns Product matrix a * b\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 * @param matrix - Input matrix to inflate\n * @param inflation - Inflation parameter for element-wise powering\n * @returns Inflated and column-normalized matrix\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 * @param matrix - Input matrix to prune\n * @param threshold - Values below this threshold are set to zero\n * @returns Pruned and re-normalized matrix\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 * @param oldMatrix - Matrix from previous iteration\n * @param newMatrix - Matrix from current iteration\n * @param tolerance - Convergence tolerance threshold\n * @returns True if the maximum difference between matrices is below tolerance\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 * @param matrix - Final converged MCL matrix\n * @param nodeIds - Array of node IDs corresponding to matrix indices\n * @returns Object containing communities and attractor nodes\n */\nfunction extractClusters(\n matrix: number[][],\n nodeIds: NodeId[],\n): {\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 (columns) to clusters based on which attractor (row) they flow to\n // After MCL convergence, matrix[i][j] > 0 means node j belongs to attractor i's cluster\n const attractorToCommunity = new Map<number, number[]>();\n\n for (let j = 0; j < n; j++) {\n // Find the attractor for this column (node j)\n // Look for the row with the highest non-zero value in column j\n let maxVal = 0;\n let attractorRow = -1;\n\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 > maxVal) {\n maxVal = val;\n attractorRow = i;\n }\n }\n\n if (attractorRow >= 0) {\n // Node j belongs to the cluster of attractor at row attractorRow\n let community = attractorToCommunity.get(attractorRow);\n if (!community) {\n community = [];\n attractorToCommunity.set(attractorRow, community);\n }\n community.push(j);\n nodeToCluster.set(j, attractorRow);\n }\n }\n\n // Convert attractor communities to node ID arrays\n for (const [, memberIndices] of attractorToCommunity) {\n communities.push(\n memberIndices\n .map((idx) => {\n const nodeId = nodeIds[idx];\n return nodeId;\n })\n .filter((node): node is NodeId => node !== undefined),\n );\n }\n\n // Handle isolated nodes (nodes with all-zero columns)\n for (let j = 0; j < n; j++) {\n if (!nodeToCluster.has(j)) {\n const nodeId = nodeIds[j];\n if (nodeId !== undefined) {\n communities.push([nodeId]);\n }\n }\n }\n\n return { communities, attractors };\n}\n\n/**\n * Calculate modularity of MCL clustering result\n * @param graph - The original graph that was clustered\n * @param communities - Array of communities (each community is an array of node IDs)\n * @returns Modularity score between -0.5 and 1.0\n */\nexport function calculateMCLModularity(graph: Graph, communities: NodeId[][]): 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, SeededRandom } 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 seed?: number; // Random seed for reproducible results\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 * Note: 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 * @param graph - The input graph to cluster\n * @param options - Spectral clustering options (k, laplacianType, etc.)\n * @returns Spectral clustering result with communities and cluster assignments\n */\nexport function spectralClustering(graph: Graph, options: SpectralClusteringOptions): SpectralClusteringResult {\n const { k, laplacianType = \"normalized\", maxIterations = 100, tolerance = 1e-4, seed } = options;\n\n // Create random function - use seeded PRNG if seed provided, otherwise Math.random\n const random = seed !== undefined ? SeededRandom.createGenerator(seed) : Math.random;\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, random);\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, random);\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 === undefined) {\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 * @param graph - The input graph\n * @param nodeIds - Array of node IDs defining matrix index order\n * @returns Square adjacency matrix with edge weights\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 === undefined) {\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 * @param adjacency - Square adjacency matrix\n * @param type - Type of Laplacian (unnormalized, normalized, or randomWalk)\n * @returns The computed Laplacian 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 (\n adjacencyVal !== undefined &&\n adjacencyVal > 0 &&\n di !== undefined &&\n dj !== undefined &&\n di > 0 &&\n dj > 0\n ) {\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 * @param matrix - The Laplacian matrix for eigendecomposition\n * @param k - Number of smallest eigenvectors to find\n * @param random - Random number generator function\n * @returns Object containing eigenvalues and corresponding eigenvectors\n */\nfunction findSmallestEigenvectors(\n matrix: number[][],\n k: number,\n random: () => number,\n): {\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, random);\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)\n .fill(0)\n .map(() => 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 * @param matrix - Matrix to normalize in place\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 * @param data - Array of data points, each point is an array of coordinates\n * @param k - Number of clusters to form\n * @param maxIterations - Maximum number of iterations\n * @param tolerance - Convergence tolerance for centroid movement\n * @param random - Random number generator function\n * @returns Object containing cluster assignments and final centroids\n */\nfunction kMeansClustering(\n data: number[][],\n k: number,\n maxIterations: number,\n tolerance = 1e-4,\n random: () => number = Math.random,\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(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] = 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 * @param matrix - The Laplacian matrix\n * @param k - Number of eigenvectors to compute (1-3)\n * @param n - Size of the matrix\n * @param random - Random number generator function\n * @returns Object containing eigenvalues and eigenvectors\n */\nfunction computeSmallestEigenvectorsSimple(\n matrix: number[][],\n k: number,\n n: number,\n random: () => number,\n): {\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)\n .fill(0)\n .map(() => 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)\n .fill(0)\n .map(() => 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 * @param graph - The bipartite graph to find maximum matching for\n * @param options - Optional configuration including left and right node partitions\n * @returns The maximum matching as a map from left nodes to right nodes and the matching size\n * @throws Error if the graph is not bipartite\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 * @param graph - The graph to check for bipartiteness\n * @returns An object with left and right node sets if bipartite, or null if not bipartite\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 * @param graph - The bipartite graph to find matching for\n * @param options - Optional configuration including left and right node partitions\n * @returns The matching as a map from left nodes to right nodes and the matching size\n * @throws Error if the graph is not bipartite\n */\nexport function greedyBipartiteMatching(graph: Graph, options: BipartiteMatchingOptions = {}): 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 * @param graph1 - The first graph to compare\n * @param graph2 - The second graph to compare\n * @param options - Optional configuration for node and edge matching predicates\n * @returns An object indicating if the graphs are isomorphic and an optional mapping between nodes\n */\nexport function isGraphIsomorphic(graph1: Graph, graph2: Graph, options: IsomorphismOptions = {}): 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 * @param g1 - The first graph being compared\n * @param g2 - The second graph being compared\n * @param state - The current VF2 algorithm state containing mappings and terminal sets\n * @param nodes1 - Array of node IDs from the first graph\n * @param nodes2 - Array of node IDs from the second graph\n * @param options - Configuration options for matching predicates\n * @param mappings - Array to collect found isomorphism mappings\n * @returns True if an isomorphism was found and search should stop, false otherwise\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 * @param g1 - The first graph being compared\n * @param g2 - The second graph being compared\n * @param state - The current VF2 algorithm state containing mappings and terminal sets\n * @param nodes1 - Array of node IDs from the first graph\n * @param nodes2 - Array of node IDs from the second graph\n * @returns Array of candidate node pairs to try matching\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 === null) {\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 === null) {\n for (const n of nodes1) {\n if (!state.core1.has(n)) {\n node1 = n;\n break;\n }\n }\n }\n\n if (node1 === null) {\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 * @param g1 - The first graph being compared\n * @param g2 - The second graph being compared\n * @param state - The current VF2 algorithm state containing mappings and terminal sets\n * @param node1 - The candidate node from the first graph\n * @param node2 - The candidate node from the second graph\n * @param options - Configuration options for matching predicates\n * @returns True if the node pair can be feasibly matched, false otherwise\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;\n let new1Out = 0;\n let term1In = 0;\n let term1Out = 0;\n let new2In = 0;\n let new2Out = 0;\n let term2In = 0;\n 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 && new1In === new2In && new1Out === new2Out;\n}\n\n/**\n * Add a pair to the mapping and update terminal sets\n * @param g1 - The first graph being compared\n * @param g2 - The second graph being compared\n * @param state - The current VF2 algorithm state containing mappings and terminal sets\n * @param node1 - The node from the first graph to add to the mapping\n * @param node2 - The node from the second graph to add to the mapping\n * @returns A new VF2 state with the pair added and terminal sets updated\n */\nfunction addPair(g1: Graph, g2: Graph, state: VF2State, node1: NodeId, node2: NodeId): 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 * @param graph1 - The first graph to compare\n * @param graph2 - The second graph to compare\n * @param options - Optional configuration for node and edge matching predicates\n * @returns An array of all possible node mappings between the 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 * @param graph - The input graph\n * @param source - The source node ID\n * @param target - The target node ID\n * @param options - Link prediction options\n * @returns The Adamic-Adar score for the node pair\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 * @param graph - The input graph\n * @param options - Link prediction options\n * @returns Array of link prediction scores sorted by score descending\n */\nexport function adamicAdarPrediction(graph: Graph, options: LinkPredictionOptions = {}): LinkPredictionScore[] {\n const { directed = false, includeExisting = false, topK } = 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 === undefined || target === undefined) {\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 * @param graph - The input graph\n * @param pairs - Array of node ID pairs to calculate scores for\n * @param options - Link prediction options\n * @returns Array of link prediction scores for the specified 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 * @param graph - The input graph\n * @param node - The node ID to get candidates for\n * @param options - Link prediction options with optional candidate list\n * @returns Array of top link prediction candidates sorted by score descending\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 { directed = false, includeExisting = false, topK = 10, candidates } = 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 * @param trainingGraph - The training graph without test edges\n * @param testEdges - Array of node pairs that are actual edges\n * @param nonEdges - Array of node pairs that are not edges\n * @param options - Link prediction options\n * @returns Evaluation metrics including precision, recall, F1 score, and AUC\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 * @param graph - The input graph\n * @param testEdges - Array of node pairs that are actual edges\n * @param nonEdges - Array of node pairs that are not edges\n * @param options - Link prediction options\n * @returns Comparison of evaluation metrics for both algorithms\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 * @param graph - The input graph\n * @param source - The source node ID\n * @param target - The target node ID\n * @param options - Link prediction options\n * @returns The number of common neighbors\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 * @param graph - The input graph\n * @param options - Link prediction options\n * @returns Array of link prediction scores sorted by score descending\n */\nexport function commonNeighborsPrediction(graph: Graph, options: LinkPredictionOptions = {}): LinkPredictionScore[] {\n const { directed = false, includeExisting = false, topK } = 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 === undefined || target === undefined) {\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 * @param graph - The input graph\n * @param pairs - Array of node ID pairs to calculate scores for\n * @param options - Link prediction options\n * @returns Array of link prediction scores for the specified 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 * @param graph - The input graph\n * @param node - The node ID to get candidates for\n * @param options - Link prediction options with optional candidate list\n * @returns Array of top link prediction candidates sorted by score descending\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 { directed = false, includeExisting = false, topK = 10, candidates } = 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 * @param trainingGraph - The training graph without test edges\n * @param testEdges - Array of node pairs that are actual edges\n * @param nonEdges - Array of node pairs that are not edges\n * @param options - Link prediction options\n * @returns Evaluation metrics including precision, recall, F1 score, and AUC\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 * @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 { numClusters, maxIterations = 100, tolerance = 1e-6, seed = 42, learningRate = 0.01, lambda = 0.1 } = 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(\n `Invalid number of clusters: ${String(numClusters)}. Must be between 1 and ${String(nodeCount)}`,\n );\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 * @param graph - The input graph\n * @param nodeId - The node ID to initialize embedding for\n * @param dim - The embedding dimension\n * @returns The initialized embedding vector\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 * @param embeddings - Map of node IDs to embedding vectors\n * @param numClusters - Number of cluster centers to initialize\n * @returns Array of initialized cluster center vectors\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 * @param graph - The input graph\n * @param embeddings - Map of node IDs to embedding vectors\n * @param _clusters - Map of node IDs to cluster assignments (reserved for future use)\n * @param learningRate - Learning rate for gradient descent\n * @param lambda - Regularization parameter\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 * @param embeddings - Map of node IDs to embedding vectors\n * @param clusters - Map of node IDs to cluster assignments\n * @param clusterCenters - Array of cluster center vectors to update\n * @param numClusters - Number of clusters\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(\n { 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 * @param graph - The input graph\n * @param embeddings - Map of node IDs to embedding vectors\n * @param clusters - Map of node IDs to cluster assignments\n * @param clusterCenters - Array of cluster center vectors\n * @param lambda - Regularization parameter\n * @returns The total loss value\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","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 * @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(\n `Graph has ${String(nodeCount)} nodes, which exceeds maxNodes (${String(maxNodes)}). Performance may be degraded.`,\n );\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 * @param graph - The input graph\n * @param nodes - Array of nodes to calculate distances between\n * @param useGraphDistance - Whether to use graph-based shortest path distances\n * @returns 2D distance matrix\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 * @param graph - The input graph\n * @param source - The source node ID\n * @returns Map of node IDs to their distances from the source\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 * @param clusters - Map of cluster IDs to cluster nodes\n * @param distanceMatrix - 2D distance matrix between nodes\n * @returns Array of merge candidates sorted by distance\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 * @param mergeCandidates - Array of merge candidates\n * @returns The closest cluster pair with their distance\n */\nfunction findClosestPair(mergeCandidates: { cluster1Id: string; cluster2Id: string; distance: number }[]): {\n cluster1Id: string;\n cluster2Id: string;\n distance: number;\n} {\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 * @param mergeCandidates - Array of merge candidates to update\n * @param oldCluster1Id - ID of first merged cluster\n * @param oldCluster2Id - ID of second merged cluster\n * @param newClusterId - ID of the newly created cluster\n * @param clusters - Map of cluster IDs to cluster nodes\n * @param distanceMatrix - 2D distance matrix between nodes\n * @param linkage - Linkage criterion to use\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 (\n candidate.cluster1Id === oldCluster1Id ||\n candidate.cluster1Id === oldCluster2Id ||\n candidate.cluster2Id === oldCluster1Id ||\n candidate.cluster2Id === oldCluster2Id\n ) {\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 * @param cluster1 - First cluster\n * @param cluster2 - Second cluster\n * @param distanceMatrix - 2D distance matrix between nodes\n * @param linkage - Linkage criterion (single, complete, average, ward)\n * @returns The distance between the two clusters\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 * @param dendrogram - The root of the dendrogram tree\n * @param numClusters - The target number of clusters\n * @returns Map of node IDs to cluster assignments\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 * @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 || currentCluster.members.size < minClusterSize * 2) {\n continue;\n }\n\n // Attempt spectral bisection\n const bisectionResult = spectralBisection(graph, currentCluster, numEigenvectors, tolerance, maxIterations);\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) {\n // 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 * @param graph - The input graph\n * @param cluster - The cluster to bisect\n * @param _numEigenvectors - Number of eigenvectors to compute (reserved for future use)\n * @param tolerance - Convergence tolerance\n * @param maxIterations - Maximum number of iterations\n * @returns Bisection result with left/right members, scores, and explanation, or null if bisection failed\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.map((value, index) => ({ value, index })).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 * @param graph - The input graph\n * @param nodes - The nodes to include in the subgraph\n * @returns The Laplacian matrix as a 2D array\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 * @param laplacian - The Laplacian matrix\n * @param tolerance - Convergence tolerance\n * @param maxIterations - Maximum number of iterations\n * @returns The Fiedler vector, or null if computation failed\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 * @param graph - The input graph\n * @param assignment - Map from node ID to community ID\n * @returns The modularity score\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","import { type AdjacencyView, INVALID_INDEX, type U32 } from \"@graphty/graph-format\";\n\n/** Result of the index-based BFS (graph-format design 14.2 Port 1). @public */\nexport interface BfsResult {\n /** Visit order, one entry per visited node; a subarray of length `visitedCount`. */\n readonly order: U32;\n /** Parent of every node, INVALID_INDEX for the start node and for unvisited nodes. */\n readonly parent: U32;\n /** Hop depth of every node, INVALID_INDEX for unvisited nodes. */\n readonly depth: U32;\n /** How many nodes were visited. */\n readonly visitedCount: number;\n}\n\n/** Options of the index-based BFS. @public */\nexport interface BfsOptions {\n /** Stop expanding at this depth; unbounded when omitted. */\n readonly maxDepth?: number | undefined;\n}\n\n/**\n * Breadth-first search over out-neighbours. Takes any `AdjacencyView`, so `s.reverse()` gives an\n * in-neighbour BFS with no extra code.\n * @param g - The adjacency to traverse\n * @param start - The node index to start from\n * @param options - Traversal options\n * @returns The visit order, the parent array, the depth array and the visited count\n * @public\n */\nexport function breadthFirstSearch(g: AdjacencyView, start: number, options: BfsOptions = {}): BfsResult {\n const { nodeCount, rowPtr, colIdx } = g;\n const parent = new Uint32Array(nodeCount).fill(INVALID_INDEX);\n const depth = new Uint32Array(nodeCount).fill(INVALID_INDEX);\n const order = new Uint32Array(nodeCount);\n const maxDepth = options.maxDepth ?? INVALID_INDEX;\n let head = 0;\n let tail = 0;\n order[tail++] = start;\n depth[start] = 0;\n while (head < tail) {\n const u = order[head++];\n const d = depth[u];\n if (d >= maxDepth) {\n continue;\n }\n const end = rowPtr[u + 1];\n for (let a = rowPtr[u]; a < end; a++) {\n const v = colIdx[a];\n if (depth[v] === INVALID_INDEX) {\n depth[v] = d + 1;\n parent[v] = u;\n order[tail++] = v;\n }\n }\n }\n return { order: order.subarray(0, tail), parent, depth, visitedCount: tail };\n}\n","import type { AdjacencyView, GraphSnapshot } from \"@graphty/graph-format\";\n\n/** Options of the index-based common-neighbour score. @public */\nexport interface CommonNeighborsOptions {\n /** Intersect out(u) with in(v) instead of the two undirected rows. */\n readonly directed?: boolean | undefined;\n}\n\n/**\n * The number of distinct common neighbours of two nodes, by a merge of their sorted rows.\n * @param s - The snapshot\n * @param u - A node index\n * @param v - A node index\n * @param o - Options\n * @returns The count of distinct common neighbours\n * @public\n */\nexport function commonNeighborsScore(s: GraphSnapshot, u: number, v: number, o: CommonNeighborsOptions = {}): number {\n const fwd: AdjacencyView = s;\n const bwd: AdjacencyView = o.directed === true ? s.reverse() : s;\n let i = fwd.rowPtr[u];\n const iEnd = fwd.rowPtr[u + 1];\n let j = bwd.rowPtr[v];\n const jEnd = bwd.rowPtr[v + 1];\n let count = 0;\n while (i < iEnd && j < jEnd) {\n const a = fwd.colIdx[i];\n const b = bwd.colIdx[j];\n if (a === b) {\n count++;\n i++;\n j++;\n while (i < iEnd && fwd.colIdx[i] === a) {\n i++;\n }\n while (j < jEnd && bwd.colIdx[j] === b) {\n j++;\n }\n } else if (a < b) {\n i++;\n } else {\n j++;\n }\n }\n return count;\n}\n","import { renumberPartition, type U32 } from \"@graphty/graph-format\";\n\n/**\n * Index-keyed union-find over `[0, size)` with union by rank and path halving. The legacy\n * `UnionFind` (`src/data-structures/union-find.ts`) is NodeId-keyed and stays where it is.\n * @public\n */\nexport class IntUnionFind {\n private readonly parent: U32;\n private readonly rank: U32;\n\n /**\n * Create a union-find whose every element is a singleton set.\n * @param size - The number of elements, each initially its own singleton set\n */\n constructor(size: number) {\n this.parent = new Uint32Array(size);\n this.rank = new Uint32Array(size);\n for (let i = 0; i < size; i++) {\n this.parent[i] = i;\n }\n }\n\n /**\n * Find the representative of an element's set, halving the path on the way up.\n * @param x - An element index\n * @returns The representative of x's set\n */\n find(x: number): number {\n let node = x;\n while (this.parent[node] !== node) {\n this.parent[node] = this.parent[this.parent[node]]; // path halving\n node = this.parent[node];\n }\n return node;\n }\n\n /**\n * Merge the sets of two elements, attaching the shallower tree under the deeper one.\n * @param a - An element index\n * @param b - An element index\n * @returns True when the two sets were distinct and have now been merged\n */\n union(a: number, b: number): boolean {\n const ra = this.find(a);\n const rb = this.find(b);\n if (ra === rb) {\n return false;\n }\n if (this.rank[ra] < this.rank[rb]) {\n this.parent[ra] = rb;\n } else if (this.rank[ra] > this.rank[rb]) {\n this.parent[rb] = ra;\n } else {\n this.parent[rb] = ra;\n this.rank[ra]++;\n }\n return true;\n }\n\n /**\n * Dense labels in FIRST-SEEN order, which is what makes `groups()` identical to the legacy\n * iteration order and identical to the GPU's after its own `renumberPartition` readback\n * (design 9.7's connectedComponents row).\n * @returns The labels and the number of distinct sets\n */\n toLabels(): { readonly labels: U32; readonly count: number } {\n const roots = new Uint32Array(this.parent.length);\n for (let i = 0; i < roots.length; i++) {\n roots[i] = this.find(i);\n }\n return renumberPartition(roots);\n }\n}\n","import { type GraphSnapshot, type U32 } from \"@graphty/graph-format\";\n\nimport { IntUnionFind } from \"./structures/union-find.js\";\n\n/** A partition of the node set (graph-format design 14.2's result table, line 3738). @public */\nexport interface LabelResult {\n /** Dense label per node index, in first-seen order. */\n readonly labels: U32;\n /** Number of distinct labels. */\n readonly count: number;\n /**\n * Node indices grouped by label, computed once and cached.\n * @returns One array per label\n */\n groups(): U32[];\n}\n\n/**\n * Wrap a dense label array as a `LabelResult`, computing the grouping on first use. Shared with the\n * Louvain port, whose result is a partition with a modularity attached.\n * @param labels - Dense label per node index\n * @param count - Number of distinct labels\n * @returns The partition\n */\nexport function withGroups(labels: U32, count: number): LabelResult {\n let cached: U32[] | null = null;\n return {\n labels,\n count,\n groups(): U32[] {\n if (cached === null) {\n const sizes = new Uint32Array(count);\n for (let i = 0; i < labels.length; i++) {\n sizes[labels[i]]++;\n }\n const out: U32[] = [];\n for (let c = 0; c < count; c++) {\n out.push(new Uint32Array(sizes[c]));\n }\n const fill = new Uint32Array(count);\n for (let i = 0; i < labels.length; i++) {\n const c = labels[i];\n out[c][fill[c]++] = i;\n }\n cached = out;\n }\n return cached;\n },\n };\n}\n\nfunction unionEdges(s: GraphSnapshot): LabelResult {\n const uf = new IntUnionFind(s.nodeCount);\n const el = s.edgeList();\n for (let e = 0; e < s.edgeCount; e++) {\n uf.union(el.src[e], el.dst[e]);\n }\n const { labels, count } = uf.toLabels();\n return withGroups(labels, count);\n}\n\n/**\n * Connected components of an UNDIRECTED snapshot.\n * @param s - An undirected snapshot\n * @returns The partition\n * @public\n */\nexport function connectedComponents(s: GraphSnapshot): LabelResult {\n if (s.directed) {\n throw new Error(\n \"Connected components requires an undirected graph. Use weaklyConnectedComponents, or pass s.toUndirected().snapshot.\",\n );\n }\n return unionEdges(s);\n}\n\n/**\n * Weakly connected components: the same union-find pass with the direction check dropped.\n * @param s - Any snapshot\n * @returns The partition\n * @public\n */\nexport function weaklyConnectedComponents(s: GraphSnapshot): LabelResult {\n return unionEdges(s);\n}\n","import type { U32 } from \"@graphty/graph-format\";\n\n/**\n * The source node of an arc, by binary search on `rowPtr`. `GraphSnapshot` exposes `arcSource(a)`\n * (`graph-format/src/snapshot/graph-snapshot.ts:544`), but an `AdjacencyView` -- which is what the\n * Port 1 and Port 2 signatures take, so that `reverse()` works as an input for free -- does not,\n * so the predecessor walk carries its own.\n * @param rowPtr - The view's nodeCount + 1 row offsets\n * @param arc - An arc index in `[0, arcCount)`\n * @returns The node index whose row contains the arc\n * @public\n */\nexport function arcSourceIn(rowPtr: U32, arc: number): number {\n let lo = 0;\n let hi = rowPtr.length - 1; // nodeCount\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (rowPtr[mid + 1] <= arc) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n return lo;\n}\n","import { type F64, INVALID_INDEX, type U32 } from \"@graphty/graph-format\";\n\n/**\n * A binary min-heap over node indices with O(log n) decrease-key, keyed by `Float64Array` values\n * (graph-format design 14.2, `graph-format-design.md:3771`). `pushOrDecrease` is the only operation\n * Dijkstra's inner loop needs: it inserts an absent node and decreases a present one, so the heap\n * never holds a stale duplicate and `pop()` needs no \"is this entry current\" check.\n * @public\n */\nexport class IndexedMinHeap {\n private readonly heap: U32; // slot -> node\n private readonly slot: U32; // node -> slot, INVALID_INDEX when absent\n private readonly key: F64; // node -> key\n private size = 0;\n\n /**\n * Create an empty heap over node indices in `[0, capacity)`.\n * @param capacity - The number of distinct node indices the heap may hold\n */\n constructor(capacity: number) {\n this.heap = new Uint32Array(capacity);\n this.slot = new Uint32Array(capacity).fill(INVALID_INDEX);\n this.key = new Float64Array(capacity);\n }\n\n /**\n * Whether the heap holds no entries.\n * @returns True when the heap holds no entries\n */\n isEmpty(): boolean {\n return this.size === 0;\n }\n\n /**\n * Insert a node that is not in the heap.\n * @param node - The node index\n * @param key - Its key\n */\n push(node: number, key: number): void {\n this.key[node] = key;\n this.heap[this.size] = node;\n this.slot[node] = this.size;\n this.size++;\n this.siftUp(this.size - 1);\n }\n\n /**\n * Insert the node, or lower its key if it is already present and the new key is smaller.\n * @param node - The node index\n * @param key - Its candidate key\n */\n pushOrDecrease(node: number, key: number): void {\n const at = this.slot[node];\n if (at === INVALID_INDEX) {\n this.push(node, key);\n return;\n }\n if (key < this.key[node]) {\n this.key[node] = key;\n this.siftUp(at);\n }\n }\n\n /**\n * Remove and return the node with the smallest key. Undefined behaviour on an empty heap;\n * callers guard with `isEmpty()`.\n * @returns The node index\n */\n pop(): number {\n const top = this.heap[0];\n this.slot[top] = INVALID_INDEX;\n this.size--;\n if (this.size > 0) {\n const moved = this.heap[this.size];\n this.heap[0] = moved;\n this.slot[moved] = 0;\n this.siftDown(0);\n }\n return top;\n }\n\n private siftUp(from: number): void {\n let at = from;\n const node = this.heap[at];\n const key = this.key[node];\n while (at > 0) {\n const parent = (at - 1) >> 1;\n const parentNode = this.heap[parent];\n if (this.key[parentNode] <= key) {\n break;\n }\n this.heap[at] = parentNode;\n this.slot[parentNode] = at;\n at = parent;\n }\n this.heap[at] = node;\n this.slot[node] = at;\n }\n\n private siftDown(from: number): void {\n let at = from;\n const node = this.heap[at];\n const key = this.key[node];\n for (;;) {\n const left = 2 * at + 1;\n if (left >= this.size) {\n break;\n }\n const right = left + 1;\n const child = right < this.size && this.key[this.heap[right]] < this.key[this.heap[left]] ? right : left;\n const childNode = this.heap[child];\n if (key <= this.key[childNode]) {\n break;\n }\n this.heap[at] = childNode;\n this.slot[childNode] = at;\n at = child;\n }\n this.heap[at] = node;\n this.slot[node] = at;\n }\n}\n","import { type AdjacencyView, INVALID_INDEX, type NumericVector, type U32 } from \"@graphty/graph-format\";\n\nimport { PathWalkError } from \"../errors.js\";\nimport { arcSourceIn } from \"./structures/arc-source.js\";\nimport { IndexedMinHeap } from \"./structures/min-heap.js\";\n\n/**\n * Single-source shortest paths, index-based (graph-format design 14.2 Port 2, line 3860).\n * `dist` is a `NumericVector` rather than the design's `F64` because ONE declaration serves both\n * the CPU port (which produces a `Float64Array`) and the dispatcher's decoration of an\n * accelerator's f32 result (plan decision PD-3, departure DEP-8A-C).\n * @public\n */\nexport interface SsspResult {\n /** Distance per node; +Infinity for unreached nodes. */\n readonly dist: NumericVector;\n /** The ARC that relaxed each node; INVALID_INDEX for the source and for unreached nodes. */\n readonly predArc: U32;\n /**\n * Node indices from the source to `target` inclusive; empty when `target` is unreached.\n * @param target - The node index to walk back from\n */\n pathTo(target: number): U32;\n /**\n * LOGICAL EDGE indices along that path, one fewer than `pathTo`; this is what graphty-element's\n * `isInPath` writes through. Empty when `target` is unreached.\n * @param target - The node index to walk back from\n */\n pathEdges(target: number): U32;\n}\n\n/** Options of the index-based SSSP. @public */\nexport interface SsspOptions {\n /** Stop relaxing beyond this distance. */\n readonly cutoff?: number | undefined;\n /** Per-arc weight override, arcCount long -- the facade passes `expandEdges(s, shadow.data)`. */\n readonly weights?: NumericVector | undefined;\n}\n\n/**\n * The arcs from `target` back to `source`, target end first. `predArc` may come from an\n * accelerator, so it is not trusted: a missing or out-of-range arc, or more than nodeCount - 1\n * steps, throws rather than walking off the array or looping.\n * @param g - The adjacency the search ran on\n * @param predArc - The search's predecessor-arc array\n * @param source - The search's source node index\n * @param target - The node to walk back from (reached, and not the source)\n * @returns Arc indices, target end first\n */\nfunction walkBack(g: AdjacencyView, predArc: U32, source: number, target: number): number[] {\n const arcs: number[] = [];\n let node = target;\n while (node !== source) {\n if (arcs.length >= g.nodeCount - 1) {\n throw new PathWalkError(source, target, \"cycle\");\n }\n const arc = predArc[node];\n if (!(arc < g.arcCount)) {\n throw new PathWalkError(source, target, \"gap\"); // INVALID_INDEX is past arcCount too\n }\n arcs.push(arc);\n node = arcSourceIn(g.rowPtr, arc);\n }\n return arcs;\n}\n\n/**\n * Walk the predecessor arcs back from `target` and return the node path, source first.\n * @param g - The adjacency the search ran on\n * @param predArc - The search's predecessor-arc array\n * @param source - The search's source node index\n * @param target - The node to walk back from\n * @returns Node indices from source to target inclusive, or an empty array when unreached\n * @throws PathWalkError when `predArc` has a gap or a cycle between `target` and `source`\n * @public\n */\nexport function walkPredArcs(g: AdjacencyView, predArc: U32, source: number, target: number): U32 {\n if (target === source) {\n return Uint32Array.of(source);\n }\n if (predArc[target] === INVALID_INDEX) {\n return new Uint32Array(0);\n }\n const reversed = [target, ...walkBack(g, predArc, source, target).map((arc) => arcSourceIn(g.rowPtr, arc))];\n const out = new Uint32Array(reversed.length);\n for (let i = 0; i < reversed.length; i++) {\n out[i] = reversed[reversed.length - 1 - i];\n }\n return out;\n}\n\n/**\n * Walk the predecessor arcs back from `target` and return the logical edges on the path.\n * @param g - The adjacency the search ran on\n * @param predArc - The search's predecessor-arc array\n * @param source - The search's source node index\n * @param target - The node to walk back from\n * @returns Logical edge indices from source to target, or an empty array when unreached\n * @throws PathWalkError when `predArc` has a gap or a cycle between `target` and `source`\n * @public\n */\nexport function walkPredEdges(g: AdjacencyView, predArc: U32, source: number, target: number): U32 {\n if (target === source || predArc[target] === INVALID_INDEX) {\n return new Uint32Array(0);\n }\n // the EXACT parallel edge, not a (u, v) lookup\n const reversed = walkBack(g, predArc, source, target).map((arc) => g.arcToEdge[arc]);\n const out = new Uint32Array(reversed.length);\n for (let i = 0; i < reversed.length; i++) {\n out[i] = reversed[reversed.length - 1 - i];\n }\n return out;\n}\n\n/**\n * Dijkstra over an adjacency view, with the predecessor recorded as the relaxing ARC so a parallel\n * edge on the path is identified exactly.\n * @param g - The adjacency to search\n * @param source - The node index to start from\n * @param options - Cutoff and per-arc weight override\n * @returns The distances, the predecessor arcs, and the two path accessors\n * @public\n */\nexport function dijkstra(g: AdjacencyView, source: number, options: SsspOptions = {}): SsspResult {\n const { nodeCount, rowPtr, colIdx } = g;\n const weights: NumericVector | null = options.weights ?? g.weights;\n const dist = new Float64Array(nodeCount).fill(Infinity);\n const predArc = new Uint32Array(nodeCount).fill(INVALID_INDEX);\n const heap = new IndexedMinHeap(nodeCount);\n const cutoff = options.cutoff ?? Infinity;\n dist[source] = 0;\n heap.push(source, 0);\n while (!heap.isEmpty()) {\n const u = heap.pop();\n const du = dist[u];\n const end = rowPtr[u + 1];\n for (let a = rowPtr[u]; a < end; a++) {\n const w = weights === null ? 1 : weights[a];\n const v = colIdx[a];\n const dv = du + w;\n if (dv < dist[v] && dv <= cutoff) {\n dist[v] = dv;\n predArc[v] = a;\n heap.pushOrDecrease(v, dv);\n }\n }\n }\n return {\n dist,\n predArc,\n pathTo: (target: number): U32 => walkPredArcs(g, predArc, source, target),\n pathEdges: (target: number): U32 => walkPredEdges(g, predArc, source, target),\n };\n}\n","import type { F64, GraphSnapshot } from \"@graphty/graph-format\";\n\n/** Options of the index-based HITS, matching the legacy `hits`. @public */\nexport interface HitsOptions {\n /** Iteration cap; default 100. */\n readonly maxIterations?: number | undefined;\n /** Convergence tolerance on the largest single-node change; default 1e-6. */\n readonly tolerance?: number | undefined;\n /**\n * `false` rescales both vectors so their largest entry is 1, which is what the legacy function\n * does when normalization is switched OFF -- the iteration itself always divides by the L2\n * norm. Default true, i.e. the L2-normalized vectors are returned unchanged.\n */\n readonly normalized?: boolean | undefined;\n /** Weight a neighbour's contribution by the arc weight; default false. */\n readonly weighted?: boolean | undefined;\n}\n\n/** Result of the index-based HITS. @public */\nexport interface HitsResult {\n /** Hub score per node index. */\n readonly hubs: F64;\n /** Authority score per node index. */\n readonly authorities: F64;\n /** Iterations actually run. */\n readonly iterations: number;\n /** Whether the largest single-node change fell below the tolerance. */\n readonly converged: boolean;\n}\n\n/**\n * Divide a vector by its L2 norm, in place; a zero vector is left alone.\n * @param v - The vector to scale\n */\nfunction l2Normalize(v: Float64Array): void {\n let sum = 0;\n for (let i = 0; i < v.length; i++) {\n sum += v[i] * v[i];\n }\n const norm = Math.sqrt(sum);\n if (norm > 0) {\n for (let i = 0; i < v.length; i++) {\n v[i] /= norm;\n }\n }\n}\n\n/**\n * Divide a vector by its largest entry, in place; left alone when that entry is not positive.\n * @param v - The vector to scale\n */\nfunction maxNormalize(v: Float64Array): void {\n let max = 0;\n for (let i = 0; i < v.length; i++) {\n if (v[i] > max) {\n max = v[i];\n }\n }\n if (max > 0) {\n for (let i = 0; i < v.length; i++) {\n v[i] /= max;\n }\n }\n}\n\n/**\n * HITS by alternating power iteration: an authority sums the hub scores of the nodes pointing at\n * it, a hub sums the authority scores of the nodes it points at, and both vectors are\n * L2-normalized every round. On an undirected snapshot the two adjacencies are the same array, so\n * the hubs and the authorities coincide.\n * @param s - The snapshot\n * @param o - Algorithm options\n * @returns The two score vectors, the iteration count and the convergence flag\n * @public\n */\nexport function hits(s: GraphSnapshot, o: HitsOptions = {}): HitsResult {\n const n = s.nodeCount;\n const maxIter = o.maxIterations ?? 100;\n const tol = o.tolerance ?? 1e-6;\n const rev = s.reverse();\n const fwdW = o.weighted === true ? s.weights : null;\n const revW = o.weighted === true ? rev.weights : null;\n let hubs = new Float64Array(n).fill(n === 0 ? 0 : 1 / Math.sqrt(n));\n let authorities = new Float64Array(n).fill(n === 0 ? 0 : 1 / Math.sqrt(n));\n let nextHubs = new Float64Array(n);\n let nextAuthorities = new Float64Array(n);\n let it = 0;\n let converged = false;\n for (; it < maxIter && !converged; it++) {\n for (let v = 0; v < n; v++) {\n let auth = 0;\n const inEnd = rev.rowPtr[v + 1];\n for (let a = rev.rowPtr[v]; a < inEnd; a++) {\n auth += hubs[rev.colIdx[a]] * (revW === null ? 1 : revW[a]);\n }\n nextAuthorities[v] = auth;\n let hub = 0;\n const outEnd = s.rowPtr[v + 1];\n for (let a = s.rowPtr[v]; a < outEnd; a++) {\n hub += authorities[s.colIdx[a]] * (fwdW === null ? 1 : fwdW[a]);\n }\n nextHubs[v] = hub;\n }\n l2Normalize(nextAuthorities);\n l2Normalize(nextHubs);\n let maxDiff = 0;\n for (let v = 0; v < n; v++) {\n const dh = Math.abs(nextHubs[v] - hubs[v]);\n if (dh > maxDiff) {\n maxDiff = dh;\n }\n const da = Math.abs(nextAuthorities[v] - authorities[v]);\n if (da > maxDiff) {\n maxDiff = da;\n }\n }\n [hubs, nextHubs] = [nextHubs, hubs];\n [authorities, nextAuthorities] = [nextAuthorities, authorities];\n converged = maxDiff < tol;\n }\n if (o.normalized === false) {\n maxNormalize(hubs);\n maxNormalize(authorities);\n }\n return { hubs, authorities, iterations: it, converged };\n}\n","import type { GraphSnapshot, U32 } from \"@graphty/graph-format\";\n\n/**\n * Result of the index-based k-core decomposition. `coreness` is the shape the accelerator seam\n * declares (`CorenessResultLike`); `maxCore` and `cores()` are what the legacy\n * `kCoreDecomposition` returns as `maxCore` and its `cores` map.\n * @public\n */\nexport interface CorenessResult {\n /** Core number per node index. */\n readonly coreness: U32;\n /** The largest core number present; 0 on an empty graph. */\n readonly maxCore: number;\n /**\n * Node indices grouped by core number, computed once and cached: `cores()[k]` holds the nodes\n * whose coreness is exactly k, so the array has `maxCore + 1` entries.\n * @returns One array per core number\n */\n cores(): U32[];\n}\n\n/**\n * Core number of every node, by the Batagelj-Zaversnik bucket peel: O(nodes + arcs), no priority\n * queue and no per-node object.\n *\n * Core numbers are defined on a SIMPLE graph, so a parallel arc counts once (parallels are\n * adjacent within a row, invariant I4) and a self-loop does not count at all -- which is what the\n * legacy implementation's adjacency-of-sets also does, and what NetworkX requires of its input.\n * @param s - An undirected snapshot\n * @returns The core numbers, the largest of them, and the lazy grouping\n * @public\n */\nexport function kCoreDecomposition(s: GraphSnapshot): CorenessResult {\n if (s.directed) {\n throw new Error(\"k-core requires an undirected graph. Pass s.toUndirected().snapshot.\");\n }\n const n = s.nodeCount;\n const { rowPtr, colIdx } = s;\n // degree[] is peeled in place: when a node is visited its entry is already its core number.\n const degree = new Uint32Array(n);\n let maxDegree = 0;\n for (let u = 0; u < n; u++) {\n let d = 0;\n let last = -1;\n const end = rowPtr[u + 1];\n for (let a = rowPtr[u]; a < end; a++) {\n const v = colIdx[a];\n if (v !== u && v !== last) {\n d++;\n }\n last = v;\n }\n degree[u] = d;\n if (d > maxDegree) {\n maxDegree = d;\n }\n }\n // Bucket sort the nodes by degree; bin[d] is the start of degree d's block in vert.\n const bin = new Uint32Array(maxDegree + 1);\n for (let u = 0; u < n; u++) {\n bin[degree[u]]++;\n }\n let start = 0;\n for (let d = 0; d <= maxDegree; d++) {\n const count = bin[d];\n bin[d] = start;\n start += count;\n }\n const vert = new Uint32Array(n);\n const pos = new Uint32Array(n);\n for (let u = 0; u < n; u++) {\n pos[u] = bin[degree[u]];\n vert[pos[u]] = u;\n bin[degree[u]]++;\n }\n for (let d = maxDegree; d > 0; d--) {\n bin[d] = bin[d - 1];\n }\n bin[0] = 0;\n // Peel in nondecreasing degree order. A neighbour of higher degree swaps to the front of its\n // bucket and loses one, which keeps vert sorted without re-sorting it.\n let maxCore = 0;\n for (let i = 0; i < n; i++) {\n const v = vert[i];\n const dv = degree[v];\n if (dv > maxCore) {\n maxCore = dv;\n }\n const end = rowPtr[v + 1];\n let last = -1;\n for (let a = rowPtr[v]; a < end; a++) {\n const u = colIdx[a];\n const skip = u === v || u === last;\n last = u;\n if (skip) {\n continue;\n }\n const du = degree[u];\n if (du > dv) {\n const pu = pos[u];\n const pw = bin[du];\n const w = vert[pw];\n if (u !== w) {\n vert[pu] = w;\n vert[pw] = u;\n pos[u] = pw;\n pos[w] = pu;\n }\n bin[du]++;\n degree[u] = du - 1;\n }\n }\n }\n let cached: U32[] | null = null;\n return {\n coreness: degree,\n maxCore,\n cores(): U32[] {\n if (cached === null) {\n const sizes = new Uint32Array(maxCore + 1);\n for (let u = 0; u < n; u++) {\n sizes[degree[u]]++;\n }\n const out: U32[] = [];\n for (let k = 0; k <= maxCore; k++) {\n out.push(new Uint32Array(sizes[k]));\n }\n const fill = new Uint32Array(maxCore + 1);\n for (let u = 0; u < n; u++) {\n const k = degree[u];\n out[k][fill[k]++] = u;\n }\n cached = out;\n }\n return cached;\n },\n };\n}\n","import type { F64, GraphSnapshot } from \"@graphty/graph-format\";\n\n/** Options of the index-based Katz centrality, matching the legacy `katzCentrality`. @public */\nexport interface KatzOptions {\n /** Attenuation factor applied to a neighbour's score; default 0.1. */\n readonly alpha?: number | undefined;\n /** Base score every node starts with and keeps; default 1. */\n readonly beta?: number | undefined;\n /** Iteration cap; default 100. */\n readonly maxIterations?: number | undefined;\n /** Convergence tolerance on the largest single-node change; default 1e-6. */\n readonly tolerance?: number | undefined;\n /** Rescale the scores to [0, 1] by min-max, as the legacy function does; default true. */\n readonly normalized?: boolean | undefined;\n /** Weight a neighbour's contribution by the arc weight; default false. */\n readonly weighted?: boolean | undefined;\n}\n\n/** Result of the index-based Katz centrality. @public */\nexport interface KatzResult {\n /** Score per node index. */\n readonly scores: F64;\n /** Iterations actually run. */\n readonly iterations: number;\n /** Whether the largest single-node change fell below the tolerance. */\n readonly converged: boolean;\n}\n\n/**\n * Katz centrality by power iteration over incoming arcs: `x[v] = alpha * sum(x[u] for u -> v) + beta`.\n *\n * `reverse()` supplies the in-arcs, and is the forward adjacency itself on an undirected snapshot,\n * so one loop serves both directions exactly as the legacy function's in-neighbours / neighbours\n * split does.\n * @param s - The snapshot\n * @param o - Algorithm options\n * @returns The scores, the iteration count and the convergence flag\n * @public\n */\nexport function katzCentrality(s: GraphSnapshot, o: KatzOptions = {}): KatzResult {\n const n = s.nodeCount;\n const alpha = o.alpha ?? 0.1;\n const beta = o.beta ?? 1;\n const maxIter = o.maxIterations ?? 100;\n const tol = o.tolerance ?? 1e-6;\n const rev = s.reverse();\n const weights = o.weighted === true ? rev.weights : null;\n let cur = new Float64Array(n).fill(beta);\n let next = new Float64Array(n);\n let it = 0;\n let converged = false;\n for (; it < maxIter && !converged; it++) {\n let maxDiff = 0;\n for (let v = 0; v < n; v++) {\n let sum = 0;\n const end = rev.rowPtr[v + 1];\n for (let a = rev.rowPtr[v]; a < end; a++) {\n sum += cur[rev.colIdx[a]] * (weights === null ? 1 : weights[a]);\n }\n next[v] = alpha * sum + beta;\n const diff = Math.abs(next[v] - cur[v]);\n if (diff > maxDiff) {\n maxDiff = diff;\n }\n }\n [cur, next] = [next, cur];\n converged = maxDiff < tol;\n }\n if (o.normalized !== false) {\n let min = Infinity;\n let max = -Infinity;\n for (let v = 0; v < n; v++) {\n if (cur[v] < min) {\n min = cur[v];\n }\n if (cur[v] > max) {\n max = cur[v];\n }\n }\n const range = max - min;\n if (range > 0) {\n for (let v = 0; v < n; v++) {\n cur[v] = (cur[v] - min) / range;\n }\n }\n }\n return { scores: cur, iterations: it, converged };\n}\n","import { type GraphSnapshot, renumberPartition } from \"@graphty/graph-format\";\n\nimport { type LabelResult, withGroups } from \"./components.js\";\n\n/** Options of the index-based Louvain, matching the legacy `louvain`. @public */\nexport interface LouvainOptions {\n /** Resolution gamma: above 1 favours smaller communities; default 1. */\n readonly resolution?: number | undefined;\n /** Cap on aggregation levels, and on node visits per node within a level; default 100. */\n readonly maxIterations?: number | undefined;\n /** Stop when a level improves modularity by less than this; default 1e-6. */\n readonly tolerance?: number | undefined;\n}\n\n/** Result of the index-based Louvain: a partition plus the modularity it reaches. @public */\nexport interface LouvainResult extends LabelResult {\n /** Modularity of the returned partition, at the requested resolution. */\n readonly modularity: number;\n /** Aggregation levels that improved the partition. */\n readonly iterations: number;\n}\n\n/**\n * One level of the Louvain hierarchy as a weighted adjacency with the self-loops lifted out.\n *\n * Self-loops live in `loop` rather than in the arc list, so the local-moving loop never meets a\n * node as its own neighbour, and `deg` (the null-model term) counts a self-loop twice, which is\n * the NetworkX weighted-degree convention: summing `deg` gives 2m at every level.\n */\ninterface Level {\n /** Node count of this level. */\n readonly n: number;\n /** n + 1 row offsets into colIdx / w. */\n readonly rowPtr: Uint32Array;\n /** Neighbour of every arc; no arc targets its own row. */\n readonly colIdx: Uint32Array;\n /** Weight of every arc. */\n readonly w: Float64Array;\n /** Self-loop weight per node, counted ONCE (as an edge weight). */\n readonly loop: Float64Array;\n /** Weighted degree per node: the row's arc weights plus twice its self-loop weight. */\n readonly deg: Float64Array;\n}\n\n/**\n * Level 0: the snapshot's own arcs, with the self-loop arcs moved into `loop`.\n * @param s - An undirected snapshot\n * @returns The first level\n */\nfunction buildLevel0(s: GraphSnapshot): Level {\n const n = s.nodeCount;\n const rowPtr = new Uint32Array(n + 1);\n for (let u = 0; u < n; u++) {\n let kept = 0;\n const end = s.rowPtr[u + 1];\n for (let a = s.rowPtr[u]; a < end; a++) {\n if (s.colIdx[a] !== u) {\n kept++;\n }\n }\n rowPtr[u + 1] = rowPtr[u] + kept;\n }\n const arcs = rowPtr[n];\n const colIdx = new Uint32Array(arcs);\n const w = new Float64Array(arcs);\n const loop = new Float64Array(n);\n const deg = new Float64Array(n);\n let k = 0;\n for (let u = 0; u < n; u++) {\n let rowWeight = 0;\n const end = s.rowPtr[u + 1];\n for (let a = s.rowPtr[u]; a < end; a++) {\n const v = s.colIdx[a];\n const weight = s.weights === null ? 1 : s.weights[a];\n if (v === u) {\n loop[u] += weight;\n } else {\n colIdx[k] = v;\n w[k] = weight;\n k++;\n rowWeight += weight;\n }\n }\n deg[u] = rowWeight + 2 * loop[u];\n }\n return { n, rowPtr, colIdx, w, loop, deg };\n}\n\n/**\n * Modularity of a partition of one level: `sum_c in_c / 2m - gamma * (tot_c / 2m)^2`, with `in_c`\n * counting each internal edge twice. This is the same quantity the legacy `calculateModularity`\n * computes over a `Graph`, written per arc.\n * @param level - The level the partition is over\n * @param comm - Community of every node of that level\n * @param count - Number of communities, so `comm` is within `[0, count)`\n * @param resolution - Resolution gamma\n * @param m2 - Twice the total edge weight\n * @returns The modularity\n */\nfunction modularityOf(level: Level, comm: Uint32Array, count: number, resolution: number, m2: number): number {\n const inside = new Float64Array(count);\n const tot = new Float64Array(count);\n for (let u = 0; u < level.n; u++) {\n const c = comm[u];\n tot[c] += level.deg[u];\n inside[c] += 2 * level.loop[u];\n const end = level.rowPtr[u + 1];\n for (let a = level.rowPtr[u]; a < end; a++) {\n if (comm[level.colIdx[a]] === c) {\n inside[c] += level.w[a];\n }\n }\n }\n let q = 0;\n for (let c = 0; c < count; c++) {\n const share = tot[c] / m2;\n q += inside[c] / m2 - resolution * share * share;\n }\n return q;\n}\n\n/**\n * Phase one: move each node to the neighbouring community with the largest modularity gain, until\n * no move is left to make.\n *\n * Nodes wait in a queue rather than in repeated sweeps over all of them, which is what makes this\n * affordable on a graph with no community structure: there the last moves are worth a millionth of\n * a point each and go on for dozens of passes, and a pass costs every node and every arc whether or\n * not anything can move. A node enters the queue when a neighbour leaves its community, so the tail\n * of the run costs the handful of nodes that can still move. Same fixed point, and it is the rule\n * networkx's `louvain_communities` follows.\n * @param level - The level to optimise\n * @param comm - Output: community of every node, overwritten with the singleton partition first\n * @param resolution - Resolution gamma\n * @param m2 - Twice the total edge weight\n * @param maxVisitsPerNode - Cap on node visits, as a multiple of the node count\n * @returns Whether any node moved\n */\nfunction localMove(level: Level, comm: Uint32Array, resolution: number, m2: number, maxVisitsPerNode: number): boolean {\n const { n } = level;\n const tot = new Float64Array(n);\n for (let u = 0; u < n; u++) {\n comm[u] = u;\n tot[u] = level.deg[u];\n }\n const acc = new Float64Array(n);\n // A visit stamp rather than a clear pass: `mark` grows monotonically over the whole run, so a\n // value left in acc by an earlier visit is never mistaken for this one's.\n const stamp = new Int32Array(n).fill(-1);\n const touched = new Uint32Array(n);\n // A ring of n + 1 slots: `queued` keeps a node out of the queue twice, so n entries is the most\n // that can be waiting.\n const capacity = n + 1;\n const queue = new Uint32Array(capacity);\n const queued = new Uint8Array(n);\n let head = 0;\n let tail = n;\n for (let u = 0; u < n; u++) {\n queue[u] = u;\n queued[u] = 1;\n }\n let mark = 0;\n let visits = 0;\n const maxVisits = maxVisitsPerNode * n;\n let movedAny = false;\n while (head !== tail && visits < maxVisits) {\n const u = queue[head];\n head = head + 1 === capacity ? 0 : head + 1;\n queued[u] = 0;\n visits++;\n const cu = comm[u];\n const ku = level.deg[u];\n tot[cu] -= ku;\n mark++;\n let cnt = 0;\n const end = level.rowPtr[u + 1];\n for (let a = level.rowPtr[u]; a < end; a++) {\n const c = comm[level.colIdx[a]];\n if (stamp[c] !== mark) {\n stamp[c] = mark;\n acc[c] = 0;\n touched[cnt++] = c;\n }\n acc[c] += level.w[a];\n }\n let best = cu;\n let bestGain = (stamp[cu] === mark ? acc[cu] : 0) - (resolution * ku * tot[cu]) / m2;\n for (let i = 0; i < cnt; i++) {\n const c = touched[i];\n if (c === cu) {\n continue;\n }\n const gain = acc[c] - (resolution * ku * tot[c]) / m2;\n if (gain > bestGain) {\n bestGain = gain;\n best = c;\n }\n }\n tot[best] += ku;\n if (best !== cu) {\n comm[u] = best;\n movedAny = true;\n // Only a neighbour outside the community u just joined can gain from u's move.\n for (let a = level.rowPtr[u]; a < end; a++) {\n const v = level.colIdx[a];\n if (queued[v] === 0 && comm[v] !== best) {\n queued[v] = 1;\n queue[tail] = v;\n tail = tail + 1 === capacity ? 0 : tail + 1;\n }\n }\n }\n }\n return movedAny;\n}\n\n/**\n * Phase two: every community becomes one node, the edges between two communities merge into one\n * arc, and the edges inside a community become that node's self-loop. Rows are NOT sorted by\n * neighbour index; nothing downstream of here needs them to be.\n * @param level - The level to collapse\n * @param comm - Dense community of every node of that level\n * @param count - Number of communities\n * @returns The next level, with `count` nodes\n */\nfunction aggregate(level: Level, comm: Uint32Array, count: number): Level {\n const start = new Uint32Array(count + 1);\n for (let u = 0; u < level.n; u++) {\n start[comm[u] + 1]++;\n }\n for (let c = 0; c < count; c++) {\n start[c + 1] += start[c];\n }\n const members = new Uint32Array(level.n);\n const fill = start.slice(0, count);\n for (let u = 0; u < level.n; u++) {\n members[fill[comm[u]]++] = u;\n }\n const rowPtr = new Uint32Array(count + 1);\n const colIdx = new Uint32Array(level.colIdx.length);\n const w = new Float64Array(level.colIdx.length);\n const loop = new Float64Array(count);\n const deg = new Float64Array(count);\n const acc = new Float64Array(count);\n const stamp = new Int32Array(count).fill(-1);\n const touched = new Uint32Array(count);\n let k = 0;\n for (let c = 0; c < count; c++) {\n rowPtr[c] = k;\n let internalArcs = 0;\n let cnt = 0;\n for (let i = start[c]; i < start[c + 1]; i++) {\n const u = members[i];\n loop[c] += level.loop[u];\n const end = level.rowPtr[u + 1];\n for (let a = level.rowPtr[u]; a < end; a++) {\n const other = comm[level.colIdx[a]];\n if (other === c) {\n internalArcs += level.w[a];\n continue;\n }\n if (stamp[other] !== c) {\n stamp[other] = c;\n acc[other] = 0;\n touched[cnt++] = other;\n }\n acc[other] += level.w[a];\n }\n }\n // An edge between two members shows up as two arcs, one from each end.\n loop[c] += internalArcs / 2;\n let rowWeight = 0;\n for (let i = 0; i < cnt; i++) {\n const other = touched[i];\n colIdx[k] = other;\n w[k] = acc[other];\n rowWeight += acc[other];\n k++;\n }\n deg[c] = rowWeight + 2 * loop[c];\n }\n rowPtr[count] = k;\n return { n: count, rowPtr, colIdx: colIdx.subarray(0, k), w: w.subarray(0, k), loop, deg };\n}\n\n/**\n * Louvain community detection over a snapshot: local moving to the best modularity gain, then\n * collapse each community into a node and repeat, until a level stops paying for itself.\n *\n * The legacy `louvain` switches implementation at 50 nodes (`useOptimized`) and its small-graph\n * path has no aggregation phase at all, so this port is not move-for-move identical to either\n * branch of it -- what it guarantees is a partition whose modularity is at least as high, measured\n * by the same formula.\n * @param s - An undirected snapshot\n * @param o - Algorithm options\n * @returns The partition, its modularity, and the number of levels that improved it\n * @public\n */\nexport function louvain(s: GraphSnapshot, o: LouvainOptions = {}): LouvainResult {\n if (s.directed) {\n throw new Error(\"Louvain requires an undirected graph. Pass s.toUndirected().snapshot.\");\n }\n const resolution = o.resolution ?? 1;\n const maxIterations = o.maxIterations ?? 100;\n const tolerance = o.tolerance ?? 1e-6;\n const n0 = s.nodeCount;\n const labels = new Uint32Array(n0);\n for (let u = 0; u < n0; u++) {\n labels[u] = u;\n }\n let level = buildLevel0(s);\n let m2 = 0;\n for (let u = 0; u < n0; u++) {\n m2 += level.deg[u];\n }\n if (m2 === 0) {\n // No edge weight to redistribute: every node is its own community and Q is 0 by definition,\n // which is what the legacy `calculateModularity` also answers.\n return { ...withGroups(labels, n0), modularity: 0, iterations: 0 };\n }\n let q = modularityOf(level, labels, n0, resolution, m2);\n let iterations = 0;\n for (let iteration = 0; iteration < maxIterations; iteration++) {\n const comm = new Uint32Array(level.n);\n if (!localMove(level, comm, resolution, m2, maxIterations)) {\n break;\n }\n const dense = renumberPartition(comm);\n const { count } = dense;\n const packed = dense.labels;\n const newQ = modularityOf(level, packed, count, resolution, m2);\n for (let u = 0; u < n0; u++) {\n labels[u] = packed[labels[u]];\n }\n iterations = iteration + 1;\n const gain = newQ - q;\n q = newQ;\n if (gain < tolerance || count === level.n) {\n break;\n }\n level = aggregate(level, packed, count);\n }\n const final = renumberPartition(labels);\n return { ...withGroups(final.labels, final.count), modularity: q, iterations };\n}\n","import type { GraphSnapshot, NumericVector, U32 } from \"@graphty/graph-format\";\n\nimport { IntUnionFind } from \"./structures/union-find.js\";\n\n/** Options of the index-based MST. @public */\nexport interface MstOptions {\n /** Per-arc weight override, arcCount long; gathered back to per-edge through `edgeToArc`. */\n readonly weights?: NumericVector | undefined;\n}\n\n/** Result of the index-based MST (graph-format design 14.2's result table, line 3745). @public */\nexport interface MstResult {\n /** Logical edge indices of the spanning forest, in the order they were accepted. */\n readonly edges: U32;\n /** Sum of the accepted edges' weights. */\n readonly totalWeight: number;\n}\n\n/**\n * Kruskal's minimum spanning forest over logical edges.\n *\n * The sort is a comparator over an f64 key array, tie-broken by edge index, rather than the\n * design's radix sort on the f32 bit pattern (plan departure DEP-8A-D): the tie-break makes it\n * stable by construction and it has to serve both the f32 arc array and an f64 override.\n * @param s - The snapshot\n * @param o - The optional per-arc weight override\n * @returns The accepted edge indices and their total weight\n * @public\n */\nexport function kruskalMST(s: GraphSnapshot, o: MstOptions = {}): MstResult {\n const el = s.edgeList();\n const m = s.edgeCount;\n const keys = new Float64Array(m);\n if (o.weights !== undefined) {\n // The override is per ARC; edgeList().arc holds the arc of each edge's declared orientation.\n for (let e = 0; e < m; e++) {\n keys[e] = o.weights[el.arc[e]];\n }\n } else if (el.weights !== null) {\n for (let e = 0; e < m; e++) {\n keys[e] = el.weights[e];\n }\n } else {\n keys.fill(1);\n }\n const order: number[] = new Array<number>(m);\n for (let e = 0; e < m; e++) {\n order[e] = e;\n }\n order.sort((a, b) => keys[a] - keys[b] || a - b);\n const uf = new IntUnionFind(s.nodeCount);\n const accepted = new Uint32Array(Math.max(s.nodeCount - 1, 0));\n let taken = 0;\n let totalWeight = 0;\n for (const e of order) {\n if (uf.union(el.src[e], el.dst[e])) {\n accepted[taken++] = e;\n totalWeight += keys[e];\n }\n }\n return { edges: accepted.subarray(0, taken), totalWeight };\n}\n","import type { F64, GraphSnapshot, NumericVector } from \"@graphty/graph-format\";\n\n/** Options of the index-based PageRank (graph-format design 14.2 Port 3, line 3892). @public */\nexport interface PageRankOptions {\n /** Probability of following a link; default 0.85. */\n readonly dampingFactor?: number | undefined;\n /** Iteration cap; default 100. */\n readonly maxIterations?: number | undefined;\n /** L1 convergence tolerance; default 1e-6. */\n readonly tolerance?: number | undefined;\n /** Use the snapshot's arc weights; default false. */\n readonly weighted?: boolean | undefined;\n}\n\n/** Result of the index-based PageRank. @public */\nexport interface PageRankResult {\n /** Score per node index. */\n readonly scores: F64;\n /** Iterations actually run. */\n readonly iterations: number;\n /** Whether the L1 delta fell below the tolerance. */\n readonly converged: boolean;\n}\n\n/**\n * PageRank by pull over `reverse()`, with the dangling mass redistributed uniformly.\n * @param s - A DIRECTED snapshot\n * @param o - Algorithm options\n * @returns The scores, the iteration count and the convergence flag\n * @public\n */\nexport function pageRank(s: GraphSnapshot, o: PageRankOptions = {}): PageRankResult {\n if (!s.directed) {\n throw new Error(\"PageRank requires a directed graph\");\n }\n const n = s.nodeCount;\n const d = o.dampingFactor ?? 0.85;\n const maxIter = o.maxIterations ?? 100;\n const tol = o.tolerance ?? 1e-6;\n const rev = s.reverse();\n const weighted = o.weighted === true && rev.weights !== null;\n const outW: NumericVector = weighted ? s.weightedOutDegree() : s.outDegree();\n let rank = new Float64Array(n).fill(1 / n);\n let next = new Float64Array(n);\n let it = 0;\n let converged = false;\n for (; it < maxIter && !converged; it++) {\n let dangling = 0;\n for (let u = 0; u < n; u++) {\n if (outW[u] === 0) {\n dangling += rank[u];\n }\n }\n const base = (1 - d) / n + (d * dangling) / n;\n let delta = 0;\n for (let v = 0; v < n; v++) {\n let acc = 0;\n const end = rev.rowPtr[v + 1];\n for (let a = rev.rowPtr[v]; a < end; a++) {\n const u = rev.colIdx[a];\n const ow = outW[u];\n if (ow > 0) {\n acc += (rank[u] * (weighted && rev.weights !== null ? rev.weights[a] : 1)) / ow;\n }\n }\n next[v] = base + d * acc;\n delta += Math.abs(next[v] - rank[v]);\n }\n [rank, next] = [next, rank];\n converged = delta < tol;\n }\n return { scores: rank, iterations: it, converged };\n}\n","/**\n * Conversion from the legacy `Graph` class to a frozen graph-format snapshot\n * (graph-format design 14.1 rule 4, 14.6 row A1). This is the ONLY bridge between the legacy\n * Map-of-Maps surface and `indexed.*`; nothing under `src/indexed/` other than this file imports\n * `../core/graph.js`.\n * @module\n */\n\nimport { GraphBuilder, type GraphSnapshot } from \"@graphty/graph-format\";\n\nimport type { Graph } from \"../core/graph.js\";\n\n/** Options of {@link toSnapshot}. @public */\nexport interface ToSnapshotOptions {\n /**\n * Record FNV-1a checksums at freeze so a caller can assert `snapshot.validate({ checksum: true })`\n * (graph-format design 14.2's first port rule: views are shared, so a port that writes into one\n * has to fail a test rather than corrupt the next call). Default false; the test suites set it.\n */\n readonly checksum?: boolean | undefined;\n}\n\ninterface CacheEntry {\n readonly mutationCount: number;\n readonly checksum: boolean;\n readonly snapshot: GraphSnapshot;\n}\n\n/**\n * One entry per graph, REPLACED rather than appended to on a mutation. The entry holds the\n * mutationCount it was built at, which is what makes a stale hit impossible -- the bug the old\n * `WeakMap<Graph, CSRGraph>` cache had (graph-format design 14.1 rule 4).\n */\nconst SNAPSHOT_CACHE = new WeakMap<Graph, CacheEntry>();\n\n/**\n * Freeze a legacy `Graph` into a `GraphSnapshot`, memoised on the graph's `mutationCount`.\n *\n * The builder is created with `weightDtype: \"f64\"` so a legacy graph's double weights survive\n * exactly: at freeze, graph-format keeps the original values in an f64 edge column with role\n * `weight` (the \"shadow\") whenever at least one of them is not f32-exact, and costs nothing when\n * they all are (graph-format design section 3.7, `graph-format/src/builder/freeze.ts:332-360`).\n * A weighted `indexed.*` port reproduces legacy f64 results by passing\n * `expandEdges(s, shadow.data)` as its per-arc `weights` override.\n *\n * Every legacy edge carries a weight (`Graph.addEdge` defaults it to 1), so the builder's\n * `weighted: \"auto\"` always allocates the arc weight array -- 4 bytes per arc. That is truthful\n * rather than wasteful: the legacy graph really does store the value.\n * @param graph - The legacy graph to convert\n * @param options - Conversion options\n * @returns A frozen snapshot of the graph's current topology and weights\n * @public\n */\nexport function toSnapshot(graph: Graph, options: ToSnapshotOptions = {}): GraphSnapshot {\n const checksum = options.checksum === true;\n const cached = SNAPSHOT_CACHE.get(graph);\n // A checksummed snapshot answers a plain request; a plain one cannot answer a checksummed\n // request -- validate({ checksum: true }) throws E_INVALID_SNAPSHOT (\"no-checksum\") when none\n // were recorded (graph-format/src/types/snapshot.ts:401-405).\n if (cached !== undefined && cached.mutationCount === graph.mutationCount && (cached.checksum || !checksum)) {\n return cached.snapshot;\n }\n const builder = new GraphBuilder({\n directed: graph.isDirected,\n weightDtype: \"f64\",\n expectedNodes: graph.nodeCount,\n expectedEdges: graph.totalEdgeCount,\n });\n for (const node of graph.nodes()) {\n builder.addNode(node.id);\n }\n for (const edge of graph.edges()) {\n builder.addEdge(edge.source, edge.target, edge.weight);\n }\n const snapshot = builder.freeze({ label: \"algorithms.toSnapshot\", checksum });\n SNAPSHOT_CACHE.set(graph, { mutationCount: graph.mutationCount, checksum, snapshot });\n return snapshot;\n}\n","/**\n * The accelerator seam of `@graphty/algorithms` (WebGPU design section 9.2). It contains NO\n * WebGPU types: an accelerator is anything that satisfies `AlgorithmAccelerator` structurally,\n * and this package never imports the GPU package (design section 9.1, the dependency direction).\n *\n * `accelerated(acc)` is the ONE dispatcher object (design section 9.2, the dispatcher rule); the\n * spelling is `accelerated(acc).pageRank(s, options)`, never\n * `runAlgorithm(snapshot, { accelerator })`. There is no try/catch anywhere below: an accelerator\n * method that throws propagates its throw unchanged, because a silent CPU fallback would hide a\n * broken device behind a slow answer.\n * @module\n */\n\nimport type { F32, F64, GraphSnapshot, NumericVector, U32 } from \"@graphty/graph-format\";\n\nimport type { BfsOptions } from \"./bfs.js\";\nimport { type SsspOptions, type SsspResult, walkPredArcs, walkPredEdges } from \"./dijkstra.js\";\nimport type { HitsOptions } from \"./hits.js\";\nimport * as indexed from \"./index.js\";\nimport type { KatzOptions } from \"./katz.js\";\nimport type { LouvainOptions } from \"./louvain.js\";\nimport type { MstOptions } from \"./mst.js\";\nimport type { PageRankOptions } from \"./pagerank.js\";\n\n// ============================================================ result shapes (design 9.2 lines 2909-2922)\n// Scores may be f32 (an accelerator) or f64 (the CPU ports), so every score field is NumericVector.\n\n/** A score vector with its convergence report. @public */\nexport interface ScoresResultLike {\n readonly scores: NumericVector;\n readonly iterations: number;\n readonly converged: boolean;\n}\n/** ScoresResultLike plus the mass held by dangling nodes. @public */\nexport interface PageRankResultLike extends ScoresResultLike {\n readonly danglingMass?: number | undefined;\n}\n/** The two HITS vectors with their convergence report. @public */\nexport interface HitsResultLike {\n readonly hubs: NumericVector;\n readonly authorities: NumericVector;\n readonly iterations: number;\n readonly converged: boolean;\n}\n/** A partition: dense labels, a count, and the grouped node indices. @public */\nexport interface LabelResultLike {\n readonly labels: U32;\n readonly count: number;\n groups(): U32[];\n}\n/** A breadth-first traversal. @public */\nexport interface BfsResultLike {\n readonly depth: U32;\n readonly parent: U32;\n readonly order: U32;\n readonly visitedCount: number;\n}\n/** Single-source distances plus the relaxing arc per node. @public */\nexport interface SsspResultLike {\n readonly dist: NumericVector;\n readonly predArc: U32;\n}\n/** SsspResultLike plus the negative-cycle flag. @public */\nexport interface BellmanFordResultLike extends SsspResultLike {\n readonly hasNegativeCycle: boolean;\n}\n/** A per-logical-edge score vector. @public */\nexport interface EdgeScoresResultLike {\n readonly scores: NumericVector;\n}\n/** An all-pairs distance matrix, row-major, n by n. @public */\nexport interface ApspResultLike {\n readonly dist: NumericVector;\n readonly n: number;\n}\n/** Per-node coreness. @public */\nexport interface CorenessResultLike {\n readonly coreness: U32;\n}\n/** A spanning forest as logical edge indices. @public */\nexport interface MstResultLike {\n readonly edges: U32;\n readonly totalWeight: number;\n}\n/** A partition with its modularity. @public */\nexport interface CommunityResultLike extends LabelResultLike {\n readonly modularity: number;\n}\n\n// ============================================================ the injected object (design 9.2 lines 2925-2948)\n\n/**\n * The structural contract an injected accelerator satisfies. EVERY member except `kind` is\n * optional: an accelerator declares only what it implements, and the dispatcher runs the CPU port\n * for everything else. The list is the design's, in full, so that an accelerator written against\n * it needs no change as the ports land.\n * @public\n */\nexport interface AlgorithmAccelerator {\n readonly kind: string;\n pageRank?(s: GraphSnapshot, options?: PageRankOptions): Promise<PageRankResultLike>;\n personalizedPageRank?(\n s: GraphSnapshot,\n personalization: F32 | F64,\n options?: PageRankOptions,\n ): Promise<PageRankResultLike>;\n hits?(s: GraphSnapshot, options?: HitsOptionsLike): Promise<HitsResultLike>;\n eigenvectorCentrality?(s: GraphSnapshot, options?: HitsOptionsLike): Promise<ScoresResultLike>;\n katzCentrality?(s: GraphSnapshot, options?: HitsOptionsLike): Promise<ScoresResultLike>;\n connectedComponents?(s: GraphSnapshot): Promise<LabelResultLike>;\n weaklyConnectedComponents?(s: GraphSnapshot): Promise<LabelResultLike>;\n breadthFirstSearch?(s: GraphSnapshot, source: number, options?: BfsOptions): Promise<BfsResultLike>;\n sssp?(s: GraphSnapshot, source: number, options?: SsspOptions): Promise<SsspResultLike>;\n bellmanFord?(s: GraphSnapshot, source: number, options?: SsspOptions): Promise<BellmanFordResultLike>;\n closenessCentrality?(s: GraphSnapshot, options?: HitsOptionsLike): Promise<ScoresResultLike>;\n betweennessCentrality?(s: GraphSnapshot, options?: BetweennessAcceleratorOptions): Promise<ScoresResultLike>;\n edgeBetweennessCentrality?(\n s: GraphSnapshot,\n options?: BetweennessAcceleratorOptions,\n ): Promise<EdgeScoresResultLike>;\n allPairsShortestPath?(s: GraphSnapshot, options?: SsspOptions): Promise<ApspResultLike>;\n kCoreDecomposition?(s: GraphSnapshot): Promise<CorenessResultLike>;\n triangleCount?(s: GraphSnapshot): Promise<{ readonly perNode: U32; readonly total: number }>;\n labelPropagation?(s: GraphSnapshot, options?: HitsOptionsLike): Promise<LabelResultLike>;\n minimumSpanningTree?(s: GraphSnapshot, options?: MstOptions): Promise<MstResultLike>;\n louvain?(s: GraphSnapshot, options?: HitsOptionsLike): Promise<CommunityResultLike>;\n release?(s: GraphSnapshot): void;\n dispose?(): void;\n}\n\n/**\n * The option shape of the power-iteration family until each one's `indexed.*` port lands and\n * brings its real option type (plan decision PD-2's \"NOT TOUCHED\" rows). It is DELIBERATELY not\n * `Record<string, unknown>`: these three are the members every one of those algorithms takes, so\n * an accelerator can honour them today and the type narrows rather than widens as ports arrive.\n * @public\n */\nexport interface HitsOptionsLike {\n readonly maxIterations?: number | undefined;\n readonly tolerance?: number | undefined;\n readonly weighted?: boolean | undefined;\n}\n\n/**\n * Betweenness options as the accelerator sees them: node INDICES, which is the only form that\n * means anything on a snapshot (plan decision PD-5).\n * @public\n */\nexport interface BetweennessAcceleratorOptions {\n readonly normalized?: boolean | undefined;\n readonly endpoints?: boolean | undefined;\n readonly sources?: readonly number[] | undefined;\n readonly k?: number | undefined;\n}\n\n// ============================================================ the dispatcher (design 9.2 lines 2950-2957)\n\n/**\n * The async dispatcher: one method per accelerable `indexed.*` function. Each delegates to the\n * accelerator when it has the method and runs the CPU port otherwise, wrapped in `Promise.resolve`\n * so both paths are async and graphty-element's `async run()` adapters treat them alike.\n *\n * The list GROWS with the A2 ports -- each port PR adds its method (plan departure DEP-8A-E).\n *\n * The four newest methods take their port's own option type, which is WIDER than the\n * `HitsOptionsLike` the accelerator side still declares: an accelerator therefore never sees Katz's\n * `alpha` / `beta` or Louvain's `resolution`, and one that is handed them would answer a different\n * question than the CPU port. Narrowing `AlgorithmAccelerator` is a change to the interface the GPU\n * package implements, so it belongs to the pull request that lands a GPU Louvain or Katz.\n * @public\n */\nexport interface AcceleratedAlgorithms {\n readonly accelerator: AlgorithmAccelerator | null;\n pageRank(s: GraphSnapshot, options?: PageRankOptions): Promise<PageRankResultLike>;\n sssp(s: GraphSnapshot, source: number, options?: SsspOptions): Promise<SsspResult>;\n breadthFirstSearch(s: GraphSnapshot, source: number, options?: BfsOptions): Promise<BfsResultLike>;\n connectedComponents(s: GraphSnapshot): Promise<LabelResultLike>;\n weaklyConnectedComponents(s: GraphSnapshot): Promise<LabelResultLike>;\n minimumSpanningTree(s: GraphSnapshot, options?: MstOptions): Promise<MstResultLike>;\n kCoreDecomposition(s: GraphSnapshot): Promise<CorenessResultLike>;\n katzCentrality(s: GraphSnapshot, options?: KatzOptions): Promise<ScoresResultLike>;\n hits(s: GraphSnapshot, options?: HitsOptions): Promise<HitsResultLike>;\n louvain(s: GraphSnapshot, options?: LouvainOptions): Promise<CommunityResultLike>;\n}\n\n/**\n * Attach `pathTo` / `pathEdges` to an accelerator's bare `{ dist, predArc }`, so both paths return\n * the design's `SsspResult` and the element keeps ONE result-writing loop. The GPU package cannot\n * attach them itself: it must not depend on the CPU package at runtime (design 9.2 line 2971, D3).\n * @param s - The snapshot the search ran on\n * @param source - The search's source node index\n * @param like - The accelerator's result\n * @returns The decorated result\n */\nfunction decorateSssp(s: GraphSnapshot, source: number, like: SsspResultLike): SsspResult {\n const { predArc } = like;\n return {\n dist: like.dist,\n predArc,\n pathTo: (target: number): U32 => walkPredArcs(s, predArc, source, target),\n pathEdges: (target: number): U32 => walkPredEdges(s, predArc, source, target),\n };\n}\n\n/**\n * Build the dispatcher for an accelerator, or for none.\n * @param acc - The injected accelerator, or `null` / `undefined` for the CPU path\n * @returns A dispatcher whose methods delegate where they can and run the CPU port otherwise\n * @public\n */\nexport function accelerated(acc: AlgorithmAccelerator | null | undefined): AcceleratedAlgorithms {\n return {\n accelerator: acc ?? null,\n pageRank: (s, options) =>\n acc?.pageRank !== undefined ? acc.pageRank(s, options) : Promise.resolve(indexed.pageRank(s, options)),\n sssp: (s, source, options) =>\n acc?.sssp !== undefined\n ? acc.sssp(s, source, options).then((like) => decorateSssp(s, source, like))\n : Promise.resolve(indexed.dijkstra(s, source, options)),\n breadthFirstSearch: (s, source, options) =>\n acc?.breadthFirstSearch !== undefined\n ? acc.breadthFirstSearch(s, source, options)\n : Promise.resolve(indexed.breadthFirstSearch(s, source, options)),\n connectedComponents: (s) =>\n acc?.connectedComponents !== undefined\n ? acc.connectedComponents(s)\n : Promise.resolve(indexed.connectedComponents(s)),\n weaklyConnectedComponents: (s) =>\n acc?.weaklyConnectedComponents !== undefined\n ? acc.weaklyConnectedComponents(s)\n : Promise.resolve(indexed.weaklyConnectedComponents(s)),\n minimumSpanningTree: (s, options) =>\n acc?.minimumSpanningTree !== undefined\n ? acc.minimumSpanningTree(s, options)\n : Promise.resolve(indexed.kruskalMST(s, options)),\n kCoreDecomposition: (s) =>\n acc?.kCoreDecomposition !== undefined\n ? acc.kCoreDecomposition(s)\n : Promise.resolve(indexed.kCoreDecomposition(s)),\n katzCentrality: (s, options) =>\n acc?.katzCentrality !== undefined\n ? acc.katzCentrality(s, options)\n : Promise.resolve(indexed.katzCentrality(s, options)),\n hits: (s, options) =>\n acc?.hits !== undefined ? acc.hits(s, options) : Promise.resolve(indexed.hits(s, options)),\n louvain: (s, options) =>\n acc?.louvain !== undefined ? acc.louvain(s, options) : Promise.resolve(indexed.louvain(s, options)),\n };\n}\n"],"names":["this","SparseTypedFastBitSet_1","require$$0","Type","SparseTypedFastBitSet","index","TypedFastBitSet_1","TypedFastBitSet","exports","require$$1","nodeId","breadthFirstSearch","hasNegativeCycle","element","dijkstra","hits","katzCentrality","pageRank","result","connectedComponents","weaklyConnectedComponents","kruskalMST","calculateModularity","getTotalEdgeWeight","getNodeDegree","nodeLabel","getNeighborCommunities","aggregate","louvain","u","v","graphToAdjacencySet","degreeV","kCoreDecomposition","communities","clusterAssignments","commonNeighborsScore","leftIndices","rightIndices","indexed.pageRank","indexed.dijkstra","indexed.breadthFirstSearch","indexed.connectedComponents","indexed.weaklyConnectedComponents","indexed.kruskalMST","indexed.kCoreDecomposition","indexed.katzCentrality","indexed.hits","indexed.louvain"],"mappings":"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","x_google_ignoreList":[2,3,4,5]}
|