@graphty/algorithms 1.3.1 → 1.5.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.
Files changed (314) hide show
  1. package/README.md +368 -422
  2. package/dist/algorithms.js +567 -264
  3. package/dist/algorithms.js.map +1 -1
  4. package/dist/src/algorithms/centrality/betweenness.d.ts +10 -0
  5. package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
  6. package/dist/src/algorithms/centrality/betweenness.js +27 -6
  7. package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
  8. package/dist/src/algorithms/centrality/closeness.d.ts +11 -2
  9. package/dist/src/algorithms/centrality/closeness.d.ts.map +1 -1
  10. package/dist/src/algorithms/centrality/closeness.js +17 -3
  11. package/dist/src/algorithms/centrality/closeness.js.map +1 -1
  12. package/dist/src/algorithms/centrality/degree.d.ts +7 -0
  13. package/dist/src/algorithms/centrality/degree.d.ts.map +1 -1
  14. package/dist/src/algorithms/centrality/degree.js +9 -6
  15. package/dist/src/algorithms/centrality/degree.js.map +1 -1
  16. package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts +21 -3
  17. package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts.map +1 -1
  18. package/dist/src/algorithms/centrality/delta-pagerank-simple.js +25 -7
  19. package/dist/src/algorithms/centrality/delta-pagerank-simple.js.map +1 -1
  20. package/dist/src/algorithms/centrality/delta-pagerank.d.ts +28 -2
  21. package/dist/src/algorithms/centrality/delta-pagerank.d.ts.map +1 -1
  22. package/dist/src/algorithms/centrality/delta-pagerank.js +30 -4
  23. package/dist/src/algorithms/centrality/delta-pagerank.js.map +1 -1
  24. package/dist/src/algorithms/centrality/eigenvector.d.ts +10 -3
  25. package/dist/src/algorithms/centrality/eigenvector.d.ts.map +1 -1
  26. package/dist/src/algorithms/centrality/eigenvector.js +11 -4
  27. package/dist/src/algorithms/centrality/eigenvector.js.map +1 -1
  28. package/dist/src/algorithms/centrality/hits.d.ts +10 -3
  29. package/dist/src/algorithms/centrality/hits.d.ts.map +1 -1
  30. package/dist/src/algorithms/centrality/hits.js +11 -4
  31. package/dist/src/algorithms/centrality/hits.js.map +1 -1
  32. package/dist/src/algorithms/centrality/index.d.ts +1 -1
  33. package/dist/src/algorithms/centrality/index.d.ts.map +1 -1
  34. package/dist/src/algorithms/centrality/index.js +1 -1
  35. package/dist/src/algorithms/centrality/index.js.map +1 -1
  36. package/dist/src/algorithms/centrality/katz.d.ts +10 -3
  37. package/dist/src/algorithms/centrality/katz.d.ts.map +1 -1
  38. package/dist/src/algorithms/centrality/katz.js +13 -8
  39. package/dist/src/algorithms/centrality/katz.js.map +1 -1
  40. package/dist/src/algorithms/centrality/pagerank.d.ts +14 -0
  41. package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -1
  42. package/dist/src/algorithms/centrality/pagerank.js +16 -1
  43. package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
  44. package/dist/src/algorithms/community/girvan-newman.d.ts +2 -3
  45. package/dist/src/algorithms/community/girvan-newman.d.ts.map +1 -1
  46. package/dist/src/algorithms/community/girvan-newman.js +21 -4
  47. package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
  48. package/dist/src/algorithms/community/index.d.ts.map +1 -1
  49. package/dist/src/algorithms/community/index.js.map +1 -1
  50. package/dist/src/algorithms/community/label-propagation.d.ts +0 -3
  51. package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -1
  52. package/dist/src/algorithms/community/label-propagation.js +13 -6
  53. package/dist/src/algorithms/community/label-propagation.js.map +1 -1
  54. package/dist/src/algorithms/community/leiden.d.ts +0 -1
  55. package/dist/src/algorithms/community/leiden.d.ts.map +1 -1
  56. package/dist/src/algorithms/community/leiden.js +37 -6
  57. package/dist/src/algorithms/community/leiden.js.map +1 -1
  58. package/dist/src/algorithms/community/louvain-optimized.d.ts +37 -0
  59. package/dist/src/algorithms/community/louvain-optimized.d.ts.map +1 -1
  60. package/dist/src/algorithms/community/louvain-optimized.js +42 -7
  61. package/dist/src/algorithms/community/louvain-optimized.js.map +1 -1
  62. package/dist/src/algorithms/community/louvain.d.ts +2 -3
  63. package/dist/src/algorithms/community/louvain.d.ts.map +1 -1
  64. package/dist/src/algorithms/community/louvain.js +19 -6
  65. package/dist/src/algorithms/community/louvain.js.map +1 -1
  66. package/dist/src/algorithms/community/modularity-utils.d.ts +0 -4
  67. package/dist/src/algorithms/community/modularity-utils.d.ts.map +1 -1
  68. package/dist/src/algorithms/community/modularity-utils.js +1 -5
  69. package/dist/src/algorithms/community/modularity-utils.js.map +1 -1
  70. package/dist/src/algorithms/components/connected.d.ts +23 -0
  71. package/dist/src/algorithms/components/connected.d.ts.map +1 -1
  72. package/dist/src/algorithms/components/connected.js +29 -3
  73. package/dist/src/algorithms/components/connected.js.map +1 -1
  74. package/dist/src/algorithms/matching/bipartite.d.ts +10 -0
  75. package/dist/src/algorithms/matching/bipartite.d.ts.map +1 -1
  76. package/dist/src/algorithms/matching/bipartite.js +10 -0
  77. package/dist/src/algorithms/matching/bipartite.js.map +1 -1
  78. package/dist/src/algorithms/matching/index.d.ts.map +1 -1
  79. package/dist/src/algorithms/matching/index.js.map +1 -1
  80. package/dist/src/algorithms/matching/isomorphism.d.ts +8 -0
  81. package/dist/src/algorithms/matching/isomorphism.d.ts.map +1 -1
  82. package/dist/src/algorithms/matching/isomorphism.js +36 -2
  83. package/dist/src/algorithms/matching/isomorphism.js.map +1 -1
  84. package/dist/src/algorithms/mst/index.d.ts.map +1 -1
  85. package/dist/src/algorithms/mst/index.js.map +1 -1
  86. package/dist/src/algorithms/mst/kruskal.d.ts +14 -0
  87. package/dist/src/algorithms/mst/kruskal.d.ts.map +1 -1
  88. package/dist/src/algorithms/mst/kruskal.js +17 -3
  89. package/dist/src/algorithms/mst/kruskal.js.map +1 -1
  90. package/dist/src/algorithms/mst/prim.d.ts +9 -0
  91. package/dist/src/algorithms/mst/prim.d.ts.map +1 -1
  92. package/dist/src/algorithms/mst/prim.js +9 -0
  93. package/dist/src/algorithms/mst/prim.js.map +1 -1
  94. package/dist/src/algorithms/shortest-path/bellman-ford.d.ts +10 -0
  95. package/dist/src/algorithms/shortest-path/bellman-ford.d.ts.map +1 -1
  96. package/dist/src/algorithms/shortest-path/bellman-ford.js +10 -0
  97. package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
  98. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts +12 -5
  99. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts.map +1 -1
  100. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +19 -17
  101. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js.map +1 -1
  102. package/dist/src/algorithms/shortest-path/dijkstra.d.ts +15 -0
  103. package/dist/src/algorithms/shortest-path/dijkstra.d.ts.map +1 -1
  104. package/dist/src/algorithms/shortest-path/dijkstra.js +15 -0
  105. package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
  106. package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts +17 -0
  107. package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts.map +1 -1
  108. package/dist/src/algorithms/shortest-path/floyd-warshall.js +17 -0
  109. package/dist/src/algorithms/shortest-path/floyd-warshall.js.map +1 -1
  110. package/dist/src/algorithms/shortest-path/index.d.ts.map +1 -1
  111. package/dist/src/algorithms/shortest-path/index.js.map +1 -1
  112. package/dist/src/algorithms/traversal/bfs-unified.d.ts +13 -0
  113. package/dist/src/algorithms/traversal/bfs-unified.d.ts.map +1 -1
  114. package/dist/src/algorithms/traversal/bfs-unified.js +37 -0
  115. package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -1
  116. package/dist/src/algorithms/traversal/bfs-variants.d.ts +23 -0
  117. package/dist/src/algorithms/traversal/bfs-variants.d.ts.map +1 -1
  118. package/dist/src/algorithms/traversal/bfs-variants.js +34 -0
  119. package/dist/src/algorithms/traversal/bfs-variants.js.map +1 -1
  120. package/dist/src/algorithms/traversal/bfs.d.ts +1 -1
  121. package/dist/src/algorithms/traversal/bfs.d.ts.map +1 -1
  122. package/dist/src/algorithms/traversal/bfs.js +1 -1
  123. package/dist/src/algorithms/traversal/bfs.js.map +1 -1
  124. package/dist/src/algorithms/traversal/dfs.d.ts +10 -0
  125. package/dist/src/algorithms/traversal/dfs.d.ts.map +1 -1
  126. package/dist/src/algorithms/traversal/dfs.js +48 -0
  127. package/dist/src/algorithms/traversal/dfs.js.map +1 -1
  128. package/dist/src/algorithms/traversal/index.d.ts.map +1 -1
  129. package/dist/src/algorithms/traversal/index.js.map +1 -1
  130. package/dist/src/benchmark-all-algorithms.d.ts +2 -0
  131. package/dist/src/benchmark-all-algorithms.d.ts.map +1 -1
  132. package/dist/src/benchmark-all-algorithms.js +32 -3
  133. package/dist/src/benchmark-all-algorithms.js.map +1 -1
  134. package/dist/src/clustering/hierarchical.d.ts +8 -1
  135. package/dist/src/clustering/hierarchical.d.ts.map +1 -1
  136. package/dist/src/clustering/hierarchical.js +22 -6
  137. package/dist/src/clustering/hierarchical.js.map +1 -1
  138. package/dist/src/clustering/index.d.ts.map +1 -1
  139. package/dist/src/clustering/index.js.map +1 -1
  140. package/dist/src/clustering/k-core.d.ts +2 -5
  141. package/dist/src/clustering/k-core.d.ts.map +1 -1
  142. package/dist/src/clustering/k-core.js +14 -12
  143. package/dist/src/clustering/k-core.js.map +1 -1
  144. package/dist/src/clustering/mcl.d.ts +6 -0
  145. package/dist/src/clustering/mcl.d.ts.map +1 -1
  146. package/dist/src/clustering/mcl.js +34 -3
  147. package/dist/src/clustering/mcl.js.map +1 -1
  148. package/dist/src/clustering/spectral.d.ts +4 -1
  149. package/dist/src/clustering/spectral.d.ts.map +1 -1
  150. package/dist/src/clustering/spectral.js +61 -28
  151. package/dist/src/clustering/spectral.js.map +1 -1
  152. package/dist/src/core/graph.d.ts +45 -0
  153. package/dist/src/core/graph.d.ts.map +1 -1
  154. package/dist/src/core/graph.js +45 -1
  155. package/dist/src/core/graph.js.map +1 -1
  156. package/dist/src/data-structures/index.d.ts.map +1 -1
  157. package/dist/src/data-structures/index.js.map +1 -1
  158. package/dist/src/data-structures/priority-queue.d.ts +18 -1
  159. package/dist/src/data-structures/priority-queue.d.ts.map +1 -1
  160. package/dist/src/data-structures/priority-queue.js +26 -5
  161. package/dist/src/data-structures/priority-queue.js.map +1 -1
  162. package/dist/src/data-structures/union-find.d.ts +21 -0
  163. package/dist/src/data-structures/union-find.d.ts.map +1 -1
  164. package/dist/src/data-structures/union-find.js +21 -0
  165. package/dist/src/data-structures/union-find.js.map +1 -1
  166. package/dist/src/flow/ford-fulkerson.d.ts +4 -2
  167. package/dist/src/flow/ford-fulkerson.d.ts.map +1 -1
  168. package/dist/src/flow/ford-fulkerson.js +31 -2
  169. package/dist/src/flow/ford-fulkerson.js.map +1 -1
  170. package/dist/src/flow/min-cut.d.ts +0 -3
  171. package/dist/src/flow/min-cut.d.ts.map +1 -1
  172. package/dist/src/flow/min-cut.js +17 -4
  173. package/dist/src/flow/min-cut.js.map +1 -1
  174. package/dist/src/index.d.ts +2 -1
  175. package/dist/src/index.d.ts.map +1 -1
  176. package/dist/src/index.js +2 -1
  177. package/dist/src/index.js.map +1 -1
  178. package/dist/src/link-prediction/adamic-adar.d.ts +26 -0
  179. package/dist/src/link-prediction/adamic-adar.d.ts.map +1 -1
  180. package/dist/src/link-prediction/adamic-adar.js +36 -10
  181. package/dist/src/link-prediction/adamic-adar.js.map +1 -1
  182. package/dist/src/link-prediction/common-neighbors.d.ts +21 -0
  183. package/dist/src/link-prediction/common-neighbors.d.ts.map +1 -1
  184. package/dist/src/link-prediction/common-neighbors.js +27 -6
  185. package/dist/src/link-prediction/common-neighbors.js.map +1 -1
  186. package/dist/src/link-prediction/index.d.ts.map +1 -1
  187. package/dist/src/optimized/bit-packed.d.ts +103 -53
  188. package/dist/src/optimized/bit-packed.d.ts.map +1 -1
  189. package/dist/src/optimized/bit-packed.js +104 -54
  190. package/dist/src/optimized/bit-packed.js.map +1 -1
  191. package/dist/src/optimized/csr-graph.d.ts +87 -24
  192. package/dist/src/optimized/csr-graph.d.ts.map +1 -1
  193. package/dist/src/optimized/csr-graph.js +87 -24
  194. package/dist/src/optimized/csr-graph.js.map +1 -1
  195. package/dist/src/optimized/direction-optimized-bfs.d.ts +37 -16
  196. package/dist/src/optimized/direction-optimized-bfs.d.ts.map +1 -1
  197. package/dist/src/optimized/direction-optimized-bfs.js +39 -20
  198. package/dist/src/optimized/direction-optimized-bfs.js.map +1 -1
  199. package/dist/src/optimized/graph-adapter.d.ts +58 -9
  200. package/dist/src/optimized/graph-adapter.d.ts.map +1 -1
  201. package/dist/src/optimized/graph-adapter.js +58 -10
  202. package/dist/src/optimized/graph-adapter.js.map +1 -1
  203. package/dist/src/optimized/index.d.ts +1 -1
  204. package/dist/src/optimized/index.d.ts.map +1 -1
  205. package/dist/src/optimized/index.js +3 -1
  206. package/dist/src/optimized/index.js.map +1 -1
  207. package/dist/src/pathfinding/astar.d.ts +25 -9
  208. package/dist/src/pathfinding/astar.d.ts.map +1 -1
  209. package/dist/src/pathfinding/astar.js +25 -10
  210. package/dist/src/pathfinding/astar.js.map +1 -1
  211. package/dist/src/pathfinding/utils.d.ts +15 -6
  212. package/dist/src/pathfinding/utils.d.ts.map +1 -1
  213. package/dist/src/pathfinding/utils.js +19 -7
  214. package/dist/src/pathfinding/utils.js.map +1 -1
  215. package/dist/src/research/grsbm.d.ts +0 -1
  216. package/dist/src/research/grsbm.d.ts.map +1 -1
  217. package/dist/src/research/grsbm.js +23 -10
  218. package/dist/src/research/grsbm.js.map +1 -1
  219. package/dist/src/research/index.d.ts.map +1 -1
  220. package/dist/src/research/index.js.map +1 -1
  221. package/dist/src/research/sync.d.ts +0 -1
  222. package/dist/src/research/sync.d.ts.map +1 -1
  223. package/dist/src/research/sync.js +29 -8
  224. package/dist/src/research/sync.js.map +1 -1
  225. package/dist/src/research/terahac.d.ts +0 -1
  226. package/dist/src/research/terahac.d.ts.map +1 -1
  227. package/dist/src/research/terahac.js +32 -4
  228. package/dist/src/research/terahac.js.map +1 -1
  229. package/dist/src/utils/graph-converters.d.ts +31 -0
  230. package/dist/src/utils/graph-converters.d.ts.map +1 -1
  231. package/dist/src/utils/graph-converters.js +31 -0
  232. package/dist/src/utils/graph-converters.js.map +1 -1
  233. package/dist/src/utils/graph-utilities.d.ts.map +1 -1
  234. package/dist/src/utils/graph-utilities.js.map +1 -1
  235. package/dist/src/utils/math-utilities.d.ts +11 -0
  236. package/dist/src/utils/math-utilities.d.ts.map +1 -1
  237. package/dist/src/utils/math-utilities.js +14 -5
  238. package/dist/src/utils/math-utilities.js.map +1 -1
  239. package/dist/src/utils/optimization-helpers.d.ts +9 -0
  240. package/dist/src/utils/optimization-helpers.d.ts.map +1 -1
  241. package/dist/src/utils/optimization-helpers.js +12 -0
  242. package/dist/src/utils/optimization-helpers.js.map +1 -1
  243. package/dist/src/utils/priorityQueue.d.ts +24 -0
  244. package/dist/src/utils/priorityQueue.d.ts.map +1 -1
  245. package/dist/src/utils/priorityQueue.js +34 -4
  246. package/dist/src/utils/priorityQueue.js.map +1 -1
  247. package/dist/tsconfig.tsbuildinfo +1 -0
  248. package/package.json +56 -65
  249. package/src/algorithms/centrality/betweenness.ts +34 -17
  250. package/src/algorithms/centrality/closeness.ts +34 -17
  251. package/src/algorithms/centrality/degree.ts +15 -19
  252. package/src/algorithms/centrality/delta-pagerank-simple.ts +36 -28
  253. package/src/algorithms/centrality/delta-pagerank.ts +34 -11
  254. package/src/algorithms/centrality/eigenvector.ts +14 -15
  255. package/src/algorithms/centrality/hits.ts +17 -17
  256. package/src/algorithms/centrality/index.ts +20 -15
  257. package/src/algorithms/centrality/katz.ts +17 -25
  258. package/src/algorithms/centrality/pagerank.ts +26 -17
  259. package/src/algorithms/community/girvan-newman.ts +39 -28
  260. package/src/algorithms/community/index.ts +6 -7
  261. package/src/algorithms/community/label-propagation.ts +20 -28
  262. package/src/algorithms/community/leiden.ts +61 -37
  263. package/src/algorithms/community/louvain-optimized.ts +49 -20
  264. package/src/algorithms/community/louvain.ts +35 -25
  265. package/src/algorithms/community/modularity-utils.ts +5 -17
  266. package/src/algorithms/components/connected.ts +40 -17
  267. package/src/algorithms/matching/bipartite.ts +17 -10
  268. package/src/algorithms/matching/index.ts +4 -4
  269. package/src/algorithms/matching/isomorphism.ts +53 -23
  270. package/src/algorithms/mst/index.ts +3 -4
  271. package/src/algorithms/mst/kruskal.ts +21 -6
  272. package/src/algorithms/mst/prim.ts +13 -4
  273. package/src/algorithms/shortest-path/bellman-ford.ts +16 -15
  274. package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +29 -29
  275. package/src/algorithms/shortest-path/dijkstra.ts +23 -17
  276. package/src/algorithms/shortest-path/floyd-warshall.ts +21 -4
  277. package/src/algorithms/shortest-path/index.ts +5 -5
  278. package/src/algorithms/traversal/bfs-unified.ts +64 -60
  279. package/src/algorithms/traversal/bfs-variants.ts +61 -37
  280. package/src/algorithms/traversal/bfs.ts +1 -7
  281. package/src/algorithms/traversal/dfs.ts +61 -42
  282. package/src/algorithms/traversal/index.ts +3 -3
  283. package/src/benchmark-all-algorithms.ts +57 -25
  284. package/src/clustering/hierarchical.ts +40 -34
  285. package/src/clustering/index.ts +8 -8
  286. package/src/clustering/k-core.ts +26 -42
  287. package/src/clustering/mcl.ts +53 -23
  288. package/src/clustering/spectral.ts +91 -57
  289. package/src/core/graph.ts +54 -14
  290. package/src/data-structures/index.ts +2 -2
  291. package/src/data-structures/priority-queue.ts +36 -11
  292. package/src/data-structures/union-find.ts +22 -1
  293. package/src/flow/ford-fulkerson.ts +62 -35
  294. package/src/flow/min-cut.ts +43 -45
  295. package/src/index.ts +3 -2
  296. package/src/link-prediction/adamic-adar.ts +65 -51
  297. package/src/link-prediction/common-neighbors.ts +45 -36
  298. package/src/link-prediction/index.ts +1 -1
  299. package/src/optimized/bit-packed.ts +106 -56
  300. package/src/optimized/csr-graph.ts +93 -30
  301. package/src/optimized/direction-optimized-bfs.ts +44 -25
  302. package/src/optimized/graph-adapter.ts +64 -16
  303. package/src/optimized/index.ts +7 -9
  304. package/src/pathfinding/astar.ts +40 -25
  305. package/src/pathfinding/utils.ts +20 -13
  306. package/src/research/grsbm.ts +31 -25
  307. package/src/research/index.ts +4 -4
  308. package/src/research/sync.ts +40 -24
  309. package/src/research/terahac.ts +54 -20
  310. package/src/utils/graph-converters.ts +42 -14
  311. package/src/utils/graph-utilities.ts +11 -37
  312. package/src/utils/math-utilities.ts +17 -8
  313. package/src/utils/optimization-helpers.ts +27 -21
  314. package/src/utils/priorityQueue.ts +40 -6
