@graphty/algorithms 1.3.1 → 1.4.2

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 (313) hide show
  1. package/README.md +358 -413
  2. package/dist/algorithms.js +564 -261
  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 +11 -4
  99. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts.map +1 -1
  100. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +18 -16
  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 +22 -9
  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 +28 -7
  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/package.json +49 -45
  248. package/src/algorithms/centrality/betweenness.ts +34 -17
  249. package/src/algorithms/centrality/closeness.ts +34 -17
  250. package/src/algorithms/centrality/degree.ts +15 -19
  251. package/src/algorithms/centrality/delta-pagerank-simple.ts +36 -28
  252. package/src/algorithms/centrality/delta-pagerank.ts +34 -11
  253. package/src/algorithms/centrality/eigenvector.ts +14 -15
  254. package/src/algorithms/centrality/hits.ts +17 -17
  255. package/src/algorithms/centrality/index.ts +20 -15
  256. package/src/algorithms/centrality/katz.ts +17 -25
  257. package/src/algorithms/centrality/pagerank.ts +26 -17
  258. package/src/algorithms/community/girvan-newman.ts +39 -28
  259. package/src/algorithms/community/index.ts +6 -7
  260. package/src/algorithms/community/label-propagation.ts +20 -28
  261. package/src/algorithms/community/leiden.ts +61 -37
  262. package/src/algorithms/community/louvain-optimized.ts +49 -20
  263. package/src/algorithms/community/louvain.ts +35 -25
  264. package/src/algorithms/community/modularity-utils.ts +5 -17
  265. package/src/algorithms/components/connected.ts +40 -17
  266. package/src/algorithms/matching/bipartite.ts +17 -10
  267. package/src/algorithms/matching/index.ts +4 -4
  268. package/src/algorithms/matching/isomorphism.ts +53 -23
  269. package/src/algorithms/mst/index.ts +3 -4
  270. package/src/algorithms/mst/kruskal.ts +21 -6
  271. package/src/algorithms/mst/prim.ts +13 -4
  272. package/src/algorithms/shortest-path/bellman-ford.ts +16 -15
  273. package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +28 -28
  274. package/src/algorithms/shortest-path/dijkstra.ts +23 -17
  275. package/src/algorithms/shortest-path/floyd-warshall.ts +21 -4
  276. package/src/algorithms/shortest-path/index.ts +5 -5
  277. package/src/algorithms/traversal/bfs-unified.ts +64 -60
  278. package/src/algorithms/traversal/bfs-variants.ts +61 -37
  279. package/src/algorithms/traversal/bfs.ts +1 -7
  280. package/src/algorithms/traversal/dfs.ts +61 -42
  281. package/src/algorithms/traversal/index.ts +3 -3
  282. package/src/benchmark-all-algorithms.ts +57 -25
  283. package/src/clustering/hierarchical.ts +40 -34
  284. package/src/clustering/index.ts +8 -8
  285. package/src/clustering/k-core.ts +26 -42
  286. package/src/clustering/mcl.ts +53 -23
  287. package/src/clustering/spectral.ts +91 -57
  288. package/src/core/graph.ts +54 -14
  289. package/src/data-structures/index.ts +2 -2
  290. package/src/data-structures/priority-queue.ts +36 -11
  291. package/src/data-structures/union-find.ts +22 -1
  292. package/src/flow/ford-fulkerson.ts +62 -35
  293. package/src/flow/min-cut.ts +43 -45
  294. package/src/index.ts +3 -2
  295. package/src/link-prediction/adamic-adar.ts +65 -51
  296. package/src/link-prediction/common-neighbors.ts +45 -36
  297. package/src/link-prediction/index.ts +1 -1
  298. package/src/optimized/bit-packed.ts +106 -56
  299. package/src/optimized/csr-graph.ts +93 -30
  300. package/src/optimized/direction-optimized-bfs.ts +44 -25
  301. package/src/optimized/graph-adapter.ts +64 -16
  302. package/src/optimized/index.ts +7 -9
  303. package/src/pathfinding/astar.ts +40 -25
  304. package/src/pathfinding/utils.ts +20 -13
  305. package/src/research/grsbm.ts +30 -24
  306. package/src/research/index.ts +4 -4
  307. package/src/research/sync.ts +39 -23
  308. package/src/research/terahac.ts +54 -20
  309. package/src/utils/graph-converters.ts +42 -14
  310. package/src/utils/graph-utilities.ts +11 -37
  311. package/src/utils/math-utilities.ts +17 -8
  312. package/src/utils/optimization-helpers.ts +27 -21
  313. package/src/utils/priorityQueue.ts +40 -6
