@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
@@ -1,5 +1,6 @@
1
- import type {Graph} from "../../core/graph.js";
2
- import type {NodeId} from "../../types/index.js";
1
+ import type { Graph } from "../../core/graph.js";
2
+ import type { NodeId } from "../../types/index.js";
3
+ import { bfsDistancesOnly, bfsWeightedDistances } from "../traversal/bfs-variants.js";
3
4
 
4
5
  /**
5
6
  * Closeness centrality implementation
@@ -25,39 +26,26 @@ export interface ClosenessCentralityOptions {
25
26
  * Consider only nodes within this distance (default: undefined = all nodes)
26
27
  */
27
28
  cutoff?: number;
29
+ /**
30
+ * Whether to use optimized BFS implementation for large graphs
31
+ */
32
+ optimized?: boolean;
28
33
  }
29
34
 
30
35
  /**
31
- * Calculate closeness centrality for all nodes
32
- */
33
- export function closenessCentrality(
34
- graph: Graph,
35
- options: ClosenessCentralityOptions = {},
36
- ): Record<string, number> {
37
- const nodes = Array.from(graph.nodes()).map((node) => node.id);
38
- const centrality: Record<string, number> = {};
39
-
40
- for (const sourceNode of nodes) {
41
- centrality[String(sourceNode)] = nodeClosenessCentrality(graph, sourceNode, options);
42
- }
43
-
44
- return centrality;
45
- }
46
-
47
- /**
48
- * Calculate closeness centrality for a specific node
36
+ * Calculate closeness centrality from distances
37
+ * @param distances - Map of node IDs to their distances from source
38
+ * @param sourceNode - The source node for distance calculations
39
+ * @param totalNodes - Total number of nodes in the graph
40
+ * @param options - Algorithm configuration options
41
+ * @returns The closeness centrality score for the source node
49
42
  */
