@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,310 @@
1
+ import type { NodeId } from "../types/index.js";
2
+ import { CompactDistanceArray, GraphBitSet } from "./bit-packed.js";
3
+ import { CSRGraph } from "./csr-graph.js";
4
+
5
+ /**
6
+ * Options for Direction-Optimized BFS
7
+ */
8
+ export interface DirectionOptimizedBFSOptions {
9
+ alpha?: number; // Default: 15 - Controls top-down to bottom-up switch
10
+ beta?: number; // Default: 18 - Controls bottom-up to top-down switch
11
+ }
12
+
13
+ /**
14
+ * Result of BFS traversal
15
+ */
16
+ export interface BFSResult<TNodeId> {
17
+ distances: Map<TNodeId, number>;
18
+ parents: Map<TNodeId, TNodeId | null>;
19
+ visitedCount: number;
20
+ }
21
+
22
+ /**
23
+ * Direction-Optimized Breadth-First Search
24
+ *
25
+ * Dynamically switches between top-down and bottom-up search strategies
26
+ * based on the size of the frontier. Particularly effective for low-diameter
27
+ * graphs like social networks.
28
+ *
29
+ * Based on: Beamer, S., Asanović, K., & Patterson, D. (2012).
30
+ * "Direction-optimizing breadth-first search." SC'12.
31
+ */
32
+ export class DirectionOptimizedBFS<TNodeId = NodeId> {
33
+ private graph: CSRGraph<TNodeId>;
34
+ private alpha: number;
35
+ private beta: number;
36
+
37
+ // Data structures
38
+ private parent: Int32Array; // -1 = unvisited, -2 = source, else parent ID
39
+ private frontier: GraphBitSet; // Current frontier bitmap
40
+ private nextFrontier: GraphBitSet; // Next level frontier
41
+ private distances: CompactDistanceArray;
42
+
43
+ /**
44
+ * Creates a new DirectionOptimizedBFS instance.
45
+ * @param graph - The CSR graph to perform BFS on
46
+ * @param options - Optional configuration for switching thresholds
47
+ */
48
+ constructor(graph: CSRGraph<TNodeId>, options?: DirectionOptimizedBFSOptions) {
49
+ this.graph = graph;
50
+ this.alpha = options?.alpha ?? 15;
51
+ this.beta = options?.beta ?? 18;
52
+
53
+ const nodeCount = graph.nodeCount();
54
+ this.parent = new Int32Array(nodeCount).fill(-1);
55
+ this.frontier = new GraphBitSet(nodeCount);
56
+ this.nextFrontier = new GraphBitSet(nodeCount);
57
+ this.distances = new CompactDistanceArray(nodeCount);
58
+ }
59
+
60
+ /**
61
+ * Perform BFS from a single source node.
62
+ * @param source - The source node ID to start the BFS from
63
+ * @returns The BFS result containing distances and parent pointers
64
+ */
65
+ search(source: TNodeId): BFSResult<TNodeId> {
66
+ const sourceIndex = this.graph.nodeToIndex(source);
67
+ this.parent[sourceIndex] = -2; // Mark as source
68
+ this.frontier.add(sourceIndex);
69
+ this.distances.set(sourceIndex, 0);
70
+
71
+ // let currentDistance = 0; // Variable not used
72
+ // Initialize edgesToCheck to total edges to prevent immediate switch to bottom-up
73
+ let edgesToCheck = this.graph.edgeCount();
74
+ let scoutCount = 0; // Will be set after first top-down step
75
+ let awakeCount = 1; // Number of nodes in current frontier
76
+ let oldAwakeCount = 0;
77
+
78
+ // Direction tracking
79
+ let useBottomUp = false;
80
+
81
+ while (!this.frontier.isEmpty()) {
82
+ oldAwakeCount = awakeCount;
83
+
84
+ if (useBottomUp) {
85
+ // Check if we should switch back to top-down
86
+ if (awakeCount >= oldAwakeCount || awakeCount > this.graph.nodeCount() / this.beta) {
87
+ useBottomUp = false;
88
+ }
89
+ } else {
90
+ // Check if we should switch to bottom-up
91
+ if (scoutCount > edgesToCheck / this.alpha) {
92
+ useBottomUp = true;
93
+ }
94
+ }
95
+
96
+ if (useBottomUp) {
97
+ awakeCount = this.bottomUpStep();
98
+ } else {
99
+ scoutCount = this.topDownStep();
100
+ awakeCount = this.nextFrontier.size();
101
+ }
102
+
103
+ // Swap frontiers
104
+ this.frontier.swap(this.nextFrontier);
105
+ this.nextFrontier.clear();
106
+
107
+ // currentDistance++; // Variable not used
108
+ edgesToCheck = this.calculateEdgesToCheck();
109
+ }
110
+
111
+ return this.buildResult();
112
+ }
113
+
114
+ /**
115
+ * Top-down BFS step - explore from frontier.
116
+ * @returns The scout count (total degree of newly discovered nodes)
117
+ */
118
+ private topDownStep(): number {
119
+ let scoutCount = 0;
120
+
121
+ // Iterate through frontier nodes
122
+ for (const node of this.frontier) {
123
+ const currentDistance = this.distances.get(node);
124
+
125
+ for (const neighbor of this.graph.iterateNeighborIndices(node)) {
126
+ if (this.parent[neighbor] === -1) {
127
+ this.parent[neighbor] = node;
128
+ this.distances.set(neighbor, currentDistance + 1);
129
+ this.nextFrontier.add(neighbor);
130
+ scoutCount += this.graph.outDegreeByIndex(neighbor);
131
+ }
132
+ }
133
+ }
134
+
135
+ return scoutCount;
136
+ }
137
+
138
+ /**
139
+ * Bottom-up BFS step - check unvisited nodes for frontier neighbors.
140
+ * @returns The number of newly discovered nodes
141
+ */
142
+ private bottomUpStep(): number {
143
+ const nodeCount = this.graph.nodeCount();
144
+ let awakeCount = 0;
145
+
146
+ // Check all unvisited nodes
147
+ for (let node = 0; node < nodeCount; node++) {
148
+ if (this.parent[node] === -1) {
149
+ // Use incoming edges for bottom-up traversal
150
+ for (const neighbor of this.graph.iterateIncomingNeighborIndices(node)) {
151
+ if (this.frontier.has(neighbor)) {
152
+ this.parent[node] = neighbor;
153
+ const neighborDist = this.distances.get(neighbor);
154
+ this.distances.set(node, neighborDist + 1);
155
+ this.nextFrontier.add(node);
156
+ awakeCount++;
157
+ break; // Found a parent, no need to check more
158
+ }
159
+ }
160
+ }
161
+ }
162
+
163
+ return awakeCount;
164
+ }
165
+
166
+ /**
167
+ * Calculate edges to check for switching heuristic.
168
+ * @returns The total number of outgoing edges from frontier nodes
169
+ */
170
+ private calculateEdgesToCheck(): number {
171
+ let count = 0;
172
+ for (const node of this.frontier) {
173
+ count += this.graph.outDegreeByIndex(node);
174
+ }
175
+ return count;
176
+ }
177
+
178
+ /**
179
+ * Build result map from internal data structures.
180
+ * @returns The BFS result containing distances and parent pointers
181
+ */
182
+ private buildResult(): BFSResult<TNodeId> {
183
+ const distances = new Map<TNodeId, number>();
184
+ const parents = new Map<TNodeId, TNodeId | null>();
185
+ let visitedCount = 0;
186
+
187
+ for (let i = 0; i < this.graph.nodeCount(); i++) {
188
+ if (this.parent[i] !== -1) {
189
+ const nodeId = this.graph.indexToNodeId(i);
190
+ distances.set(nodeId, this.distances.get(i));
191
+
192
+ if (this.parent[i] === -2) {
193
+ // Source node
194
+ parents.set(nodeId, null);
195
+ } else {
196
+ // Regular node with parent
197
+ const parentIndex = this.parent[i];
198
+ if (parentIndex !== undefined && parentIndex >= 0) {
199
+ parents.set(nodeId, this.graph.indexToNodeId(parentIndex));
200
+ }
201
+ }
202
+
203
+ visitedCount++;
204
+ }
205
+ }
206
+
207
+ return { distances, parents, visitedCount };
208
+ }
209
+
210
+ /**
211
+ * Perform multi-source BFS from multiple source nodes.
212
+ * @param sources - Array of source node IDs to start the BFS from
213
+ * @returns The BFS result containing distances and parent pointers
214
+ */
215
+ searchMultiple(sources: TNodeId[]): BFSResult<TNodeId> {
216
+ // Initialize multiple sources
217
+ for (const source of sources) {
218
+ const sourceIndex = this.graph.nodeToIndex(source);
219
+ this.parent[sourceIndex] = -2; // Mark as source
220
+ this.frontier.add(sourceIndex);
221
+ this.distances.set(sourceIndex, 0);
222
+ }
223
+
224
+ // let currentDistance = 0; // Variable not used
225
+ let edgesToCheck = 0;
226
+ let scoutCount = 0;
227
+
228
+ // Calculate initial edges to check
229
+ for (const node of this.frontier) {
230
+ const degree = this.graph.outDegreeByIndex(node);
231
+ edgesToCheck += degree;
232
+ scoutCount += degree;
233
+ }
234
+
235
+ let awakeCount = sources.length;
236
+ let oldAwakeCount = 0;
237
+ let useBottomUp = false;
238
+
239
+ while (!this.frontier.isEmpty()) {
240
+ oldAwakeCount = awakeCount;
241
+
242
+ if (useBottomUp) {
243
+ if (awakeCount >= oldAwakeCount || awakeCount > this.graph.nodeCount() / this.beta) {
244
+ useBottomUp = false;
245
+ }
246
+ } else {
247
+ if (scoutCount > edgesToCheck / this.alpha) {
248
+ useBottomUp = true;
249
+ }
250
+ }
251
+
252
+ if (useBottomUp) {
253
+ awakeCount = this.bottomUpStep();
254
+ } else {
255
+ scoutCount = this.topDownStep();
256
+ awakeCount = this.nextFrontier.size();
257
+ }
258
+
259
+ this.frontier.swap(this.nextFrontier);
260
+ this.nextFrontier.clear();
261
+
262
+ // currentDistance++; // Variable not used
263
+ edgesToCheck = this.calculateEdgesToCheck();
264
+ }
265
+
266
+ return this.buildResult();
267
+ }
268
+
269
+ /**
270
+ * Reset internal state for reuse
271
+ */
272
+ reset(): void {
273
+ this.parent.fill(-1);
274
+ this.frontier.clear();
275
+ this.nextFrontier.clear();
276
+ this.distances.clear();
277
+ }
278
+ }
279
+
280
+ /**
281
+ * Convenience function for single-source BFS.
282
+ * @param graph - The CSR graph to perform BFS on
283
+ * @param source - The source node ID to start the BFS from
284
+ * @param options - Optional configuration for switching thresholds
285
+ * @returns The BFS result containing distances and parent pointers
286
+ */
287
+ export function directionOptimizedBFS<TNodeId = NodeId>(
288
+ graph: CSRGraph<TNodeId>,
289
+ source: TNodeId,
290
+ options?: DirectionOptimizedBFSOptions,
291
+ ): BFSResult<TNodeId> {
292
+ const bfs = new DirectionOptimizedBFS(graph, options);
293
+ return bfs.search(source);
294
+ }
295
+
296
+ /**
297
+ * Convenience function for multi-source BFS.
298
+ * @param graph - The CSR graph to perform BFS on
299
+ * @param sources - Array of source node IDs to start the BFS from
300
+ * @param options - Optional configuration for switching thresholds
301
+ * @returns The BFS result containing distances and parent pointers
302
+ */
303
+ export function directionOptimizedBFSMultiple<TNodeId = NodeId>(
304
+ graph: CSRGraph<TNodeId>,
305
+ sources: TNodeId[],
306
+ options?: DirectionOptimizedBFSOptions,
307
+ ): BFSResult<TNodeId> {
308
+ const bfs = new DirectionOptimizedBFS(graph, options);
309
+ return bfs.searchMultiple(sources);
310
+ }
@@ -0,0 +1,248 @@
1
+ import type { Graph } from "../core/graph.js";
2
+ import type { NodeId } from "../types/index.js";
3
+ import { CSRGraph, type ReadonlyGraph } from "./csr-graph.js";
4
+
5
+ /**
6
+ * Adapter to convert standard Graph to CSR format
7
+ *
8
+ * Provides transparent conversion while maintaining API compatibility
9
+ */
10
+ export class GraphAdapter<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
11
+ private csrGraph: CSRGraph<TNodeId>;
12
+
13
+ /**
14
+ * Creates a new GraphAdapter that wraps or converts a graph to CSR format.
15
+ * @param graph - The graph to adapt (either standard Graph or ReadonlyGraph)
16
+ */
17
+ constructor(graph: Graph | ReadonlyGraph<TNodeId>) {
18
+ // Check if already a CSRGraph
19
+ if (graph instanceof CSRGraph) {
20
+ this.csrGraph = graph as CSRGraph<TNodeId>;
21
+ } else {
22
+ // Convert to CSR format
23
+ this.csrGraph = this.convertToCSR(graph);
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Convert standard graph to CSR format.
29
+ * @param graph - The graph to convert
30
+ * @returns A new CSRGraph instance
31
+ */
32
+ private convertToCSR(graph: Graph | ReadonlyGraph<TNodeId>): CSRGraph<TNodeId> {
33
+ const adjacencyList = new Map<TNodeId, TNodeId[]>();
34
+ const weights = new Map<string, number>();
35
+
36
+ // Handle both Graph and ReadonlyGraph interfaces
37
+ if ("nodes" in graph && typeof graph.nodes === "function") {
38
+ // Build adjacency list from Graph
39
+ for (const node of graph.nodes()) {
40
+ const nodeId = (node as { id: TNodeId }).id;
41
+ const neighbors: TNodeId[] = [];
42
+
43
+ const graphTyped = graph as Graph;
44
+ for (const neighborId of graphTyped.neighbors(nodeId as NodeId)) {
45
+ neighbors.push(neighborId as TNodeId);
46
+
47
+ // Get edge weight if available
48
+ if ("getEdge" in graph && typeof graph.getEdge === "function") {
49
+ const edge = graphTyped.getEdge(nodeId as NodeId, neighborId);
50
+ if (edge?.weight !== undefined) {
51
+ weights.set(`${String(nodeId)}-${String(neighborId)}`, edge.weight);
52
+ }
53
+ }
54
+ }
55
+
56
+ adjacencyList.set(nodeId, neighbors);
57
+ }
58
+ } else if ("nodeIds" in graph && typeof graph.nodeIds === "function") {
59
+ // Handle ReadonlyGraph with nodeIds method
60
+ interface ReadonlyGraphWithNodeIds {
61
+ nodeIds(): Iterable<TNodeId>;
62
+ edges?(): Iterable<{ source: TNodeId; target: TNodeId; weight?: number }>;
63
+ }
64
+ const readonlyGraph = graph as ReadonlyGraphWithNodeIds;
65
+ for (const nodeId of readonlyGraph.nodeIds()) {
66
+ adjacencyList.set(nodeId, []);
67
+ }
68
+
69
+ // Build adjacency from edges
70
+ if ("edges" in readonlyGraph && typeof readonlyGraph.edges === "function") {
71
+ for (const edge of readonlyGraph.edges()) {
72
+ const neighbors = adjacencyList.get(edge.source);
73
+ if (neighbors) {
74
+ neighbors.push(edge.target);
75
+ if (edge.weight !== undefined) {
76
+ weights.set(`${String(edge.source)}-${String(edge.target)}`, edge.weight);
77
+ }
78
+ }
79
+ }
80
+ }
81
+ }
82
+
83
+ return new CSRGraph(adjacencyList, weights.size > 0 ? weights : undefined);
84
+ }
85
+
86
+ // Delegate all methods to CSR implementation
87
+ /**
88
+ * Get the total number of nodes in the graph.
89
+ * @returns The number of nodes
90
+ */
91
+ nodeCount(): number {
92
+ return this.csrGraph.nodeCount();
93
+ }
94
+
95
+ /**
96
+ * Get the total number of edges in the graph.
97
+ * @returns The number of edges
98
+ */
99
+ edgeCount(): number {
100
+ return this.csrGraph.edgeCount();
101
+ }
102
+
103
+ /**
104
+ * Check if a node exists in the graph.
105
+ * @param nodeId - The node ID to check
106
+ * @returns True if the node exists, false otherwise
107
+ */
108
+ hasNode(nodeId: TNodeId): boolean {
109
+ return this.csrGraph.hasNode(nodeId);
110
+ }
111
+
112
+ /**
113
+ * Check if an edge exists between two nodes.
114
+ * @param source - The source node ID
115
+ * @param target - The target node ID
116
+ * @returns True if the edge exists, false otherwise
117
+ */
118
+ hasEdge(source: TNodeId, target: TNodeId): boolean {
119
+ return this.csrGraph.hasEdge(source, target);
120
+ }
121
+
122
+ /**
123
+ * Get neighbors of a node as node IDs.
124
+ * @param nodeId - The node ID to get neighbors for
125
+ * @returns An iterator over neighbor node IDs
126
+ */
127
+ neighbors(nodeId: TNodeId): IterableIterator<TNodeId> {
128
+ return this.csrGraph.neighbors(nodeId);
129
+ }
130
+
131
+ /**
132
+ * Get the out-degree (number of outgoing edges) of a node.
133
+ * @param nodeId - The node ID to get the out-degree for
134
+ * @returns The number of outgoing edges from the node
135
+ */
136
+ outDegree(nodeId: TNodeId): number {
137
+ return this.csrGraph.outDegree(nodeId);
138
+ }
139
+
140
+ /**
141
+ * Get all nodes in the graph.
142
+ * @returns An iterator over all node IDs
143
+ */
144
+ nodes(): IterableIterator<TNodeId> {
145
+ return this.csrGraph.nodes();
146
+ }
147
+
148
+ /**
149
+ * Get the underlying CSR graph.
150
+ * @returns The CSRGraph instance used internally
151
+ */
152
+ getCSRGraph(): CSRGraph<TNodeId> {
153
+ return this.csrGraph;
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Configuration for graph algorithm optimizations
159
+ */
160
+ export interface GraphAlgorithmConfig {
161
+ // Enable optimizations
162
+ useDirectionOptimizedBFS?: boolean;
163
+ useCSRFormat?: boolean;
164
+ useBitPackedStructures?: boolean;
165
+
166
+ // Algorithm-specific parameters
167
+ bfsAlpha?: number;
168
+ bfsBeta?: number;
169
+
170
+ // Memory vs speed tradeoffs
171
+ preallocateSize?: number;
172
+ enableCaching?: boolean;
173
+ }
174
+
175
+ /**
176
+ * Configure optimizations globally.
177
+ * @deprecated This function is a no-op and will be removed in a future version
178
+ * @param _config - The configuration object (ignored)
179
+ */
180
+ export function configureOptimizations(_config: GraphAlgorithmConfig): void {
181
+ // No-op for backward compatibility
182
+ }
183
+
184
+ /**
185
+ * Get current configuration.
186
+ * @deprecated This function returns empty config and will be removed in a future version
187
+ * @returns An empty configuration object
188
+ */
189
+ export function getOptimizationConfig(): GraphAlgorithmConfig {
190
+ return {};
191
+ }
192
+
193
+ /**
194
+ * Check if a graph is already in CSR format.
195
+ * @param graph - The graph to check
196
+ * @returns True if the graph is a CSRGraph instance
197
+ */
198
+ export function isCSRGraph<TNodeId = NodeId>(graph: unknown): graph is CSRGraph<TNodeId> {
199
+ return graph instanceof CSRGraph;
200
+ }
201
+
202
+ /**
203
+ * Convert any graph to CSR format.
204
+ * @param graph - The graph to convert
205
+ * @returns A CSRGraph instance (either the original if already CSR, or a new converted one)
206
+ */
207
+ export function toCSRGraph<TNodeId = NodeId>(
208
+ graph: Graph | ReadonlyGraph<TNodeId> | CSRGraph<TNodeId>,
209
+ ): CSRGraph<TNodeId> {
210
+ if (isCSRGraph<TNodeId>(graph)) {
211
+ return graph;
212
+ }
213
+
214
+ const adapter = new GraphAdapter<TNodeId>(graph);
215
+ return adapter.getCSRGraph();
216
+ }
217
+
218
+ /**
219
+ * Create an optimized graph from nodes and edges.
220
+ * @param nodes - Array of node IDs
221
+ * @param edges - Array of edge tuples [source, target, weight?]
222
+ * @returns A new CSRGraph instance
223
+ */
224
+ export function createOptimizedGraph<TNodeId = NodeId>(
225
+ nodes: TNodeId[],
226
+ edges: [TNodeId, TNodeId, number?][],
227
+ ): CSRGraph<TNodeId> {
228
+ const adjacencyList = new Map<TNodeId, TNodeId[]>();
229
+ const weights = new Map<string, number>();
230
+
231
+ // Initialize nodes
232
+ for (const node of nodes) {
233
+ adjacencyList.set(node, []);
234
+ }
235
+
236
+ // Add edges
237
+ for (const [source, target, weight] of edges) {
238
+ const neighbors = adjacencyList.get(source);
239
+ if (neighbors) {
240
+ neighbors.push(target);
241
+ if (weight !== undefined) {
242
+ weights.set(`${String(source)}-${String(target)}`, weight);
243
+ }
244
+ }
245
+ }
246
+
247
+ return new CSRGraph(adjacencyList, weights.size > 0 ? weights : undefined);
248
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Optimized graph algorithm implementations
3
+ *
4
+ * High-performance implementations using:
5
+ * - Direction-Optimized BFS
6
+ * - Compressed Sparse Row (CSR) format
7
+ * - Bit-packed data structures
8
+ */
9
+
10
+ // Configuration and optimization control
11
+ // These deprecated functions are intentionally re-exported for backward compatibility
12
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
13
+ export { configureOptimizations, getOptimizationConfig, type GraphAlgorithmConfig } from "./graph-adapter.js";
14
+
15
+ // Note: The main BFS functions in algorithms/traversal/bfs.ts automatically
16
+ // use these optimizations for large graphs (>10k nodes) when optimizations are enabled.
17
+ // No manual configuration needed - just use breadthFirstSearch, shortestPathBFS, etc.
18
+ //
19
+ // The previously exported bfsOptimized, shortestPathBFSOptimized, and
20
+ // singleSourceShortestPathBFSOptimized functions have been removed since they
21
+ // are no longer needed. All optimization happens automatically.
22
+
23
+ // BFS optimization functions have been removed. The main BFS functions
24
+ // (breadthFirstSearch, shortestPathBFS, singleSourceShortestPathBFS)
25
+ // in algorithms/traversal/bfs.ts now automatically use optimizations
26
+ // for large graphs without requiring manual configuration.
27
+
28
+ // Export data structures for advanced users
29
+ export { CompactDistanceArray, GraphBitSet, VisitedBitArray } from "./bit-packed.js";
30
+ export { CSRGraph } from "./csr-graph.js";
31
+ export { DirectionOptimizedBFS } from "./direction-optimized-bfs.js";
32
+
33
+ // Export utilities
34
+ export { createOptimizedGraph, isCSRGraph, toCSRGraph } from "./graph-adapter.js";