@@ -1,4 +1,8 @@
1
1
  class Graph {
2
+ /**
3
+ * Creates a new Graph instance.
4
+ * @param config - Configuration options for the graph
5
+ */
2
6
  constructor(config = {}) {
3
7
  this.config = {
4
8
  directed: false,
@@ -13,6 +17,8 @@ class Graph {
13
17
  }
14
18
  /**
15
19
  * Add a node to the graph
20
+ * @param id - The unique identifier for the node
21
+ * @param data - Optional key-value data to attach to the node
16
22
  */
17
23
  addNode(id, data) {
18
24
  if (!this.nodeMap.has(id)) {
@@ -25,6 +31,8 @@ class Graph {
25
31
  }
26
32
  /**
27
33
  * Remove a node from the graph
34
+ * @param id - The unique identifier of the node to remove
35
+ * @returns True if the node was removed, false if it did not exist
28
36
  */
29
37
  removeNode(id) {
30
38
  if (!this.nodeMap.has(id)) {
@@ -59,6 +67,10 @@ class Graph {
59
67
  }
60
68
  /**
61
69
  * Add an edge to the graph
70
+ * @param source - The source node identifier
71
+ * @param target - The target node identifier
72
+ * @param weight - The weight of the edge (defaults to 1)
73
+ * @param data - Optional key-value data to attach to the edge
62
74
  */
63
75
  addEdge(source, target, weight = 1, data) {
64
76
  this.addNode(source);
@@ -92,6 +104,9 @@ class Graph {
92
104
  }
93
105
  /**
94
106
  * Remove an edge from the graph
107
+ * @param source - The source node identifier
108
+ * @param target - The target node identifier
109
+ * @returns True if the edge was removed, false if it did not exist
95
110
  */
96
111
  removeEdge(source, target) {
97
112
  const sourceEdges = this.adjacencyList.get(source);
@@ -115,12 +130,17 @@ class Graph {
115
130
  }
116
131
  /**
117
132
  * Check if a node exists in the graph
133
+ * @param id - The unique identifier of the node to check
134
+ * @returns True if the node exists, false otherwise
118
135
  */
119
136
  hasNode(id) {
120
137
  return this.nodeMap.has(id);
121
138
  }
122
139
  /**
123
140
  * Check if an edge exists in the graph
141
+ * @param source - The source node identifier
142
+ * @param target - The target node identifier
143
+ * @returns True if the edge exists, false otherwise
124
144
  */
125
145
  hasEdge(source, target) {
126
146
  const sourceEdges = this.adjacencyList.get(source);
@@ -128,12 +148,17 @@ class Graph {
128
148
  }
129
149
  /**
130
150
  * Get a node by ID
151
+ * @param id - The unique identifier of the node to retrieve
152
+ * @returns The node if found, undefined otherwise
131
153
  */
132
154
  getNode(id) {
133
155
  return this.nodeMap.get(id);
134
156
  }
135
157
  /**
136
158
  * Get an edge by source and target
159
+ * @param source - The source node identifier
160
+ * @param target - The target node identifier
161
+ * @returns The edge if found, undefined otherwise
137
162
  */
138
163
  getEdge(source, target) {
139
164
  const sourceEdges = this.adjacencyList.get(source);
@@ -141,30 +166,35 @@ class Graph {
141
166
  }
142
167
  /**
143
168
  * Get the number of nodes in the graph
169
+ * @returns The total count of nodes
144
170
  */
145
171
  get nodeCount() {
146
172
  return this.nodeMap.size;
147
173
  }
148
174
  /**
149
175
  * Get the number of edges in the graph
176
+ * @returns The total count of edges
150
177
  */
151
178
  get totalEdgeCount() {
152
179
  return this.edgeCount;
153
180
  }
154
181
  /**
155
182
  * Check if the graph is directed
183
+ * @returns True if the graph is directed, false otherwise
156
184
  */
157
185
  get isDirected() {
158
186
  return this.config.directed;
159
187
  }
160
188
  /**
161
189
  * Get all nodes in the graph
190
+ * @returns An iterator over all nodes
162
191
  */
163
192
  nodes() {
164
193
  return this.nodeMap.values();
165
194
  }
166
195
  /**
167
196
  * Get all edges in the graph
197
+ * @yields Each unique edge in the graph
168
198
  */
169
199
  *edges() {
170
200
  for (const [source, edges] of this.adjacencyList) {
@@ -178,6 +208,8 @@ class Graph {
178
208
  }
179
209
  /**
180
210
  * Get neighbors of a node (outgoing edges)
211
+ * @param nodeId - The node identifier to get neighbors for
212
+ * @returns An iterator over the neighbor node identifiers
181
213
  */
182
214
  neighbors(nodeId) {
183
215
  const edges = this.adjacencyList.get(nodeId);
@@ -185,6 +217,8 @@ class Graph {
185
217
  }
186
218
  /**
187
219
  * Get incoming neighbors of a node (directed graphs only)
220
+ * @param nodeId - The node identifier to get incoming neighbors for
221
+ * @returns An iterator over the incoming neighbor node identifiers
188
222
  */
189
223
  inNeighbors(nodeId) {
190
224
  if (!this.config.directed) {
@@ -195,12 +229,16 @@ class Graph {
195
229
  }
196
230
  /**
197
231
  * Get outgoing neighbors of a node
232
+ * @param nodeId - The node identifier to get outgoing neighbors for
233
+ * @returns An iterator over the outgoing neighbor node identifiers
198
234
  */
199
235
  outNeighbors(nodeId) {
200
236
  return this.neighbors(nodeId);
201
237
  }
202
238
  /**
203
239
  * Get the degree of a node
240
+ * @param nodeId - The node identifier to get the degree for
241
+ * @returns The total degree of the node
204
242
  */
205
243
  degree(nodeId) {
206
244
  if (this.config.directed) {
@@ -211,6 +249,8 @@ class Graph {
211
249
  }
212
250
  /**
213
251
  * Get the in-degree of a node
252
+ * @param nodeId - The node identifier to get the in-degree for
253
+ * @returns The number of incoming edges to the node
214
254
  */
215
255
  inDegree(nodeId) {
216
256
  if (!this.config.directed) {
@@ -221,6 +261,8 @@ class Graph {
221
261
  }
222
262
  /**
223
263
  * Get the out-degree of a node
264
+ * @param nodeId - The node identifier to get the out-degree for
265
+ * @returns The number of outgoing edges from the node
224
266
  */
225
267
  outDegree(nodeId) {
226
268
  const edges = this.adjacencyList.get(nodeId);
@@ -228,6 +270,7 @@ class Graph {
228
270
  }
229
271
  /**
230
272
  * Create a copy of the graph
273
+ * @returns A new Graph instance with the same nodes and edges
231
274
  */
232
275
  clone() {
233
276
  const cloned = new Graph(this.config);
@@ -235,17 +278,13 @@ class Graph {
235
278
  cloned.addNode(node.id, node.data ? { ...node.data } : void 0);
236
279
  }
237
280
  for (const edge of this.edges()) {
238
- cloned.addEdge(
239
- edge.source,
240
- edge.target,
241
- edge.weight,
242
- edge.data ? { ...edge.data } : void 0
243
- );
281
+ cloned.addEdge(edge.source, edge.target, edge.weight, edge.data ? { ...edge.data } : void 0);
244
282
  }
245
283
  return cloned;
246
284
  }
247
285
  /**
248
286
  * Get graph configuration
287
+ * @returns A copy of the graph configuration object
249
288
  */
250
289
  getConfig() {
251
290
  return { ...this.config };
@@ -262,6 +301,7 @@ class Graph {
262
301
  /**
263
302
  * Get the number of unique edges in the graph
264
303
  * For undirected graphs, each edge is counted once
304
+ * @returns The count of unique edges
265
305
  */
266
306
  get uniqueEdgeCount() {
267
307
  if (this.config.directed) {
@@ -339,7 +379,7 @@ function requireSparseTypedFastBitSet() {
339
379
  }
340
380
  var SparseTypedFastBitSet$1 = (
341
381
  /** @class */
342
- function() {
382
+ (function() {
343
383
  function SparseTypedFastBitSet2(iterable, data) {
344
384
  var e_1, _a;
345
385
  if (data === void 0) {
@@ -1520,7 +1560,7 @@ function requireSparseTypedFastBitSet() {
1520
1560
  }
1521
1561
  };
1522
1562
  return SparseTypedFastBitSet2;
1523
- }()
1563
+ })()
1524
1564
  );
1525
1565
  SparseTypedFastBitSet.SparseTypedFastBitSet = SparseTypedFastBitSet$1;
1526
1566
  return SparseTypedFastBitSet;
@@ -1552,7 +1592,7 @@ function requireTypedFastBitSet() {
1552
1592
  }
1553
1593
  var TypedFastBitSet$1 = (
1554
1594
  /** @class */
1555
- function() {
1595
+ (function() {
1556
1596
  function TypedFastBitSet2(iterable, words) {
1557
1597
  var e_1, _a;
1558
1598
  if (words === void 0) {
@@ -2044,7 +2084,7 @@ function requireTypedFastBitSet() {
2044
2084
  return answer;
2045
2085
  };
2046
2086
  return TypedFastBitSet2;
2047
- }()
2087
+ })()
2048
2088
  );
2049
2089
  TypedFastBitSet.TypedFastBitSet = TypedFastBitSet$1;
2050
2090
  return TypedFastBitSet;
@@ -2053,8 +2093,8 @@ var hasRequiredLib;
2053
2093
  function requireLib() {
2054
2094
  if (hasRequiredLib) return lib;
2055
2095
  hasRequiredLib = 1;
2056
- (function(exports) {
2057
- var __createBinding = lib && lib.__createBinding || (Object.create ? function(o, m, k, k2) {
2096
+ (function(exports$1) {
2097
+ var __createBinding = lib && lib.__createBinding || (Object.create ? (function(o, m, k, k2) {
2058
2098
  if (k2 === void 0) k2 = k;
2059
2099
  var desc = Object.getOwnPropertyDescriptor(m, k);
2060
2100
  if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
@@ -2063,21 +2103,25 @@ function requireLib() {
2063
2103
  } };
2064
2104
  }
2065
2105
  Object.defineProperty(o, k2, desc);
2066
- } : function(o, m, k, k2) {
2106
+ }) : (function(o, m, k, k2) {
2067
2107
  if (k2 === void 0) k2 = k;
2068
2108
  o[k2] = m[k];
2069
- });
2070
- var __exportStar = lib && lib.__exportStar || function(m, exports2) {
2071
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
2109
+ }));
2110
+ var __exportStar = lib && lib.__exportStar || function(m, exports$12) {
2111
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports$12, p)) __createBinding(exports$12, m, p);
2072
2112
  };
2073
- Object.defineProperty(exports, "__esModule", { value: true });
2074
- __exportStar(requireSparseTypedFastBitSet(), exports);
2075
- __exportStar(requireTypedFastBitSet(), exports);
2113
+ Object.defineProperty(exports$1, "__esModule", { value: true });
2114
+ __exportStar(requireSparseTypedFastBitSet(), exports$1);
2115
+ __exportStar(requireTypedFastBitSet(), exports$1);
2076
2116
  })(lib);
2077
2117
  return lib;
2078
2118
  }
2079
2119
  var libExports = requireLib();
2080
2120
  class GraphBitSet {
2121
+ /**
2122
+ * Creates a new GraphBitSet with optional pre-allocated capacity.
2123
+ * @param capacity - The initial capacity to pre-allocate for the bitset
2124
+ */
2081
2125
  constructor(capacity) {
2082
2126
  this._cardinality = 0;
2083
2127
  this.bitset = new libExports.TypedFastBitSet();
@@ -2086,8 +2130,9 @@ class GraphBitSet {
2086
2130
  }
2087
2131
  }
2088
2132
  /**
2089
- * Add a single element
2090
- */
2133
+ * Add a single element to the set.
2134
+ * @param index - The element index to add
2135
+ */
2091
2136
  add(index) {
2092
2137
  if (!this.bitset.has(index)) {
2093
2138
  this.bitset.add(index);
@@ -2095,8 +2140,9 @@ class GraphBitSet {
2095
2140
  }
2096
2141
  }
2097
2142
  /**
2098
- * Remove a single element
2099
- */
2143
+ * Remove a single element from the set.
2144
+ * @param index - The element index to remove
2145
+ */
2100
2146
  remove(index) {
2101
2147
  if (this.bitset.has(index)) {
2102
2148
  this.bitset.remove(index);
@@ -2104,27 +2150,32 @@ class GraphBitSet {
2104
2150
  }
2105
2151
  }
2106
2152
  /**
2107
- * Check if element exists
2108
- */
2153
+ * Check if an element exists in the set.
2154
+ * @param index - The element index to check
2155
+ * @returns True if the element exists, false otherwise
2156
+ */
2109
2157
  has(index) {
2110
2158
  return this.bitset.has(index);
2111
2159
  }
2112
2160
  /**
2113
- * Clear all elements
2114
- */
2161
+ * Clear all elements
2162
+ */
2115
2163
  clear() {
2116
2164
  this.bitset.clear();
2117
2165
  this._cardinality = 0;
2118
2166
  }
2119
2167
  /**
2120
- * Check if empty
2121
- */
2168
+ * Check if the set is empty.
2169
+ * @returns True if the set contains no elements, false otherwise
2170
+ */
2122
2171
  isEmpty() {
2123
2172
  return this._cardinality === 0;
2124
2173
  }
2125
2174
  /**
2126
- * Optimized for graph algorithms - add range of indices
2127
- */
2175
+ * Optimized for graph algorithms - add a range of indices.
2176
+ * @param start - The starting index (inclusive)
2177
+ * @param end - The ending index (exclusive)
2178
+ */
2128
2179
  addRange(start, end) {
2129
2180
  for (let i = start; i < end; i++) {
2130
2181
  if (!this.bitset.has(i)) {
@@ -2134,39 +2185,51 @@ class GraphBitSet {
2134
2185
  }
2135
2186
  }
2136
2187
  /**
2137
- * Fast cardinality tracking
2138
- */
2188
+ * Fast cardinality tracking - get the number of elements in the set.
2189
+ * @returns The number of elements in the set
2190
+ */
2139
2191
  size() {
2140
2192
  return this._cardinality;
2141
2193
  }
2142
2194
  /**
2143
- * Batch operations for frontier management - swap contents
2144
- */
2195
+ * Batch operations for frontier management - swap contents with another GraphBitSet.
2196
+ * @param other - The GraphBitSet to swap contents with
2197
+ */
2145
2198
  swap(other) {
2146
2199
  [this.bitset, other.bitset] = [other.bitset, this.bitset];
2147
2200
  [this._cardinality, other._cardinality] = [other._cardinality, this._cardinality];
2148
2201
  }
2149
2202
  /**
2150
- * Efficient iteration
2151
- */
2203
+ * Efficient iteration over all elements in the set.
2204
+ * @yields The indices of elements in the set
2205
+ */
2152
2206
  *[Symbol.iterator]() {
2153
2207
  yield* this.bitset;
2154
2208
  }
2155
2209
  /**
2156
- * Set operations with cardinality tracking
2157
- */
2210
+ * Perform union operation with another GraphBitSet, updating this set in place.
2211
+ * @param other - The GraphBitSet to union with
2212
+ */
2158
2213
  union(other) {
2159
2214
  const result = this.bitset.union(other.bitset);
2160
2215
  this.bitset = result;
2161
2216
  const size = this.bitset.size();
2162
2217
  this._cardinality = size;
2163
2218
  }
2219
+ /**
2220
+ * Perform intersection operation with another GraphBitSet, updating this set in place.
2221
+ * @param other - The GraphBitSet to intersect with
2222
+ */
2164
2223
  intersection(other) {
2165
2224
  const result = this.bitset.intersection(other.bitset);
2166
2225
  this.bitset = result;
2167
2226
  const size = this.bitset.size();
2168
2227
  this._cardinality = size;
2169
2228
  }
2229
+ /**
2230
+ * Perform difference operation with another GraphBitSet, updating this set in place.
2231
+ * @param other - The GraphBitSet to subtract from this set
2232
+ */
2170
2233
  difference(other) {
2171
2234
  const result = this.bitset.difference(other.bitset);
2172
2235
  this.bitset = result;
@@ -2174,8 +2237,9 @@ class GraphBitSet {
2174
2237
  this._cardinality = size;
2175
2238
  }
2176
2239
  /**
2177
- * Clone the bitset
2178
- */
2240
+ * Clone the bitset.
2241
+ * @returns A new GraphBitSet with the same elements
2242
+ */
2179
2243
  clone() {
2180
2244
  const cloned = new GraphBitSet();
2181
2245
  cloned.bitset = this.bitset.clone();
@@ -2184,14 +2248,19 @@ class GraphBitSet {
2184
2248
  }
2185
2249
  }
2186
2250
  class VisitedBitArray {
2251
+ /**
2252
+ * Creates a new VisitedBitArray with the specified size.
2253
+ * @param size - The number of bits to allocate
2254
+ */
2187
2255
  constructor(size) {
2188
2256
  this._size = size;
2189
2257
  this.wordCount = Math.ceil(size / 32);
2190
2258
  this.words = new Uint32Array(this.wordCount);
2191
2259
  }
2192
2260
  /**
2193
- * Set bit at index
2194
- */
2261
+ * Set bit at the specified index.
2262
+ * @param index - The bit index to set
2263
+ */
2195
2264
  set(index) {
2196
2265
  if (index < 0 || index >= this._size) {
2197
2266
  throw new Error(`Index ${String(index)} out of bounds [0, ${String(this._size)})`);
@@ -2204,8 +2273,10 @@ class VisitedBitArray {
2204
2273
  }
2205
2274
  }
2206
2275
  /**
2207
- * Get bit at index
2208
- */
2276
+ * Get bit value at the specified index.
2277
+ * @param index - The bit index to get
2278
+ * @returns True if the bit is set, false otherwise
2279
+ */
2209
2280
  get(index) {
2210
2281
  if (index < 0 || index >= this._size) {
2211
2282
  return false;
@@ -2216,14 +2287,15 @@ class VisitedBitArray {
2216
2287
  return word !== void 0 && (word & 1 << bitIndex) !== 0;
2217
2288
  }
2218
2289
  /**
2219
- * Clear all bits
2220
- */
2290
+ * Clear all bits
2291
+ */
2221
2292
  clear() {
2222
2293
  this.words.fill(0);
2223
2294
  }
2224
2295
  /**
2225
- * Toggle bit at index
2226
- */
2296
+ * Toggle bit at the specified index.
2297
+ * @param index - The bit index to toggle
2298
+ */
2227
2299
  toggle(index) {
2228
2300
  if (index < 0 || index >= this._size) {
2229
2301
  throw new Error(`Index ${String(index)} out of bounds [0, ${String(this._size)})`);
@@ -2236,8 +2308,9 @@ class VisitedBitArray {
2236
2308
  }
2237
2309
  }
2238
2310
  /**
2239
- * Population count for statistics
2240
- */
2311
+ * Population count for statistics - count the number of set bits.
2312
+ * @returns The number of bits set to 1
2313
+ */
2241
2314
  popcount() {
2242
2315
  let count = 0;
2243
2316
  for (let i = 0; i < this.wordCount; i++) {
@@ -2249,9 +2322,11 @@ class VisitedBitArray {
2249
2322
  return count;
2250
2323
  }
2251
2324
  /**
2252
- * Efficient population count for a single word
2253
- * Uses bit manipulation tricks for fast counting
2254
- */
2325
+ * Efficient population count for a single word.
2326
+ * Uses bit manipulation tricks for fast counting.
2327
+ * @param n - The 32-bit word to count
2328
+ * @returns The number of bits set to 1 in the word
2329
+ */
2255
2330
  popcountWord(n) {
2256
2331
  let x = n;
2257
2332
  x = x - (x >>> 1 & 1431655765);
@@ -2259,14 +2334,16 @@ class VisitedBitArray {
2259
2334
  return (x + (x >>> 4) & 252645135) * 16843009 >>> 24;
2260
2335
  }
2261
2336
  /**
2262
- * Get size of the bit array
2263
- */
2337
+ * Get size of the bit array.
2338
+ * @returns The total number of bits in the array
2339
+ */
2264
2340
  size() {
2265
2341
  return this._size;
2266
2342
  }
2267
2343
  /**
2268
- * Check if all bits are zero
2269
- */
2344
+ * Check if all bits are zero.
2345
+ * @returns True if no bits are set, false otherwise
2346
+ */
2270
2347
  isEmpty() {
2271
2348
  for (let i = 0; i < this.wordCount; i++) {
2272
2349
  if (this.words[i] !== 0) {
@@ -2276,16 +2353,18 @@ class VisitedBitArray {
2276
2353
  return true;
2277
2354
  }
2278
2355
  /**
2279
- * Set multiple bits from array
2280
- */
2356
+ * Set multiple bits from an array of indices.
2357
+ * @param indices - Array of bit indices to set
2358
+ */
2281
2359
  setMultiple(indices) {
2282
2360
  for (const index of indices) {
2283
2361
  this.set(index);
2284
2362
  }
2285
2363
  }
2286
2364
  /**
2287
- * Get indices of all set bits
2288
- */
2365
+ * Get indices of all set bits.
2366
+ * @returns Array containing the indices of all bits that are set to 1
2367
+ */
2289
2368
  getSetIndices() {
2290
2369
  const indices = [];
2291
2370
  for (let wordIndex = 0; wordIndex < this.wordCount; wordIndex++) {
@@ -2306,14 +2385,20 @@ class VisitedBitArray {
2306
2385
  }
2307
2386
  }
2308
2387
  const _CompactDistanceArray = class _CompactDistanceArray {
2388
+ /**
2389
+ * Creates a new CompactDistanceArray with the specified size.
2390
+ * @param size - The number of distance values to store
2391
+ */
2309
2392
  constructor(size) {
2310
2393
  this._size = size;
2311
2394
  this.data = new Uint16Array(size);
2312
2395
  this.data.fill(_CompactDistanceArray.INFINITY);
2313
2396
  }
2314
2397
  /**
2315
- * Set distance at index
2316
- */
2398
+ * Set distance at the specified index.
2399
+ * @param index - The node index to set the distance for
2400
+ * @param distance - The distance value to set
2401
+ */
2317
2402
  set(index, distance) {
2318
2403
  if (distance >= _CompactDistanceArray.INFINITY) {
2319
2404
  throw new Error(`Distance exceeds maximum value (${String(_CompactDistanceArray.INFINITY - 1)})`);
@@ -2321,27 +2406,32 @@ const _CompactDistanceArray = class _CompactDistanceArray {
2321
2406
  this.data[index] = distance;
2322
2407
  }
2323
2408
  /**
2324
- * Get distance at index
2325
- */
2409
+ * Get distance at the specified index.
2410
+ * @param index - The node index to get the distance for
2411
+ * @returns The distance value, or INFINITY if not set
2412
+ */
2326
2413
  get(index) {
2327
2414
  const value = this.data[index];
2328
2415
  return value ?? _CompactDistanceArray.INFINITY;
2329
2416
  }
2330
2417
  /**
2331
- * Check if node has been visited
2332
- */
2418
+ * Check if a node has been visited (has a valid distance).
2419
+ * @param index - The node index to check
2420
+ * @returns True if the node has been visited, false otherwise
2421
+ */
2333
2422
  isVisited(index) {
2334
2423
  return this.data[index] !== _CompactDistanceArray.INFINITY;
2335
2424
  }
2336
2425
  /**
2337
- * Reset all distances
2338
- */
2426
+ * Reset all distances to unvisited state.
2427
+ */
2339
2428
  clear() {
2340
2429
  this.data.fill(_CompactDistanceArray.INFINITY);
2341
2430
  }
2342
2431
  /**
2343
- * Get size
2344
- */
2432
+ * Get the size of the distance array.
2433
+ * @returns The number of elements in the array
2434
+ */
2345
2435
  size() {
2346
2436
  return this._size;
2347
2437
  }
@@ -2349,6 +2439,11 @@ const _CompactDistanceArray = class _CompactDistanceArray {
2349
2439
  _CompactDistanceArray.INFINITY = 65535;
2350
2440
  let CompactDistanceArray = _CompactDistanceArray;
2351
2441
  class DirectionOptimizedBFS {
2442
+ /**
2443
+ * Creates a new DirectionOptimizedBFS instance.
2444
+ * @param graph - The CSR graph to perform BFS on
2445
+ * @param options - Optional configuration for switching thresholds
2446
+ */
2352
2447
  constructor(graph, options) {
2353
2448
  this.graph = graph;
2354
2449
  this.alpha = options?.alpha ?? 15;
@@ -2360,8 +2455,10 @@ class DirectionOptimizedBFS {
2360
2455
  this.distances = new CompactDistanceArray(nodeCount);
2361
2456
  }
2362
2457
  /**
2363
- * Perform BFS from a single source
2364
- */
2458
+ * Perform BFS from a single source node.
2459
+ * @param source - The source node ID to start the BFS from
2460
+ * @returns The BFS result containing distances and parent pointers
2461
+ */
2365
2462
  search(source) {
2366
2463
  const sourceIndex = this.graph.nodeToIndex(source);
2367
2464
  this.parent[sourceIndex] = -2;
@@ -2396,8 +2493,9 @@ class DirectionOptimizedBFS {
2396
2493
  return this.buildResult();
2397
2494
  }
2398
2495
  /**
2399
- * Top-down BFS step - explore from frontier
2400
- */
2496
+ * Top-down BFS step - explore from frontier.
2497
+ * @returns The scout count (total degree of newly discovered nodes)
2498
+ */
2401
2499
  topDownStep() {
2402
2500
  let scoutCount = 0;
2403
2501
  for (const node of this.frontier) {
@@ -2414,8 +2512,9 @@ class DirectionOptimizedBFS {
2414
2512
  return scoutCount;
2415
2513
  }
2416
2514
  /**
2417
- * Bottom-up BFS step - check unvisited nodes
2418
- */
2515
+ * Bottom-up BFS step - check unvisited nodes for frontier neighbors.
2516
+ * @returns The number of newly discovered nodes
2517
+ */
2419
2518
  bottomUpStep() {
2420
2519
  const nodeCount = this.graph.nodeCount();
2421
2520
  let awakeCount = 0;
@@ -2436,8 +2535,9 @@ class DirectionOptimizedBFS {
2436
2535
  return awakeCount;
2437
2536
  }
2438
2537
  /**
2439
- * Calculate edges to check for switching heuristic
2440
- */
2538
+ * Calculate edges to check for switching heuristic.
2539
+ * @returns The total number of outgoing edges from frontier nodes
2540
+ */
2441
2541
  calculateEdgesToCheck() {
2442
2542
  let count = 0;
2443
2543
  for (const node of this.frontier) {
@@ -2446,8 +2546,9 @@ class DirectionOptimizedBFS {
2446
2546
  return count;
2447
2547
  }
2448
2548
  /**
2449
- * Build result map from internal data structures
2450
- */
2549
+ * Build result map from internal data structures.
2550
+ * @returns The BFS result containing distances and parent pointers
2551
+ */
2451
2552
  buildResult() {
2452
2553
  const distances = /* @__PURE__ */ new Map();
2453
2554
  const parents = /* @__PURE__ */ new Map();
@@ -2470,8 +2571,10 @@ class DirectionOptimizedBFS {
2470
2571
  return { distances, parents, visitedCount };
2471
2572
  }
2472
2573
  /**
2473
- * Perform multi-source BFS
2474
- */
2574
+ * Perform multi-source BFS from multiple source nodes.
2575
+ * @param sources - Array of source node IDs to start the BFS from
2576
+ * @returns The BFS result containing distances and parent pointers
2577
+ */
2475
2578
  searchMultiple(sources) {
2476
2579
  for (const source of sources) {
2477
2580
  const sourceIndex = this.graph.nodeToIndex(source);
@@ -2513,8 +2616,8 @@ class DirectionOptimizedBFS {
2513
2616
  return this.buildResult();
2514
2617
  }
2515
2618
  /**
2516
- * Reset internal state for reuse
2517
- */
2619
+ * Reset internal state for reuse
2620
+ */
2518
2621
  reset() {
2519
2622
  this.parent.fill(-1);
2520
2623
  this.frontier.clear();
@@ -2523,12 +2626,22 @@ class DirectionOptimizedBFS {
2523
2626
  }
2524
2627
  }
2525
2628
  class CSRGraph {
2629
+ /**
2630
+ * Creates a new CSRGraph from an adjacency list representation.
2631
+ * @param adjacencyList - Map of node IDs to arrays of neighbor node IDs
2632
+ * @param weights - Optional map of edge weights keyed by "source-target" strings
2633
+ * @param buildReverse - Whether to build reverse edges for bottom-up BFS (default true)
2634
+ */
2526
2635
  constructor(adjacencyList, weights, buildReverse = true) {
2527
2636
  this.data = this.buildCSR(adjacencyList, weights, buildReverse);
2528
2637
  }
2529
2638
  /**
2530
- * Build CSR structure from adjacency list
2531
- */
2639
+ * Build CSR structure from adjacency list.
2640
+ * @param adjacencyList - Map of node IDs to arrays of neighbor node IDs
2641
+ * @param weights - Optional map of edge weights keyed by "source-target" strings
2642
+ * @param buildReverse - Whether to build reverse edges for bottom-up BFS
2643
+ * @returns The constructed CSR graph data structure
2644
+ */
2532
2645
  buildCSR(adjacencyList, weights, buildReverse = true) {
2533
2646
  const allNodes = /* @__PURE__ */ new Set();
2534
2647
  for (const [source, neighbors] of adjacencyList) {
@@ -2631,15 +2744,34 @@ class CSRGraph {
2631
2744
  return result;
2632
2745
  }
2633
2746
  // Core API methods
2747
+ /**
2748
+ * Get the total number of nodes in the graph.
2749
+ * @returns The number of nodes
2750
+ */
2634
2751
  nodeCount() {
2635
2752
  return this.data.indexToNodeId.length;
2636
2753
  }
2754
+ /**
2755
+ * Get the total number of edges in the graph.
2756
+ * @returns The number of edges
2757
+ */
2637
2758
  edgeCount() {
2638
2759
  return this.data.columnIndices.length;
2639
2760
  }
2761
+ /**
2762
+ * Check if a node exists in the graph.
2763
+ * @param nodeId - The node ID to check
2764
+ * @returns True if the node exists, false otherwise
2765
+ */
2640
2766
  hasNode(nodeId) {
2641
2767
  return this.data.nodeIdToIndex.has(nodeId);
2642
2768
  }
2769
+ /**
2770
+ * Check if an edge exists between two nodes.
2771
+ * @param source - The source node ID
2772
+ * @param target - The target node ID
2773
+ * @returns True if the edge exists, false otherwise
2774
+ */
2643
2775
  hasEdge(source, target) {
2644
2776
  const sourceIndex = this.data.nodeIdToIndex.get(source);
2645
2777
  const targetIndex = this.data.nodeIdToIndex.get(target);
@@ -2654,8 +2786,10 @@ class CSRGraph {
2654
2786
  return this.binarySearch(this.data.columnIndices, targetIndex, start, end) !== -1;
2655
2787
  }
2656
2788
  /**
2657
- * Get neighbors as node IDs
2658
- */
2789
+ * Get neighbors of a node as node IDs.
2790
+ * @param nodeId - The node ID to get neighbors for
2791
+ * @returns An iterator over neighbor node IDs
2792
+ */
2659
2793
  neighbors(nodeId) {
2660
2794
  const nodeIndex = this.data.nodeIdToIndex.get(nodeId);
2661
2795
  if (nodeIndex === void 0) {
@@ -2680,14 +2814,17 @@ class CSRGraph {
2680
2814
  return generateNeighbors();
2681
2815
  }
2682
2816
  /**
2683
- * Get all nodes
2684
- */
2817
+ * Get all nodes in the graph.
2818
+ * @returns An iterator over all node IDs
2819
+ */
2685
2820
  nodes() {
2686
2821
  return this.data.indexToNodeId.values();
2687
2822
  }
2688
2823
  /**
2689
- * Get neighbors as indices (internal use)
2690
- */
2824
+ * Get neighbors as indices (internal use).
2825
+ * @param nodeIndex - The internal index of the node
2826
+ * @returns Array of neighbor indices
2827
+ */
2691
2828
  getNeighborIndices(nodeIndex) {
2692
2829
  if (nodeIndex < 0 || nodeIndex >= this.data.indexToNodeId.length) {
2693
2830
  return [];
@@ -2699,6 +2836,11 @@ class CSRGraph {
2699
2836
  }
2700
2837
  return Array.from(this.data.columnIndices.subarray(start, end));
2701
2838
  }
2839
+ /**
2840
+ * Get the out-degree (number of outgoing edges) of a node.
2841
+ * @param nodeId - The node ID to get the out-degree for
2842
+ * @returns The number of outgoing edges from the node
2843
+ */
2702
2844
  outDegree(nodeId) {
2703
2845
  const nodeIndex = this.data.nodeIdToIndex.get(nodeId);
2704
2846
  if (nodeIndex === void 0) {
@@ -2707,8 +2849,10 @@ class CSRGraph {
2707
2849
  return this.outDegreeByIndex(nodeIndex);
2708
2850
  }
2709
2851
  /**
2710
- * Get out-degree by index (internal use)
2711
- */
2852
+ * Get out-degree by index (internal use).
2853
+ * @param nodeIndex - The internal index of the node
2854
+ * @returns The number of outgoing edges from the node
2855
+ */
2712
2856
  outDegreeByIndex(nodeIndex) {
2713
2857
  const start = this.data.rowPointers[nodeIndex];
2714
2858
  const end = this.data.rowPointers[nodeIndex + 1];
@@ -2718,8 +2862,10 @@ class CSRGraph {
2718
2862
  return 0;
2719
2863
  }
2720
2864
  /**
2721
- * Iterator support for neighbor indices
2722
- */
2865
+ * Iterator support for neighbor indices.
2866
+ * @param nodeIndex - The internal index of the node
2867
+ * @yields The indices of neighboring nodes
2868
+ */
2723
2869
  *iterateNeighborIndices(nodeIndex) {
2724
2870
  const start = this.data.rowPointers[nodeIndex];
2725
2871
  const end = this.data.rowPointers[nodeIndex + 1];
@@ -2733,8 +2879,10 @@ class CSRGraph {
2733
2879
  }
2734
2880
  }
2735
2881
  /**
2736
- * Iterator support for incoming neighbor indices (for bottom-up BFS)
2737
- */
2882
+ * Iterator support for incoming neighbor indices (for bottom-up BFS).
2883
+ * @param nodeIndex - The internal index of the node
2884
+ * @yields The indices of nodes with edges pointing to this node
2885
+ */
2738
2886
  *iterateIncomingNeighborIndices(nodeIndex) {
2739
2887
  if (!this.data.reverseRowPointers || !this.data.reverseColumnIndices) {
2740
2888
  return;
@@ -2751,8 +2899,10 @@ class CSRGraph {
2751
2899
  }
2752
2900
  }
2753
2901
  /**
2754
- * Convert node ID to index
2755
- */
2902
+ * Convert node ID to internal index.
2903
+ * @param nodeId - The node ID to convert
2904
+ * @returns The internal index for the node
2905
+ */
2756
2906
  nodeToIndex(nodeId) {
2757
2907
  const index = this.data.nodeIdToIndex.get(nodeId);
2758
2908
  if (index === void 0) {
@@ -2761,8 +2911,10 @@ class CSRGraph {
2761
2911
  return index;
2762
2912
  }
2763
2913
  /**
2764
- * Convert index to node ID
2765
- */
2914
+ * Convert internal index to node ID.
2915
+ * @param index - The internal index to convert
2916
+ * @returns The node ID for the given index
2917
+ */
2766
2918
  indexToNodeId(index) {
2767
2919
  const nodeId = this.data.indexToNodeId[index];
2768
2920
  if (nodeId === void 0) {
@@ -2771,8 +2923,11 @@ class CSRGraph {
2771
2923
  return nodeId;
2772
2924
  }
2773
2925
  /**
2774
- * Get edge weight
2775
- */
2926
+ * Get edge weight between two nodes.
2927
+ * @param source - The source node ID
2928
+ * @param target - The target node ID
2929
+ * @returns The edge weight, or undefined if the edge doesn't exist or has no weight
2930
+ */
2776
2931
  getEdgeWeight(source, target) {
2777
2932
  if (!this.data.edgeWeights) {
2778
2933
  return void 0;
@@ -2794,8 +2949,13 @@ class CSRGraph {
2794
2949
  return this.data.edgeWeights[edgeIndex];
2795
2950
  }
2796
2951
  /**
2797
- * Binary search for target in sorted array
2798
- */
2952
+ * Binary search for target in sorted array.
2953
+ * @param arr - The typed array to search in
2954
+ * @param target - The value to search for
2955
+ * @param start - The starting index (inclusive)
2956
+ * @param end - The ending index (exclusive)
2957
+ * @returns The index of the target, or -1 if not found
2958
+ */
2799
2959
  binarySearch(arr, target, start, end) {
2800
2960
  let left = start;
2801
2961
  let right = end - 1;
@@ -2817,8 +2977,14 @@ class CSRGraph {
2817
2977
  return -1;
2818
2978
  }
2819
2979
  /**
2820
- * Create CSR graph from standard Graph
2821
- */
2980
+ * Create CSR graph from standard Graph interface.
2981
+ * @param graph - The graph object to convert, must implement nodes, neighbors, hasNode, and optionally getEdge
2982
+ * @param graph.nodes - Function that returns an iterator over node objects with id property
2983
+ * @param graph.neighbors - Function that returns an iterator over neighbor node IDs
2984
+ * @param graph.hasNode - Function that checks if a node exists in the graph
2985
+ * @param graph.getEdge - Optional function that returns edge data including weight
2986
+ * @returns A new CSRGraph instance
2987
+ */
2822
2988
  static fromGraph(graph) {
2823
2989
  const adjacencyList = /* @__PURE__ */ new Map();
2824
2990
  const weights = /* @__PURE__ */ new Map();
@@ -2839,6 +3005,10 @@ class CSRGraph {
2839
3005
  }
2840
3006
  }
2841
3007
  class GraphAdapter {
3008
+ /**
3009
+ * Creates a new GraphAdapter that wraps or converts a graph to CSR format.
3010
+ * @param graph - The graph to adapt (either standard Graph or ReadonlyGraph)
3011
+ */
2842
3012
  constructor(graph) {
2843
3013
  if (graph instanceof CSRGraph) {
2844
3014
  this.csrGraph = graph;
@@ -2847,8 +3017,10 @@ class GraphAdapter {
2847
3017
  }
2848
3018
  }
2849
3019
  /**
2850
- * Convert standard graph to CSR format
2851
- */
3020
+ * Convert standard graph to CSR format.
3021
+ * @param graph - The graph to convert
3022
+ * @returns A new CSRGraph instance
3023
+ */
2852
3024
  convertToCSR(graph) {
2853
3025
  const adjacencyList = /* @__PURE__ */ new Map();
2854
3026
  const weights = /* @__PURE__ */ new Map();
@@ -2888,30 +3060,64 @@ class GraphAdapter {
2888
3060
  return new CSRGraph(adjacencyList, weights.size > 0 ? weights : void 0);
2889
3061
  }
2890
3062
  // Delegate all methods to CSR implementation
3063
+ /**
3064
+ * Get the total number of nodes in the graph.
3065
+ * @returns The number of nodes
3066
+ */
2891
3067
  nodeCount() {
2892
3068
  return this.csrGraph.nodeCount();
2893
3069
  }
3070
+ /**
3071
+ * Get the total number of edges in the graph.
3072
+ * @returns The number of edges
3073
+ */
2894
3074
  edgeCount() {
2895
3075
  return this.csrGraph.edgeCount();
2896
3076
  }
3077
+ /**
3078
+ * Check if a node exists in the graph.
3079
+ * @param nodeId - The node ID to check
3080
+ * @returns True if the node exists, false otherwise
3081
+ */
2897
3082
  hasNode(nodeId) {
2898
3083
  return this.csrGraph.hasNode(nodeId);
2899
3084
  }
3085
+ /**
3086
+ * Check if an edge exists between two nodes.
3087
+ * @param source - The source node ID
3088
+ * @param target - The target node ID
3089
+ * @returns True if the edge exists, false otherwise
3090
+ */
2900
3091
  hasEdge(source, target) {
2901
3092
  return this.csrGraph.hasEdge(source, target);
2902
3093
  }
3094
+ /**
3095
+ * Get neighbors of a node as node IDs.
3096
+ * @param nodeId - The node ID to get neighbors for
3097
+ * @returns An iterator over neighbor node IDs
3098
+ */
2903
3099
  neighbors(nodeId) {
2904
3100
  return this.csrGraph.neighbors(nodeId);
2905
3101
  }
3102
+ /**
3103
+ * Get the out-degree (number of outgoing edges) of a node.
3104
+ * @param nodeId - The node ID to get the out-degree for
3105
+ * @returns The number of outgoing edges from the node
3106
+ */
2906
3107
  outDegree(nodeId) {
2907
3108
  return this.csrGraph.outDegree(nodeId);
2908
3109
  }
3110
+ /**
3111
+ * Get all nodes in the graph.
3112
+ * @returns An iterator over all node IDs
3113
+ */
2909
3114
  nodes() {
2910
3115
  return this.csrGraph.nodes();
2911
3116
  }
2912
3117
  /**
2913
- * Get the underlying CSR graph
2914
- */
3118
+ * Get the underlying CSR graph.
3119
+ * @returns The CSRGraph instance used internally
3120
+ */
2915
3121
  getCSRGraph() {
2916
3122
  return this.csrGraph;
2917
3123
  }
@@ -2962,12 +3168,8 @@ function reconstructPath(target, predecessor) {
2962
3168
  return path;
2963
3169
  }
2964
3170
  function getCommonNeighbors(graph, source, target, directed = false) {
2965
- const sourceNeighbors = new Set(
2966
- directed ? graph.outNeighbors(source) : graph.neighbors(source)
2967
- );
2968
- const targetNeighbors = new Set(
2969
- directed ? graph.outNeighbors(target) : graph.neighbors(target)
2970
- );
3171
+ const sourceNeighbors = new Set(directed ? graph.outNeighbors(source) : graph.neighbors(source));
3172
+ const targetNeighbors = new Set(directed ? graph.outNeighbors(target) : graph.neighbors(target));
2971
3173
  const common = /* @__PURE__ */ new Set();
2972
3174
  for (const neighbor of sourceNeighbors) {
2973
3175
  if (targetNeighbors.has(neighbor)) {
@@ -3528,12 +3730,18 @@ function hasNegativeCycle(graph) {
3528
3730
  return false;
3529
3731
  }
3530
3732
  class PriorityQueue {
3733
+ /**
3734
+ * Creates a new PriorityQueue instance.
3735
+ * @param compareFn - Custom comparison function for priorities. Returns negative if a has higher priority than b.
3736
+ */
3531
3737
  constructor(compareFn) {
3532
3738
  this.heap = [];
3533
3739
  this.compareFn = compareFn ?? ((a, b) => a - b);
3534
3740
  }
3535
3741
  /**
3536
3742
  * Add an item with the given priority to the queue
3743
+ * @param item - The item to add to the queue
3744
+ * @param priority - The priority value for the item (lower values have higher priority in min-heap)
3537
3745
  */
3538
3746
  enqueue(item, priority) {
3539
3747
  const element = { item, priority };
@@ -3542,6 +3750,7 @@ class PriorityQueue {
3542
3750
  }
3543
3751
  /**
3544
3752
  * Remove and return the item with the highest priority
3753
+ * @returns The item with the highest priority, or undefined if the queue is empty
3545
3754
  */
3546
3755
  dequeue() {
3547
3756
  if (this.heap.length === 0) {
@@ -3563,6 +3772,7 @@ class PriorityQueue {
3563
3772
  }
3564
3773
  /**
3565
3774
  * View the item with the highest priority without removing it
3775
+ * @returns The item with the highest priority, or undefined if the queue is empty
3566
3776
  */
3567
3777
  peek() {
3568
3778
  const first = this.heap[0];
@@ -3570,19 +3780,23 @@ class PriorityQueue {
3570
3780
  }
3571
3781
  /**
3572
3782
  * Check if the queue is empty
3783
+ * @returns True if the queue has no items, false otherwise
3573
3784
  */
3574
3785
  isEmpty() {
3575
3786
  return this.heap.length === 0;
3576
3787
  }
3577
3788
  /**
3578
3789
  * Get the number of items in the queue
3790
+ * @returns The number of items currently in the queue
3579
3791
  */
3580
3792
  size() {
3581
3793
  return this.heap.length;
3582
3794
  }
3583
3795
  /**
3584
3796
  * Update the priority of an item if it exists in the queue
3585
- * Returns true if the item was found and updated
3797
+ * @param item - The item whose priority should be updated
3798
+ * @param newPriority - The new priority value for the item
3799
+ * @returns True if the item was found and updated, false otherwise
3586
3800
  */
3587
3801
  updatePriority(item, newPriority) {
3588
3802
  const index = this.heap.findIndex((element2) => element2.item === item);
@@ -3610,12 +3824,14 @@ class PriorityQueue {
3610
3824
  }
3611
3825
  /**
3612
3826
  * Convert queue to array (for testing/debugging)
3827
+ * @returns An array of all items with their priorities
3613
3828
  */
3614
3829
  toArray() {
3615
3830
  return [...this.heap];
3616
3831
  }
3617
3832
  /**
3618
3833
  * Move element up the heap until heap property is satisfied
3834
+ * @param index - The index of the element to heapify up
3619
3835
  */
3620
3836
  heapifyUp(index) {
3621
3837
  if (index === 0) {
@@ -3631,6 +3847,7 @@ class PriorityQueue {
3631
3847
  }
3632
3848
  /**
3633
3849
  * Move element down the heap until heap property is satisfied
3850
+ * @param index - The index of the element to heapify down
3634
3851
  */
3635
3852
  heapifyDown(index) {
3636
3853
  const leftChildIndex = 2 * index + 1;
@@ -3653,6 +3870,8 @@ class PriorityQueue {
3653
3870
  }
3654
3871
  /**
3655
3872
  * Swap two elements in the heap
3873
+ * @param i - Index of the first element
3874
+ * @param j - Index of the second element
3656
3875
  */
3657
3876
  swap(i, j) {
3658
3877
  const temp = this.heap[i];
@@ -3664,6 +3883,10 @@ class PriorityQueue {
3664
3883
  }
3665
3884
  }
3666
3885
  class BidirectionalDijkstra {
3886
+ /**
3887
+ * Creates a new BidirectionalDijkstra instance
3888
+ * @param graph - The graph to search for shortest paths
3889
+ */
3667
3890
  constructor(graph) {
3668
3891
  this.meetingNode = null;
3669
3892
  this.shortestDistance = Infinity;
@@ -3680,8 +3903,11 @@ class BidirectionalDijkstra {
3680
3903
  };
3681
3904
  }
3682
3905
  /**
3683
- * Find shortest path between source and target nodes
3684
- */
3906
+ * Find shortest path between source and target nodes
3907
+ * @param source - The starting node for the path
3908
+ * @param target - The destination node for the path
3909
+ * @returns The shortest path result or null if no path exists
3910
+ */
3685
3911
  findShortestPath(source, target) {
3686
3912
  this.reset();
3687
3913
  if (!this.graph.hasNode(source)) {
@@ -3773,7 +3999,7 @@ class BidirectionalDijkstra {
3773
3999
  }
3774
4000
  return false;
3775
4001
  }
3776
- getMinDistance(frontier) {
4002
+ _getMinDistance(frontier) {
3777
4003
  if (frontier.isEmpty()) {
3778
4004
  return Infinity;
3779
4005
  }
@@ -3806,8 +4032,8 @@ class BidirectionalDijkstra {
3806
4032
  return path;
3807
4033
  }
3808
4034
  /**
3809
- * Reset the search state for reuse
3810
- */
4035
+ * Reset the search state for reuse
4036
+ */
3811
4037
  reset() {
3812
4038
  this.forwardSearch = this.initSearchState();
3813
4039
  this.backwardSearch = this.initSearchState();
@@ -4583,7 +4809,12 @@ function nodeClosenessCentrality(graph, node, options = {}) {
4583
4809
  if (!graph.hasNode(node)) {
4584
4810
  throw new Error(`Node ${String(node)} not found in graph`);
4585
4811
  }
4586
- const distances = bfsDistancesOnly(graph, node, options.cutoff, options.optimized !== void 0 ? { optimized: options.optimized } : {});
4812
+ const distances = bfsDistancesOnly(
4813
+ graph,
4814
+ node,
4815
+ options.cutoff,
4816
+ options.optimized !== void 0 ? { optimized: options.optimized } : {}
4817
+ );
4587
4818
  const totalNodes = graph.nodeCount;
4588
4819
  return calculateClosenessFromDistances(distances, node, totalNodes, options);
4589
4820
  }
@@ -4599,7 +4830,12 @@ function nodeWeightedClosenessCentrality(graph, node, options = {}) {
4599
4830
  if (!graph.hasNode(node)) {
4600
4831
  throw new Error(`Node ${String(node)} not found in graph`);
4601
4832
  }
4602
- const distances = bfsWeightedDistances(graph, node, options.cutoff, options.optimized !== void 0 ? { optimized: options.optimized } : {});
4833
+ const distances = bfsWeightedDistances(
4834
+ graph,
4835
+ node,
4836
+ options.cutoff,
4837
+ options.optimized !== void 0 ? { optimized: options.optimized } : {}
4838
+ );
4603
4839
  const totalNodes = graph.nodeCount;
4604
4840
  return calculateClosenessFromDistances(distances, node, totalNodes, options);
4605
4841
  }
@@ -4666,6 +4902,10 @@ function nodeDegreeCentrality(graph, nodeId, options = {}) {
4666
4902
  return options.normalized && maxPossibleDegree > 0 ? degree / maxPossibleDegree : degree;
4667
4903
  }
4668
4904
  class DeltaPageRank {
4905
+ /**
4906
+ * Creates a new DeltaPageRank instance for the given graph.
4907
+ * @param graph - The directed graph to compute PageRank on
4908
+ */
4669
4909
  constructor(graph) {
4670
4910
  if (!graph.isDirected) {
4671
4911
  throw new Error("DeltaPageRank requires a directed graph");
@@ -4701,6 +4941,11 @@ class DeltaPageRank {
4701
4941
  }
4702
4942
  }
4703
4943
  }
4944
+ /**
4945
+ * Computes PageRank scores using delta-based iteration for faster convergence.
4946
+ * @param options - Configuration options for PageRank computation
4947
+ * @returns Map of node IDs to their PageRank scores
4948
+ */
4704
4949
  compute(options = {}) {
4705
4950
  const {
4706
4951
  dampingFactor = 0.85,
@@ -4796,8 +5041,11 @@ class DeltaPageRank {
4796
5041
  return new Map(this.scores);
4797
5042
  }
4798
5043
  /**
4799
- * Update PageRank scores after graph modification
4800
- * This is where delta-based approach really shines
5044
+ * Update PageRank scores after graph modification.
5045
+ * This is where delta-based approach really shines.
5046
+ * @param modifiedNodes - Set of nodes that were modified (edges added/removed)
5047
+ * @param options - Configuration options for PageRank computation
5048
+ * @returns Updated PageRank scores
4801
5049
  */
4802
5050
  update(modifiedNodes, options = {}) {
4803
5051
  this.activeNodes.clear();
@@ -4825,6 +5073,10 @@ class DeltaPageRank {
4825
5073
  }
4826
5074
  }
4827
5075
  class PriorityDeltaPageRank {
5076
+ /**
5077
+ * Creates a new PriorityDeltaPageRank instance for the given graph.
5078
+ * @param graph - The directed graph to compute PageRank on
5079
+ */
4828
5080
  constructor(graph) {
4829
5081
  if (!graph.isDirected) {
4830
5082
  throw new Error("PriorityDeltaPageRank requires a directed graph");
@@ -4858,6 +5110,12 @@ class PriorityDeltaPageRank {
4858
5110
  }
4859
5111
  }
4860
5112
  }
5113
+ /**
5114
+ * Computes PageRank scores using priority queue-based delta iteration.
5115
+ * Processes nodes in order of their delta magnitude for optimal convergence.
5116
+ * @param options - Configuration options for PageRank computation
5117
+ * @returns Map of node IDs to their PageRank scores
5118
+ */
4861
5119
  computeWithPriority(options = {}) {
4862
5120
  const {
4863
5121
  dampingFactor = 0.85,
@@ -4935,12 +5193,7 @@ class PriorityDeltaPageRank {
4935
5193
  }
4936
5194
  }
4937
5195
  function eigenvectorCentrality(graph, options = {}) {
4938
- const {
4939
- maxIterations = 100,
4940
- tolerance = 1e-6,
4941
- normalized = true,
4942
- startVector
4943
- } = options;
5196
+ const { maxIterations = 100, tolerance = 1e-6, normalized = true, startVector } = options;
4944
5197
  const centrality = {};
4945
5198
  const nodes = Array.from(graph.nodes());
4946
5199
  const nodeIds = nodes.map((node) => node.id);
@@ -5031,11 +5284,7 @@ function nodeEigenvectorCentrality(graph, nodeId, options = {}) {
5031
5284
  return centrality[nodeId.toString()] ?? 0;
5032
5285
  }
5033
5286
  function hits(graph, options = {}) {
5034
- const {
5035
- maxIterations = 100,
5036
- tolerance = 1e-6,
5037
- normalized = true
5038
- } = options;
5287
+ const { maxIterations = 100, tolerance = 1e-6, normalized = true } = options;
5039
5288
  const hubs = {};
5040
5289
  const authorities = {};
5041
5290
  const nodes = Array.from(graph.nodes());
@@ -5159,13 +5408,7 @@ function nodeHITS(graph, nodeId, options = {}) {
5159
5408
  };
5160
5409
  }
5161
5410
  function katzCentrality(graph, options = {}) {
5162
- const {
5163
- alpha = 0.1,
5164
- beta = 1,
5165
- maxIterations = 100,
5166
- tolerance = 1e-6,
5167
- normalized = true
5168
- } = options;
5411
+ const { alpha = 0.1, beta = 1, maxIterations = 100, tolerance = 1e-6, normalized = true } = options;
5169
5412
  const centrality = {};
5170
5413
  const nodes = Array.from(graph.nodes());
5171
5414
  const nodeIds = nodes.map((node) => node.id);
@@ -5229,6 +5472,10 @@ function nodeKatzCentrality(graph, nodeId, options = {}) {
5229
5472
  return centrality[nodeId.toString()] ?? 0;
5230
5473
  }
5231
5474
  class SimpleDeltaPageRank {
5475
+ /**
5476
+ * Creates a new SimpleDeltaPageRank instance for the given graph.
5477
+ * @param graph - The directed graph to compute PageRank on
5478
+ */
5232
5479
  constructor(graph) {
5233
5480
  this.previousScores = null;
5234
5481
  if (!graph.isDirected) {
@@ -5237,14 +5484,18 @@ class SimpleDeltaPageRank {
5237
5484
  this.graph = graph;
5238
5485
  this.nodeCount = graph.nodeCount;
5239
5486
  }
5487
+ /**
5488
+ * Computes PageRank scores for all nodes in the graph using power iteration.
5489
+ * @param options - Configuration options for PageRank computation
5490
+ * @param options.dampingFactor - Probability of following a link (default: 0.85)
5491
+ * @param options.tolerance - Convergence tolerance threshold (default: 1e-6)
5492
+ * @param options.maxIterations - Maximum number of iterations (default: 100)
5493
+ * @param options.personalization - Personalization vector for Personalized PageRank
5494
+ * @param options.weight - Edge attribute name for weighted PageRank
5495
+ * @returns Map of node IDs to their PageRank scores
5496
+ */
5240
5497
  compute(options = {}) {
5241
- const {
5242
- dampingFactor = 0.85,
5243
- tolerance = 1e-6,
5244
- maxIterations = 100,
5245
- personalization,
5246
- weight
5247
- } = options;
5498
+ const { dampingFactor = 0.85, tolerance = 1e-6, maxIterations = 100, personalization, weight } = options;
5248
5499
  if (this.nodeCount === 0) {
5249
5500
  return /* @__PURE__ */ new Map();
5250
5501
  }
@@ -5348,22 +5599,20 @@ class SimpleDeltaPageRank {
5348
5599
  /**
5349
5600
  * Perform incremental update after graph modification.
5350
5601
  * This is where delta-based approach provides significant speedup.
5351
- *
5352
- * @param modifiedNodes Set of nodes that were modified (edges added/removed)
5353
- * @param options Computation options
5602
+ * @param modifiedNodes - Set of nodes that were modified (edges added/removed)
5603
+ * @param options - Computation options
5604
+ * @param options.dampingFactor - Probability of following a link (default: 0.85)
5605
+ * @param options.tolerance - Convergence tolerance threshold (default: 1e-6)
5606
+ * @param options.maxIterations - Maximum number of iterations (default: 100)
5607
+ * @param options.personalization - Personalization vector for Personalized PageRank
5608
+ * @param options.weight - Edge attribute name for weighted PageRank
5354
5609
  * @returns Updated PageRank scores
5355
5610
  */
5356
5611
  update(modifiedNodes, options = {}) {
5357
5612
  if (!this.previousScores) {
5358
5613
  return this.compute(options);
5359
5614
  }
5360
- const {
5361
- dampingFactor = 0.85,
5362
- tolerance = 1e-6,
5363
- maxIterations = 100,
5364
- personalization,
5365
- weight
5366
- } = options;
5615
+ const { dampingFactor = 0.85, tolerance = 1e-6, maxIterations = 100, personalization, weight } = options;
5367
5616
  const scores = new Map(this.previousScores);
5368
5617
  const newScores = /* @__PURE__ */ new Map();
5369
5618
  for (const node of this.graph.nodes()) {
@@ -5679,6 +5928,10 @@ function normalizeRanks(ranks) {
5679
5928
  }
5680
5929
  }
5681
5930
  class UnionFind {
5931
+ /**
5932
+ * Creates a new UnionFind data structure with the given elements.
5933
+ * @param elements - Array of elements to initialize the data structure with
5934
+ */
5682
5935
  constructor(elements) {
5683
5936
  this.parent = /* @__PURE__ */ new Map();
5684
5937
  this.rank = /* @__PURE__ */ new Map();
@@ -5690,6 +5943,8 @@ class UnionFind {
5690
5943
  }
5691
5944
  /**
5692
5945
  * Find the root of the set containing the element with path compression
5946
+ * @param element - The element to find the root for
5947
+ * @returns The root element of the set containing the given element
5693
5948
  */
5694
5949
  find(element) {
5695
5950
  const parent = this.parent.get(element);
@@ -5707,6 +5962,8 @@ class UnionFind {
5707
5962
  }
5708
5963
  /**
5709
5964
  * Union two sets using union by rank
5965
+ * @param elementA - The first element whose set should be merged
5966
+ * @param elementB - The second element whose set should be merged
5710
5967
  */
5711
5968
  union(elementA, elementB) {
5712
5969
  const rootA = this.find(elementA);
@@ -5731,6 +5988,9 @@ class UnionFind {
5731
5988
  }
5732
5989
  /**
5733
5990
  * Check if two elements are in the same connected component
5991
+ * @param elementA - The first element to check
5992
+ * @param elementB - The second element to check
5993
+ * @returns True if both elements are in the same component, false otherwise
5734
5994
  */
5735
5995
  connected(elementA, elementB) {
5736
5996
  try {
@@ -5741,12 +6001,15 @@ class UnionFind {
5741
6001
  }
5742
6002
  /**
5743
6003
  * Get the number of connected components
6004
+ * @returns The current count of disjoint components
5744
6005
  */
5745
6006
  getComponentCount() {
5746
6007
  return this.componentCount;
5747
6008
  }
5748
6009
  /**
5749
6010
  * Get all elements that belong to the same component as the given element
6011
+ * @param element - The element whose component should be retrieved
6012
+ * @returns Array of all elements in the same component
5750
6013
  */
5751
6014
  getComponent(element) {
5752
6015
  const root = this.find(element);
@@ -5760,6 +6023,7 @@ class UnionFind {
5760
6023
  }
5761
6024
  /**
5762
6025
  * Get all connected components as separate arrays
6026
+ * @returns Array of arrays, where each inner array contains elements of one component
5763
6027
  */
5764
6028
  getAllComponents() {
5765
6029
  const componentMap = /* @__PURE__ */ new Map();
@@ -5777,12 +6041,15 @@ class UnionFind {
5777
6041
  }
5778
6042
  /**
5779
6043
  * Get the size of the component containing the given element
6044
+ * @param element - The element whose component size should be retrieved
6045
+ * @returns The number of elements in the component containing the given element
5780
6046
  */
5781
6047
  getComponentSize(element) {
5782
6048
  return this.getComponent(element).length;
5783
6049
  }
5784
6050
  /**
5785
6051
  * Add a new element to the data structure
6052
+ * @param element - The element to add as a new singleton set
5786
6053
  */
5787
6054
  addElement(element) {
5788
6055
  if (this.parent.has(element)) {
@@ -5794,12 +6061,15 @@ class UnionFind {
5794
6061
  }
5795
6062
  /**
5796
6063
  * Check if an element exists in the data structure
6064
+ * @param element - The element to check for
6065
+ * @returns True if the element exists, false otherwise
5797
6066
  */
5798
6067
  hasElement(element) {
5799
6068
  return this.parent.has(element);
5800
6069
  }
5801
6070
  /**
5802
6071
  * Get the total number of elements
6072
+ * @returns The total count of all elements in the data structure
5803
6073
  */
5804
6074
  size() {
5805
6075
  return this.parent.size;
@@ -5807,7 +6077,9 @@ class UnionFind {
5807
6077
  }
5808
6078
  function connectedComponents(graph) {
5809
6079
  if (graph.isDirected) {
5810
- throw new Error("Connected components algorithm requires an undirected graph. Use stronglyConnectedComponents for directed graphs.");
6080
+ throw new Error(
6081
+ "Connected components algorithm requires an undirected graph. Use stronglyConnectedComponents for directed graphs."
6082
+ );
5811
6083
  }
5812
6084
  const nodes = Array.from(graph.nodes()).map((node) => node.id);
5813
6085
  if (nodes.length === 0) {
@@ -5854,9 +6126,7 @@ function largestConnectedComponent(graph) {
5854
6126
  if (components.length === 0) {
5855
6127
  return [];
5856
6128
  }
5857
- return components.reduce(
5858
- (largest, current) => current.length > largest.length ? current : largest
5859
- );
6129
+ return components.reduce((largest, current) => current.length > largest.length ? current : largest);
5860
6130
  }
5861
6131
  function getConnectedComponent(graph, nodeId) {
5862
6132
  if (!graph.hasNode(nodeId)) {
@@ -5932,7 +6202,9 @@ function isStronglyConnected(graph) {
5932
6202
  }
5933
6203
  function weaklyConnectedComponents(graph) {
5934
6204
  if (!graph.isDirected) {
5935
- throw new Error("Weakly connected components are for directed graphs. Use connectedComponents for undirected graphs.");
6205
+ throw new Error(
6206
+ "Weakly connected components are for directed graphs. Use connectedComponents for undirected graphs."
6207
+ );
5936
6208
  }
5937
6209
  const nodes = Array.from(graph.nodes()).map((node) => node.id);
5938
6210
  if (nodes.length === 0) {
@@ -6116,9 +6388,7 @@ function girvanNewman(graph, options = {}) {
6116
6388
  workingGraph.removeEdge(source, target);
6117
6389
  }
6118
6390
  components = getConnectedComponentsResult(workingGraph);
6119
- const validCommunities = components.components.filter(
6120
- (community) => community.length >= minCommunitySize
6121
- );
6391
+ const validCommunities = components.components.filter((community) => community.length >= minCommunitySize);
6122
6392
  const modularity = calculateModularity$3(graph, components.componentMap);
6123
6393
  dendrogram.push({
6124
6394
  communities: validCommunities,
@@ -6324,6 +6594,10 @@ function graphToMap(graph) {
6324
6594
  return map;
6325
6595
  }
6326
6596
  class SeededRandom {
6597
+ /**
6598
+ * Creates a new SeededRandom instance with the given seed.
6599
+ * @param seed - The seed value for reproducible random number generation
6600
+ */
6327
6601
  constructor(seed) {
6328
6602
  this.m = 2147483648;
6329
6603
  this.a = 1103515245;
@@ -6332,6 +6606,7 @@ class SeededRandom {
6332
6606
  }
6333
6607
  /**
6334
6608
  * Generate next random number between 0 and 1
6609
+ * @returns A pseudo-random number in the range [0, 1]
6335
6610
  */
6336
6611
  next() {
6337
6612
  this.seed = (this.a * this.seed + this.c) % this.m;
@@ -6339,6 +6614,8 @@ class SeededRandom {
6339
6614
  }
6340
6615
  /**
6341
6616
  * Create a generator function for backward compatibility
6617
+ * @param seed - The seed value for reproducible random number generation
6618
+ * @returns A function that returns the next random number when called
6342
6619
  */
6343
6620
  static createGenerator(seed) {
6344
6621
  const rng = new SeededRandom(seed);
@@ -6373,10 +6650,7 @@ function euclideanDistance(a, b) {
6373
6650
  return Math.sqrt(sum);
6374
6651
  }
6375
6652
  function labelPropagationImpl(graph, options = {}) {
6376
- const {
6377
- maxIterations = 100,
6378
- randomSeed = 42
6379
- } = options;
6653
+ const { maxIterations = 100, randomSeed = 42 } = options;
6380
6654
  if (graph.size === 0) {
6381
6655
  return {
6382
6656
  communities: /* @__PURE__ */ new Map(),
@@ -6459,9 +6733,7 @@ function labelPropagationImpl(graph, options = {}) {
6459
6733
  };
6460
6734
  }
6461
6735
  function labelPropagationAsyncImpl(graph, options = {}) {
6462
- const {
6463
- maxIterations = 100
6464
- } = options;
6736
+ const { maxIterations = 100 } = options;
6465
6737
  if (graph.size === 0) {
6466
6738
  return {
6467
6739
  communities: /* @__PURE__ */ new Map(),
@@ -6535,10 +6807,7 @@ function labelPropagationAsyncImpl(graph, options = {}) {
6535
6807
  };
6536
6808
  }
6537
6809
  function labelPropagationSemiSupervisedImpl(graph, seedLabels, options = {}) {
6538
- const {
6539
- maxIterations = 100,
6540
- randomSeed = 42
6541
- } = options;
6810
+ const { maxIterations = 100, randomSeed = 42 } = options;
6542
6811
  const random = SeededRandom.createGenerator(randomSeed);
6543
6812
  const labels = /* @__PURE__ */ new Map();
6544
6813
  const nodes = Array.from(graph.keys());
@@ -6620,12 +6889,7 @@ function labelPropagationSemiSupervised(graph, seedLabels, options = {}) {
6620
6889
  return labelPropagationSemiSupervisedImpl(graphMap, seedLabels, options);
6621
6890
  }
6622
6891
  function leidenImpl(inputGraph, options = {}) {
6623
- const {
6624
- resolution = 1,
6625
- randomSeed = 42,
6626
- maxIterations = 100,
6627
- threshold = 1e-7
6628
- } = options;
6892
+ const { resolution = 1, randomSeed = 42, maxIterations = 100, threshold = 1e-7 } = options;
6629
6893
  if (inputGraph.size === 0) {
6630
6894
  return {
6631
6895
  communities: /* @__PURE__ */ new Map(),
@@ -6691,10 +6955,7 @@ function leidenImpl(inputGraph, options = {}) {
6691
6955
  }
6692
6956
  }
6693
6957
  createAggregateNetwork(currentGraph, communities);
6694
- const subsetPartition = refinePartition(
6695
- currentGraph,
6696
- communities
6697
- );
6958
+ const subsetPartition = refinePartition(currentGraph, communities);
6698
6959
  for (const [node, newCommunity] of subsetPartition) {
6699
6960
  communities.set(node, newCommunity);
6700
6961
  }
@@ -6976,6 +7237,10 @@ function leiden(graph, options = {}) {
6976
7237
  return leidenImpl(graphMap, options);
6977
7238
  }
6978
7239
  class OptimizedLouvain {
7240
+ /**
7241
+ * Create an optimized Louvain detector for the given graph
7242
+ * @param graph - The input graph to detect communities in
7243
+ */
6979
7244
  constructor(graph) {
6980
7245
  this.graph = graph;
6981
7246
  this.communities = /* @__PURE__ */ new Map();
@@ -6991,6 +7256,8 @@ class OptimizedLouvain {
6991
7256
  }
6992
7257
  /**
6993
7258
  * Run optimized Louvain algorithm
7259
+ * @param options - Algorithm configuration options
7260
+ * @returns Community detection result with communities, modularity, and iterations
6994
7261
  */
6995
7262
  detectCommunities(options = {}) {
6996
7263
  const {
@@ -7074,6 +7341,7 @@ class OptimizedLouvain {
7074
7341
  }
7075
7342
  /**
7076
7343
  * Get nodes ordered by importance (degree * log(weight))
7344
+ * @returns Array of node IDs sorted by descending importance
7077
7345
  */
7078
7346
  getNodesInImportanceOrder() {
7079
7347
  const nodeImportance = /* @__PURE__ */ new Map();
@@ -7086,6 +7354,12 @@ class OptimizedLouvain {
7086
7354
  }
7087
7355
  /**
7088
7356
  * Perform local moving phase with optimizations
7357
+ * @param nodes - Array of node IDs to process
7358
+ * @param options - Local moving options
7359
+ * @param options.pruneLeaves - Whether to skip leaf nodes
7360
+ * @param options.threshold - Minimum gain threshold for moves
7361
+ * @param options.resolution - Resolution parameter for modularity
7362
+ * @returns True if any improvement was made, false otherwise
7089
7363
  */
7090
7364
  performLocalMoving(nodes, options) {
7091
7365
  const { pruneLeaves, threshold, resolution } = options;
@@ -7129,6 +7403,8 @@ class OptimizedLouvain {
7129
7403
  }
7130
7404
  /**
7131
7405
  * Check if node is a leaf (degree 1)
7406
+ * @param nodeId - The node ID to check
7407
+ * @returns True if the node has degree 1, false otherwise
7132
7408
  */
7133
7409
  isLeafNode(nodeId) {
7134
7410
  const degree = this.nodeDegrees.get(nodeId) ?? 0;
@@ -7136,12 +7412,19 @@ class OptimizedLouvain {
7136
7412
  }
7137
7413
  /**
7138
7414
  * Get adaptive threshold that decreases with iterations
7415
+ * @param iteration - Current iteration number
7416
+ * @param baseThreshold - Base threshold value to scale
7417
+ * @returns Adaptive threshold value that decays over iterations
7139
7418
  */
7140
7419
  getAdaptiveThreshold(iteration, baseThreshold) {
7141
7420
  return baseThreshold * Math.pow(0.5, iteration / 10);
7142
7421
  }
7143
7422
  /**
7144
7423
  * Calculate modularity gain from moving a node to a community
7424
+ * @param nodeId - The node ID to move
7425
+ * @param targetCommunity - The target community ID
7426
+ * @param resolution - Resolution parameter for modularity calculation
7427
+ * @returns The modularity gain from moving the node
7145
7428
  */
7146
7429
  calculateModularityGain(nodeId, targetCommunity, resolution) {
7147
7430
  const nodeWeight = this.nodeWeights.get(nodeId) ?? 0;
@@ -7166,6 +7449,8 @@ class OptimizedLouvain {
7166
7449
  }
7167
7450
  /**
7168
7451
  * Remove node from community (for gain calculation)
7452
+ * @param nodeId - The node ID to remove
7453
+ * @param community - The community ID to remove from
7169
7454
  */
7170
7455
  removeNodeFromCommunity(nodeId, community) {
7171
7456
  const nodeWeight = this.nodeWeights.get(nodeId) ?? 0;
@@ -7174,6 +7459,8 @@ class OptimizedLouvain {
7174
7459
  }
7175
7460
  /**
7176
7461
  * Add node to community
7462
+ * @param nodeId - The node ID to add
7463
+ * @param community - The community ID to add to
7177
7464
  */
7178
7465
  addNodeToCommunity(nodeId, community) {
7179
7466
  const nodeWeight = this.nodeWeights.get(nodeId) ?? 0;
@@ -7182,6 +7469,8 @@ class OptimizedLouvain {
7182
7469
  }
7183
7470
  /**
7184
7471
  * Get neighboring communities of a node
7472
+ * @param nodeId - The node ID to find neighbor communities for
7473
+ * @returns Set of community IDs that neighbors belong to
7185
7474
  */
7186
7475
  getNeighborCommunities(nodeId) {
7187
7476
  const communities = /* @__PURE__ */ new Set();
@@ -7203,6 +7492,8 @@ class OptimizedLouvain {
7203
7492
  }
7204
7493
  /**
7205
7494
  * Calculate total modularity
7495
+ * @param resolution - Resolution parameter for modularity calculation
7496
+ * @returns The modularity score of the current partition
7206
7497
  */
7207
7498
  calculateModularity(resolution) {
7208
7499
  if (this.totalWeight === 0) {
@@ -7233,6 +7524,7 @@ class OptimizedLouvain {
7233
7524
  }
7234
7525
  /**
7235
7526
  * Get pruning statistics
7527
+ * @returns Statistics about nodes pruned during optimization
7236
7528
  */
7237
7529
  getPruningStats() {
7238
7530
  return { ...this.pruningStats };
@@ -7433,6 +7725,10 @@ function extractCommunities(communities) {
7433
7725
  return Array.from(communityMap.values());
7434
7726
  }
7435
7727
  class MinPriorityQueue {
7728
+ /**
7729
+ * Creates a new MinPriorityQueue instance.
7730
+ * @param compareFunction - Custom comparison function. Returns negative if a has higher priority than b.
7731
+ */
7436
7732
  constructor(compareFunction) {
7437
7733
  this.heap = [];
7438
7734
  this.compare = compareFunction ?? ((a, b) => this.defaultCompare(a, b));
@@ -7498,10 +7794,18 @@ class MinPriorityQueue {
7498
7794
  }
7499
7795
  }
7500
7796
  }
7797
+ /**
7798
+ * Insert a value into the priority queue.
7799
+ * @param value - The value to insert
7800
+ */
7501
7801
  insert(value) {
7502
7802
  this.heap.push(value);
7503
7803
  this.heapifyUp(this.heap.length - 1);
7504
7804
  }
7805
+ /**
7806
+ * Remove and return the minimum value from the priority queue.
7807
+ * @returns The minimum value, or undefined if the queue is empty
7808
+ */
7505
7809
  extractMin() {
7506
7810
  if (this.heap.length === 0) {
7507
7811
  return void 0;
@@ -7517,20 +7821,35 @@ class MinPriorityQueue {
7517
7821
  }
7518
7822
  return min;
7519
7823
  }
7824
+ /**
7825
+ * View the minimum value without removing it.
7826
+ * @returns The minimum value, or undefined if the queue is empty
7827
+ */
7520
7828
  peek() {
7521
7829
  return this.heap[0];
7522
7830
  }
7831
+ /**
7832
+ * Check if the priority queue is empty.
7833
+ * @returns True if the queue has no items, false otherwise
7834
+ */
7523
7835
  isEmpty() {
7524
7836
  return this.heap.length === 0;
7525
7837
  }
7838
+ /**
7839
+ * Get the number of items in the priority queue.
7840
+ * @returns The number of items currently in the queue
7841
+ */
7526
7842
  size() {
7527
7843
  return this.heap.length;
7528
7844
  }
7529
7845
  }
7530
7846
  const pathfindingUtils = {
7531
7847
  /**
7532
- * Reconstructs a path from start to goal using the cameFrom map
7533
- */
7848
+ * Reconstructs a path from start to goal using the cameFrom map
7849
+ * @param cameFrom - Map of each node to its predecessor on the path
7850
+ * @param goal - The goal node to reconstruct the path to
7851
+ * @returns An array of nodes representing the path from start to goal
7852
+ */
7534
7853
  reconstructPath(cameFrom, goal) {
7535
7854
  const path = [goal];
7536
7855
  let current = goal;
@@ -7545,8 +7864,12 @@ const pathfindingUtils = {
7545
7864
  return path;
7546
7865
  },
7547
7866
  /**
7548
- * Creates a grid graph for testing pathfinding algorithms
7549
- */
7867
+ * Creates a grid graph for testing pathfinding algorithms
7868
+ * @param width - The width of the grid
7869
+ * @param height - The height of the grid
7870
+ * @param obstacles - Set of obstacle coordinates as "x,y" strings
7871
+ * @returns A grid graph with 4-directional movement
7872
+ */
7550
7873
  createGridGraph(width, height, obstacles = /* @__PURE__ */ new Set()) {
7551
7874
  const graph = /* @__PURE__ */ new Map();
7552
7875
  for (let x = 0; x < width; x++) {
@@ -7581,8 +7904,10 @@ const pathfindingUtils = {
7581
7904
  return graph;
7582
7905
  },
7583
7906
  /**
7584
- * Parses a grid coordinate string
7585
- */
7907
+ * Parses a grid coordinate string
7908
+ * @param coord - The coordinate string in "x,y" format
7909
+ * @returns A tuple of [x, y] coordinates
7910
+ */
7586
7911
  parseGridCoordinate(coord) {
7587
7912
  const parts = coord.split(",").map(Number);
7588
7913
  const x = parts[0];
@@ -7722,27 +8047,38 @@ function astarWithDetails(graph, start, goal, heuristic) {
7722
8047
  }
7723
8048
  const heuristics = {
7724
8049
  /**
7725
- * Manhattan distance heuristic for grid-based graphs
7726
- */
8050
+ * Manhattan distance heuristic for grid-based graphs
8051
+ * @param a - First coordinate as [x, y] tuple
8052
+ * @param b - Second coordinate as [x, y] tuple
8053
+ * @returns The Manhattan distance between the two points
8054
+ */
7727
8055
  manhattan: (a, b) => {
7728
8056
  return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
7729
8057
  },
7730
8058
  /**
7731
- * Euclidean distance heuristic
7732
- */
8059
+ * Euclidean distance heuristic
8060
+ * @param a - First coordinate as [x, y] tuple
8061
+ * @param b - Second coordinate as [x, y] tuple
8062
+ * @returns The Euclidean distance between the two points
8063
+ */
7733
8064
  euclidean: (a, b) => {
7734
8065
  return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2));
7735
8066
  },
7736
8067
  /**
7737
- * Chebyshev distance heuristic (diagonal movement allowed)
7738
- */
8068
+ * Chebyshev distance heuristic (diagonal movement allowed)
8069
+ * @param a - First coordinate as [x, y] tuple
8070
+ * @param b - Second coordinate as [x, y] tuple
8071
+ * @returns The Chebyshev distance between the two points
8072
+ */
7739
8073
  chebyshev: (a, b) => {
7740
8074
  return Math.max(Math.abs(a[0] - b[0]), Math.abs(a[1] - b[1]));
7741
8075
  },
7742
8076
  /**
7743
- * Zero heuristic (makes A* behave like Dijkstra)
7744
- */
7745
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
8077
+ * Zero heuristic (makes A* behave like Dijkstra)
8078
+ * @param _a - First node (unused)
8079
+ * @param _b - Second node (unused)
8080
+ * @returns Always returns 0
8081
+ */
7746
8082
  zero: (_a, _b) => 0
7747
8083
  };
7748
8084
  function createResidualGraph(graph) {
@@ -8900,10 +9236,12 @@ function extractClusters(matrix, nodeIds) {
8900
9236
  }
8901
9237
  }
8902
9238
  if (clusterNodes.length > 0) {
8903
- communities.push(clusterNodes.map((idx) => {
8904
- const nodeId = nodeIds[idx];
8905
- return nodeId;
8906
- }).filter((node) => node !== void 0));
9239
+ communities.push(
9240
+ clusterNodes.map((idx) => {
9241
+ const nodeId = nodeIds[idx];
9242
+ return nodeId;
9243
+ }).filter((node) => node !== void 0)
9244
+ );
8907
9245
  clusterIndex++;
8908
9246
  }
8909
9247
  }
@@ -8943,12 +9281,7 @@ function calculateMCLModularity(graph, communities) {
8943
9281
  return modularity / (2 * m);
8944
9282
  }
8945
9283
  function spectralClustering(graph, options) {
8946
- const {
8947
- k,
8948
- laplacianType = "normalized",
8949
- maxIterations = 100,
8950
- tolerance = 1e-4
8951
- } = options;
9284
+ const { k, laplacianType = "normalized", maxIterations = 100, tolerance = 1e-4 } = options;
8952
9285
  if (k < 1 || !Number.isInteger(k)) {
8953
9286
  throw new Error("k must be a positive integer");
8954
9287
  }
@@ -9738,10 +10071,7 @@ function adamicAdarScore(graph, source, target, options = {}) {
9738
10071
  const commonNeighborsSet = directed ? getIntermediateNodes(graph, source, target) : getCommonNeighbors(graph, source, target, false);
9739
10072
  let score = 0;
9740
10073
  for (const neighbor of commonNeighborsSet) {
9741
- const degree = directed ? graph.outDegree(neighbor) : (
9742
- // Use out-degree for directed graphs
9743
- graph.degree(neighbor)
9744
- );
10074
+ const degree = directed ? graph.outDegree(neighbor) : graph.degree(neighbor);
9745
10075
  if (degree > 1) {
9746
10076
  score += 1 / Math.log(degree);
9747
10077
  } else if (degree === 1) {
@@ -9751,11 +10081,7 @@ function adamicAdarScore(graph, source, target, options = {}) {
9751
10081
  return score;
9752
10082
  }
9753
10083
  function adamicAdarPrediction(graph, options = {}) {
9754
- const {
9755
- directed = false,
9756
- includeExisting = false,
9757
- topK
9758
- } = options;
10084
+ const { directed = false, includeExisting = false, topK } = options;
9759
10085
  const scores = [];
9760
10086
  const nodes = Array.from(graph.nodes()).map((n) => n.id);
9761
10087
  for (let i = 0; i < nodes.length; i++) {
@@ -9794,12 +10120,7 @@ function getTopAdamicAdarCandidatesForNode(graph, node, options = {}) {
9794
10120
  if (!graph.hasNode(node)) {
9795
10121
  return [];
9796
10122
  }
9797
- const {
9798
- directed = false,
9799
- includeExisting = false,
9800
- topK = 10,
9801
- candidates
9802
- } = options;
10123
+ const { directed = false, includeExisting = false, topK = 10, candidates } = options;
9803
10124
  const scores = [];
9804
10125
  const targetNodes = candidates ?? Array.from(graph.nodes()).map((n) => n.id);
9805
10126
  for (const target of targetNodes) {
@@ -9938,11 +10259,7 @@ function commonNeighborsScore(graph, source, target, options = {}) {
9938
10259
  return commonNeighborsSet.size;
9939
10260
  }
9940
10261
  function commonNeighborsPrediction(graph, options = {}) {
9941
- const {
9942
- directed = false,
9943
- includeExisting = false,
9944
- topK
9945
- } = options;
10262
+ const { directed = false, includeExisting = false, topK } = options;
9946
10263
  const scores = [];
9947
10264
  const nodes = Array.from(graph.nodes()).map((n) => n.id);
9948
10265
  for (let i = 0; i < nodes.length; i++) {
@@ -9981,12 +10298,7 @@ function getTopCandidatesForNode(graph, node, options = {}) {
9981
10298
  if (!graph.hasNode(node)) {
9982
10299
  return [];
9983
10300
  }
9984
- const {
9985
- directed = false,
9986
- includeExisting = false,
9987
- topK = 10,
9988
- candidates
9989
- } = options;
10301
+ const { directed = false, includeExisting = false, topK = 10, candidates } = options;
9990
10302
  const scores = [];
9991
10303
  const targetNodes = candidates ?? Array.from(graph.nodes()).map((n) => n.id);
9992
10304
  for (const target of targetNodes) {
@@ -10056,14 +10368,7 @@ function evaluateCommonNeighbors(trainingGraph, testEdges, nonEdges, options = {
10056
10368
  };
10057
10369
  }
10058
10370
  function syncClustering(graph, config) {
10059
- const {
10060
- numClusters,
10061
- maxIterations = 100,
10062
- tolerance = 1e-6,
10063
- seed = 42,
10064
- learningRate = 0.01,
10065
- lambda = 0.1
10066
- } = config;
10371
+ const { numClusters, maxIterations = 100, tolerance = 1e-6, seed = 42, learningRate = 0.01, lambda = 0.1 } = config;
10067
10372
  const originalRandom = Math.random;
10068
10373
  const rng = SeededRandom.createGenerator(seed);
10069
10374
  Math.random = rng;
@@ -10079,7 +10384,9 @@ function syncClustering(graph, config) {
10079
10384
  };
10080
10385
  }
10081
10386
  if (numClusters <= 0 || numClusters > nodeCount) {
10082
- throw new Error(`Invalid number of clusters: ${String(numClusters)}. Must be between 1 and ${String(nodeCount)}`);
10387
+ throw new Error(
10388
+ `Invalid number of clusters: ${String(numClusters)}. Must be between 1 and ${String(nodeCount)}`
10389
+ );
10083
10390
  }
10084
10391
  const embeddingDim = Math.min(64, nodeCount);
10085
10392
  const embeddings = /* @__PURE__ */ new Map();
@@ -10197,7 +10504,7 @@ function initializeClusterCenters(embeddings, numClusters) {
10197
10504
  }
10198
10505
  return centers;
10199
10506
  }
10200
- function updateEmbeddings(graph, embeddings, clusters, learningRate, lambda) {
10507
+ function updateEmbeddings(graph, embeddings, _clusters, learningRate, lambda) {
10201
10508
  const gradients = /* @__PURE__ */ new Map();
10202
10509
  for (const [nodeId, embedding] of embeddings) {
10203
10510
  gradients.set(nodeId, new Array(embedding.length).fill(0));
@@ -10344,7 +10651,9 @@ function teraHAC(graph, config = {}) {
10344
10651
  throw new Error("Cannot cluster empty graph");
10345
10652
  }
10346
10653
  if (nodeCount > maxNodes) {
10347
- onWarning(`Graph has ${String(nodeCount)} nodes, which exceeds maxNodes (${String(maxNodes)}). Performance may be degraded.`);
10654
+ onWarning(
10655
+ `Graph has ${String(nodeCount)} nodes, which exceeds maxNodes (${String(maxNodes)}). Performance may be degraded.`
10656
+ );
10348
10657
  }
10349
10658
  const clusters = /* @__PURE__ */ new Map();
10350
10659
  let nextClusterId = nodeCount;
@@ -10680,13 +10989,7 @@ function grsbm(graph, config = {}) {
10680
10989
  if (currentCluster.depth >= maxDepth || currentCluster.members.size < minClusterSize * 2) {
10681
10990
  continue;
10682
10991
  }
10683
- const bisectionResult = spectralBisection(
10684
- graph,
10685
- currentCluster,
10686
- numEigenvectors,
10687
- tolerance,
10688
- maxIterations
10689
- );
10992
+ const bisectionResult = spectralBisection(graph, currentCluster, numEigenvectors, tolerance, maxIterations);
10690
10993
  if (!bisectionResult) {
10691
10994
  continue;
10692
10995
  }
@@ -10759,7 +11062,7 @@ function grsbm(graph, config = {}) {
10759
11062
  explanation: explanations
10760
11063
  };
10761
11064
  }
10762
- function spectralBisection(graph, cluster, numEigenvectors, tolerance, maxIterations) {
11065
+ function spectralBisection(graph, cluster, _numEigenvectors, tolerance, maxIterations) {
10763
11066
  const members = Array.from(cluster.members);
10764
11067
  const n = members.length;
10765
11068
  if (n < 4) {