graphwise 1.8.1 → 1.9.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/dist/{adjacency-map-D-Ul7V1r.js → adjacency-map-BtKzcuJq.js} +1 -1
- package/dist/{adjacency-map-D-Ul7V1r.js.map → adjacency-map-BtKzcuJq.js.map} +1 -1
- package/dist/{adjacency-map-B6wPtmaq.cjs → adjacency-map-JqBnMNkF.cjs} +1 -1
- package/dist/{adjacency-map-B6wPtmaq.cjs.map → adjacency-map-JqBnMNkF.cjs.map} +1 -1
- package/dist/async/index.cjs +2 -2
- package/dist/async/index.js +2 -2
- package/dist/expansion/index.cjs +1 -1
- package/dist/expansion/index.js +1 -1
- package/dist/{expansion-sldRognt.js → expansion-ClDhlMK8.js} +4 -4
- package/dist/{expansion-sldRognt.js.map → expansion-ClDhlMK8.js.map} +1 -1
- package/dist/{expansion-FkmEYlrQ.cjs → expansion-DaTroIyv.cjs} +4 -4
- package/dist/{expansion-FkmEYlrQ.cjs.map → expansion-DaTroIyv.cjs.map} +1 -1
- package/dist/extraction/index.cjs +1 -1
- package/dist/extraction/index.js +1 -1
- package/dist/gpu/csr.d.ts +29 -30
- package/dist/gpu/csr.d.ts.map +1 -1
- package/dist/gpu/dispatch.d.ts +31 -0
- package/dist/gpu/dispatch.d.ts.map +1 -0
- package/dist/gpu/dispatch.unit.test.d.ts +5 -0
- package/dist/gpu/dispatch.unit.test.d.ts.map +1 -0
- package/dist/gpu/index.cjs +15 -410
- package/dist/gpu/index.d.ts +3 -1
- package/dist/gpu/index.d.ts.map +1 -1
- package/dist/gpu/index.js +2 -400
- package/dist/gpu/kernels/bfs/kernel.d.ts +59 -0
- package/dist/gpu/kernels/bfs/kernel.d.ts.map +1 -0
- package/dist/gpu/kernels/bfs/logic.d.ts +47 -0
- package/dist/gpu/kernels/bfs/logic.d.ts.map +1 -0
- package/dist/gpu/kernels/bfs/logic.unit.test.d.ts +2 -0
- package/dist/gpu/kernels/bfs/logic.unit.test.d.ts.map +1 -0
- package/dist/gpu/kernels/degree-histogram/kernel.d.ts +32 -0
- package/dist/gpu/kernels/degree-histogram/kernel.d.ts.map +1 -0
- package/dist/gpu/kernels/degree-histogram/logic.d.ts +45 -0
- package/dist/gpu/kernels/degree-histogram/logic.d.ts.map +1 -0
- package/dist/gpu/kernels/degree-histogram/logic.unit.test.d.ts +2 -0
- package/dist/gpu/kernels/degree-histogram/logic.unit.test.d.ts.map +1 -0
- package/dist/gpu/kernels/jaccard/kernel.d.ts +40 -0
- package/dist/gpu/kernels/jaccard/kernel.d.ts.map +1 -0
- package/dist/gpu/kernels/jaccard/logic.d.ts +43 -0
- package/dist/gpu/kernels/jaccard/logic.d.ts.map +1 -0
- package/dist/gpu/kernels/jaccard/logic.unit.test.d.ts +2 -0
- package/dist/gpu/kernels/jaccard/logic.unit.test.d.ts.map +1 -0
- package/dist/gpu/kernels/pagerank/kernel.d.ts +44 -0
- package/dist/gpu/kernels/pagerank/kernel.d.ts.map +1 -0
- package/dist/gpu/kernels/pagerank/logic.d.ts +50 -0
- package/dist/gpu/kernels/pagerank/logic.d.ts.map +1 -0
- package/dist/gpu/kernels/pagerank/logic.unit.test.d.ts +2 -0
- package/dist/gpu/kernels/pagerank/logic.unit.test.d.ts.map +1 -0
- package/dist/gpu/kernels/spmv/kernel.d.ts +43 -0
- package/dist/gpu/kernels/spmv/kernel.d.ts.map +1 -0
- package/dist/gpu/kernels/spmv/logic.d.ts +31 -0
- package/dist/gpu/kernels/spmv/logic.d.ts.map +1 -0
- package/dist/gpu/kernels/spmv/logic.unit.test.d.ts +2 -0
- package/dist/gpu/kernels/spmv/logic.unit.test.d.ts.map +1 -0
- package/dist/gpu/operations.d.ts +76 -0
- package/dist/gpu/operations.d.ts.map +1 -0
- package/dist/gpu/operations.unit.test.d.ts +5 -0
- package/dist/gpu/operations.unit.test.d.ts.map +1 -0
- package/dist/gpu/root.d.ts +53 -0
- package/dist/gpu/root.d.ts.map +1 -0
- package/dist/gpu/root.unit.test.d.ts +2 -0
- package/dist/gpu/root.unit.test.d.ts.map +1 -0
- package/dist/gpu/types.d.ts +3 -8
- package/dist/gpu/types.d.ts.map +1 -1
- package/dist/gpu-CHiCN0wa.js +16945 -0
- package/dist/gpu-CHiCN0wa.js.map +1 -0
- package/dist/gpu-Y6owRVMi.cjs +17028 -0
- package/dist/gpu-Y6owRVMi.cjs.map +1 -0
- package/dist/graph/index.cjs +1 -1
- package/dist/graph/index.js +1 -1
- package/dist/index/index.cjs +18 -15
- package/dist/index/index.js +10 -10
- package/dist/{jaccard-Yddrtt5D.js → jaccard-3rCdilwm.js} +2 -2
- package/dist/{jaccard-Yddrtt5D.js.map → jaccard-3rCdilwm.js.map} +1 -1
- package/dist/{jaccard-Bmd1IEFO.cjs → jaccard-Bys9_dGW.cjs} +2 -2
- package/dist/{jaccard-Bmd1IEFO.cjs.map → jaccard-Bys9_dGW.cjs.map} +1 -1
- package/dist/{kmeans-D3yX5QFs.cjs → kmeans-B8x9D1kt.cjs} +1 -1
- package/dist/{kmeans-D3yX5QFs.cjs.map → kmeans-B8x9D1kt.cjs.map} +1 -1
- package/dist/{kmeans-DVCe61Me.js → kmeans-DKkL9rAN.js} +1 -1
- package/dist/{kmeans-DVCe61Me.js.map → kmeans-DKkL9rAN.js.map} +1 -1
- package/dist/{ops-4nmI-pwk.cjs → ops-djAsQQSh.cjs} +2 -2
- package/dist/{ops-4nmI-pwk.cjs.map → ops-djAsQQSh.cjs.map} +1 -1
- package/dist/{ops-Zsu4ecEG.js → ops-upIi6JIi.js} +2 -2
- package/dist/{ops-Zsu4ecEG.js.map → ops-upIi6JIi.js.map} +1 -1
- package/dist/{priority-queue-ChVLoG6T.cjs → priority-queue-BIiD1L0k.cjs} +1 -1
- package/dist/{priority-queue-ChVLoG6T.cjs.map → priority-queue-BIiD1L0k.cjs.map} +1 -1
- package/dist/{priority-queue-DqCuFTR8.js → priority-queue-CFDd5cBg.js} +1 -1
- package/dist/{priority-queue-DqCuFTR8.js.map → priority-queue-CFDd5cBg.js.map} +1 -1
- package/dist/ranking/index.cjs +2 -2
- package/dist/ranking/index.js +2 -2
- package/dist/ranking/mi/index.cjs +2 -2
- package/dist/ranking/mi/index.js +2 -2
- package/dist/{ranking-mUm9rV-C.js → ranking-3ez5m67U.js} +2 -2
- package/dist/{ranking-mUm9rV-C.js.map → ranking-3ez5m67U.js.map} +1 -1
- package/dist/{ranking-riRrEVAR.cjs → ranking-DVvajgUZ.cjs} +2 -2
- package/dist/{ranking-riRrEVAR.cjs.map → ranking-DVvajgUZ.cjs.map} +1 -1
- package/dist/seeds/index.cjs +1 -1
- package/dist/seeds/index.js +1 -1
- package/dist/structures/index.cjs +1 -1
- package/dist/structures/index.js +1 -1
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/{utils-CcIrKAEb.js → utils-BodeE2Mo.js} +1 -1
- package/dist/{utils-CcIrKAEb.js.map → utils-BodeE2Mo.js.map} +1 -1
- package/dist/{utils-CpyzmzIF.cjs → utils-CDtCcsyF.cjs} +1 -1
- package/dist/{utils-CpyzmzIF.cjs.map → utils-CDtCcsyF.cjs.map} +1 -1
- package/package.json +3 -1
- package/dist/gpu/context.d.ts +0 -118
- package/dist/gpu/context.d.ts.map +0 -1
- package/dist/gpu/context.unit.test.d.ts +0 -2
- package/dist/gpu/context.unit.test.d.ts.map +0 -1
- package/dist/gpu/index.cjs.map +0 -1
- package/dist/gpu/index.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adjacency-map-D-Ul7V1r.js","names":[],"sources":["../src/graph/adjacency-map.ts"],"sourcesContent":["/**\n * Adjacency map graph implementation.\n *\n * This module provides a flexible graph implementation using nested Maps\n * for efficient adjacency list representation. It supports both directed\n * and undirected graphs with builder pattern for convenient construction.\n */\n\nimport type { NodeId, NodeData, EdgeData, Direction } from \"./types\";\nimport type { MutableGraph } from \"./interfaces\";\n\n/**\n * Graph implementation using adjacency map data structure.\n *\n * Uses Map<NodeId, N> for node storage and Map<NodeId, Map<NodeId, E>>\n * for adjacency representation. This provides O(1) average-case lookup\n * for nodes and edges, with memory proportional to V + E.\n *\n * @typeParam N - Node data type, must extend NodeData\n * @typeParam E - Edge data type, must extend EdgeData\n *\n * @example\n * ```typescript\n * // Create a directed citation graph\n * const graph = AdjacencyMapGraph.directed<AuthorNode, CitationEdge>()\n * .addNode({ id: 'A1', name: 'Alice' })\n * .addNode({ id: 'B1', name: 'Bob' })\n * .addEdge({ source: 'A1', target: 'B1', year: 2024 });\n * ```\n */\nexport class AdjacencyMapGraph<\n\tN extends NodeData = NodeData,\n\tE extends EdgeData = EdgeData,\n> implements MutableGraph<N, E> {\n\treadonly directed: boolean;\n\n\tprivate readonly nodes: Map<NodeId, N>;\n\tprivate readonly adjacency: Map<NodeId, Map<NodeId, E>>;\n\tprivate readonly reverseAdjacency: Map<NodeId, Map<NodeId, E>> | null;\n\tprivate _edgeCount: number;\n\n\tprivate constructor(directed: boolean) {\n\t\tthis.directed = directed;\n\t\tthis.nodes = new Map();\n\t\tthis.adjacency = new Map();\n\t\tthis.reverseAdjacency = directed ? new Map() : null;\n\t\tthis._edgeCount = 0;\n\t}\n\n\t/**\n\t * Create a new directed graph.\n\t *\n\t * In a directed graph, edges have direction from source to target.\n\t * The `neighbours` method with direction 'out' returns successors,\n\t * and direction 'in' returns predecessors.\n\t *\n\t * @typeParam N - Node data type\n\t * @typeParam E - Edge data type\n\t * @returns A new empty directed graph\n\t */\n\tstatic directed<\n\t\tN extends NodeData = NodeData,\n\t\tE extends EdgeData = EdgeData,\n\t>(): AdjacencyMapGraph<N, E> {\n\t\treturn new AdjacencyMapGraph<N, E>(true);\n\t}\n\n\t/**\n\t * Create a new undirected graph.\n\t *\n\t * In an undirected graph, edges have no direction. Adding an edge\n\t * from A to B automatically creates the connection from B to A.\n\t *\n\t * @typeParam N - Node data type\n\t * @typeParam E - Edge data type\n\t * @returns A new empty undirected graph\n\t */\n\tstatic undirected<\n\t\tN extends NodeData = NodeData,\n\t\tE extends EdgeData = EdgeData,\n\t>(): AdjacencyMapGraph<N, E> {\n\t\treturn new AdjacencyMapGraph<N, E>(false);\n\t}\n\n\tget nodeCount(): number {\n\t\treturn this.nodes.size;\n\t}\n\n\tget edgeCount(): number {\n\t\treturn this._edgeCount;\n\t}\n\n\thasNode(id: NodeId): boolean {\n\t\treturn this.nodes.has(id);\n\t}\n\n\tgetNode(id: NodeId): N | undefined {\n\t\treturn this.nodes.get(id);\n\t}\n\n\t/**\n\t * Iterate over all node identifiers in the graph.\n\t *\n\t * @returns An iterable of all node IDs\n\t */\n\t*nodeIds(): Iterable<NodeId> {\n\t\tyield* this.nodes.keys();\n\t}\n\n\tneighbours(id: NodeId, direction: Direction = \"out\"): Iterable<NodeId> {\n\t\tif (!this.nodes.has(id)) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.directed) {\n\t\t\tif (direction === \"out\") {\n\t\t\t\treturn this.adjacency.get(id)?.keys() ?? [];\n\t\t\t}\n\t\t\tif (direction === \"in\") {\n\t\t\t\treturn this.reverseAdjacency?.get(id)?.keys() ?? [];\n\t\t\t}\n\t\t\t// direction === 'both'\n\t\t\treturn this.iterateBothDirections(id);\n\t\t}\n\n\t\t// Undirected: all neighbours are in adjacency\n\t\treturn this.adjacency.get(id)?.keys() ?? [];\n\t}\n\n\tprivate *iterateBothDirections(id: NodeId): Iterable<NodeId> {\n\t\tconst seen = new Set<NodeId>();\n\n\t\t// Yield outgoing neighbours\n\t\tconst outNeighbours = this.adjacency.get(id);\n\t\tif (outNeighbours !== undefined) {\n\t\t\tfor (const neighbour of outNeighbours.keys()) {\n\t\t\t\tif (!seen.has(neighbour)) {\n\t\t\t\t\tseen.add(neighbour);\n\t\t\t\t\tyield neighbour;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Yield incoming neighbours\n\t\tconst inNeighbours = this.reverseAdjacency?.get(id);\n\t\tif (inNeighbours !== undefined) {\n\t\t\tfor (const neighbour of inNeighbours.keys()) {\n\t\t\t\tif (!seen.has(neighbour)) {\n\t\t\t\t\tseen.add(neighbour);\n\t\t\t\t\tyield neighbour;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tdegree(id: NodeId, direction: Direction = \"out\"): number {\n\t\tif (!this.nodes.has(id)) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tif (this.directed) {\n\t\t\tif (direction === \"out\") {\n\t\t\t\treturn this.adjacency.get(id)?.size ?? 0;\n\t\t\t}\n\t\t\tif (direction === \"in\") {\n\t\t\t\treturn this.reverseAdjacency?.get(id)?.size ?? 0;\n\t\t\t}\n\t\t\t// direction === 'both': count unique neighbours\n\t\t\tconst outSize = this.adjacency.get(id)?.size ?? 0;\n\t\t\tconst inSize = this.reverseAdjacency?.get(id)?.size ?? 0;\n\t\t\t// Simple sum is sufficient as edges are stored separately\n\t\t\treturn outSize + inSize;\n\t\t}\n\n\t\t// Undirected\n\t\treturn this.adjacency.get(id)?.size ?? 0;\n\t}\n\n\tgetEdge(source: NodeId, target: NodeId): E | undefined {\n\t\t// For undirected, try both orders\n\t\tconst forward = this.adjacency.get(source)?.get(target);\n\t\tif (forward !== undefined) {\n\t\t\treturn forward;\n\t\t}\n\n\t\tif (!this.directed) {\n\t\t\treturn this.adjacency.get(target)?.get(source);\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t*edges(): Iterable<E> {\n\t\tconst emitted = new Set<string>();\n\n\t\tfor (const [, neighbours] of this.adjacency) {\n\t\t\tfor (const [, edge] of neighbours) {\n\t\t\t\tif (this.directed) {\n\t\t\t\t\tyield edge;\n\t\t\t\t} else {\n\t\t\t\t\t// For undirected, avoid emitting duplicate edges\n\t\t\t\t\tconst key = this.edgeKey(edge.source, edge.target);\n\t\t\t\t\tif (!emitted.has(key)) {\n\t\t\t\t\t\temitted.add(key);\n\t\t\t\t\t\tyield edge;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate edgeKey(source: NodeId, target: NodeId): string {\n\t\t// Create a canonical key for undirected edges\n\t\tconst [a, b] = source < target ? [source, target] : [target, source];\n\t\treturn `${a}::${b}`;\n\t}\n\n\t/**\n\t * Add a node to the graph (builder pattern).\n\t *\n\t * If a node with the same ID already exists, it is not replaced.\n\t *\n\t * @param node - The node data to add\n\t * @returns this (for method chaining)\n\t */\n\taddNode(node: N): this {\n\t\tif (!this.nodes.has(node.id)) {\n\t\t\tthis.nodes.set(node.id, node);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add an edge to the graph (builder pattern).\n\t *\n\t * @param edge - The edge data to add\n\t * @returns this (for method chaining)\n\t * @throws Error if either endpoint node does not exist\n\t */\n\taddEdge(edge: E): this {\n\t\t// Ensure both nodes exist\n\t\tif (!this.nodes.has(edge.source) || !this.nodes.has(edge.target)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot add edge: nodes ${edge.source} and/or ${edge.target} do not exist`,\n\t\t\t);\n\t\t}\n\n\t\tif (!this.directed) {\n\t\t\t// Canonical direction: source < target (prevents duplicate storage)\n\t\t\tconst [cSource, cTarget] =\n\t\t\t\tedge.source < edge.target\n\t\t\t\t\t? [edge.source, edge.target]\n\t\t\t\t\t: [edge.target, edge.source];\n\t\t\t// Check if edge already exists before incrementing edgeCount\n\t\t\tconst existingEdge = this.adjacency.get(cSource)?.get(cTarget);\n\t\t\tif (existingEdge !== undefined) {\n\t\t\t\t// Edge already exists — update data but don't increment count\n\t\t\t\tthis.adjacency.get(cSource)?.set(cTarget, edge);\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}\n\n\t\t// Store in forward adjacency\n\t\tlet forwardMap = this.adjacency.get(edge.source);\n\t\tif (forwardMap === undefined) {\n\t\t\tforwardMap = new Map();\n\t\t\tthis.adjacency.set(edge.source, forwardMap);\n\t\t}\n\n\t\tconst isNewEdge = !forwardMap.has(edge.target);\n\t\tforwardMap.set(edge.target, edge);\n\n\t\tif (this.directed) {\n\t\t\t// Store reverse reference for efficient predecessor lookup\n\t\t\tlet reverseMap = this.reverseAdjacency?.get(edge.target);\n\t\t\tif (reverseMap === undefined) {\n\t\t\t\treverseMap = new Map();\n\t\t\t\tthis.reverseAdjacency?.set(edge.target, reverseMap);\n\t\t\t}\n\t\t\treverseMap.set(edge.source, edge);\n\t\t} else {\n\t\t\t// For undirected, also store in reverse direction\n\t\t\tlet reverseMap = this.adjacency.get(edge.target);\n\t\t\tif (reverseMap === undefined) {\n\t\t\t\treverseMap = new Map();\n\t\t\t\tthis.adjacency.set(edge.target, reverseMap);\n\t\t\t}\n\t\t\treverseMap.set(edge.source, edge);\n\t\t}\n\n\t\tif (isNewEdge) {\n\t\t\tthis._edgeCount++;\n\t\t}\n\t\treturn this;\n\t}\n\n\tremoveNode(id: NodeId): boolean {\n\t\tif (!this.nodes.has(id)) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Remove all outgoing edges from this node\n\t\tconst outNeighbours = [...(this.adjacency.get(id)?.keys() ?? [])];\n\t\tfor (const neighbour of outNeighbours) {\n\t\t\tthis.removeEdgeInternal(id, neighbour);\n\t\t}\n\n\t\t// For directed graphs, also remove incoming edges to this node\n\t\tif (this.directed && this.reverseAdjacency !== null) {\n\t\t\tconst inNeighbours = [...(this.reverseAdjacency.get(id)?.keys() ?? [])];\n\t\t\tfor (const neighbour of inNeighbours) {\n\t\t\t\t// Remove the edge from neighbour -> id\n\t\t\t\tthis.removeEdgeFromDirected(neighbour, id);\n\t\t\t}\n\t\t}\n\n\t\t// Remove the node itself\n\t\tthis.nodes.delete(id);\n\t\tthis.adjacency.delete(id);\n\t\tthis.reverseAdjacency?.delete(id);\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Remove an edge from a directed graph, updating both adjacency maps.\n\t * This handles the case where we're removing an edge that points TO the removed node.\n\t */\n\tprivate removeEdgeFromDirected(source: NodeId, target: NodeId): void {\n\t\t// Remove from forward adjacency (source -> target)\n\t\tconst forwardMap = this.adjacency.get(source);\n\t\tif (forwardMap?.delete(target) === true) {\n\t\t\tthis._edgeCount--;\n\t\t}\n\n\t\t// Remove from reverse adjacency\n\t\tthis.reverseAdjacency?.get(target)?.delete(source);\n\t}\n\n\tprivate removeEdgeInternal(source: NodeId, target: NodeId): void {\n\t\t// Remove from forward adjacency\n\t\tconst forwardMap = this.adjacency.get(source);\n\t\tif (forwardMap?.delete(target) === true) {\n\t\t\tthis._edgeCount--;\n\t\t}\n\n\t\tif (this.directed) {\n\t\t\t// Remove from reverse adjacency\n\t\t\tthis.reverseAdjacency?.get(target)?.delete(source);\n\t\t} else {\n\t\t\t// For undirected, remove both directions\n\t\t\tthis.adjacency.get(target)?.delete(source);\n\t\t}\n\t}\n\n\tremoveEdge(source: NodeId, target: NodeId): boolean {\n\t\t// Check if edge exists\n\t\tif (!this.hasEdgeInternal(source, target)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.removeEdgeInternal(source, target);\n\t\treturn true;\n\t}\n\n\tprivate hasEdgeInternal(source: NodeId, target: NodeId): boolean {\n\t\tconst forward = this.adjacency.get(source)?.has(target) === true;\n\t\tif (forward) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (!this.directed) {\n\t\t\treturn this.adjacency.get(target)?.has(source) === true;\n\t\t}\n\n\t\treturn false;\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"adjacency-map-BtKzcuJq.js","names":[],"sources":["../src/graph/adjacency-map.ts"],"sourcesContent":["/**\n * Adjacency map graph implementation.\n *\n * This module provides a flexible graph implementation using nested Maps\n * for efficient adjacency list representation. It supports both directed\n * and undirected graphs with builder pattern for convenient construction.\n */\n\nimport type { NodeId, NodeData, EdgeData, Direction } from \"./types\";\nimport type { MutableGraph } from \"./interfaces\";\n\n/**\n * Graph implementation using adjacency map data structure.\n *\n * Uses Map<NodeId, N> for node storage and Map<NodeId, Map<NodeId, E>>\n * for adjacency representation. This provides O(1) average-case lookup\n * for nodes and edges, with memory proportional to V + E.\n *\n * @typeParam N - Node data type, must extend NodeData\n * @typeParam E - Edge data type, must extend EdgeData\n *\n * @example\n * ```typescript\n * // Create a directed citation graph\n * const graph = AdjacencyMapGraph.directed<AuthorNode, CitationEdge>()\n * .addNode({ id: 'A1', name: 'Alice' })\n * .addNode({ id: 'B1', name: 'Bob' })\n * .addEdge({ source: 'A1', target: 'B1', year: 2024 });\n * ```\n */\nexport class AdjacencyMapGraph<\n\tN extends NodeData = NodeData,\n\tE extends EdgeData = EdgeData,\n> implements MutableGraph<N, E> {\n\treadonly directed: boolean;\n\n\tprivate readonly nodes: Map<NodeId, N>;\n\tprivate readonly adjacency: Map<NodeId, Map<NodeId, E>>;\n\tprivate readonly reverseAdjacency: Map<NodeId, Map<NodeId, E>> | null;\n\tprivate _edgeCount: number;\n\n\tprivate constructor(directed: boolean) {\n\t\tthis.directed = directed;\n\t\tthis.nodes = new Map();\n\t\tthis.adjacency = new Map();\n\t\tthis.reverseAdjacency = directed ? new Map() : null;\n\t\tthis._edgeCount = 0;\n\t}\n\n\t/**\n\t * Create a new directed graph.\n\t *\n\t * In a directed graph, edges have direction from source to target.\n\t * The `neighbours` method with direction 'out' returns successors,\n\t * and direction 'in' returns predecessors.\n\t *\n\t * @typeParam N - Node data type\n\t * @typeParam E - Edge data type\n\t * @returns A new empty directed graph\n\t */\n\tstatic directed<\n\t\tN extends NodeData = NodeData,\n\t\tE extends EdgeData = EdgeData,\n\t>(): AdjacencyMapGraph<N, E> {\n\t\treturn new AdjacencyMapGraph<N, E>(true);\n\t}\n\n\t/**\n\t * Create a new undirected graph.\n\t *\n\t * In an undirected graph, edges have no direction. Adding an edge\n\t * from A to B automatically creates the connection from B to A.\n\t *\n\t * @typeParam N - Node data type\n\t * @typeParam E - Edge data type\n\t * @returns A new empty undirected graph\n\t */\n\tstatic undirected<\n\t\tN extends NodeData = NodeData,\n\t\tE extends EdgeData = EdgeData,\n\t>(): AdjacencyMapGraph<N, E> {\n\t\treturn new AdjacencyMapGraph<N, E>(false);\n\t}\n\n\tget nodeCount(): number {\n\t\treturn this.nodes.size;\n\t}\n\n\tget edgeCount(): number {\n\t\treturn this._edgeCount;\n\t}\n\n\thasNode(id: NodeId): boolean {\n\t\treturn this.nodes.has(id);\n\t}\n\n\tgetNode(id: NodeId): N | undefined {\n\t\treturn this.nodes.get(id);\n\t}\n\n\t/**\n\t * Iterate over all node identifiers in the graph.\n\t *\n\t * @returns An iterable of all node IDs\n\t */\n\t*nodeIds(): Iterable<NodeId> {\n\t\tyield* this.nodes.keys();\n\t}\n\n\tneighbours(id: NodeId, direction: Direction = \"out\"): Iterable<NodeId> {\n\t\tif (!this.nodes.has(id)) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.directed) {\n\t\t\tif (direction === \"out\") {\n\t\t\t\treturn this.adjacency.get(id)?.keys() ?? [];\n\t\t\t}\n\t\t\tif (direction === \"in\") {\n\t\t\t\treturn this.reverseAdjacency?.get(id)?.keys() ?? [];\n\t\t\t}\n\t\t\t// direction === 'both'\n\t\t\treturn this.iterateBothDirections(id);\n\t\t}\n\n\t\t// Undirected: all neighbours are in adjacency\n\t\treturn this.adjacency.get(id)?.keys() ?? [];\n\t}\n\n\tprivate *iterateBothDirections(id: NodeId): Iterable<NodeId> {\n\t\tconst seen = new Set<NodeId>();\n\n\t\t// Yield outgoing neighbours\n\t\tconst outNeighbours = this.adjacency.get(id);\n\t\tif (outNeighbours !== undefined) {\n\t\t\tfor (const neighbour of outNeighbours.keys()) {\n\t\t\t\tif (!seen.has(neighbour)) {\n\t\t\t\t\tseen.add(neighbour);\n\t\t\t\t\tyield neighbour;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Yield incoming neighbours\n\t\tconst inNeighbours = this.reverseAdjacency?.get(id);\n\t\tif (inNeighbours !== undefined) {\n\t\t\tfor (const neighbour of inNeighbours.keys()) {\n\t\t\t\tif (!seen.has(neighbour)) {\n\t\t\t\t\tseen.add(neighbour);\n\t\t\t\t\tyield neighbour;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tdegree(id: NodeId, direction: Direction = \"out\"): number {\n\t\tif (!this.nodes.has(id)) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tif (this.directed) {\n\t\t\tif (direction === \"out\") {\n\t\t\t\treturn this.adjacency.get(id)?.size ?? 0;\n\t\t\t}\n\t\t\tif (direction === \"in\") {\n\t\t\t\treturn this.reverseAdjacency?.get(id)?.size ?? 0;\n\t\t\t}\n\t\t\t// direction === 'both': count unique neighbours\n\t\t\tconst outSize = this.adjacency.get(id)?.size ?? 0;\n\t\t\tconst inSize = this.reverseAdjacency?.get(id)?.size ?? 0;\n\t\t\t// Simple sum is sufficient as edges are stored separately\n\t\t\treturn outSize + inSize;\n\t\t}\n\n\t\t// Undirected\n\t\treturn this.adjacency.get(id)?.size ?? 0;\n\t}\n\n\tgetEdge(source: NodeId, target: NodeId): E | undefined {\n\t\t// For undirected, try both orders\n\t\tconst forward = this.adjacency.get(source)?.get(target);\n\t\tif (forward !== undefined) {\n\t\t\treturn forward;\n\t\t}\n\n\t\tif (!this.directed) {\n\t\t\treturn this.adjacency.get(target)?.get(source);\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t*edges(): Iterable<E> {\n\t\tconst emitted = new Set<string>();\n\n\t\tfor (const [, neighbours] of this.adjacency) {\n\t\t\tfor (const [, edge] of neighbours) {\n\t\t\t\tif (this.directed) {\n\t\t\t\t\tyield edge;\n\t\t\t\t} else {\n\t\t\t\t\t// For undirected, avoid emitting duplicate edges\n\t\t\t\t\tconst key = this.edgeKey(edge.source, edge.target);\n\t\t\t\t\tif (!emitted.has(key)) {\n\t\t\t\t\t\temitted.add(key);\n\t\t\t\t\t\tyield edge;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate edgeKey(source: NodeId, target: NodeId): string {\n\t\t// Create a canonical key for undirected edges\n\t\tconst [a, b] = source < target ? [source, target] : [target, source];\n\t\treturn `${a}::${b}`;\n\t}\n\n\t/**\n\t * Add a node to the graph (builder pattern).\n\t *\n\t * If a node with the same ID already exists, it is not replaced.\n\t *\n\t * @param node - The node data to add\n\t * @returns this (for method chaining)\n\t */\n\taddNode(node: N): this {\n\t\tif (!this.nodes.has(node.id)) {\n\t\t\tthis.nodes.set(node.id, node);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add an edge to the graph (builder pattern).\n\t *\n\t * @param edge - The edge data to add\n\t * @returns this (for method chaining)\n\t * @throws Error if either endpoint node does not exist\n\t */\n\taddEdge(edge: E): this {\n\t\t// Ensure both nodes exist\n\t\tif (!this.nodes.has(edge.source) || !this.nodes.has(edge.target)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot add edge: nodes ${edge.source} and/or ${edge.target} do not exist`,\n\t\t\t);\n\t\t}\n\n\t\tif (!this.directed) {\n\t\t\t// Canonical direction: source < target (prevents duplicate storage)\n\t\t\tconst [cSource, cTarget] =\n\t\t\t\tedge.source < edge.target\n\t\t\t\t\t? [edge.source, edge.target]\n\t\t\t\t\t: [edge.target, edge.source];\n\t\t\t// Check if edge already exists before incrementing edgeCount\n\t\t\tconst existingEdge = this.adjacency.get(cSource)?.get(cTarget);\n\t\t\tif (existingEdge !== undefined) {\n\t\t\t\t// Edge already exists — update data but don't increment count\n\t\t\t\tthis.adjacency.get(cSource)?.set(cTarget, edge);\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}\n\n\t\t// Store in forward adjacency\n\t\tlet forwardMap = this.adjacency.get(edge.source);\n\t\tif (forwardMap === undefined) {\n\t\t\tforwardMap = new Map();\n\t\t\tthis.adjacency.set(edge.source, forwardMap);\n\t\t}\n\n\t\tconst isNewEdge = !forwardMap.has(edge.target);\n\t\tforwardMap.set(edge.target, edge);\n\n\t\tif (this.directed) {\n\t\t\t// Store reverse reference for efficient predecessor lookup\n\t\t\tlet reverseMap = this.reverseAdjacency?.get(edge.target);\n\t\t\tif (reverseMap === undefined) {\n\t\t\t\treverseMap = new Map();\n\t\t\t\tthis.reverseAdjacency?.set(edge.target, reverseMap);\n\t\t\t}\n\t\t\treverseMap.set(edge.source, edge);\n\t\t} else {\n\t\t\t// For undirected, also store in reverse direction\n\t\t\tlet reverseMap = this.adjacency.get(edge.target);\n\t\t\tif (reverseMap === undefined) {\n\t\t\t\treverseMap = new Map();\n\t\t\t\tthis.adjacency.set(edge.target, reverseMap);\n\t\t\t}\n\t\t\treverseMap.set(edge.source, edge);\n\t\t}\n\n\t\tif (isNewEdge) {\n\t\t\tthis._edgeCount++;\n\t\t}\n\t\treturn this;\n\t}\n\n\tremoveNode(id: NodeId): boolean {\n\t\tif (!this.nodes.has(id)) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Remove all outgoing edges from this node\n\t\tconst outNeighbours = [...(this.adjacency.get(id)?.keys() ?? [])];\n\t\tfor (const neighbour of outNeighbours) {\n\t\t\tthis.removeEdgeInternal(id, neighbour);\n\t\t}\n\n\t\t// For directed graphs, also remove incoming edges to this node\n\t\tif (this.directed && this.reverseAdjacency !== null) {\n\t\t\tconst inNeighbours = [...(this.reverseAdjacency.get(id)?.keys() ?? [])];\n\t\t\tfor (const neighbour of inNeighbours) {\n\t\t\t\t// Remove the edge from neighbour -> id\n\t\t\t\tthis.removeEdgeFromDirected(neighbour, id);\n\t\t\t}\n\t\t}\n\n\t\t// Remove the node itself\n\t\tthis.nodes.delete(id);\n\t\tthis.adjacency.delete(id);\n\t\tthis.reverseAdjacency?.delete(id);\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Remove an edge from a directed graph, updating both adjacency maps.\n\t * This handles the case where we're removing an edge that points TO the removed node.\n\t */\n\tprivate removeEdgeFromDirected(source: NodeId, target: NodeId): void {\n\t\t// Remove from forward adjacency (source -> target)\n\t\tconst forwardMap = this.adjacency.get(source);\n\t\tif (forwardMap?.delete(target) === true) {\n\t\t\tthis._edgeCount--;\n\t\t}\n\n\t\t// Remove from reverse adjacency\n\t\tthis.reverseAdjacency?.get(target)?.delete(source);\n\t}\n\n\tprivate removeEdgeInternal(source: NodeId, target: NodeId): void {\n\t\t// Remove from forward adjacency\n\t\tconst forwardMap = this.adjacency.get(source);\n\t\tif (forwardMap?.delete(target) === true) {\n\t\t\tthis._edgeCount--;\n\t\t}\n\n\t\tif (this.directed) {\n\t\t\t// Remove from reverse adjacency\n\t\t\tthis.reverseAdjacency?.get(target)?.delete(source);\n\t\t} else {\n\t\t\t// For undirected, remove both directions\n\t\t\tthis.adjacency.get(target)?.delete(source);\n\t\t}\n\t}\n\n\tremoveEdge(source: NodeId, target: NodeId): boolean {\n\t\t// Check if edge exists\n\t\tif (!this.hasEdgeInternal(source, target)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.removeEdgeInternal(source, target);\n\t\treturn true;\n\t}\n\n\tprivate hasEdgeInternal(source: NodeId, target: NodeId): boolean {\n\t\tconst forward = this.adjacency.get(source)?.has(target) === true;\n\t\tif (forward) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (!this.directed) {\n\t\t\treturn this.adjacency.get(target)?.has(source) === true;\n\t\t}\n\n\t\treturn false;\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adjacency-map-B6wPtmaq.cjs","names":[],"sources":["../src/graph/adjacency-map.ts"],"sourcesContent":["/**\n * Adjacency map graph implementation.\n *\n * This module provides a flexible graph implementation using nested Maps\n * for efficient adjacency list representation. It supports both directed\n * and undirected graphs with builder pattern for convenient construction.\n */\n\nimport type { NodeId, NodeData, EdgeData, Direction } from \"./types\";\nimport type { MutableGraph } from \"./interfaces\";\n\n/**\n * Graph implementation using adjacency map data structure.\n *\n * Uses Map<NodeId, N> for node storage and Map<NodeId, Map<NodeId, E>>\n * for adjacency representation. This provides O(1) average-case lookup\n * for nodes and edges, with memory proportional to V + E.\n *\n * @typeParam N - Node data type, must extend NodeData\n * @typeParam E - Edge data type, must extend EdgeData\n *\n * @example\n * ```typescript\n * // Create a directed citation graph\n * const graph = AdjacencyMapGraph.directed<AuthorNode, CitationEdge>()\n * .addNode({ id: 'A1', name: 'Alice' })\n * .addNode({ id: 'B1', name: 'Bob' })\n * .addEdge({ source: 'A1', target: 'B1', year: 2024 });\n * ```\n */\nexport class AdjacencyMapGraph<\n\tN extends NodeData = NodeData,\n\tE extends EdgeData = EdgeData,\n> implements MutableGraph<N, E> {\n\treadonly directed: boolean;\n\n\tprivate readonly nodes: Map<NodeId, N>;\n\tprivate readonly adjacency: Map<NodeId, Map<NodeId, E>>;\n\tprivate readonly reverseAdjacency: Map<NodeId, Map<NodeId, E>> | null;\n\tprivate _edgeCount: number;\n\n\tprivate constructor(directed: boolean) {\n\t\tthis.directed = directed;\n\t\tthis.nodes = new Map();\n\t\tthis.adjacency = new Map();\n\t\tthis.reverseAdjacency = directed ? new Map() : null;\n\t\tthis._edgeCount = 0;\n\t}\n\n\t/**\n\t * Create a new directed graph.\n\t *\n\t * In a directed graph, edges have direction from source to target.\n\t * The `neighbours` method with direction 'out' returns successors,\n\t * and direction 'in' returns predecessors.\n\t *\n\t * @typeParam N - Node data type\n\t * @typeParam E - Edge data type\n\t * @returns A new empty directed graph\n\t */\n\tstatic directed<\n\t\tN extends NodeData = NodeData,\n\t\tE extends EdgeData = EdgeData,\n\t>(): AdjacencyMapGraph<N, E> {\n\t\treturn new AdjacencyMapGraph<N, E>(true);\n\t}\n\n\t/**\n\t * Create a new undirected graph.\n\t *\n\t * In an undirected graph, edges have no direction. Adding an edge\n\t * from A to B automatically creates the connection from B to A.\n\t *\n\t * @typeParam N - Node data type\n\t * @typeParam E - Edge data type\n\t * @returns A new empty undirected graph\n\t */\n\tstatic undirected<\n\t\tN extends NodeData = NodeData,\n\t\tE extends EdgeData = EdgeData,\n\t>(): AdjacencyMapGraph<N, E> {\n\t\treturn new AdjacencyMapGraph<N, E>(false);\n\t}\n\n\tget nodeCount(): number {\n\t\treturn this.nodes.size;\n\t}\n\n\tget edgeCount(): number {\n\t\treturn this._edgeCount;\n\t}\n\n\thasNode(id: NodeId): boolean {\n\t\treturn this.nodes.has(id);\n\t}\n\n\tgetNode(id: NodeId): N | undefined {\n\t\treturn this.nodes.get(id);\n\t}\n\n\t/**\n\t * Iterate over all node identifiers in the graph.\n\t *\n\t * @returns An iterable of all node IDs\n\t */\n\t*nodeIds(): Iterable<NodeId> {\n\t\tyield* this.nodes.keys();\n\t}\n\n\tneighbours(id: NodeId, direction: Direction = \"out\"): Iterable<NodeId> {\n\t\tif (!this.nodes.has(id)) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.directed) {\n\t\t\tif (direction === \"out\") {\n\t\t\t\treturn this.adjacency.get(id)?.keys() ?? [];\n\t\t\t}\n\t\t\tif (direction === \"in\") {\n\t\t\t\treturn this.reverseAdjacency?.get(id)?.keys() ?? [];\n\t\t\t}\n\t\t\t// direction === 'both'\n\t\t\treturn this.iterateBothDirections(id);\n\t\t}\n\n\t\t// Undirected: all neighbours are in adjacency\n\t\treturn this.adjacency.get(id)?.keys() ?? [];\n\t}\n\n\tprivate *iterateBothDirections(id: NodeId): Iterable<NodeId> {\n\t\tconst seen = new Set<NodeId>();\n\n\t\t// Yield outgoing neighbours\n\t\tconst outNeighbours = this.adjacency.get(id);\n\t\tif (outNeighbours !== undefined) {\n\t\t\tfor (const neighbour of outNeighbours.keys()) {\n\t\t\t\tif (!seen.has(neighbour)) {\n\t\t\t\t\tseen.add(neighbour);\n\t\t\t\t\tyield neighbour;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Yield incoming neighbours\n\t\tconst inNeighbours = this.reverseAdjacency?.get(id);\n\t\tif (inNeighbours !== undefined) {\n\t\t\tfor (const neighbour of inNeighbours.keys()) {\n\t\t\t\tif (!seen.has(neighbour)) {\n\t\t\t\t\tseen.add(neighbour);\n\t\t\t\t\tyield neighbour;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tdegree(id: NodeId, direction: Direction = \"out\"): number {\n\t\tif (!this.nodes.has(id)) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tif (this.directed) {\n\t\t\tif (direction === \"out\") {\n\t\t\t\treturn this.adjacency.get(id)?.size ?? 0;\n\t\t\t}\n\t\t\tif (direction === \"in\") {\n\t\t\t\treturn this.reverseAdjacency?.get(id)?.size ?? 0;\n\t\t\t}\n\t\t\t// direction === 'both': count unique neighbours\n\t\t\tconst outSize = this.adjacency.get(id)?.size ?? 0;\n\t\t\tconst inSize = this.reverseAdjacency?.get(id)?.size ?? 0;\n\t\t\t// Simple sum is sufficient as edges are stored separately\n\t\t\treturn outSize + inSize;\n\t\t}\n\n\t\t// Undirected\n\t\treturn this.adjacency.get(id)?.size ?? 0;\n\t}\n\n\tgetEdge(source: NodeId, target: NodeId): E | undefined {\n\t\t// For undirected, try both orders\n\t\tconst forward = this.adjacency.get(source)?.get(target);\n\t\tif (forward !== undefined) {\n\t\t\treturn forward;\n\t\t}\n\n\t\tif (!this.directed) {\n\t\t\treturn this.adjacency.get(target)?.get(source);\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t*edges(): Iterable<E> {\n\t\tconst emitted = new Set<string>();\n\n\t\tfor (const [, neighbours] of this.adjacency) {\n\t\t\tfor (const [, edge] of neighbours) {\n\t\t\t\tif (this.directed) {\n\t\t\t\t\tyield edge;\n\t\t\t\t} else {\n\t\t\t\t\t// For undirected, avoid emitting duplicate edges\n\t\t\t\t\tconst key = this.edgeKey(edge.source, edge.target);\n\t\t\t\t\tif (!emitted.has(key)) {\n\t\t\t\t\t\temitted.add(key);\n\t\t\t\t\t\tyield edge;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate edgeKey(source: NodeId, target: NodeId): string {\n\t\t// Create a canonical key for undirected edges\n\t\tconst [a, b] = source < target ? [source, target] : [target, source];\n\t\treturn `${a}::${b}`;\n\t}\n\n\t/**\n\t * Add a node to the graph (builder pattern).\n\t *\n\t * If a node with the same ID already exists, it is not replaced.\n\t *\n\t * @param node - The node data to add\n\t * @returns this (for method chaining)\n\t */\n\taddNode(node: N): this {\n\t\tif (!this.nodes.has(node.id)) {\n\t\t\tthis.nodes.set(node.id, node);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add an edge to the graph (builder pattern).\n\t *\n\t * @param edge - The edge data to add\n\t * @returns this (for method chaining)\n\t * @throws Error if either endpoint node does not exist\n\t */\n\taddEdge(edge: E): this {\n\t\t// Ensure both nodes exist\n\t\tif (!this.nodes.has(edge.source) || !this.nodes.has(edge.target)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot add edge: nodes ${edge.source} and/or ${edge.target} do not exist`,\n\t\t\t);\n\t\t}\n\n\t\tif (!this.directed) {\n\t\t\t// Canonical direction: source < target (prevents duplicate storage)\n\t\t\tconst [cSource, cTarget] =\n\t\t\t\tedge.source < edge.target\n\t\t\t\t\t? [edge.source, edge.target]\n\t\t\t\t\t: [edge.target, edge.source];\n\t\t\t// Check if edge already exists before incrementing edgeCount\n\t\t\tconst existingEdge = this.adjacency.get(cSource)?.get(cTarget);\n\t\t\tif (existingEdge !== undefined) {\n\t\t\t\t// Edge already exists — update data but don't increment count\n\t\t\t\tthis.adjacency.get(cSource)?.set(cTarget, edge);\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}\n\n\t\t// Store in forward adjacency\n\t\tlet forwardMap = this.adjacency.get(edge.source);\n\t\tif (forwardMap === undefined) {\n\t\t\tforwardMap = new Map();\n\t\t\tthis.adjacency.set(edge.source, forwardMap);\n\t\t}\n\n\t\tconst isNewEdge = !forwardMap.has(edge.target);\n\t\tforwardMap.set(edge.target, edge);\n\n\t\tif (this.directed) {\n\t\t\t// Store reverse reference for efficient predecessor lookup\n\t\t\tlet reverseMap = this.reverseAdjacency?.get(edge.target);\n\t\t\tif (reverseMap === undefined) {\n\t\t\t\treverseMap = new Map();\n\t\t\t\tthis.reverseAdjacency?.set(edge.target, reverseMap);\n\t\t\t}\n\t\t\treverseMap.set(edge.source, edge);\n\t\t} else {\n\t\t\t// For undirected, also store in reverse direction\n\t\t\tlet reverseMap = this.adjacency.get(edge.target);\n\t\t\tif (reverseMap === undefined) {\n\t\t\t\treverseMap = new Map();\n\t\t\t\tthis.adjacency.set(edge.target, reverseMap);\n\t\t\t}\n\t\t\treverseMap.set(edge.source, edge);\n\t\t}\n\n\t\tif (isNewEdge) {\n\t\t\tthis._edgeCount++;\n\t\t}\n\t\treturn this;\n\t}\n\n\tremoveNode(id: NodeId): boolean {\n\t\tif (!this.nodes.has(id)) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Remove all outgoing edges from this node\n\t\tconst outNeighbours = [...(this.adjacency.get(id)?.keys() ?? [])];\n\t\tfor (const neighbour of outNeighbours) {\n\t\t\tthis.removeEdgeInternal(id, neighbour);\n\t\t}\n\n\t\t// For directed graphs, also remove incoming edges to this node\n\t\tif (this.directed && this.reverseAdjacency !== null) {\n\t\t\tconst inNeighbours = [...(this.reverseAdjacency.get(id)?.keys() ?? [])];\n\t\t\tfor (const neighbour of inNeighbours) {\n\t\t\t\t// Remove the edge from neighbour -> id\n\t\t\t\tthis.removeEdgeFromDirected(neighbour, id);\n\t\t\t}\n\t\t}\n\n\t\t// Remove the node itself\n\t\tthis.nodes.delete(id);\n\t\tthis.adjacency.delete(id);\n\t\tthis.reverseAdjacency?.delete(id);\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Remove an edge from a directed graph, updating both adjacency maps.\n\t * This handles the case where we're removing an edge that points TO the removed node.\n\t */\n\tprivate removeEdgeFromDirected(source: NodeId, target: NodeId): void {\n\t\t// Remove from forward adjacency (source -> target)\n\t\tconst forwardMap = this.adjacency.get(source);\n\t\tif (forwardMap?.delete(target) === true) {\n\t\t\tthis._edgeCount--;\n\t\t}\n\n\t\t// Remove from reverse adjacency\n\t\tthis.reverseAdjacency?.get(target)?.delete(source);\n\t}\n\n\tprivate removeEdgeInternal(source: NodeId, target: NodeId): void {\n\t\t// Remove from forward adjacency\n\t\tconst forwardMap = this.adjacency.get(source);\n\t\tif (forwardMap?.delete(target) === true) {\n\t\t\tthis._edgeCount--;\n\t\t}\n\n\t\tif (this.directed) {\n\t\t\t// Remove from reverse adjacency\n\t\t\tthis.reverseAdjacency?.get(target)?.delete(source);\n\t\t} else {\n\t\t\t// For undirected, remove both directions\n\t\t\tthis.adjacency.get(target)?.delete(source);\n\t\t}\n\t}\n\n\tremoveEdge(source: NodeId, target: NodeId): boolean {\n\t\t// Check if edge exists\n\t\tif (!this.hasEdgeInternal(source, target)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.removeEdgeInternal(source, target);\n\t\treturn true;\n\t}\n\n\tprivate hasEdgeInternal(source: NodeId, target: NodeId): boolean {\n\t\tconst forward = this.adjacency.get(source)?.has(target) === true;\n\t\tif (forward) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (!this.directed) {\n\t\t\treturn this.adjacency.get(target)?.has(source) === true;\n\t\t}\n\n\t\treturn false;\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"adjacency-map-JqBnMNkF.cjs","names":[],"sources":["../src/graph/adjacency-map.ts"],"sourcesContent":["/**\n * Adjacency map graph implementation.\n *\n * This module provides a flexible graph implementation using nested Maps\n * for efficient adjacency list representation. It supports both directed\n * and undirected graphs with builder pattern for convenient construction.\n */\n\nimport type { NodeId, NodeData, EdgeData, Direction } from \"./types\";\nimport type { MutableGraph } from \"./interfaces\";\n\n/**\n * Graph implementation using adjacency map data structure.\n *\n * Uses Map<NodeId, N> for node storage and Map<NodeId, Map<NodeId, E>>\n * for adjacency representation. This provides O(1) average-case lookup\n * for nodes and edges, with memory proportional to V + E.\n *\n * @typeParam N - Node data type, must extend NodeData\n * @typeParam E - Edge data type, must extend EdgeData\n *\n * @example\n * ```typescript\n * // Create a directed citation graph\n * const graph = AdjacencyMapGraph.directed<AuthorNode, CitationEdge>()\n * .addNode({ id: 'A1', name: 'Alice' })\n * .addNode({ id: 'B1', name: 'Bob' })\n * .addEdge({ source: 'A1', target: 'B1', year: 2024 });\n * ```\n */\nexport class AdjacencyMapGraph<\n\tN extends NodeData = NodeData,\n\tE extends EdgeData = EdgeData,\n> implements MutableGraph<N, E> {\n\treadonly directed: boolean;\n\n\tprivate readonly nodes: Map<NodeId, N>;\n\tprivate readonly adjacency: Map<NodeId, Map<NodeId, E>>;\n\tprivate readonly reverseAdjacency: Map<NodeId, Map<NodeId, E>> | null;\n\tprivate _edgeCount: number;\n\n\tprivate constructor(directed: boolean) {\n\t\tthis.directed = directed;\n\t\tthis.nodes = new Map();\n\t\tthis.adjacency = new Map();\n\t\tthis.reverseAdjacency = directed ? new Map() : null;\n\t\tthis._edgeCount = 0;\n\t}\n\n\t/**\n\t * Create a new directed graph.\n\t *\n\t * In a directed graph, edges have direction from source to target.\n\t * The `neighbours` method with direction 'out' returns successors,\n\t * and direction 'in' returns predecessors.\n\t *\n\t * @typeParam N - Node data type\n\t * @typeParam E - Edge data type\n\t * @returns A new empty directed graph\n\t */\n\tstatic directed<\n\t\tN extends NodeData = NodeData,\n\t\tE extends EdgeData = EdgeData,\n\t>(): AdjacencyMapGraph<N, E> {\n\t\treturn new AdjacencyMapGraph<N, E>(true);\n\t}\n\n\t/**\n\t * Create a new undirected graph.\n\t *\n\t * In an undirected graph, edges have no direction. Adding an edge\n\t * from A to B automatically creates the connection from B to A.\n\t *\n\t * @typeParam N - Node data type\n\t * @typeParam E - Edge data type\n\t * @returns A new empty undirected graph\n\t */\n\tstatic undirected<\n\t\tN extends NodeData = NodeData,\n\t\tE extends EdgeData = EdgeData,\n\t>(): AdjacencyMapGraph<N, E> {\n\t\treturn new AdjacencyMapGraph<N, E>(false);\n\t}\n\n\tget nodeCount(): number {\n\t\treturn this.nodes.size;\n\t}\n\n\tget edgeCount(): number {\n\t\treturn this._edgeCount;\n\t}\n\n\thasNode(id: NodeId): boolean {\n\t\treturn this.nodes.has(id);\n\t}\n\n\tgetNode(id: NodeId): N | undefined {\n\t\treturn this.nodes.get(id);\n\t}\n\n\t/**\n\t * Iterate over all node identifiers in the graph.\n\t *\n\t * @returns An iterable of all node IDs\n\t */\n\t*nodeIds(): Iterable<NodeId> {\n\t\tyield* this.nodes.keys();\n\t}\n\n\tneighbours(id: NodeId, direction: Direction = \"out\"): Iterable<NodeId> {\n\t\tif (!this.nodes.has(id)) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.directed) {\n\t\t\tif (direction === \"out\") {\n\t\t\t\treturn this.adjacency.get(id)?.keys() ?? [];\n\t\t\t}\n\t\t\tif (direction === \"in\") {\n\t\t\t\treturn this.reverseAdjacency?.get(id)?.keys() ?? [];\n\t\t\t}\n\t\t\t// direction === 'both'\n\t\t\treturn this.iterateBothDirections(id);\n\t\t}\n\n\t\t// Undirected: all neighbours are in adjacency\n\t\treturn this.adjacency.get(id)?.keys() ?? [];\n\t}\n\n\tprivate *iterateBothDirections(id: NodeId): Iterable<NodeId> {\n\t\tconst seen = new Set<NodeId>();\n\n\t\t// Yield outgoing neighbours\n\t\tconst outNeighbours = this.adjacency.get(id);\n\t\tif (outNeighbours !== undefined) {\n\t\t\tfor (const neighbour of outNeighbours.keys()) {\n\t\t\t\tif (!seen.has(neighbour)) {\n\t\t\t\t\tseen.add(neighbour);\n\t\t\t\t\tyield neighbour;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Yield incoming neighbours\n\t\tconst inNeighbours = this.reverseAdjacency?.get(id);\n\t\tif (inNeighbours !== undefined) {\n\t\t\tfor (const neighbour of inNeighbours.keys()) {\n\t\t\t\tif (!seen.has(neighbour)) {\n\t\t\t\t\tseen.add(neighbour);\n\t\t\t\t\tyield neighbour;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tdegree(id: NodeId, direction: Direction = \"out\"): number {\n\t\tif (!this.nodes.has(id)) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tif (this.directed) {\n\t\t\tif (direction === \"out\") {\n\t\t\t\treturn this.adjacency.get(id)?.size ?? 0;\n\t\t\t}\n\t\t\tif (direction === \"in\") {\n\t\t\t\treturn this.reverseAdjacency?.get(id)?.size ?? 0;\n\t\t\t}\n\t\t\t// direction === 'both': count unique neighbours\n\t\t\tconst outSize = this.adjacency.get(id)?.size ?? 0;\n\t\t\tconst inSize = this.reverseAdjacency?.get(id)?.size ?? 0;\n\t\t\t// Simple sum is sufficient as edges are stored separately\n\t\t\treturn outSize + inSize;\n\t\t}\n\n\t\t// Undirected\n\t\treturn this.adjacency.get(id)?.size ?? 0;\n\t}\n\n\tgetEdge(source: NodeId, target: NodeId): E | undefined {\n\t\t// For undirected, try both orders\n\t\tconst forward = this.adjacency.get(source)?.get(target);\n\t\tif (forward !== undefined) {\n\t\t\treturn forward;\n\t\t}\n\n\t\tif (!this.directed) {\n\t\t\treturn this.adjacency.get(target)?.get(source);\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t*edges(): Iterable<E> {\n\t\tconst emitted = new Set<string>();\n\n\t\tfor (const [, neighbours] of this.adjacency) {\n\t\t\tfor (const [, edge] of neighbours) {\n\t\t\t\tif (this.directed) {\n\t\t\t\t\tyield edge;\n\t\t\t\t} else {\n\t\t\t\t\t// For undirected, avoid emitting duplicate edges\n\t\t\t\t\tconst key = this.edgeKey(edge.source, edge.target);\n\t\t\t\t\tif (!emitted.has(key)) {\n\t\t\t\t\t\temitted.add(key);\n\t\t\t\t\t\tyield edge;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate edgeKey(source: NodeId, target: NodeId): string {\n\t\t// Create a canonical key for undirected edges\n\t\tconst [a, b] = source < target ? [source, target] : [target, source];\n\t\treturn `${a}::${b}`;\n\t}\n\n\t/**\n\t * Add a node to the graph (builder pattern).\n\t *\n\t * If a node with the same ID already exists, it is not replaced.\n\t *\n\t * @param node - The node data to add\n\t * @returns this (for method chaining)\n\t */\n\taddNode(node: N): this {\n\t\tif (!this.nodes.has(node.id)) {\n\t\t\tthis.nodes.set(node.id, node);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add an edge to the graph (builder pattern).\n\t *\n\t * @param edge - The edge data to add\n\t * @returns this (for method chaining)\n\t * @throws Error if either endpoint node does not exist\n\t */\n\taddEdge(edge: E): this {\n\t\t// Ensure both nodes exist\n\t\tif (!this.nodes.has(edge.source) || !this.nodes.has(edge.target)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot add edge: nodes ${edge.source} and/or ${edge.target} do not exist`,\n\t\t\t);\n\t\t}\n\n\t\tif (!this.directed) {\n\t\t\t// Canonical direction: source < target (prevents duplicate storage)\n\t\t\tconst [cSource, cTarget] =\n\t\t\t\tedge.source < edge.target\n\t\t\t\t\t? [edge.source, edge.target]\n\t\t\t\t\t: [edge.target, edge.source];\n\t\t\t// Check if edge already exists before incrementing edgeCount\n\t\t\tconst existingEdge = this.adjacency.get(cSource)?.get(cTarget);\n\t\t\tif (existingEdge !== undefined) {\n\t\t\t\t// Edge already exists — update data but don't increment count\n\t\t\t\tthis.adjacency.get(cSource)?.set(cTarget, edge);\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}\n\n\t\t// Store in forward adjacency\n\t\tlet forwardMap = this.adjacency.get(edge.source);\n\t\tif (forwardMap === undefined) {\n\t\t\tforwardMap = new Map();\n\t\t\tthis.adjacency.set(edge.source, forwardMap);\n\t\t}\n\n\t\tconst isNewEdge = !forwardMap.has(edge.target);\n\t\tforwardMap.set(edge.target, edge);\n\n\t\tif (this.directed) {\n\t\t\t// Store reverse reference for efficient predecessor lookup\n\t\t\tlet reverseMap = this.reverseAdjacency?.get(edge.target);\n\t\t\tif (reverseMap === undefined) {\n\t\t\t\treverseMap = new Map();\n\t\t\t\tthis.reverseAdjacency?.set(edge.target, reverseMap);\n\t\t\t}\n\t\t\treverseMap.set(edge.source, edge);\n\t\t} else {\n\t\t\t// For undirected, also store in reverse direction\n\t\t\tlet reverseMap = this.adjacency.get(edge.target);\n\t\t\tif (reverseMap === undefined) {\n\t\t\t\treverseMap = new Map();\n\t\t\t\tthis.adjacency.set(edge.target, reverseMap);\n\t\t\t}\n\t\t\treverseMap.set(edge.source, edge);\n\t\t}\n\n\t\tif (isNewEdge) {\n\t\t\tthis._edgeCount++;\n\t\t}\n\t\treturn this;\n\t}\n\n\tremoveNode(id: NodeId): boolean {\n\t\tif (!this.nodes.has(id)) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Remove all outgoing edges from this node\n\t\tconst outNeighbours = [...(this.adjacency.get(id)?.keys() ?? [])];\n\t\tfor (const neighbour of outNeighbours) {\n\t\t\tthis.removeEdgeInternal(id, neighbour);\n\t\t}\n\n\t\t// For directed graphs, also remove incoming edges to this node\n\t\tif (this.directed && this.reverseAdjacency !== null) {\n\t\t\tconst inNeighbours = [...(this.reverseAdjacency.get(id)?.keys() ?? [])];\n\t\t\tfor (const neighbour of inNeighbours) {\n\t\t\t\t// Remove the edge from neighbour -> id\n\t\t\t\tthis.removeEdgeFromDirected(neighbour, id);\n\t\t\t}\n\t\t}\n\n\t\t// Remove the node itself\n\t\tthis.nodes.delete(id);\n\t\tthis.adjacency.delete(id);\n\t\tthis.reverseAdjacency?.delete(id);\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Remove an edge from a directed graph, updating both adjacency maps.\n\t * This handles the case where we're removing an edge that points TO the removed node.\n\t */\n\tprivate removeEdgeFromDirected(source: NodeId, target: NodeId): void {\n\t\t// Remove from forward adjacency (source -> target)\n\t\tconst forwardMap = this.adjacency.get(source);\n\t\tif (forwardMap?.delete(target) === true) {\n\t\t\tthis._edgeCount--;\n\t\t}\n\n\t\t// Remove from reverse adjacency\n\t\tthis.reverseAdjacency?.get(target)?.delete(source);\n\t}\n\n\tprivate removeEdgeInternal(source: NodeId, target: NodeId): void {\n\t\t// Remove from forward adjacency\n\t\tconst forwardMap = this.adjacency.get(source);\n\t\tif (forwardMap?.delete(target) === true) {\n\t\t\tthis._edgeCount--;\n\t\t}\n\n\t\tif (this.directed) {\n\t\t\t// Remove from reverse adjacency\n\t\t\tthis.reverseAdjacency?.get(target)?.delete(source);\n\t\t} else {\n\t\t\t// For undirected, remove both directions\n\t\t\tthis.adjacency.get(target)?.delete(source);\n\t\t}\n\t}\n\n\tremoveEdge(source: NodeId, target: NodeId): boolean {\n\t\t// Check if edge exists\n\t\tif (!this.hasEdgeInternal(source, target)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.removeEdgeInternal(source, target);\n\t\treturn true;\n\t}\n\n\tprivate hasEdgeInternal(source: NodeId, target: NodeId): boolean {\n\t\tconst forward = this.adjacency.get(source)?.has(target) === true;\n\t\tif (forward) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (!this.directed) {\n\t\t\treturn this.adjacency.get(target)?.has(source) === true;\n\t\t}\n\n\t\treturn false;\n\t}\n}\n"],"mappings":"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"}
|
package/dist/async/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_utils = require("../utils-
|
|
3
|
-
const require_ops = require("../ops-
|
|
2
|
+
const require_utils = require("../utils-CDtCcsyF.cjs");
|
|
3
|
+
const require_ops = require("../ops-djAsQQSh.cjs");
|
|
4
4
|
exports.collectAsyncIterable = require_utils.collectAsyncIterable;
|
|
5
5
|
exports.defaultYieldStrategy = require_utils.defaultYieldStrategy;
|
|
6
6
|
exports.opDegree = require_ops.opDegree;
|
package/dist/async/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as defaultYieldStrategy, t as collectAsyncIterable } from "../utils-
|
|
2
|
-
import { a as opNeighbours, c as resolveAsyncOp, d as runSync, i as opHasNode, l as resolveSyncOp, n as opGetEdge, o as opProgress, r as opGetNode, s as opYield, t as opDegree, u as runAsync } from "../ops-
|
|
1
|
+
import { n as defaultYieldStrategy, t as collectAsyncIterable } from "../utils-BodeE2Mo.js";
|
|
2
|
+
import { a as opNeighbours, c as resolveAsyncOp, d as runSync, i as opHasNode, l as resolveSyncOp, n as opGetEdge, o as opProgress, r as opGetNode, s as opYield, t as opDegree, u as runAsync } from "../ops-upIi6JIi.js";
|
|
3
3
|
export { collectAsyncIterable, defaultYieldStrategy, opDegree, opGetEdge, opGetNode, opHasNode, opNeighbours, opProgress, opYield, resolveAsyncOp, resolveSyncOp, runAsync, runSync };
|
package/dist/expansion/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_expansion = require("../expansion-
|
|
2
|
+
const require_expansion = require("../expansion-DaTroIyv.cjs");
|
|
3
3
|
exports.base = require_expansion.base;
|
|
4
4
|
exports.baseAsync = require_expansion.baseAsync;
|
|
5
5
|
exports.dfsPriority = require_expansion.dfsPriority;
|
package/dist/expansion/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as pipe, B as base, C as tideAsync, D as reachAsync, E as reach, F as haeAsync, I as dome, L as domeAsync, M as edge, N as edgeAsync, O as sage, P as hae, R as domeHighDegree, S as tide, T as mazeAsync, V as baseAsync, _ as fuseAsync, a as dfsPriorityFn, b as lace, c as frontierBalanced, d as standardBfsAsync, f as flux, g as fuse, h as siftAsync, i as dfsPriorityAsync, j as pipeAsync, k as sageAsync, l as frontierBalancedAsync, m as sift, n as kHop, o as randomPriority, p as fluxAsync, r as dfsPriority, s as randomPriorityAsync, t as randomWalk, u as standardBfs, v as warp, w as maze, x as laceAsync, y as warpAsync, z as domeHighDegreeAsync } from "../expansion-
|
|
1
|
+
import { A as pipe, B as base, C as tideAsync, D as reachAsync, E as reach, F as haeAsync, I as dome, L as domeAsync, M as edge, N as edgeAsync, O as sage, P as hae, R as domeHighDegree, S as tide, T as mazeAsync, V as baseAsync, _ as fuseAsync, a as dfsPriorityFn, b as lace, c as frontierBalanced, d as standardBfsAsync, f as flux, g as fuse, h as siftAsync, i as dfsPriorityAsync, j as pipeAsync, k as sageAsync, l as frontierBalancedAsync, m as sift, n as kHop, o as randomPriority, p as fluxAsync, r as dfsPriority, s as randomPriorityAsync, t as randomWalk, u as standardBfs, v as warp, w as maze, x as laceAsync, y as warpAsync, z as domeHighDegreeAsync } from "../expansion-ClDhlMK8.js";
|
|
2
2
|
export { base, baseAsync, dfsPriority, dfsPriorityAsync, dfsPriorityFn, dome, domeAsync, domeHighDegree, domeHighDegreeAsync, edge, edgeAsync, flux, fluxAsync, frontierBalanced, frontierBalancedAsync, fuse, fuseAsync, hae, haeAsync, kHop, lace, laceAsync, maze, mazeAsync, pipe, pipeAsync, randomPriority, randomPriorityAsync, randomWalk, reach, reachAsync, sage, sageAsync, sift, siftAsync, standardBfs, standardBfsAsync, tide, tideAsync, warp, warpAsync };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as PriorityQueue } from "./priority-queue-
|
|
2
|
-
import { a as opNeighbours, d as runSync, t as opDegree, u as runAsync } from "./ops-
|
|
1
|
+
import { t as PriorityQueue } from "./priority-queue-CFDd5cBg.js";
|
|
2
|
+
import { a as opNeighbours, d as runSync, t as opDegree, u as runAsync } from "./ops-upIi6JIi.js";
|
|
3
3
|
import { localTypeEntropy } from "./utils/index.js";
|
|
4
|
-
import { t as jaccard } from "./jaccard-
|
|
4
|
+
import { t as jaccard } from "./jaccard-3rCdilwm.js";
|
|
5
5
|
//#region src/expansion/base-helpers.ts
|
|
6
6
|
/**
|
|
7
7
|
* Check whether expansion should continue given current progress.
|
|
@@ -1701,4 +1701,4 @@ function emptyResult(startTime) {
|
|
|
1701
1701
|
//#endregion
|
|
1702
1702
|
export { pipe as A, base as B, tideAsync as C, reachAsync as D, reach as E, haeAsync as F, dome as I, domeAsync as L, edge as M, edgeAsync as N, sage as O, hae as P, domeHighDegree as R, tide as S, mazeAsync as T, baseAsync as V, fuseAsync as _, dfsPriorityFn as a, lace as b, frontierBalanced as c, standardBfsAsync as d, flux as f, fuse as g, siftAsync as h, dfsPriorityAsync as i, pipeAsync as j, sageAsync as k, frontierBalancedAsync as l, sift as m, kHop as n, randomPriority as o, fluxAsync as p, dfsPriority as r, randomPriorityAsync as s, randomWalk as t, standardBfs as u, warp as v, maze as w, laceAsync as x, warpAsync as y, domeHighDegreeAsync as z };
|
|
1703
1703
|
|
|
1704
|
-
//# sourceMappingURL=expansion-
|
|
1704
|
+
//# sourceMappingURL=expansion-ClDhlMK8.js.map
|