@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,580 @@
1
+ /* eslint-disable no-console */
2
+ /**
3
+ * Comprehensive benchmark suite for ALL 98 algorithms in @graphty/algorithms
4
+ *
5
+ * Two modes:
6
+ * - Full benchmark: Completes in under 1 hour
7
+ * - Quick benchmark: Completes in under 2 minutes
8
+ */
9
+
10
+ import * as algorithms from "./algorithms/index.js";
11
+ import { Graph } from "./core/graph.js";
12
+
13
+ interface BenchmarkResult {
14
+ algorithm: string;
15
+ category: string;
16
+ executionTime: number;
17
+ success: boolean;
18
+ error?: string;
19
+ nodeCount: number;
20
+ edgeCount: number;
21
+ mode: "quick" | "full";
22
+ }
23
+
24
+ const ALGORITHM_CATEGORIES = {
25
+ traversal: {
26
+ algorithms: [
27
+ "breadthFirstSearch",
28
+ "isBipartite",
29
+ "shortestPathBFS",
30
+ "singleSourceShortestPathBFS",
31
+ "depthFirstSearch",
32
+ "findStronglyConnectedComponents",
33
+ "hasCycleDFS",
34
+ "topologicalSort",
35
+ ],
36
+ config: {
37
+ name: "Traversal",
38
+ quick: { nodes: 1000, edges: 5000, runs: 3 },
39
+ full: { nodes: 10000, edges: 50000, runs: 10 },
40
+ },
41
+ },
42
+ shortestPath: {
43
+ algorithms: [
44
+ "bellmanFord",
45
+ "bellmanFordPath",
46
+ "hasNegativeCycle",
47
+ "allPairsShortestPath",
48
+ "dijkstra",
49
+ "dijkstraPath",
50
+ "singleSourceShortestPath",
51
+ "floydWarshall",
52
+ "floydWarshallPath",
53
+ "transitiveClosure",
54
+ ],
55
+ config: {
56
+ name: "Shortest Path",
57
+ quick: { nodes: 100, edges: 500, runs: 1 }, // Smaller for O(V³) algorithms
58
+ full: { nodes: 500, edges: 2500, runs: 3 },
59
+ },
60
+ },
61
+ centrality: {
62
+ algorithms: [
63
+ "betweennessCentrality",
64
+ "closenessCentrality",
65
+ "degreeCentrality",
66
+ "eigenvectorCentrality",
67
+ "hits",
68
+ "katzCentrality",
69
+ "pageRank",
70
+ "personalizedPageRank",
71
+ ],
72
+ config: {
73
+ name: "Centrality",
74
+ quick: { nodes: 500, edges: 2500, runs: 1 },
75
+ full: { nodes: 2000, edges: 10000, runs: 3 },
76
+ },
77
+ },
78
+ components: {
79
+ algorithms: [
80
+ "connectedComponents",
81
+ "connectedComponentsDFS",
82
+ "stronglyConnectedComponents",
83
+ "weaklyConnectedComponents",
84
+ "isConnected",
85
+ "isStronglyConnected",
86
+ "isWeaklyConnected",
87
+ "numberOfConnectedComponents",
88
+ "largestConnectedComponent",
89
+ "getConnectedComponent",
90
+ ],
91
+ config: {
92
+ name: "Components",
93
+ quick: { nodes: 2000, edges: 10000, runs: 3 },
94
+ full: { nodes: 10000, edges: 50000, runs: 10 },
95
+ },
96
+ },
97
+ mst: {
98
+ algorithms: ["kruskalMST", "primMST", "minimumSpanningTree"],
99
+ config: {
100
+ name: "Minimum Spanning Tree",
101
+ quick: { nodes: 1000, edges: 5000, runs: 5 },
102
+ full: { nodes: 5000, edges: 25000, runs: 10 },
103
+ },
104
+ },
105
+ community: {
106
+ algorithms: ["girvanNewman", "labelPropagation", "leiden", "louvain"],
107
+ config: {
108
+ name: "Community Detection",
109
+ quick: { nodes: 200, edges: 1000, runs: 1 }, // Very expensive algorithms
110
+ full: { nodes: 1000, edges: 5000, runs: 2 },
111
+ },
112
+ },
113
+ matching: {
114
+ algorithms: ["bipartitePartition", "greedyBipartiteMatching", "maximumBipartiteMatching"],
115
+ config: {
116
+ name: "Matching",
117
+ quick: { nodes: 500, edges: 1000, runs: 3 },
118
+ full: { nodes: 2000, edges: 4000, runs: 5 },
119
+ },
120
+ },
121
+ } as const;
122
+
123
+ /**
124
+ * Main benchmark runner
125
+ * @param mode - The benchmark mode: "quick" for fast tests or "full" for comprehensive tests
126
+ * @returns Array of benchmark results for all tested algorithms
127
+ */
128
+ export function runAllAlgorithmsBenchmark(mode: "quick" | "full" = "full"): BenchmarkResult[] {
129
+ const startTime = Date.now();
130
+ const timeLimit = mode === "quick" ? 2 * 60 * 1000 : 60 * 60 * 1000; // 2 min or 1 hour
131
+
132
+ console.log(
133
+ `šŸš€ ${mode === "quick" ? "Quick" : "Comprehensive"} Benchmark - All ${String(getTotalAlgorithmCount())} Algorithms`,
134
+ );
135
+ console.log(`=${"=".repeat(60)}`);
136
+ console.log(`Time limit: ${mode === "quick" ? "2 minutes" : "1 hour"}`);
137
+ console.log(`Start time: ${new Date().toLocaleTimeString()}\n`);
138
+
139
+ const results: BenchmarkResult[] = [];
140
+ let totalTested = 0;
141
+ let totalPassed = 0;
142
+
143
+ for (const [categoryKey, categoryData] of Object.entries(ALGORITHM_CATEGORIES)) {
144
+ const elapsed = Date.now() - startTime;
145
+ if (elapsed > timeLimit) {
146
+ console.log("ā° Time limit reached, stopping benchmark");
147
+ break;
148
+ }
149
+
150
+ console.log(`\nšŸ“Š ${categoryData.config.name} Algorithms`);
151
+ console.log("-".repeat(categoryData.config.name.length + 12));
152
+
153
+ const config = categoryData.config[mode];
154
+ const graph = createTestGraph(config.nodes, config.edges, categoryKey);
155
+
156
+ for (const algoName of categoryData.algorithms) {
157
+ const elapsed = Date.now() - startTime;
158
+ if (elapsed > timeLimit) {
159
+ console.log(`ā° Time limit reached in category ${categoryData.config.name}`);
160
+ break;
161
+ }
162
+
163
+ const result = benchmarkAlgorithm(algoName, categoryData.config.name, graph, config.runs, mode);
164
+ results.push(result);
165
+ totalTested++;
166
+
167
+ if (result.success) {
168
+ totalPassed++;
169
+ console.log(` āœ… ${algoName}: ${result.executionTime.toFixed(2)}ms`);
170
+ } else {
171
+ console.log(` āŒ ${algoName}: ${result.error?.substring(0, 50) ?? "Failed"}`);
172
+ }
173
+ }
174
+ }
175
+
176
+ const totalTime = (Date.now() - startTime) / 1000;
177
+
178
+ console.log("\nšŸ“ˆ Benchmark Complete");
179
+ console.log("===================");
180
+ console.log(`Total time: ${totalTime.toFixed(1)}s`);
181
+ console.log(`Algorithms tested: ${String(totalTested)}`);
182
+ console.log(
183
+ `Success rate: ${String(totalPassed)}/${String(totalTested)} (${((totalPassed / totalTested) * 100).toFixed(1)}%)`,
184
+ );
185
+
186
+ if (mode === "full") {
187
+ displayDetailedResults(results);
188
+ }
189
+
190
+ return results;
191
+ }
192
+
193
+ /**
194
+ * Benchmark a single algorithm
195
+ * @param algoName - The name of the algorithm to benchmark
196
+ * @param category - The category the algorithm belongs to
197
+ * @param graph - The test graph to run the algorithm on
198
+ * @param runs - Number of times to run the algorithm for averaging
199
+ * @param mode - The benchmark mode (quick or full)
200
+ * @returns The benchmark result containing timing and success information
201
+ */
202
+ function benchmarkAlgorithm(
203
+ algoName: string,
204
+ category: string,
205
+ graph: Graph,
206
+ runs: number,
207
+ mode: "quick" | "full",
208
+ ): BenchmarkResult {
209
+ const algo = (algorithms as Record<string, unknown>)[algoName];
210
+
211
+ if (!algo || typeof algo !== "function") {
212
+ return {
213
+ algorithm: algoName,
214
+ category,
215
+ executionTime: 0,
216
+ success: false,
217
+ error: "Algorithm not found or not a function",
218
+ nodeCount: graph.nodeCount,
219
+ edgeCount: graph.uniqueEdgeCount,
220
+ mode,
221
+ };
222
+ }
223
+
224
+ try {
225
+ const times: number[] = [];
226
+
227
+ for (let i = 0; i < runs; i++) {
228
+ const args = getAlgorithmArgs(algoName, graph);
229
+ const start = performance.now();
230
+
231
+ (algo as (...args: unknown[]) => unknown)(...args);
232
+
233
+ const time = performance.now() - start;
234
+ times.push(time);
235
+ }
236
+
237
+ // Use median time to avoid outliers
238
+ times.sort((a, b) => a - b);
239
+ const medianTime = times[Math.floor(times.length / 2)] ?? 0;
240
+
241
+ return {
242
+ algorithm: algoName,
243
+ category,
244
+ executionTime: medianTime,
245
+ success: true,
246
+ nodeCount: graph.nodeCount,
247
+ edgeCount: graph.uniqueEdgeCount,
248
+ mode,
249
+ };
250
+ } catch (error) {
251
+ return {
252
+ algorithm: algoName,
253
+ category,
254
+ executionTime: 0,
255
+ success: false,
256
+ error: error instanceof Error ? error.message : String(error),
257
+ nodeCount: graph.nodeCount,
258
+ edgeCount: graph.uniqueEdgeCount,
259
+ mode,
260
+ };
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Get appropriate arguments for each algorithm
266
+ * @param algoName - The name of the algorithm to get arguments for
267
+ * @param graph - The base graph to use for generating arguments
268
+ * @returns Array of arguments to pass to the algorithm function
269
+ */
270
+ function getAlgorithmArgs(algoName: string, graph: Graph): unknown[] {
271
+ // Get random nodes for algorithms that need them
272
+ const nodes = Array.from(graph.nodes()).map((n) => n.id);
273
+ const randomNode = nodes[Math.floor(Math.random() * nodes.length)];
274
+ const randomNode2 = nodes[Math.floor(Math.random() * nodes.length)];
275
+
276
+ // Algorithm-specific argument mapping
277
+ switch (algoName) {
278
+ // Single source algorithms
279
+ case "breadthFirstSearch":
280
+ case "depthFirstSearch":
281
+ case "singleSourceShortestPathBFS":
282
+ case "singleSourceShortestPath":
283
+ case "dijkstra":
284
+ case "bellmanFord":
285
+ return [graph, randomNode];
286
+
287
+ // PageRank algorithms need directed graph
288
+ case "pageRank": {
289
+ const directedForPR = createDirectedGraph(graph);
290
+ return [directedForPR];
291
+ }
292
+
293
+ case "personalizedPageRank": {
294
+ const directedForPPR = createDirectedGraph(graph);
295
+ const personalNodes = [randomNode]; // Array of nodes for personalization
296
+ return [directedForPPR, personalNodes];
297
+ }
298
+
299
+ // Two node algorithms
300
+ case "shortestPathBFS":
301
+ case "dijkstraPath":
302
+ case "bellmanFordPath":
303
+ return [graph, randomNode, randomNode2];
304
+
305
+ // Component-specific algorithms
306
+ case "getConnectedComponent":
307
+ return [graph, randomNode];
308
+
309
+ // Algorithms that need specific graph types
310
+ case "topologicalSort":
311
+ case "findStronglyConnectedComponents":
312
+ case "stronglyConnectedComponents":
313
+ case "weaklyConnectedComponents":
314
+ case "isStronglyConnected":
315
+ case "isWeaklyConnected": {
316
+ // Create a directed version of the graph for these algorithms
317
+ const directedGraph = createDirectedGraph(graph);
318
+ return [directedGraph];
319
+ }
320
+
321
+ // Bipartite algorithms need bipartite graphs
322
+ case "bipartitePartition":
323
+ case "greedyBipartiteMatching":
324
+ case "maximumBipartiteMatching": {
325
+ const bipartiteGraph = createBipartiteGraph(Math.floor(graph.nodeCount / 2));
326
+ return [bipartiteGraph];
327
+ }
328
+
329
+ // Community detection algorithms
330
+ case "labelPropagation":
331
+ case "leiden":
332
+ case "louvain":
333
+ case "girvanNewman":
334
+ return [graph, {}]; // Pass empty options
335
+
336
+ // Default: just the graph
337
+ default:
338
+ return [graph];
339
+ }
340
+ }
341
+
342
+ /**
343
+ * Create test graph appropriate for each algorithm category
344
+ * @param nodes - Number of nodes in the test graph
345
+ * @param edges - Target number of edges in the test graph
346
+ * @param category - The algorithm category to optimize the graph structure for
347
+ * @returns A new test graph with the specified structure
348
+ */
349
+ function createTestGraph(nodes: number, edges: number, category: string): Graph {
350
+ const graph = new Graph();
351
+
352
+ // Add nodes
353
+ for (let i = 0; i < nodes; i++) {
354
+ graph.addNode(i);
355
+ }
356
+
357
+ // Create different graph structures for different algorithm categories
358
+ switch (category) {
359
+ case "shortestPath":
360
+ // Sparse connected graph for shortest path algorithms
361
+ createConnectedGraph(graph, Math.min(edges, nodes * 3));
362
+ break;
363
+
364
+ case "centrality":
365
+ // Small-world graph good for centrality analysis
366
+ createSmallWorldGraph(graph, Math.floor(edges / nodes));
367
+ break;
368
+
369
+ case "community":
370
+ // Graph with community structure
371
+ createCommunityGraph(graph, edges);
372
+ break;
373
+
374
+ default:
375
+ // Random connected graph
376
+ createConnectedGraph(graph, edges);
377
+ }
378
+
379
+ return graph;
380
+ }
381
+
382
+ /**
383
+ * Create a connected random graph
384
+ * @param graph - The graph to add edges to
385
+ * @param targetEdges - Target number of edges to create
386
+ */
387
+ function createConnectedGraph(graph: Graph, targetEdges: number): void {
388
+ const nodes = graph.nodeCount;
389
+
390
+ // First create a spanning tree to ensure connectivity
391
+ for (let i = 1; i < nodes; i++) {
392
+ const parent = Math.floor(Math.random() * i);
393
+ graph.addEdge(parent, i);
394
+ }
395
+
396
+ // Add remaining edges randomly
397
+ let edgesAdded = nodes - 1;
398
+ while (edgesAdded < targetEdges) {
399
+ const source = Math.floor(Math.random() * nodes);
400
+ const target = Math.floor(Math.random() * nodes);
401
+
402
+ if (source !== target && !graph.hasEdge(source, target)) {
403
+ graph.addEdge(source, target);
404
+ edgesAdded++;
405
+ }
406
+ }
407
+ }
408
+
409
+ /**
410
+ * Create small-world graph (Watts-Strogatz model)
411
+ * @param graph - The graph to add edges to
412
+ * @param avgDegree - Target average degree for each node
413
+ */
414
+ function createSmallWorldGraph(graph: Graph, avgDegree: number): void {
415
+ const nodes = graph.nodeCount;
416
+ const k = Math.floor(avgDegree / 2);
417
+
418
+ // Ring lattice
419
+ for (let i = 0; i < nodes; i++) {
420
+ for (let j = 1; j <= k; j++) {
421
+ const target = (i + j) % nodes;
422
+ graph.addEdge(i, target);
423
+ }
424
+ }
425
+
426
+ // Rewire some edges
427
+ const rewireProb = 0.1;
428
+ for (let i = 0; i < nodes; i++) {
429
+ for (let j = 1; j <= k; j++) {
430
+ if (Math.random() < rewireProb) {
431
+ const oldTarget = (i + j) % nodes;
432
+ const newTarget = Math.floor(Math.random() * nodes);
433
+ if (newTarget !== i && !graph.hasEdge(i, newTarget)) {
434
+ graph.removeEdge(i, oldTarget);
435
+ graph.addEdge(i, newTarget);
436
+ }
437
+ }
438
+ }
439
+ }
440
+ }
441
+
442
+ /**
443
+ * Create graph with community structure
444
+ * @param graph - The graph to add edges to
445
+ * @param targetEdges - Target number of edges to create
446
+ */
447
+ function createCommunityGraph(graph: Graph, targetEdges: number): void {
448
+ const nodes = graph.nodeCount;
449
+ const communities = Math.min(5, Math.floor(nodes / 20)); // 5 communities max
450
+ const communitySize = Math.floor(nodes / communities);
451
+
452
+ let edgesAdded = 0;
453
+
454
+ // Create dense connections within communities
455
+ for (let c = 0; c < communities; c++) {
456
+ const start = c * communitySize;
457
+ const end = Math.min((c + 1) * communitySize, nodes);
458
+
459
+ for (let i = start; i < end && edgesAdded < targetEdges; i++) {
460
+ for (let j = i + 1; j < end && edgesAdded < targetEdges; j++) {
461
+ if (Math.random() < 0.8) {
462
+ // High probability within community
463
+ graph.addEdge(i, j);
464
+ edgesAdded++;
465
+ }
466
+ }
467
+ }
468
+ }
469
+
470
+ // Add sparse connections between communities
471
+ while (edgesAdded < targetEdges) {
472
+ const source = Math.floor(Math.random() * nodes);
473
+ const target = Math.floor(Math.random() * nodes);
474
+
475
+ if (source !== target && !graph.hasEdge(source, target)) {
476
+ graph.addEdge(source, target);
477
+ edgesAdded++;
478
+ }
479
+ }
480
+ }
481
+
482
+ /**
483
+ * Create directed version of graph
484
+ * @param undirectedGraph - The undirected graph to convert
485
+ * @returns A new directed graph with the same nodes and edges
486
+ */
487
+ function createDirectedGraph(undirectedGraph: Graph): Graph {
488
+ const directedGraph = new Graph({ directed: true });
489
+
490
+ // Copy nodes
491
+ for (const node of undirectedGraph.nodes()) {
492
+ directedGraph.addNode(node.id);
493
+ }
494
+
495
+ // Copy edges as directed
496
+ for (const edge of undirectedGraph.edges()) {
497
+ directedGraph.addEdge(edge.source, edge.target);
498
+ }
499
+
500
+ return directedGraph;
501
+ }
502
+
503
+ /**
504
+ * Create bipartite graph
505
+ * @param nodesPerPartition - Number of nodes in each partition
506
+ * @returns A new bipartite graph with sparse connections between partitions
507
+ */
508
+ function createBipartiteGraph(nodesPerPartition: number): Graph {
509
+ const graph = new Graph();
510
+
511
+ // Add nodes (0 to n-1 in first partition, n to 2n-1 in second)
512
+ for (let i = 0; i < nodesPerPartition * 2; i++) {
513
+ graph.addNode(i);
514
+ }
515
+
516
+ // Add edges only between partitions
517
+ for (let i = 0; i < nodesPerPartition; i++) {
518
+ for (let j = nodesPerPartition; j < nodesPerPartition * 2; j++) {
519
+ if (Math.random() < 0.3) {
520
+ // Sparse bipartite graph
521
+ graph.addEdge(i, j);
522
+ }
523
+ }
524
+ }
525
+
526
+ return graph;
527
+ }
528
+
529
+ /**
530
+ * Get total algorithm count
531
+ * @returns The total number of algorithms across all categories
532
+ */
533
+ function getTotalAlgorithmCount(): number {
534
+ return Object.values(ALGORITHM_CATEGORIES).reduce((total, category) => total + category.algorithms.length, 0);
535
+ }
536
+
537
+ /**
538
+ * Display detailed results for full benchmark
539
+ * @param results - Array of benchmark results to display
540
+ */
541
+ function displayDetailedResults(results: BenchmarkResult[]): void {
542
+ console.log("\nšŸ“Š Detailed Results");
543
+ console.log("==================");
544
+
545
+ const categories = new Map<string, BenchmarkResult[]>();
546
+
547
+ for (const result of results) {
548
+ if (!categories.has(result.category)) {
549
+ categories.set(result.category, []);
550
+ }
551
+
552
+ categories.get(result.category)?.push(result);
553
+ }
554
+
555
+ for (const [category, categoryResults] of categories) {
556
+ console.log(`\n${category}:`);
557
+ console.log("-".repeat(category.length + 1));
558
+
559
+ const successful = categoryResults.filter((r) => r.success);
560
+ const failed = categoryResults.filter((r) => !r.success);
561
+
562
+ if (successful.length > 0) {
563
+ const avgTime = successful.reduce((sum, r) => sum + r.executionTime, 0) / successful.length;
564
+ console.log(` Average time: ${avgTime.toFixed(2)}ms`);
565
+ const minTime = Math.min(...successful.map((r) => r.executionTime));
566
+ const maxTime = Math.max(...successful.map((r) => r.executionTime));
567
+ console.log(` Range: ${minTime.toFixed(2)}ms - ${maxTime.toFixed(2)}ms`);
568
+ }
569
+
570
+ if (failed.length > 0) {
571
+ console.log(` Failed algorithms: ${failed.map((r) => r.algorithm).join(", ")}`);
572
+ }
573
+ }
574
+ }
575
+
576
+ // Run benchmark if called directly
577
+ if (typeof process !== "undefined" && import.meta.url === `file://${process.argv[1] ?? ""}`) {
578
+ const mode = process.argv.includes("--quick") ? "quick" : "full";
579
+ runAllAlgorithmsBenchmark(mode);
580
+ }