@graphty/algorithms 1.2.0 → 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 (337) hide show
  1. package/README.md +375 -276
  2. package/dist/algorithms.d.ts +42 -2
  3. package/dist/algorithms.js +11402 -2
  4. package/dist/algorithms.js.map +1 -1
  5. package/dist/src/algorithms/centrality/betweenness.d.ts +14 -0
  6. package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
  7. package/dist/src/algorithms/centrality/betweenness.js +144 -169
  8. package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
  9. package/dist/src/algorithms/centrality/closeness.d.ts +35 -1
  10. package/dist/src/algorithms/centrality/closeness.d.ts.map +1 -1
  11. package/dist/src/algorithms/centrality/closeness.js +70 -149
  12. package/dist/src/algorithms/centrality/closeness.js.map +1 -1
  13. package/dist/src/algorithms/centrality/degree.d.ts +7 -0
  14. package/dist/src/algorithms/centrality/degree.d.ts.map +1 -1
  15. package/dist/src/algorithms/centrality/degree.js +12 -9
  16. package/dist/src/algorithms/centrality/degree.js.map +1 -1
  17. package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts +57 -0
  18. package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts.map +1 -0
  19. package/dist/src/algorithms/centrality/delta-pagerank-simple.js +304 -0
  20. package/dist/src/algorithms/centrality/delta-pagerank-simple.js.map +1 -0
  21. package/dist/src/algorithms/centrality/delta-pagerank.d.ts +106 -0
  22. package/dist/src/algorithms/centrality/delta-pagerank.d.ts.map +1 -0
  23. package/dist/src/algorithms/centrality/delta-pagerank.js +320 -0
  24. package/dist/src/algorithms/centrality/delta-pagerank.js.map +1 -0
  25. package/dist/src/algorithms/centrality/eigenvector.d.ts +10 -3
  26. package/dist/src/algorithms/centrality/eigenvector.d.ts.map +1 -1
  27. package/dist/src/algorithms/centrality/eigenvector.js +11 -4
  28. package/dist/src/algorithms/centrality/eigenvector.js.map +1 -1
  29. package/dist/src/algorithms/centrality/hits.d.ts +10 -3
  30. package/dist/src/algorithms/centrality/hits.d.ts.map +1 -1
  31. package/dist/src/algorithms/centrality/hits.js +11 -4
  32. package/dist/src/algorithms/centrality/hits.js.map +1 -1
  33. package/dist/src/algorithms/centrality/index.d.ts +3 -1
  34. package/dist/src/algorithms/centrality/index.d.ts.map +1 -1
  35. package/dist/src/algorithms/centrality/index.js +2 -1
  36. package/dist/src/algorithms/centrality/index.js.map +1 -1
  37. package/dist/src/algorithms/centrality/katz.d.ts +10 -3
  38. package/dist/src/algorithms/centrality/katz.d.ts.map +1 -1
  39. package/dist/src/algorithms/centrality/katz.js +13 -8
  40. package/dist/src/algorithms/centrality/katz.js.map +1 -1
  41. package/dist/src/algorithms/centrality/pagerank.d.ts +31 -0
  42. package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -1
  43. package/dist/src/algorithms/centrality/pagerank.js +61 -1
  44. package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
  45. package/dist/src/algorithms/community/girvan-newman.d.ts +2 -3
  46. package/dist/src/algorithms/community/girvan-newman.d.ts.map +1 -1
  47. package/dist/src/algorithms/community/girvan-newman.js +67 -57
  48. package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
  49. package/dist/src/algorithms/community/index.d.ts +2 -0
  50. package/dist/src/algorithms/community/index.d.ts.map +1 -1
  51. package/dist/src/algorithms/community/index.js.map +1 -1
  52. package/dist/src/algorithms/community/label-propagation.d.ts +11 -4
  53. package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -1
  54. package/dist/src/algorithms/community/label-propagation.js +60 -38
  55. package/dist/src/algorithms/community/label-propagation.js.map +1 -1
  56. package/dist/src/algorithms/community/leiden.d.ts +3 -3
  57. package/dist/src/algorithms/community/leiden.d.ts.map +1 -1
  58. package/dist/src/algorithms/community/leiden.js +70 -44
  59. package/dist/src/algorithms/community/leiden.js.map +1 -1
  60. package/dist/src/algorithms/community/louvain-optimized.d.ts +149 -0
  61. package/dist/src/algorithms/community/louvain-optimized.d.ts.map +1 -0
  62. package/dist/src/algorithms/community/louvain-optimized.js +338 -0
  63. package/dist/src/algorithms/community/louvain-optimized.js.map +1 -0
  64. package/dist/src/algorithms/community/louvain.d.ts +2 -3
  65. package/dist/src/algorithms/community/louvain.d.ts.map +1 -1
  66. package/dist/src/algorithms/community/louvain.js +35 -81
  67. package/dist/src/algorithms/community/louvain.js.map +1 -1
  68. package/dist/src/algorithms/community/modularity-utils.d.ts +55 -0
  69. package/dist/src/algorithms/community/modularity-utils.d.ts.map +1 -0
  70. package/dist/src/algorithms/community/modularity-utils.js +108 -0
  71. package/dist/src/algorithms/community/modularity-utils.js.map +1 -0
  72. package/dist/src/algorithms/components/connected.d.ts +23 -0
  73. package/dist/src/algorithms/components/connected.d.ts.map +1 -1
  74. package/dist/src/algorithms/components/connected.js +29 -3
  75. package/dist/src/algorithms/components/connected.js.map +1 -1
  76. package/dist/src/algorithms/matching/bipartite.d.ts +10 -0
  77. package/dist/src/algorithms/matching/bipartite.d.ts.map +1 -1
  78. package/dist/src/algorithms/matching/bipartite.js +18 -40
  79. package/dist/src/algorithms/matching/bipartite.js.map +1 -1
  80. package/dist/src/algorithms/matching/index.d.ts.map +1 -1
  81. package/dist/src/algorithms/matching/index.js.map +1 -1
  82. package/dist/src/algorithms/matching/isomorphism.d.ts +8 -0
  83. package/dist/src/algorithms/matching/isomorphism.d.ts.map +1 -1
  84. package/dist/src/algorithms/matching/isomorphism.js +36 -2
  85. package/dist/src/algorithms/matching/isomorphism.js.map +1 -1
  86. package/dist/src/algorithms/mst/index.d.ts.map +1 -1
  87. package/dist/src/algorithms/mst/index.js.map +1 -1
  88. package/dist/src/algorithms/mst/kruskal.d.ts +14 -0
  89. package/dist/src/algorithms/mst/kruskal.d.ts.map +1 -1
  90. package/dist/src/algorithms/mst/kruskal.js +17 -3
  91. package/dist/src/algorithms/mst/kruskal.js.map +1 -1
  92. package/dist/src/algorithms/mst/prim.d.ts +9 -0
  93. package/dist/src/algorithms/mst/prim.d.ts.map +1 -1
  94. package/dist/src/algorithms/mst/prim.js +9 -0
  95. package/dist/src/algorithms/mst/prim.js.map +1 -1
  96. package/dist/src/algorithms/shortest-path/bellman-ford.d.ts +10 -0
  97. package/dist/src/algorithms/shortest-path/bellman-ford.d.ts.map +1 -1
  98. package/dist/src/algorithms/shortest-path/bellman-ford.js +11 -12
  99. package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
  100. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts +44 -0
  101. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts.map +1 -0
  102. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +195 -0
  103. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js.map +1 -0
  104. package/dist/src/algorithms/shortest-path/dijkstra.d.ts +20 -2
  105. package/dist/src/algorithms/shortest-path/dijkstra.d.ts.map +1 -1
  106. package/dist/src/algorithms/shortest-path/dijkstra.js +30 -14
  107. package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
  108. package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts +17 -0
  109. package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts.map +1 -1
  110. package/dist/src/algorithms/shortest-path/floyd-warshall.js +17 -0
  111. package/dist/src/algorithms/shortest-path/floyd-warshall.js.map +1 -1
  112. package/dist/src/algorithms/shortest-path/index.d.ts.map +1 -1
  113. package/dist/src/algorithms/shortest-path/index.js.map +1 -1
  114. package/dist/src/algorithms/traversal/bfs-unified.d.ts +42 -0
  115. package/dist/src/algorithms/traversal/bfs-unified.d.ts.map +1 -0
  116. package/dist/src/algorithms/traversal/bfs-unified.js +370 -0
  117. package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -0
  118. package/dist/src/algorithms/traversal/bfs-variants.d.ts +77 -0
  119. package/dist/src/algorithms/traversal/bfs-variants.d.ts.map +1 -0
  120. package/dist/src/algorithms/traversal/bfs-variants.js +402 -0
  121. package/dist/src/algorithms/traversal/bfs-variants.js.map +1 -0
  122. package/dist/src/algorithms/traversal/bfs.d.ts +4 -18
  123. package/dist/src/algorithms/traversal/bfs.d.ts.map +1 -1
  124. package/dist/src/algorithms/traversal/bfs.js +5 -182
  125. package/dist/src/algorithms/traversal/bfs.js.map +1 -1
  126. package/dist/src/algorithms/traversal/dfs.d.ts +10 -0
  127. package/dist/src/algorithms/traversal/dfs.d.ts.map +1 -1
  128. package/dist/src/algorithms/traversal/dfs.js +48 -0
  129. package/dist/src/algorithms/traversal/dfs.js.map +1 -1
  130. package/dist/src/algorithms/traversal/index.d.ts.map +1 -1
  131. package/dist/src/algorithms/traversal/index.js.map +1 -1
  132. package/dist/src/benchmark-all-algorithms.d.ts +25 -0
  133. package/dist/src/benchmark-all-algorithms.d.ts.map +1 -0
  134. package/dist/src/benchmark-all-algorithms.js +491 -0
  135. package/dist/src/benchmark-all-algorithms.js.map +1 -0
  136. package/dist/src/clustering/hierarchical.d.ts +23 -15
  137. package/dist/src/clustering/hierarchical.d.ts.map +1 -1
  138. package/dist/src/clustering/hierarchical.js +226 -224
  139. package/dist/src/clustering/hierarchical.js.map +1 -1
  140. package/dist/src/clustering/index.d.ts +4 -2
  141. package/dist/src/clustering/index.d.ts.map +1 -1
  142. package/dist/src/clustering/index.js +2 -2
  143. package/dist/src/clustering/index.js.map +1 -1
  144. package/dist/src/clustering/k-core.d.ts +17 -19
  145. package/dist/src/clustering/k-core.d.ts.map +1 -1
  146. package/dist/src/clustering/k-core.js +68 -30
  147. package/dist/src/clustering/k-core.js.map +1 -1
  148. package/dist/src/clustering/mcl.d.ts +6 -0
  149. package/dist/src/clustering/mcl.d.ts.map +1 -1
  150. package/dist/src/clustering/mcl.js +34 -3
  151. package/dist/src/clustering/mcl.js.map +1 -1
  152. package/dist/src/clustering/spectral.d.ts +11 -0
  153. package/dist/src/clustering/spectral.d.ts.map +1 -1
  154. package/dist/src/clustering/spectral.js +99 -47
  155. package/dist/src/clustering/spectral.js.map +1 -1
  156. package/dist/src/core/graph.d.ts +45 -0
  157. package/dist/src/core/graph.d.ts.map +1 -1
  158. package/dist/src/core/graph.js +49 -5
  159. package/dist/src/core/graph.js.map +1 -1
  160. package/dist/src/data-structures/index.d.ts.map +1 -1
  161. package/dist/src/data-structures/index.js.map +1 -1
  162. package/dist/src/data-structures/priority-queue.d.ts +18 -1
  163. package/dist/src/data-structures/priority-queue.d.ts.map +1 -1
  164. package/dist/src/data-structures/priority-queue.js +26 -5
  165. package/dist/src/data-structures/priority-queue.js.map +1 -1
  166. package/dist/src/data-structures/union-find.d.ts +21 -0
  167. package/dist/src/data-structures/union-find.d.ts.map +1 -1
  168. package/dist/src/data-structures/union-find.js +21 -0
  169. package/dist/src/data-structures/union-find.js.map +1 -1
  170. package/dist/src/flow/ford-fulkerson.d.ts +20 -12
  171. package/dist/src/flow/ford-fulkerson.d.ts.map +1 -1
  172. package/dist/src/flow/ford-fulkerson.js +170 -217
  173. package/dist/src/flow/ford-fulkerson.js.map +1 -1
  174. package/dist/src/flow/min-cut.d.ts +6 -8
  175. package/dist/src/flow/min-cut.d.ts.map +1 -1
  176. package/dist/src/flow/min-cut.js +34 -12
  177. package/dist/src/flow/min-cut.js.map +1 -1
  178. package/dist/src/index.d.ts +3 -1
  179. package/dist/src/index.d.ts.map +1 -1
  180. package/dist/src/index.js +6 -1
  181. package/dist/src/index.js.map +1 -1
  182. package/dist/src/link-prediction/adamic-adar.d.ts +26 -0
  183. package/dist/src/link-prediction/adamic-adar.d.ts.map +1 -1
  184. package/dist/src/link-prediction/adamic-adar.js +47 -30
  185. package/dist/src/link-prediction/adamic-adar.js.map +1 -1
  186. package/dist/src/link-prediction/common-neighbors.d.ts +21 -0
  187. package/dist/src/link-prediction/common-neighbors.d.ts.map +1 -1
  188. package/dist/src/link-prediction/common-neighbors.js +31 -14
  189. package/dist/src/link-prediction/common-neighbors.js.map +1 -1
  190. package/dist/src/link-prediction/index.d.ts.map +1 -1
  191. package/dist/src/optimized/bit-packed.d.ts +193 -0
  192. package/dist/src/optimized/bit-packed.d.ts.map +1 -0
  193. package/dist/src/optimized/bit-packed.js +342 -0
  194. package/dist/src/optimized/bit-packed.js.map +1 -0
  195. package/dist/src/optimized/csr-graph.d.ts +149 -0
  196. package/dist/src/optimized/csr-graph.d.ts.map +1 -0
  197. package/dist/src/optimized/csr-graph.js +404 -0
  198. package/dist/src/optimized/csr-graph.js.map +1 -0
  199. package/dist/src/optimized/direction-optimized-bfs.d.ts +95 -0
  200. package/dist/src/optimized/direction-optimized-bfs.d.ts.map +1 -0
  201. package/dist/src/optimized/direction-optimized-bfs.js +242 -0
  202. package/dist/src/optimized/direction-optimized-bfs.js.map +1 -0
  203. package/dist/src/optimized/graph-adapter.d.ts +111 -0
  204. package/dist/src/optimized/graph-adapter.d.ts.map +1 -0
  205. package/dist/src/optimized/graph-adapter.js +194 -0
  206. package/dist/src/optimized/graph-adapter.js.map +1 -0
  207. package/dist/src/optimized/index.d.ts +14 -0
  208. package/dist/src/optimized/index.d.ts.map +1 -0
  209. package/dist/src/optimized/index.js +30 -0
  210. package/dist/src/optimized/index.js.map +1 -0
  211. package/dist/src/pathfinding/astar.d.ts +25 -9
  212. package/dist/src/pathfinding/astar.d.ts.map +1 -1
  213. package/dist/src/pathfinding/astar.js +25 -10
  214. package/dist/src/pathfinding/astar.js.map +1 -1
  215. package/dist/src/pathfinding/utils.d.ts +15 -6
  216. package/dist/src/pathfinding/utils.d.ts.map +1 -1
  217. package/dist/src/pathfinding/utils.js +19 -7
  218. package/dist/src/pathfinding/utils.js.map +1 -1
  219. package/dist/src/research/grsbm.d.ts +0 -1
  220. package/dist/src/research/grsbm.d.ts.map +1 -1
  221. package/dist/src/research/grsbm.js +28 -23
  222. package/dist/src/research/grsbm.js.map +1 -1
  223. package/dist/src/research/index.d.ts.map +1 -1
  224. package/dist/src/research/index.js.map +1 -1
  225. package/dist/src/research/sync.d.ts +0 -1
  226. package/dist/src/research/sync.d.ts.map +1 -1
  227. package/dist/src/research/sync.js +31 -36
  228. package/dist/src/research/sync.js.map +1 -1
  229. package/dist/src/research/terahac.d.ts +2 -1
  230. package/dist/src/research/terahac.d.ts.map +1 -1
  231. package/dist/src/research/terahac.js +39 -7
  232. package/dist/src/research/terahac.js.map +1 -1
  233. package/dist/src/types/index.d.ts +8 -0
  234. package/dist/src/types/index.d.ts.map +1 -1
  235. package/dist/src/utils/algorithm-utilities.d.ts +2 -0
  236. package/dist/src/utils/algorithm-utilities.d.ts.map +1 -0
  237. package/dist/src/utils/algorithm-utilities.js +2 -0
  238. package/dist/src/utils/algorithm-utilities.js.map +1 -0
  239. package/dist/src/utils/graph-converters.d.ts +110 -0
  240. package/dist/src/utils/graph-converters.d.ts.map +1 -0
  241. package/dist/src/utils/graph-converters.js +227 -0
  242. package/dist/src/utils/graph-converters.js.map +1 -0
  243. package/dist/src/utils/graph-utilities.d.ts +62 -0
  244. package/dist/src/utils/graph-utilities.d.ts.map +1 -0
  245. package/dist/src/utils/graph-utilities.js +148 -0
  246. package/dist/src/utils/graph-utilities.js.map +1 -0
  247. package/dist/src/utils/index.d.ts +5 -0
  248. package/dist/src/utils/index.d.ts.map +1 -0
  249. package/dist/src/utils/index.js +5 -0
  250. package/dist/src/utils/index.js.map +1 -0
  251. package/dist/src/utils/math-utilities.d.ts +63 -0
  252. package/dist/src/utils/math-utilities.d.ts.map +1 -0
  253. package/dist/src/utils/math-utilities.js +132 -0
  254. package/dist/src/utils/math-utilities.js.map +1 -0
  255. package/dist/src/utils/matrix-utilities.d.ts +2 -0
  256. package/dist/src/utils/matrix-utilities.d.ts.map +1 -0
  257. package/dist/src/utils/matrix-utilities.js +2 -0
  258. package/dist/src/utils/matrix-utilities.js.map +1 -0
  259. package/dist/src/utils/optimization-helpers.d.ts +42 -0
  260. package/dist/src/utils/optimization-helpers.d.ts.map +1 -0
  261. package/dist/src/utils/optimization-helpers.js +59 -0
  262. package/dist/src/utils/optimization-helpers.js.map +1 -0
  263. package/dist/src/utils/priorityQueue.d.ts +24 -0
  264. package/dist/src/utils/priorityQueue.d.ts.map +1 -1
  265. package/dist/src/utils/priorityQueue.js +34 -4
  266. package/dist/src/utils/priorityQueue.js.map +1 -1
  267. package/package.json +58 -39
  268. package/src/algorithms/centrality/betweenness.ts +185 -200
  269. package/src/algorithms/centrality/closeness.ts +93 -194
  270. package/src/algorithms/centrality/degree.ts +18 -22
  271. package/src/algorithms/centrality/delta-pagerank-simple.ts +374 -0
  272. package/src/algorithms/centrality/delta-pagerank.ts +458 -0
  273. package/src/algorithms/centrality/eigenvector.ts +14 -15
  274. package/src/algorithms/centrality/hits.ts +17 -17
  275. package/src/algorithms/centrality/index.ts +20 -13
  276. package/src/algorithms/centrality/katz.ts +17 -25
  277. package/src/algorithms/centrality/pagerank.ts +91 -16
  278. package/src/algorithms/community/girvan-newman.ts +90 -86
  279. package/src/algorithms/community/index.ts +6 -5
  280. package/src/algorithms/community/label-propagation.ts +69 -48
  281. package/src/algorithms/community/leiden.ts +88 -65
  282. package/src/algorithms/community/louvain-optimized.ts +474 -0
  283. package/src/algorithms/community/louvain.ts +52 -122
  284. package/src/algorithms/community/modularity-utils.ts +134 -0
  285. package/src/algorithms/components/connected.ts +40 -17
  286. package/src/algorithms/matching/bipartite.ts +24 -53
  287. package/src/algorithms/matching/index.ts +4 -4
  288. package/src/algorithms/matching/isomorphism.ts +53 -23
  289. package/src/algorithms/mst/index.ts +3 -4
  290. package/src/algorithms/mst/kruskal.ts +21 -6
  291. package/src/algorithms/mst/prim.ts +13 -4
  292. package/src/algorithms/shortest-path/bellman-ford.ts +16 -28
  293. package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +248 -0
  294. package/src/algorithms/shortest-path/dijkstra.ts +38 -30
  295. package/src/algorithms/shortest-path/floyd-warshall.ts +21 -4
  296. package/src/algorithms/shortest-path/index.ts +5 -5
  297. package/src/algorithms/traversal/bfs-unified.ts +437 -0
  298. package/src/algorithms/traversal/bfs-variants.ts +520 -0
  299. package/src/algorithms/traversal/bfs.ts +5 -229
  300. package/src/algorithms/traversal/dfs.ts +61 -42
  301. package/src/algorithms/traversal/index.ts +3 -3
  302. package/src/benchmark-all-algorithms.ts +580 -0
  303. package/src/clustering/hierarchical.ts +268 -272
  304. package/src/clustering/index.ts +8 -6
  305. package/src/clustering/k-core.ts +93 -61
  306. package/src/clustering/mcl.ts +53 -23
  307. package/src/clustering/spectral.ts +130 -72
  308. package/src/core/graph.ts +58 -18
  309. package/src/data-structures/index.ts +2 -2
  310. package/src/data-structures/priority-queue.ts +36 -11
  311. package/src/data-structures/union-find.ts +22 -1
  312. package/src/flow/ford-fulkerson.ts +221 -262
  313. package/src/flow/min-cut.ts +59 -51
  314. package/src/index.ts +9 -2
  315. package/src/link-prediction/adamic-adar.ts +75 -74
  316. package/src/link-prediction/common-neighbors.ts +49 -49
  317. package/src/link-prediction/index.ts +1 -1
  318. package/src/optimized/bit-packed.ts +390 -0
  319. package/src/optimized/csr-graph.ts +518 -0
  320. package/src/optimized/direction-optimized-bfs.ts +310 -0
  321. package/src/optimized/graph-adapter.ts +248 -0
  322. package/src/optimized/index.ts +34 -0
  323. package/src/pathfinding/astar.ts +40 -25
  324. package/src/pathfinding/utils.ts +20 -13
  325. package/src/research/grsbm.ts +36 -39
  326. package/src/research/index.ts +4 -4
  327. package/src/research/sync.ts +41 -54
  328. package/src/research/terahac.ts +63 -21
  329. package/src/types/index.ts +8 -0
  330. package/src/utils/algorithm-utilities.ts +2 -0
  331. package/src/utils/graph-converters.ts +269 -0
  332. package/src/utils/graph-utilities.ts +173 -0
  333. package/src/utils/index.ts +4 -0
  334. package/src/utils/math-utilities.ts +149 -0
  335. package/src/utils/matrix-utilities.ts +2 -0
  336. package/src/utils/optimization-helpers.ts +87 -0
  337. package/src/utils/priorityQueue.ts +40 -6