50
- export function nodeClosenessCentrality(
51
- graph: Graph,
52
- node: NodeId,
53
- options: ClosenessCentralityOptions = {},
43
+ function calculateClosenessFromDistances(
44
+ distances: Map<NodeId, number>,
45
+ sourceNode: NodeId,
46
+ totalNodes: number,
47
+ options: ClosenessCentralityOptions,
54
48
  ): number {
55
- if (!graph.hasNode(node)) {
56
- throw new Error(`Node ${String(node)} not found in graph`);
57
- }
58
-
59
- const distances = singleSourceShortestPathLengths(graph, node, options.cutoff);
60
-
61
49
  if (distances.size <= 1) {
62
50
  return 0; // No other nodes reachable
63
51
  }
@@ -66,18 +54,23 @@ export function nodeClosenessCentrality(
66
54
 
67
55
  if (options.harmonic) {
68
56
  // Harmonic centrality: sum of reciprocals of distances
69
- for (const [targetNode, distance] of Array.from(distances)) {
70
- if (targetNode !== node && distance > 0) {
57
+ for (const [targetNode, distance] of distances) {
58
+ if (targetNode !== sourceNode && distance > 0 && distance < Infinity) {
71
59
  centrality += 1 / distance;
72
60
  }
73
61
  }
62
+
63
+ // Normalization for harmonic centrality
64
+ if (options.normalized && totalNodes > 1) {
65
+ centrality = centrality / (totalNodes - 1);
66
+ }
74
67
  } else {
75
68
  // Standard closeness: reciprocal of sum of distances
76
69
  let totalDistance = 0;
77
70
  let reachableNodes = 0;
78
71
 
79
- for (const [targetNode, distance] of Array.from(distances)) {
80
- if (targetNode !== node) {
72
+ for (const [targetNode, distance] of distances) {
73
+ if (targetNode !== sourceNode && distance < Infinity) {
81
74
  totalDistance += distance;
82
75
  reachableNodes++;
83
76
  }
@@ -87,74 +80,77 @@ export function nodeClosenessCentrality(
87
80
  centrality = 1 / totalDistance;
88
81
 
89
82
  // Wasserman and Faust normalization for disconnected graphs
90
- if (options.normalized) {
91
- const n = Array.from(graph.nodes()).length;
92
- centrality = centrality * reachableNodes / (n - 1);
83
+ if (options.normalized && totalNodes > 1) {
84
+ centrality = (centrality * reachableNodes) / (totalNodes - 1);
93
85
  }
94
86
  }
95
87
  }
96
88
 
97
- // Normalization for harmonic centrality
98
- if (options.harmonic && options.normalized) {
99
- const n = Array.from(graph.nodes()).length;
100
- if (n > 1) {
101
- centrality = centrality / (n - 1);
102
- }
103
- }
104
-
105
89
  return centrality;
106
90
  }
107
91
 
108
92
  /**
109
- * Single-source shortest path lengths using BFS (for unweighted graphs)
93
+ * Calculate closeness centrality for all nodes in the graph
94
+ *
95
+ * Closeness centrality measures how close a node is to all other nodes
96
+ * in the graph. It is the reciprocal of the sum of the shortest path
97
+ * distances to all other reachable nodes.
98
+ * @param graph - The input graph
99
+ * @param options - Algorithm options
100
+ * @returns Centrality scores for each node
101
+ * @example
102
+ * ```typescript
103
+ * const graph = new Graph();
104
+ * graph.addEdge("A", "B");
105
+ * graph.addEdge("B", "C");
106
+ *
107
+ * const centrality = closenessCentrality(graph);
108
+ * // { A: 0.5, B: 1.0, C: 0.5 }
109
+ * ```
110
+ *
111
+ * Time Complexity: O(V * (V + E)) for unweighted graphs
112
+ * Space Complexity: O(V)
110
113
  */
111
- function singleSourceShortestPathLengths(
112
- graph: Graph,
113
- source: NodeId,
114
- cutoff?: number,
115
- ): Map<NodeId, number> {
116
- const distances = new Map<NodeId, number>();
117
- const visited = new Set<NodeId>();
118
- const queue: {node: NodeId, distance: number}[] = [];
119
-
120
- // Initialize
121
- queue.push({node: source, distance: 0});
122
- visited.add(source);
123
- distances.set(source, 0);
124
-
125
- while (queue.length > 0) {
126
- const current = queue.shift();
127
- if (!current) {
128
- break;
129
- }
130
-
131
- // Skip if beyond cutoff
132
- if (cutoff !== undefined && current.distance >= cutoff) {
133
- continue;
134
- }
114
+ export function closenessCentrality(graph: Graph, options: ClosenessCentralityOptions = {}): Record<string, number> {
115
+ const nodes = Array.from(graph.nodes()).map((node) => node.id);
116
+ const centrality: Record<string, number> = {};
135
117
 
136
- // Explore neighbors
137
- for (const neighbor of Array.from(graph.neighbors(current.node))) {
138
- if (!visited.has(neighbor)) {
139
- const newDistance = current.distance + 1;
118
+ for (const sourceNode of nodes) {
119
+ centrality[String(sourceNode)] = nodeClosenessCentrality(graph, sourceNode, options);
120
+ }
140
121
 
141
- // Skip if beyond cutoff
142
- if (cutoff !== undefined && newDistance > cutoff) {
143
- continue;
144
- }
122
+ return centrality;
123
+ }
145
124
 
146
- visited.add(neighbor);
147
- distances.set(neighbor, newDistance);
148
- queue.push({node: neighbor, distance: newDistance});
149
- }
150
- }
125
+ /**
126
+ * Calculate closeness centrality for a specific node
127
+ * @param graph - The input graph to analyze
128
+ * @param node - The node to calculate centrality for
129
+ * @param options - Algorithm configuration options
130
+ * @returns The closeness centrality score for the node
131
+ */
132
+ export function nodeClosenessCentrality(graph: Graph, node: NodeId, options: ClosenessCentralityOptions = {}): number {
133
+ if (!graph.hasNode(node)) {
134
+ throw new Error(`Node ${String(node)} not found in graph`);
151
135
  }
152
136
 
153
- return distances;
137
+ // Use optimized BFS variant for unweighted graphs
138
+ const distances = bfsDistancesOnly(
139
+ graph,
140
+ node,
141
+ options.cutoff,
142
+ options.optimized !== undefined ? { optimized: options.optimized } : {},
143
+ );
144
+ const totalNodes = graph.nodeCount;
145
+
146
+ return calculateClosenessFromDistances(distances, node, totalNodes, options);
154
147
  }
155
148
 
156
149
  /**
157
150
  * Calculate weighted closeness centrality using Dijkstra's algorithm
151
+ * @param graph - The input graph to analyze
152
+ * @param options - Algorithm configuration options
153
+ * @returns Centrality scores for each node keyed by node ID
158
154
  */
159
155
  export function weightedClosenessCentrality(
160
156
  graph: Graph,
@@ -172,6 +168,10 @@ export function weightedClosenessCentrality(
172
168
 
173
169
  /**
174
170
  * Calculate weighted closeness centrality for a specific node using Dijkstra
171
+ * @param graph - The input graph to analyze
172
+ * @param node - The node to calculate centrality for
173
+ * @param options - Algorithm configuration options
174
+ * @returns The weighted closeness centrality score for the node
175
175
  */
176
176
  export function nodeWeightedClosenessCentrality(
177
177
  graph: Graph,
@@ -182,115 +182,14 @@ export function nodeWeightedClosenessCentrality(
182
182
  throw new Error(`Node ${String(node)} not found in graph`);
183
183
  }
184
184
 
185
- const distances = dijkstraDistances(graph, node, options.cutoff);
186
-
187
- if (distances.size <= 1) {
188
- return 0; // No other nodes reachable
189
- }
190
-
191
- let centrality = 0;
192
-
193
- if (options.harmonic) {
194
- // Harmonic centrality: sum of reciprocals of distances
195
- for (const [targetNode, distance] of Array.from(distances)) {
196
- if (targetNode !== node && distance > 0 && distance < Infinity) {
197
- centrality += 1 / distance;
198
- }
199
- }
200
- } else {
201
- // Standard closeness: reciprocal of sum of distances
202
- let totalDistance = 0;
203
- let reachableNodes = 0;
204
-
205
- for (const [targetNode, distance] of Array.from(distances)) {
206
- if (targetNode !== node && distance < Infinity) {
207
- totalDistance += distance;
208
- reachableNodes++;
209
- }
210
- }
211
-
212
- if (totalDistance > 0) {
213
- centrality = 1 / totalDistance;
214
-
215
- // Wasserman and Faust normalization for disconnected graphs
216
- if (options.normalized) {
217
- const n = Array.from(graph.nodes()).length;
218
- centrality = centrality * reachableNodes / (n - 1);
219
- }
220
- }
221
- }
222
-
223
- // Normalization for harmonic centrality
224
- if (options.harmonic && options.normalized) {
225
- const n = Array.from(graph.nodes()).length;
226
- if (n > 1) {
227
- centrality = centrality / (n - 1);
228
- }
229
- }
230
-
231
- return centrality;
232
- }
233
-
234
- /**
235
- * Single-source shortest path distances using Dijkstra's algorithm
236
- */
237
- function dijkstraDistances(
238
- graph: Graph,
239
- source: NodeId,
240
- cutoff?: number,
241
- ): Map<NodeId, number> {
242
- const distances = new Map<NodeId, number>();
243
- const visited = new Set<NodeId>();
244
- const pq: {node: NodeId, distance: number}[] = [];
245
-
246
- // Initialize distances
247
- for (const node of Array.from(graph.nodes())) {
248
- distances.set(node.id, node.id === source ? 0 : Infinity);
249
- }
250
-
251
- pq.push({node: source, distance: 0});
252
-
253
- while (pq.length > 0) {
254
- // Simple priority queue (could be optimized with a proper heap)
255
- pq.sort((a, b) => a.distance - b.distance);
256
- const current = pq.shift();
257
-
258
- if (!current || visited.has(current.node)) {
259
- continue;
260
- }
261
-
262
- visited.add(current.node);
263
-
264
- // Skip if beyond cutoff
265
- if (cutoff !== undefined && current.distance > cutoff) {
266
- continue;
267
- }
268
-
269
- // Explore neighbors
270
- for (const neighbor of Array.from(graph.neighbors(current.node))) {
271
- if (visited.has(neighbor)) {
272
- continue;
273
- }
274
-
275
- const edge = graph.getEdge(current.node, neighbor);
276
- if (!edge) {
277
- continue;
278
- }
279
-
280
- const edgeWeight = edge.weight ?? 1;
281
- const tentativeDistance = current.distance + edgeWeight;
282
- const currentDistance = distances.get(neighbor) ?? Infinity;
283
-
284
- if (tentativeDistance < currentDistance) {
285
- distances.set(neighbor, tentativeDistance);
286
-
287
- // Skip if beyond cutoff
288
- if (cutoff === undefined || tentativeDistance <= cutoff) {
289
- pq.push({node: neighbor, distance: tentativeDistance});
290
- }
291
- }
292
- }
293
- }
185
+ // Use optimized weighted BFS variant (simplified Dijkstra)
186
+ const distances = bfsWeightedDistances(
187
+ graph,
188
+ node,
189
+ options.cutoff,
190
+ options.optimized !== undefined ? { optimized: options.optimized } : {},
191
+ );
192
+ const totalNodes = graph.nodeCount;
294
193
 
295
- return distances;
194
+ return calculateClosenessFromDistances(distances, node, totalNodes, options);
296
195
  }
@@ -1,5 +1,5 @@
1
- import type {Graph} from "../../core/graph.js";
2
- import type {CentralityOptions, CentralityResult} from "../../types/index.js";
1
+ import type { Graph } from "../../core/graph.js";
2
+ import type { CentralityOptions, CentralityResult } from "../../types/index.js";
3
3
 
4
4
  /**
5
5
  * Degree centrality implementation
@@ -10,18 +10,18 @@ import type {CentralityOptions, CentralityResult} from "../../types/index.js";
10
10
 
11
11
  /**
12
12
  * Calculate degree centrality for all nodes in the graph
13
+ * @param graph - The input graph to analyze
14
+ * @param options - Algorithm configuration options
15
+ * @returns Centrality scores for each node keyed by node ID
13
16
  */
14
- export function degreeCentrality(
15
- graph: Graph,
16
- options: CentralityOptions = {},
17
- ): CentralityResult {
17
+ export function degreeCentrality(graph: Graph, options: CentralityOptions = {}): CentralityResult {
18
18
  const centrality: CentralityResult = {};
19
- const {nodeCount} = graph;
19
+ const { nodeCount } = graph;
20
20
 
21
- // Calculate normalization factor
22
- const maxPossibleDegree = graph.isDirected ? nodeCount - 1 : nodeCount - 1;
21
+ // Calculate normalization factor (same for both directed and undirected graphs)
22
+ const maxPossibleDegree = nodeCount - 1;
23
23
 
24
- for (const node of Array.from(graph.nodes())) {
24
+ for (const node of graph.nodes()) {
25
25
  let degree: number;
26
26
 
27
27
  if (graph.isDirected && options.mode) {
@@ -49,9 +49,7 @@ export function degreeCentrality(
49
49
  }
50
50
 
51
51
  // Apply normalization if requested
52
- const normalizedDegree = options.normalized && maxPossibleDegree > 0 ?
53
- degree / maxPossibleDegree :
54
- degree;
52
+ const normalizedDegree = options.normalized && maxPossibleDegree > 0 ? degree / maxPossibleDegree : degree;
55
53
 
56
54
  centrality[node.id.toString()] = normalizedDegree;
57
55
  }
@@ -61,17 +59,17 @@ export function degreeCentrality(
61
59
 
62
60
  /**
63
61
  * Calculate degree centrality for a specific node
62
+ * @param graph - The input graph to analyze
63
+ * @param nodeId - The node to calculate centrality for
64
+ * @param options - Algorithm configuration options
65
+ * @returns The degree centrality score for the node
64
66
  */
65
- export function nodeDegreeCentrality(
66
- graph: Graph,
67
- nodeId: string | number,
68
- options: CentralityOptions = {},
69
- ): number {
67
+ export function nodeDegreeCentrality(graph: Graph, nodeId: string | number, options: CentralityOptions = {}): number {
70
68
  if (!graph.hasNode(nodeId)) {
71
69
  throw new Error(`Node ${String(nodeId)} not found in graph`);
72
70
  }
73
71
 
74
- const {nodeCount} = graph;
72
+ const { nodeCount } = graph;
75
73
  let degree: number;
76
74
 
77
75
  if (graph.isDirected && options.mode) {
@@ -99,7 +97,5 @@ export function nodeDegreeCentrality(
99
97
  // Apply normalization if requested
100
98
  const maxPossibleDegree = nodeCount - 1;
101
99
 
102
- return options.normalized && maxPossibleDegree > 0 ?
103
- degree / maxPossibleDegree :
104
- degree;
100
+ return options.normalized && maxPossibleDegree > 0 ? degree / maxPossibleDegree : degree;
105
101
  }