@@ -1,6 +1,6 @@
1
- import type {Graph} from "../../core/graph.js";
2
- import {UnionFind} from "../../data-structures/union-find.js";
3
- import type {NodeId} from "../../types/index.js";
1
+ import type { Graph } from "../../core/graph.js";
2
+ import { UnionFind } from "../../data-structures/union-find.js";
3
+ import type { NodeId } from "../../types/index.js";
4
4
 
5
5
  /**
6
6
  * Connected components algorithms
@@ -11,10 +11,14 @@ import type {NodeId} from "../../types/index.js";
11
11
 
12
12
  /**
13
13
  * Find connected components in an undirected graph using Union-Find
14
+ * @param graph - The input graph (must be undirected)
15
+ * @returns Array of connected components, each containing an array of node IDs
14
16
  */
15
17
  export function connectedComponents(graph: Graph): NodeId[][] {
16
18
  if (graph.isDirected) {
17
- throw new Error("Connected components algorithm requires an undirected graph. Use stronglyConnectedComponents for directed graphs.");
19
+ throw new Error(
20
+ "Connected components algorithm requires an undirected graph. Use stronglyConnectedComponents for directed graphs.",
21
+ );
18
22
  }
19
23
 
20
24
  const nodes = Array.from(graph.nodes()).map((node) => node.id);
@@ -35,6 +39,8 @@ export function connectedComponents(graph: Graph): NodeId[][] {
35
39
 
36
40
  /**
37
41
  * Find connected components using DFS (alternative implementation)
42
+ * @param graph - The input graph (must be undirected)
43
+ * @returns Array of connected components, each containing an array of node IDs
38
44
  */
39
45
  export function connectedComponentsDFS(graph: Graph): NodeId[][] {
40
46
  if (graph.isDirected) {
@@ -57,13 +63,12 @@ export function connectedComponentsDFS(graph: Graph): NodeId[][] {
57
63
 
58
64
  /**
59
65
  * DFS helper for connected components
66
+ * @param graph - The input graph
67
+ * @param nodeId - The starting node ID
68
+ * @param visited - Set of already visited node IDs
69
+ * @param component - Array to accumulate component members
60
70
  */
61
- function dfsComponent(
62
- graph: Graph,
63
- nodeId: NodeId,
64
- visited: Set<NodeId>,
65
- component: NodeId[],
66
- ): void {
71
+ function dfsComponent(graph: Graph, nodeId: NodeId, visited: Set<NodeId>, component: NodeId[]): void {
67
72
  visited.add(nodeId);
68
73
  component.push(nodeId);
69
74
 
@@ -76,6 +81,8 @@ function dfsComponent(
76
81
 
77
82
  /**
78
83
  * Find the number of connected components
84
+ * @param graph - The input graph (must be undirected)
85
+ * @returns The number of connected components in the graph
79
86
  */
80
87
  export function numberOfConnectedComponents(graph: Graph): number {
81
88
  return connectedComponents(graph).length;
@@ -83,6 +90,8 @@ export function numberOfConnectedComponents(graph: Graph): number {
83
90
 
84
91
  /**
85
92
  * Check if the graph is connected (has exactly one connected component)
93
+ * @param graph - The input graph (must be undirected)
94
+ * @returns True if the graph is connected, false otherwise
86
95
  */
87
96
  export function isConnected(graph: Graph): boolean {
88
97
  return numberOfConnectedComponents(graph) <= 1;
@@ -90,6 +99,8 @@ export function isConnected(graph: Graph): boolean {
90
99
 
91
100
  /**
92
101
  * Find the largest connected component
102
+ * @param graph - The input graph (must be undirected)
103
+ * @returns Array of node IDs in the largest connected component
93
104
  */
94
105
  export function largestConnectedComponent(graph: Graph): NodeId[] {
95
106
  const components = connectedComponents(graph);
@@ -98,13 +109,14 @@ export function largestConnectedComponent(graph: Graph): NodeId[] {
98
109
  return [];
99
110
  }
100
111
 
101
- return components.reduce((largest, current) =>
102
- current.length > largest.length ? current : largest,
103
- );
112
+ return components.reduce((largest, current) => (current.length > largest.length ? current : largest));
104
113
  }
105
114
 
106
115
  /**
107
116
  * Get the connected component containing a specific node
117
+ * @param graph - The input graph (must be undirected)
118
+ * @param nodeId - The node ID to find the component for
119
+ * @returns Array of node IDs in the same component as the specified node
108
120
  */
109
121
  export function getConnectedComponent(graph: Graph, nodeId: NodeId): NodeId[] {
110
122
  if (!graph.hasNode(nodeId)) {
@@ -125,6 +137,8 @@ export function getConnectedComponent(graph: Graph, nodeId: NodeId): NodeId[] {
125
137
 
126
138
  /**
127
139
  * Find strongly connected components using Tarjan's algorithm
140
+ * @param graph - The input graph (must be directed)
141
+ * @returns Array of strongly connected components, each containing an array of node IDs
128
142
  */
129
143
  export function stronglyConnectedComponents(graph: Graph): NodeId[][] {
130
144
  if (!graph.isDirected) {
@@ -198,6 +212,8 @@ export function stronglyConnectedComponents(graph: Graph): NodeId[][] {
198
212
 
199
213
  /**
200
214
  * Check if a directed graph is strongly connected
215
+ * @param graph - The input graph (must be directed)
216
+ * @returns True if the graph is strongly connected, false otherwise
201
217
  */
202
218
  export function isStronglyConnected(graph: Graph): boolean {
203
219
  if (!graph.isDirected) {
@@ -211,10 +227,14 @@ export function isStronglyConnected(graph: Graph): boolean {
211
227
  /**
212
228
  * Find weakly connected components in a directed graph
213
229
  * (treat the graph as undirected for connectivity)
230
+ * @param graph - The input graph (must be directed)
231
+ * @returns Array of weakly connected components, each containing an array of node IDs
214
232
  */
215
233
  export function weaklyConnectedComponents(graph: Graph): NodeId[][] {
216
234
  if (!graph.isDirected) {
217
- throw new Error("Weakly connected components are for directed graphs. Use connectedComponents for undirected graphs.");
235
+ throw new Error(
236
+ "Weakly connected components are for directed graphs. Use connectedComponents for undirected graphs.",
237
+ );
218
238
  }
219
239
 
220
240
  const nodes = Array.from(graph.nodes()).map((node) => node.id);
@@ -235,6 +255,8 @@ export function weaklyConnectedComponents(graph: Graph): NodeId[][] {
235
255
 
236
256
  /**
237
257
  * Check if a directed graph is weakly connected
258
+ * @param graph - The input graph (must be directed)
259
+ * @returns True if the graph is weakly connected, false otherwise
238
260
  */
239
261
  export function isWeaklyConnected(graph: Graph): boolean {
240
262
  if (!graph.isDirected) {
@@ -246,6 +268,8 @@ export function isWeaklyConnected(graph: Graph): boolean {
246
268
 
247
269
  /**
248
270
  * Find condensation graph (quotient graph of strongly connected components)
271
+ * @param graph - The input graph (must be directed)
272
+ * @returns Object containing the condensed graph, component map, and component arrays
249
273
  */
250
274
  export function condensationGraph(graph: Graph): {
251
275
  condensedGraph: Graph;
@@ -258,7 +282,7 @@ export function condensationGraph(graph: Graph): {
258
282
 
259
283
  const components = stronglyConnectedComponents(graph);
260
284
  const componentMap = new Map<NodeId, number>();
261
- const condensedGraph = new (graph.constructor as new (config: {directed: boolean}) => Graph)({directed: true});
285
+ const condensedGraph = new (graph.constructor as new (config: { directed: boolean }) => Graph)({ directed: true });
262
286
 
263
287
  // Map each node to its component index
264
288
  for (let i = 0; i < components.length; i++) {
@@ -279,8 +303,7 @@ export function condensationGraph(graph: Graph): {
279
303
  const sourceComponent = componentMap.get(edge.source);
280
304
  const targetComponent = componentMap.get(edge.target);
281
305
 
282
- if (sourceComponent !== undefined && targetComponent !== undefined &&
283
- sourceComponent !== targetComponent) {
306
+ if (sourceComponent !== undefined && targetComponent !== undefined && sourceComponent !== targetComponent) {
284
307
  const edgeKey = `${String(sourceComponent)}-${String(targetComponent)}`;
285
308
 
286
309
  if (!addedEdges.has(edgeKey)) {
@@ -1,6 +1,6 @@
1
- import type {Graph} from "../../core/graph.js";
2
- import type {NodeId} from "../../types/index.js";
3
- import {bfsColoringWithPartitions} from "../traversal/bfs-variants.js";
1
+ import type { Graph } from "../../core/graph.js";
2
+ import type { NodeId } from "../../types/index.js";
3
+ import { bfsColoringWithPartitions } from "../traversal/bfs-variants.js";
4
4
 
5
5
  /**
6
6
  * Maximum Bipartite Matching implementation using Hopcroft-Karp algorithm
@@ -25,13 +25,17 @@ export interface BipartiteMatchingOptions {
25
25
  /**
26
26
  * Find maximum matching in a bipartite graph using augmenting path algorithm
27
27
  * (simplified implementation that's more reliable than Hopcroft-Karp for this context)
28
+ * @param graph - The bipartite graph to find maximum matching for
29
+ * @param options - Optional configuration including left and right node partitions
30
+ * @returns The maximum matching as a map from left nodes to right nodes and the matching size
31
+ * @throws Error if the graph is not bipartite
28
32
  */
29
33
  export function maximumBipartiteMatching(
30
34
  graph: Graph,
31
35
  options: BipartiteMatchingOptions = {},
32
36
  ): BipartiteMatchingResult {
33
37
  // If partitions not provided, try to infer them
34
- let {leftNodes, rightNodes} = options;
38
+ let { leftNodes, rightNodes } = options;
35
39
 
36
40
  if (!leftNodes || !rightNodes) {
37
41
  const partition = bipartitePartition(graph);
@@ -87,8 +91,10 @@ export function maximumBipartiteMatching(
87
91
 
88
92
  /**
89
93
  * Check if graph is bipartite and return the partition
94
+ * @param graph - The graph to check for bipartiteness
95
+ * @returns An object with left and right node sets if bipartite, or null if not bipartite
90
96
  */
91
- export function bipartitePartition(graph: Graph): {left: Set<NodeId>, right: Set<NodeId>} | null {
97
+ export function bipartitePartition(graph: Graph): { left: Set<NodeId>; right: Set<NodeId> } | null {
92
98
  const result = bfsColoringWithPartitions(graph);
93
99
 
94
100
  if (!result.isBipartite || !result.partitions) {
@@ -104,12 +110,13 @@ export function bipartitePartition(graph: Graph): {left: Set<NodeId>, right: Set
104
110
  /**
105
111
  * Simple greedy bipartite matching algorithm
106
112
  * Useful for comparison or when Hopcroft-Karp is overkill
113
+ * @param graph - The bipartite graph to find matching for
114
+ * @param options - Optional configuration including left and right node partitions
115
+ * @returns The matching as a map from left nodes to right nodes and the matching size
116
+ * @throws Error if the graph is not bipartite
107
117
  */
108
- export function greedyBipartiteMatching(
109
- graph: Graph,
110
- options: BipartiteMatchingOptions = {},
111
- ): BipartiteMatchingResult {
112
- let {leftNodes, rightNodes} = options;
118
+ export function greedyBipartiteMatching(graph: Graph, options: BipartiteMatchingOptions = {}): BipartiteMatchingResult {
119
+ let { leftNodes, rightNodes } = options;
113
120
 
114
121
  if (!leftNodes || !rightNodes) {
115
122
  const partition = bipartitePartition(graph);
@@ -2,7 +2,7 @@
2
2
  * Graph matching algorithms
3
3
  */
4
4
 
5
- export type {BipartiteMatchingOptions, BipartiteMatchingResult} from "./bipartite.js";
6
- export {bipartitePartition, greedyBipartiteMatching, maximumBipartiteMatching} from "./bipartite.js";
7
- export type {IsomorphismOptions, IsomorphismResult} from "./isomorphism.js";
8
- export {findAllIsomorphisms, isGraphIsomorphic} from "./isomorphism.js";
5
+ export type { BipartiteMatchingOptions, BipartiteMatchingResult } from "./bipartite.js";
6
+ export { bipartitePartition, greedyBipartiteMatching, maximumBipartiteMatching } from "./bipartite.js";
7
+ export type { IsomorphismOptions, IsomorphismResult } from "./isomorphism.js";
8
+ export { findAllIsomorphisms, isGraphIsomorphic } from "./isomorphism.js";
@@ -1,5 +1,5 @@
1
- import type {Graph} from "../../core/graph.js";
2
- import type {NodeId} from "../../types/index.js";
1
+ import type { Graph } from "../../core/graph.js";
2
+ import type { NodeId } from "../../types/index.js";
3
3
 
4
4
  /**
5
5
  * Graph Isomorphism (VF2) algorithm implementation
@@ -37,19 +37,19 @@ interface VF2State {
37
37
 
38
38
  /**
39
39
  * Check if two graphs are isomorphic using VF2 algorithm
40
+ * @param graph1 - The first graph to compare
41
+ * @param graph2 - The second graph to compare
42
+ * @param options - Optional configuration for node and edge matching predicates
43
+ * @returns An object indicating if the graphs are isomorphic and an optional mapping between nodes
40
44
  */
41
- export function isGraphIsomorphic(
42
- graph1: Graph,
43
- graph2: Graph,
44
- options: IsomorphismOptions = {},
45
- ): IsomorphismResult {
45
+ export function isGraphIsomorphic(graph1: Graph, graph2: Graph, options: IsomorphismOptions = {}): IsomorphismResult {
46
46
  // Quick checks
47
47
  if (graph1.nodeCount !== graph2.nodeCount || graph1.totalEdgeCount !== graph2.totalEdgeCount) {
48
- return {isIsomorphic: false};
48
+ return { isIsomorphic: false };
49
49
  }
50
50
 
51
51
  if (graph1.isDirected !== graph2.isDirected) {
52
- return {isIsomorphic: false};
52
+ return { isIsomorphic: false };
53
53
  }
54
54
 
55
55
  const nodes1 = Array.from(graph1.nodes()).map((n) => n.id);
@@ -61,7 +61,7 @@ export function isGraphIsomorphic(
61
61
 
62
62
  for (let i = 0; i < degrees1.length; i++) {
63
63
  if (degrees1[i] !== degrees2[i]) {
64
- return {isIsomorphic: false};
64
+ return { isIsomorphic: false };
65
65
  }
66
66
  }
67
67
 
@@ -87,11 +87,19 @@ export function isGraphIsomorphic(
87
87
  };
88
88
  }
89
89
 
90
- return {isIsomorphic: false};
90
+ return { isIsomorphic: false };
91
91
  }
92
92
 
93
93
  /**
94
94
  * VF2 recursive search
95
+ * @param g1 - The first graph being compared
96
+ * @param g2 - The second graph being compared
97
+ * @param state - The current VF2 algorithm state containing mappings and terminal sets
98
+ * @param nodes1 - Array of node IDs from the first graph
99
+ * @param nodes2 - Array of node IDs from the second graph
100
+ * @param options - Configuration options for matching predicates
101
+ * @param mappings - Array to collect found isomorphism mappings
102
+ * @returns True if an isomorphism was found and search should stop, false otherwise
95
103
  */
96
104
  function vf2Recurse(
97
105
  g1: Graph,
@@ -127,6 +135,12 @@ function vf2Recurse(
127
135
 
128
136
  /**
129
137
  * Get candidate pairs for the next mapping
138
+ * @param g1 - The first graph being compared
139
+ * @param g2 - The second graph being compared
140
+ * @param state - The current VF2 algorithm state containing mappings and terminal sets
141
+ * @param nodes1 - Array of node IDs from the first graph
142
+ * @param nodes2 - Array of node IDs from the second graph
143
+ * @returns Array of candidate node pairs to try matching
130
144
  */
131
145
  function getCandidatePairs(
132
146
  g1: Graph,
@@ -187,6 +201,13 @@ function getCandidatePairs(
187
201
 
188
202
  /**
189
203
  * Check if a pair is feasible
204
+ * @param g1 - The first graph being compared
205
+ * @param g2 - The second graph being compared
206
+ * @param state - The current VF2 algorithm state containing mappings and terminal sets
207
+ * @param node1 - The candidate node from the first graph
208
+ * @param node2 - The candidate node from the second graph
209
+ * @param options - Configuration options for matching predicates
210
+ * @returns True if the node pair can be feasibly matched, false otherwise
190
211
  */
191
212
  function isFeasible(
192
213
  g1: Graph,
@@ -222,8 +243,14 @@ function isFeasible(
222
243
  }
223
244
 
224
245
  // Check terminal set sizes
225
- let new1In = 0; let new1Out = 0; let term1In = 0; let term1Out = 0;
226
- let new2In = 0; let new2Out = 0; let term2In = 0; let term2Out = 0;
246
+ let new1In = 0;
247
+ let new1Out = 0;
248
+ let term1In = 0;
249
+ let term1Out = 0;
250
+ let new2In = 0;
251
+ let new2Out = 0;
252
+ let term2In = 0;
253
+ let term2Out = 0;
227
254
 
228
255
  for (const neighbor of neighbors1) {
229
256
  if (state.core1.has(neighbor)) {
@@ -271,20 +298,19 @@ function isFeasible(
271
298
  }
272
299
  }
273
300
 
274
- return term1In === term2In && term1Out === term2Out &&
275
- new1In === new2In && new1Out === new2Out;
301
+ return term1In === term2In && term1Out === term2Out && new1In === new2In && new1Out === new2Out;
276
302
  }
277
303
 
278
304
  /**
279
305
  * Add a pair to the mapping and update terminal sets
306
+ * @param g1 - The first graph being compared
307
+ * @param g2 - The second graph being compared
308
+ * @param state - The current VF2 algorithm state containing mappings and terminal sets
309
+ * @param node1 - The node from the first graph to add to the mapping
310
+ * @param node2 - The node from the second graph to add to the mapping
311
+ * @returns A new VF2 state with the pair added and terminal sets updated
280
312
  */
281
- function addPair(
282
- g1: Graph,
283
- g2: Graph,
284
- state: VF2State,
285
- node1: NodeId,
286
- node2: NodeId,
287
- ): VF2State {
313
+ function addPair(g1: Graph, g2: Graph, state: VF2State, node1: NodeId, node2: NodeId): VF2State {
288
314
  const newState: VF2State = {
289
315
  core1: new Map(state.core1),
290
316
  core2: new Map(state.core2),
@@ -340,6 +366,10 @@ function addPair(
340
366
 
341
367
  /**
342
368
  * Find all isomorphisms between two graphs
369
+ * @param graph1 - The first graph to compare
370
+ * @param graph2 - The second graph to compare
371
+ * @param options - Optional configuration for node and edge matching predicates
372
+ * @returns An array of all possible node mappings between the graphs
343
373
  */
344
374
  export function findAllIsomorphisms(
345
375
  graph1: Graph,
@@ -386,7 +416,7 @@ export function findAllIsomorphisms(
386
416
 
387
417
  // Find all isomorphisms
388
418
  const mappings: Map<NodeId, NodeId>[] = [];
389
- vf2Recurse(graph1, graph2, state, nodes1, nodes2, {... options, findAllMappings: true}, mappings);
419
+ vf2Recurse(graph1, graph2, state, nodes1, nodes2, { ...options, findAllMappings: true }, mappings);
390
420
 
391
421
  return mappings;
392
422
  }
@@ -1,4 +1,3 @@
1
- export type {MSTResult} from "./kruskal.js";
2
- export {kruskalMST, minimumSpanningTree} from "./kruskal.js";
3
- export {primMST} from "./prim.js";
4
-
1
+ export type { MSTResult } from "./kruskal.js";
2
+ export { kruskalMST, minimumSpanningTree } from "./kruskal.js";
3
+ export { primMST } from "./prim.js";
@@ -1,12 +1,20 @@
1
- import {Graph} from "../../core/graph.js";
2
- import {UnionFind} from "../../data-structures/union-find.js";
3
- import type {Edge} from "../../types/index.js";
1
+ import { Graph } from "../../core/graph.js";
2
+ import { UnionFind } from "../../data-structures/union-find.js";
3
+ import type { Edge } from "../../types/index.js";
4
4
 
5
5
  export interface MSTResult {
6
6
  edges: Edge[];
7
7
  totalWeight: number;
8
8
  }
9
9
 
10
+ /**
11
+ * Computes the minimum spanning tree of an undirected graph using Kruskal's algorithm.
12
+ * The algorithm sorts edges by weight and greedily adds edges that don't create cycles,
13
+ * using a union-find data structure to efficiently detect cycles.
14
+ * @param graph - The undirected graph to compute the MST for
15
+ * @returns The minimum spanning tree as a set of edges and the total weight
16
+ * @throws Error if the graph is directed or not connected
17
+ */
10
18
  export function kruskalMST(graph: Graph): MSTResult {
11
19
  if (graph.isDirected) {
12
20
  throw new Error("Kruskal's algorithm requires an undirected graph");
@@ -16,9 +24,10 @@ export function kruskalMST(graph: Graph): MSTResult {
16
24
  const visitedEdges = new Set<string>();
17
25
 
18
26
  for (const edge of Array.from(graph.edges())) {
19
- const edgeKey = edge.source < edge.target ?
20
- `${String(edge.source)}-${String(edge.target)}` :
21
- `${String(edge.target)}-${String(edge.source)}`;
27
+ const edgeKey =
28
+ edge.source < edge.target
29
+ ? `${String(edge.source)}-${String(edge.target)}`
30
+ : `${String(edge.target)}-${String(edge.source)}`;
22
31
 
23
32
  if (!visitedEdges.has(edgeKey)) {
24
33
  visitedEdges.add(edgeKey);
@@ -56,6 +65,12 @@ export function kruskalMST(graph: Graph): MSTResult {
56
65
  };
57
66
  }
58
67
 
68
+ /**
69
+ * Alias for kruskalMST. Computes the minimum spanning tree of an undirected graph.
70
+ * @param graph - The undirected graph to compute the MST for
71
+ * @returns The minimum spanning tree as a set of edges and the total weight
72
+ * @throws Error if the graph is directed or not connected
73
+ */
59
74
  export function minimumSpanningTree(graph: Graph): MSTResult {
60
75
  return kruskalMST(graph);
61
76
  }
@@ -1,8 +1,17 @@
1
- import {Graph} from "../../core/graph.js";
2
- import {PriorityQueue} from "../../data-structures/priority-queue.js";
3
- import type {Edge, NodeId} from "../../types/index.js";
4
- import type {MSTResult} from "./kruskal.js";
1
+ import { Graph } from "../../core/graph.js";
2
+ import { PriorityQueue } from "../../data-structures/priority-queue.js";
3
+ import type { Edge, NodeId } from "../../types/index.js";
4
+ import type { MSTResult } from "./kruskal.js";
5
5
 
6
+ /**
7
+ * Computes the minimum spanning tree of an undirected graph using Prim's algorithm.
8
+ * The algorithm grows the MST from a starting node by repeatedly adding the minimum
9
+ * weight edge that connects a node in the tree to a node outside the tree.
10
+ * @param graph - The undirected graph to compute the MST for
11
+ * @param startNode - Optional starting node; if not provided, uses the first node in the graph
12
+ * @returns The minimum spanning tree as a set of edges and the total weight
13
+ * @throws Error if the graph is directed, the start node is not found, or the graph is not connected
14
+ */
6
15
  export function primMST(graph: Graph, startNode?: NodeId): MSTResult {
7
16
  if (graph.isDirected) {
8
17
  throw new Error("Prim's algorithm requires an undirected graph");
@@ -1,6 +1,6 @@
1
- import type {Graph} from "../../core/graph.js";
2
- import type {NodeId, ShortestPathResult} from "../../types/index.js";
3
- import {reconstructPath} from "../../utils/graph-utilities.js";
1
+ import type { Graph } from "../../core/graph.js";
2
+ import type { NodeId, ShortestPathResult } from "../../types/index.js";
3
+ import { reconstructPath } from "../../utils/graph-utilities.js";
4
4
 
5
5
  /**
6
6
  * Bellman-Ford algorithm implementation for single-source shortest paths
@@ -44,12 +44,12 @@ export interface BellmanFordResult {
44
44
 
45
45
  /**
46
46
  * Find shortest paths from source using Bellman-Ford algorithm
47
+ * @param graph - The graph to search
48
+ * @param source - The starting node for the search
49
+ * @param options - Algorithm options including optional target for early termination
50
+ * @returns The distances, predecessors, and negative cycle information
47
51
  */
48
- export function bellmanFord(
49
- graph: Graph,
50
- source: NodeId,
51
- options: BellmanFordOptions = {},
52
- ): BellmanFordResult {
52
+ export function bellmanFord(graph: Graph, source: NodeId, options: BellmanFordOptions = {}): BellmanFordResult {
53
53
  if (!graph.hasNode(source)) {
54
54
  throw new Error(`Source node ${String(source)} not found in graph`);
55
55
  }
@@ -130,12 +130,12 @@ export function bellmanFord(
130
130
 
131
131
  /**
132
132
  * Find shortest path between two specific nodes using Bellman-Ford
133
+ * @param graph - The graph to search
134
+ * @param source - The starting node for the path
135
+ * @param target - The destination node for the path
136
+ * @returns The shortest path result or null if no path exists
133
137
  */
134
- export function bellmanFordPath(
135
- graph: Graph,
136
- source: NodeId,
137
- target: NodeId,
138
- ): ShortestPathResult | null {
138
+ export function bellmanFordPath(graph: Graph, source: NodeId, target: NodeId): ShortestPathResult | null {
139
139
  if (!graph.hasNode(source)) {
140
140
  throw new Error(`Source node ${String(source)} not found in graph`);
141
141
  }
@@ -144,7 +144,7 @@ export function bellmanFordPath(
144
144
  throw new Error(`Target node ${String(target)} not found in graph`);
145
145
  }
146
146
 
147
- const result = bellmanFord(graph, source, {target});
147
+ const result = bellmanFord(graph, source, { target });
148
148
 
149
149
  if (result.hasNegativeCycle) {
150
150
  throw new Error("Graph contains a negative cycle");
@@ -168,6 +168,8 @@ export function bellmanFordPath(
168
168
 
169
169
  /**
170
170
  * Check if graph has negative cycles using Bellman-Ford
171
+ * @param graph - The graph to check for negative cycles
172
+ * @returns True if the graph contains a negative cycle
171
173
  */
172
174
  export function hasNegativeCycle(graph: Graph): boolean {
173
175
  const nodes = Array.from(graph.nodes());
@@ -198,4 +200,3 @@ export function hasNegativeCycle(graph: Graph): boolean {
198
200
 
199
201
  return false;
200
202
  }
201
-
@@ -1,6 +1,6 @@
1
- import type {Graph} from "../../core/graph.js";
2
- import {PriorityQueue} from "../../data-structures/priority-queue.js";
3
- import type {NodeId, ShortestPathResult} from "../../types/index.js";
1
+ import type { Graph } from "../../core/graph.js";
2
+ import { PriorityQueue } from "../../data-structures/priority-queue.js";
3
+ import type { NodeId, ShortestPathResult } from "../../types/index.js";
4
4
 
5
5
  interface SearchState {
6
6
  distances: Map<NodeId, number>;
@@ -30,6 +30,10 @@ export class BidirectionalDijkstra {
30
30
  private meetingNode: NodeId | null = null;
31
31
  private shortestDistance = Infinity;
32
32
 
33
+ /**
34
+ * Creates a new BidirectionalDijkstra instance
35
+ * @param graph - The graph to search for shortest paths
36
+ */
33
37
  constructor(graph: Graph) {
34
38
  this.graph = graph;
35
39
  this.forwardSearch = this.initSearchState();
@@ -46,10 +50,13 @@ export class BidirectionalDijkstra {
46
50
  }
47
51
 
48
52
  /**
49
- * Find shortest path between source and target nodes
50
- */
53
+ * Find shortest path between source and target nodes
54
+ * @param source - The starting node for the path
55
+ * @param target - The destination node for the path
56
+ * @returns The shortest path result or null if no path exists
57
+ */
51
58
  public findShortestPath(source: NodeId, target: NodeId): ShortestPathResult | null {
52
- // Reset state for new search
59
+ // Reset state for new search
53
60
  this.reset();
54
61
  if (!this.graph.hasNode(source)) {
55
62
  throw new Error(`Source node ${String(source)} not found in graph`);
@@ -79,15 +86,16 @@ export class BidirectionalDijkstra {
79
86
  this.backwardSearch.frontier.enqueue(target, 0);
80
87
 
81
88
  // Main search loop
82
- while (!this.forwardSearch.frontier.isEmpty() ||
83
- !this.backwardSearch.frontier.isEmpty()) {
89
+ while (!this.forwardSearch.frontier.isEmpty() || !this.backwardSearch.frontier.isEmpty()) {
84
90
  // Alternate between forward and backward search
85
91
  // Choose the search with smaller frontier for better performance
86
92
  let searchExpanded = false;
87
93
 
88
- if (!this.forwardSearch.frontier.isEmpty() &&
89
- (this.backwardSearch.frontier.isEmpty() ||
90
- this.forwardSearch.frontier.size() <= this.backwardSearch.frontier.size())) {
94
+ if (
95
+ !this.forwardSearch.frontier.isEmpty() &&
96
+ (this.backwardSearch.frontier.isEmpty() ||
97
+ this.forwardSearch.frontier.size() <= this.backwardSearch.frontier.size())
98
+ ) {
91
99
  if (this.expandSearch(this.forwardSearch, this.backwardSearch, true)) {
92
100
  break;
93
101
  }
@@ -102,8 +110,7 @@ export class BidirectionalDijkstra {
102
110
  }
103
111
 
104
112
  // Continue until both frontiers are empty or we've found an optimal path
105
- if (this.forwardSearch.frontier.isEmpty() &&
106
- this.backwardSearch.frontier.isEmpty()) {
113
+ if (this.forwardSearch.frontier.isEmpty() && this.backwardSearch.frontier.isEmpty()) {
107
114
  break;
108
115
  }
109
116
  }
@@ -119,11 +126,7 @@ export class BidirectionalDijkstra {
119
126
  };
120
127
  }
121
128
 
122
- private expandSearch(
123
- search: SearchState,
124
- oppositeSearch: SearchState,
125
- isForward: boolean,
126
- ): boolean {
129
+ private expandSearch(search: SearchState, oppositeSearch: SearchState, isForward: boolean): boolean {
127
130
  const current = search.frontier.dequeue();
128
131
  if (current === undefined) {
129
132
  return false;
@@ -150,18 +153,16 @@ export class BidirectionalDijkstra {
150
153
  }
151
154
 
152
155
  // Explore neighbors
153
- const neighbors = isForward ?
154
- Array.from(this.graph.neighbors(current)) :
155
- Array.from(this.graph.inNeighbors(current));
156
+ const neighbors = isForward
157
+ ? Array.from(this.graph.neighbors(current))
158
+ : Array.from(this.graph.inNeighbors(current));
156
159
 
157
160
  for (const neighbor of neighbors) {
158
161
  if (search.visited.has(neighbor)) {
159
162
  continue;
160
163
  }
161
164
 
162
- const edge = isForward ?
163
- this.graph.getEdge(current, neighbor) :
164
- this.graph.getEdge(neighbor, current);
165
+ const edge = isForward ? this.graph.getEdge(current, neighbor) : this.graph.getEdge(neighbor, current);
165
166
 
166
167
  if (!edge) {
167
168
  continue;
@@ -175,8 +176,7 @@ export class BidirectionalDijkstra {
175
176
  const newDistance = distance + edgeWeight;
176
177
  const currentNeighborDistance = search.distances.get(neighbor);
177
178
 
178
- if (!search.distances.has(neighbor) ||
179
- newDistance < (currentNeighborDistance ?? Infinity)) {
179
+ if (!search.distances.has(neighbor) || newDistance < (currentNeighborDistance ?? Infinity)) {
180
180
  search.distances.set(neighbor, newDistance);
181
181
  search.previous.set(neighbor, current);
182
182
  search.frontier.enqueue(neighbor, newDistance);
@@ -237,8 +237,8 @@ export class BidirectionalDijkstra {
237
237
  }
238
238
 
239
239
  /**
240
- * Reset the search state for reuse
241
- */
240
+ * Reset the search state for reuse
241
+ */
242
242
  public reset(): void {
243
243
  this.forwardSearch = this.initSearchState();
244
244
  this.backwardSearch = this.initSearchState();