@@ -0,0 +1,520 @@
1
+ import type { Graph } from "../../core/graph.js";
2
+ import { PriorityQueue } from "../../data-structures/priority-queue.js";
3
+ import { CSRGraph } from "../../optimized/csr-graph.js";
4
+ import { DirectionOptimizedBFS } from "../../optimized/direction-optimized-bfs.js";
5
+ import { toCSRGraph } from "../../optimized/graph-adapter.js";
6
+ import type { NodeId } from "../../types/index.js";
7
+
8
+ /**
9
+ * Threshold for switching to CSR-optimized implementations.
10
+ * Based on benchmarks showing CSR benefits at this scale due to
11
+ * improved cache locality and reduced memory allocation overhead.
12
+ */
13
+ const LARGE_GRAPH_THRESHOLD = 10000;
14
+
15
+ /**
16
+ * BFS that tracks shortest path counts (for betweenness centrality)
17
+ *
18
+ * This variant of BFS computes:
19
+ * - Shortest distances from source to all reachable nodes
20
+ * - All predecessors on shortest paths
21
+ * - Number of shortest paths (sigma)
22
+ * - Stack of nodes in reverse BFS order
23
+ * @param graph - The input graph to traverse
24
+ * @param source - The source node to start BFS from
25
+ * @param options - Configuration options
26
+ * @param options.optimized - Whether to use CSR-optimized implementation for large graphs
27
+ * @returns Object containing distances, predecessors, path counts (sigma), and traversal stack
28
+ */
29
+ export function bfsWithPathCounting(
30
+ graph: Graph,
31
+ source: NodeId,
32
+ options: { optimized?: boolean } = {},
33
+ ): {
34
+ distances: Map<NodeId, number>;
35
+ predecessors: Map<NodeId, NodeId[]>;
36
+ sigma: Map<NodeId, number>;
37
+ stack: NodeId[];
38
+ } {
39
+ const useOptimized = options.optimized ?? false;
40
+
41
+ // Use CSR format for large graphs
42
+ if (useOptimized && graph.nodeCount > LARGE_GRAPH_THRESHOLD) {
43
+ const csrGraph = toCSRGraph(graph);
44
+ return bfsWithPathCountingCSR(csrGraph, source);
45
+ }
46
+
47
+ const distances = new Map<NodeId, number>();
48
+ const predecessors = new Map<NodeId, NodeId[]>();
49
+ const sigma = new Map<NodeId, number>();
50
+ const stack: NodeId[] = [];
51
+ const queue: NodeId[] = [];
52
+
53
+ // Initialize
54
+ distances.set(source, 0);
55
+ sigma.set(source, 1);
56
+ queue.push(source);
57
+
58
+ while (queue.length > 0) {
59
+ const current = queue.shift();
60
+ if (current === undefined) {
61
+ continue;
62
+ }
63
+
64
+ stack.push(current);
65
+
66
+ const currentDistance = distances.get(current) ?? 0;
67
+ const currentSigma = sigma.get(current) ?? 0;
68
+
69
+ // Process neighbors
70
+ const neighbors = graph.neighbors(current);
71
+ for (const neighbor of neighbors) {
72
+ // First time visiting this neighbor
73
+ if (!distances.has(neighbor)) {
74
+ distances.set(neighbor, currentDistance + 1);
75
+ queue.push(neighbor);
76
+ }
77
+
78
+ // Found a shortest path to neighbor
79
+ if (distances.get(neighbor) === currentDistance + 1) {
80
+ const neighborSigma = sigma.get(neighbor) ?? 0;
81
+ sigma.set(neighbor, neighborSigma + currentSigma);
82
+
83
+ const preds = predecessors.get(neighbor) ?? [];
84
+ preds.push(current);
85
+ predecessors.set(neighbor, preds);
86
+ }
87
+ }
88
+ }
89
+
90
+ return {
91
+ distances,
92
+ predecessors,
93
+ sigma,
94
+ stack,
95
+ };
96
+ }
97
+
98
+ /**
99
+ * BFS that only returns distances (for closeness centrality)
100
+ *
101
+ * Optimized variant that skips predecessor tracking
102
+ * @param graph - The input graph to traverse
103
+ * @param source - The source node to start BFS from
104
+ * @param cutoff - Maximum distance to explore (optional)
105
+ * @param options - Configuration options
106
+ * @param options.optimized - Whether to use CSR-optimized implementation for large graphs
107
+ * @returns Map of node IDs to their shortest distances from the source
108
+ */
109
+ export function bfsDistancesOnly(
110
+ graph: Graph,
111
+ source: NodeId,
112
+ cutoff?: number,
113
+ options: { optimized?: boolean } = {},
114
+ ): Map<NodeId, number> {
115
+ const useOptimized = options.optimized ?? false;
116
+
117
+ // Use CSR format for large graphs
118
+ if (useOptimized && graph.nodeCount > LARGE_GRAPH_THRESHOLD) {
119
+ const csrGraph = toCSRGraph(graph);
120
+ return bfsDistancesOnlyCSR(csrGraph, source, cutoff);
121
+ }
122
+
123
+ const distances = new Map<NodeId, number>();
124
+ const queue: NodeId[] = [];
125
+
126
+ distances.set(source, 0);
127
+ queue.push(source);
128
+
129
+ while (queue.length > 0) {
130
+ const current = queue.shift();
131
+ if (current === undefined) {
132
+ continue;
133
+ }
134
+
135
+ const currentDistance = distances.get(current) ?? 0;
136
+
137
+ // Stop if we've reached the cutoff distance
138
+ if (cutoff !== undefined && currentDistance >= cutoff) {
139
+ continue;
140
+ }
141
+
142
+ const neighbors = graph.neighbors(current);
143
+ for (const neighbor of neighbors) {
144
+ if (!distances.has(neighbor)) {
145
+ distances.set(neighbor, currentDistance + 1);
146
+ queue.push(neighbor);
147
+ }
148
+ }
149
+ }
150
+
151
+ return distances;
152
+ }
153
+
154
+ /**
155
+ * BFS for bipartite checking with partition sets
156
+ *
157
+ * Returns whether the graph is bipartite and the two partitions if it is
158
+ * @param graph - The input graph to check for bipartiteness
159
+ * @returns Object with bipartite status and optional partition sets
160
+ */
161
+ export function bfsColoringWithPartitions(graph: Graph): {
162
+ isBipartite: boolean;
163
+ partitions?: [Set<NodeId>, Set<NodeId>];
164
+ } {
165
+ const colors = new Map<NodeId, number>();
166
+ const partitionA = new Set<NodeId>();
167
+ const partitionB = new Set<NodeId>();
168
+
169
+ // Handle disconnected components
170
+ for (const node of graph.nodes()) {
171
+ if (!colors.has(node.id)) {
172
+ const queue: NodeId[] = [node.id];
173
+ colors.set(node.id, 0);
174
+ partitionA.add(node.id);
175
+
176
+ while (queue.length > 0) {
177
+ const current = queue.shift();
178
+ if (current === undefined) {
179
+ continue;
180
+ }
181
+
182
+ const currentColor = colors.get(current) ?? 0;
183
+ const nextColor = 1 - currentColor;
184
+
185
+ for (const neighbor of graph.neighbors(current)) {
186
+ if (!colors.has(neighbor)) {
187
+ colors.set(neighbor, nextColor);
188
+ queue.push(neighbor);
189
+
190
+ if (nextColor === 0) {
191
+ partitionA.add(neighbor);
192
+ } else {
193
+ partitionB.add(neighbor);
194
+ }
195
+ } else if (colors.get(neighbor) === currentColor) {
196
+ // Same color as current node - not bipartite
197
+ return { isBipartite: false };
198
+ }
199
+ }
200
+ }
201
+ }
202
+ }
203
+
204
+ return {
205
+ isBipartite: true,
206
+ partitions: [partitionA, partitionB],
207
+ };
208
+ }
209
+
210
+ /**
211
+ * BFS for finding augmenting paths (for flow algorithms)
212
+ *
213
+ * Finds a path from source to sink in a residual graph with positive capacity
214
+ * @param residualGraph - Map representing the residual graph with capacities
215
+ * @param source - The source node ID
216
+ * @param sink - The sink node ID
217
+ * @returns Object with path and capacity, or null if no path exists
218
+ */
219
+ export function bfsAugmentingPath(
220
+ residualGraph: Map<string, Map<string, number>>,
221
+ source: string,
222
+ sink: string,
223
+ ): {
224
+ path: string[];
225
+ pathCapacity: number;
226
+ } | null {
227
+ const parent = new Map<string, string | null>();
228
+ const queue: string[] = [];
229
+
230
+ parent.set(source, null);
231
+ queue.push(source);
232
+
233
+ while (queue.length > 0) {
234
+ const current = queue.shift();
235
+ if (current === undefined) {
236
+ continue;
237
+ }
238
+
239
+ if (current === sink) {
240
+ // Reconstruct path
241
+ const path: string[] = [];
242
+ let node: string | null = sink;
243
+ let pathCapacity = Infinity;
244
+
245
+ while (node !== null) {
246
+ path.unshift(node);
247
+ const parentNode = parent.get(node);
248
+
249
+ if (parentNode !== null && parentNode !== undefined) {
250
+ const capacity = residualGraph.get(parentNode)?.get(node) ?? 0;
251
+ pathCapacity = Math.min(pathCapacity, capacity);
252
+ }
253
+
254
+ node = parentNode ?? null;
255
+ }
256
+
257
+ return { path, pathCapacity };
258
+ }
259
+
260
+ const neighbors = residualGraph.get(current);
261
+ if (neighbors) {
262
+ for (const [neighbor, capacity] of neighbors) {
263
+ if (!parent.has(neighbor) && capacity > 0) {
264
+ parent.set(neighbor, current);
265
+ queue.push(neighbor);
266
+ }
267
+ }
268
+ }
269
+ }
270
+
271
+ return null;
272
+ }
273
+
274
+ /**
275
+ * BFS for weighted graphs using priority queue (simplified Dijkstra)
276
+ *
277
+ * Returns distances from source using edge weights
278
+ * @param graph - The input weighted graph to traverse
279
+ * @param source - The source node to start BFS from
280
+ * @param cutoff - Maximum distance to explore (optional)
281
+ * @param options - Configuration options
282
+ * @param options.optimized - Whether to use CSR-optimized implementation for large graphs
283
+ * @returns Map of node IDs to their shortest weighted distances from the source
284
+ */
285
+ export function bfsWeightedDistances(
286
+ graph: Graph,
287
+ source: NodeId,
288
+ cutoff?: number,
289
+ options: { optimized?: boolean } = {},
290
+ ): Map<NodeId, number> {
291
+ const useOptimized = options.optimized ?? false;
292
+
293
+ // Use CSR format for large graphs
294
+ if (useOptimized && graph.nodeCount > LARGE_GRAPH_THRESHOLD) {
295
+ const csrGraph = toCSRGraph(graph);
296
+ return bfsWeightedDistancesCSR(csrGraph, source, cutoff);
297
+ }
298
+
299
+ const distances = new Map<NodeId, number>();
300
+ const visited = new Set<NodeId>();
301
+
302
+ // Use efficient priority queue instead of array-based queue
303
+ const queue = new PriorityQueue<NodeId>();
304
+
305
+ distances.set(source, 0);
306
+ queue.enqueue(source, 0);
307
+
308
+ while (!queue.isEmpty()) {
309
+ const current = queue.dequeue();
310
+ if (current === undefined) {
311
+ continue;
312
+ }
313
+
314
+ const currentDist = distances.get(current) ?? 0;
315
+
316
+ if (visited.has(current)) {
317
+ continue;
318
+ }
319
+
320
+ visited.add(current);
321
+
322
+ // Stop if we've reached the cutoff distance
323
+ if (cutoff !== undefined && currentDist >= cutoff) {
324
+ continue;
325
+ }
326
+
327
+ for (const neighbor of graph.neighbors(current)) {
328
+ if (!visited.has(neighbor)) {
329
+ const edge = graph.getEdge(current, neighbor);
330
+ const weight = edge?.weight ?? 1;
331
+ const newDistance = currentDist + weight;
332
+
333
+ const oldDistance = distances.get(neighbor);
334
+ if (oldDistance === undefined || newDistance < oldDistance) {
335
+ distances.set(neighbor, newDistance);
336
+ queue.enqueue(neighbor, newDistance);
337
+ }
338
+ }
339
+ }
340
+ }
341
+
342
+ return distances;
343
+ }
344
+
345
+ /**
346
+ * CSR-optimized version of bfsWithPathCounting
347
+ * @param graph - The CSR graph representation
348
+ * @param source - The source node to start BFS from
349
+ * @returns Object containing distances, predecessors, path counts (sigma), and traversal stack
350
+ */
351
+ function bfsWithPathCountingCSR(
352
+ graph: CSRGraph,
353
+ source: NodeId,
354
+ ): {
355
+ distances: Map<NodeId, number>;
356
+ predecessors: Map<NodeId, NodeId[]>;
357
+ sigma: Map<NodeId, number>;
358
+ stack: NodeId[];
359
+ } {
360
+ const distances = new Map<NodeId, number>();
361
+ const predecessors = new Map<NodeId, NodeId[]>();
362
+ const sigma = new Map<NodeId, number>();
363
+ const stack: NodeId[] = [];
364
+ const queue: NodeId[] = [];
365
+
366
+ // Initialize
367
+ distances.set(source, 0);
368
+ sigma.set(source, 1);
369
+ queue.push(source);
370
+
371
+ while (queue.length > 0) {
372
+ const current = queue.shift();
373
+ if (current === undefined) {
374
+ continue;
375
+ }
376
+
377
+ stack.push(current);
378
+
379
+ const currentDistance = distances.get(current) ?? 0;
380
+ const currentSigma = sigma.get(current) ?? 0;
381
+
382
+ // Process neighbors using CSR iteration
383
+ for (const neighbor of graph.neighbors(current)) {
384
+ // First time visiting this neighbor
385
+ if (!distances.has(neighbor)) {
386
+ distances.set(neighbor, currentDistance + 1);
387
+ queue.push(neighbor);
388
+ }
389
+
390
+ // Found a shortest path to neighbor
391
+ if (distances.get(neighbor) === currentDistance + 1) {
392
+ const neighborSigma = sigma.get(neighbor) ?? 0;
393
+ sigma.set(neighbor, neighborSigma + currentSigma);
394
+
395
+ const preds = predecessors.get(neighbor) ?? [];
396
+ preds.push(current);
397
+ predecessors.set(neighbor, preds);
398
+ }
399
+ }
400
+ }
401
+
402
+ return {
403
+ distances,
404
+ predecessors,
405
+ sigma,
406
+ stack,
407
+ };
408
+ }
409
+
410
+ /**
411
+ * CSR-optimized version of bfsDistancesOnly
412
+ * @param graph - The CSR graph representation
413
+ * @param source - The source node to start BFS from
414
+ * @param cutoff - Maximum distance to explore (optional)
415
+ * @returns Map of node IDs to their shortest distances from the source
416
+ */
417
+ function bfsDistancesOnlyCSR(graph: CSRGraph, source: NodeId, cutoff?: number): Map<NodeId, number> {
418
+ // Use Direction-Optimized BFS for best performance
419
+ if (graph.nodeCount() > LARGE_GRAPH_THRESHOLD) {
420
+ const dobfs = new DirectionOptimizedBFS(graph);
421
+ const result = dobfs.search(source);
422
+
423
+ // Filter by cutoff if specified
424
+ if (cutoff !== undefined) {
425
+ const filtered = new Map<NodeId, number>();
426
+ for (const [nodeId, distance] of result.distances) {
427
+ if (distance <= cutoff) {
428
+ filtered.set(nodeId, distance);
429
+ }
430
+ }
431
+ return filtered;
432
+ }
433
+
434
+ return result.distances;
435
+ }
436
+
437
+ // Fallback to standard BFS on CSR
438
+ const distances = new Map<NodeId, number>();
439
+ const queue: NodeId[] = [];
440
+
441
+ distances.set(source, 0);
442
+ queue.push(source);
443
+
444
+ while (queue.length > 0) {
445
+ const current = queue.shift();
446
+ if (current === undefined) {
447
+ continue;
448
+ }
449
+
450
+ const currentDistance = distances.get(current) ?? 0;
451
+
452
+ // Stop if we've reached the cutoff distance
453
+ if (cutoff !== undefined && currentDistance >= cutoff) {
454
+ continue;
455
+ }
456
+
457
+ for (const neighbor of graph.neighbors(current)) {
458
+ if (!distances.has(neighbor)) {
459
+ distances.set(neighbor, currentDistance + 1);
460
+ queue.push(neighbor);
461
+ }
462
+ }
463
+ }
464
+
465
+ return distances;
466
+ }
467
+
468
+ /**
469
+ * CSR-optimized version of bfsWeightedDistances
470
+ * @param graph - The CSR graph representation
471
+ * @param source - The source node to start BFS from
472
+ * @param cutoff - Maximum distance to explore (optional)
473
+ * @returns Map of node IDs to their shortest weighted distances from the source
474
+ */
475
+ function bfsWeightedDistancesCSR(graph: CSRGraph, source: NodeId, cutoff?: number): Map<NodeId, number> {
476
+ const distances = new Map<NodeId, number>();
477
+ const visited = new Set<NodeId>();
478
+
479
+ // Use efficient priority queue
480
+ const queue = new PriorityQueue<NodeId>();
481
+
482
+ distances.set(source, 0);
483
+ queue.enqueue(source, 0);
484
+
485
+ while (!queue.isEmpty()) {
486
+ const current = queue.dequeue();
487
+ if (current === undefined) {
488
+ continue;
489
+ }
490
+
491
+ const currentDist = distances.get(current) ?? 0;
492
+
493
+ if (visited.has(current)) {
494
+ continue;
495
+ }
496
+
497
+ visited.add(current);
498
+
499
+ // Stop if we've reached the cutoff distance
500
+ if (cutoff !== undefined && currentDist >= cutoff) {
501
+ continue;
502
+ }
503
+
504
+ for (const neighbor of graph.neighbors(current)) {
505
+ if (!visited.has(neighbor)) {
506
+ // Use actual edge weight from CSR graph, default to 1
507
+ const weight = graph.getEdgeWeight(current, neighbor) ?? 1;
508
+ const newDistance = currentDist + weight;
509
+
510
+ const oldDistance = distances.get(neighbor);
511
+ if (oldDistance === undefined || newDistance < oldDistance) {
512
+ distances.set(neighbor, newDistance);
513
+ queue.enqueue(neighbor, newDistance);
514
+ }
515
+ }
516
+ }
517
+ }
518
+
519
+ return distances;
520
+ }