@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 { SimpleDeltaPageRank } from "./delta-pagerank-simple.js";
3
4
 
4
5
  /**
5
6
  * PageRank algorithm implementation
@@ -36,6 +37,12 @@ export interface PageRankOptions {
36
37
  * Weight attribute for weighted PageRank (default: null = unweighted)
37
38
  */
38
39
  weight?: string;
40
+ /**
41
+ * Use delta-based optimization for faster convergence.
42
+ * Defaults to true for graphs with >100 nodes, false for smaller graphs.
43
+ * Set explicitly to override automatic heuristic.
44
+ */
45
+ useDelta?: boolean;
39
46
  }
40
47
 
41
48
  /**
@@ -58,11 +65,22 @@ export interface PageRankResult {
58
65
 
59
66
  /**
60
67
  * Calculate PageRank for all nodes in the graph
68
+ *
69
+ * Uses delta-based optimization by default for improved performance on larger graphs.
70
+ * Automatically falls back to standard algorithm for very small graphs.
71
+ *
72
+ * The delta-based approach provides significant speedup for:
73
+ * - Incremental updates after graph modifications
74
+ * - Graphs with localized changes
75
+ * - Early convergence detection per vertex
76
+ *
77
+ * For initial computation on small-medium graphs, standard algorithm may be faster
78
+ * due to lower overhead.
79
+ * @param graph - The directed input graph to analyze
80
+ * @param options - Algorithm configuration options
81
+ * @returns PageRank result containing ranks, iteration count, and convergence status
61
82
  */
62
- export function pageRank(
63
- graph: Graph,
64
- options: PageRankOptions = {},
65
- ): PageRankResult {
83
+ export function pageRank(graph: Graph, options: PageRankOptions = {}): PageRankResult {
66
84
  const {
67
85
  dampingFactor = 0.85,
68
86
  maxIterations = 100,
@@ -84,7 +102,50 @@ export function pageRank(
84
102
  const n = nodes.length;
85
103
 
86
104
  if (n === 0) {
87
- return {ranks: {}, iterations: 0, converged: true};
105
+ return { ranks: {}, iterations: 0, converged: true };
106
+ }
107
+
108
+ // Use delta-based optimization by default for larger graphs
109
+ // Only disable if explicitly requested or graph is very small (overhead dominates)
110
+ const shouldUseDelta = options.useDelta !== false && n > 100;
111
+
112
+ if (shouldUseDelta) {
113
+ // Use optimized delta-based implementation
114
+
115
+ const deltaOptions: {
116
+ dampingFactor: number;
117
+ tolerance: number;
118
+ maxIterations: number;
119
+ personalization?: Map<NodeId, number>;
120
+ weight?: string;
121
+ } = {
122
+ dampingFactor,
123
+ tolerance,
124
+ maxIterations,
125
+ };
126
+
127
+ if (personalization) {
128
+ deltaOptions.personalization = personalization;
129
+ }
130
+
131
+ if (weight) {
132
+ deltaOptions.weight = weight;
133
+ }
134
+
135
+ const deltaPageRank = new SimpleDeltaPageRank(graph);
136
+ const deltaRanks = deltaPageRank.compute(deltaOptions);
137
+
138
+ // Convert to string-keyed record
139
+ const result: Record<string, number> = {};
140
+ for (const [nodeId, rank] of deltaRanks) {
141
+ result[String(nodeId)] = rank;
142
+ }
143
+
144
+ return {
145
+ ranks: result,
146
+ iterations: maxIterations, // For now, assume we used all iterations
147
+ converged: true,
148
+ };
88
149
  }
89
150
 
90
151
  // Initialize PageRank values
@@ -160,7 +221,7 @@ export function pageRank(
160
221
  }
161
222
 
162
223
  if (danglingSum > 0) {
163
- const danglingContribution = dampingFactor * danglingSum / n;
224
+ const danglingContribution = (dampingFactor * danglingSum) / n;
164
225
  for (const nodeId of nodes) {
165
226
  const currentRank = newRanks.get(nodeId) ?? 0;
166
227
  if (personalVector) {
@@ -223,12 +284,21 @@ export function pageRank(
223
284
 
224
285
  /**
225
286
  * Calculate Personalized PageRank for a specific set of source nodes
287
+ * @param graph - The directed input graph to analyze
288
+ * @param personalNodes - Nodes to personalize the PageRank towards
289
+ * @param options - Algorithm configuration options
290
+ * @returns PageRank result containing ranks, iteration count, and convergence status
226
291
  */
227
292
  export function personalizedPageRank(
228
293
  graph: Graph,
229
294
  personalNodes: NodeId[],
230
295
  options: Omit<PageRankOptions, "personalization"> = {},
231
296
  ): PageRankResult {
297
+ // Handle empty personal nodes by falling back to standard PageRank
298
+ if (personalNodes.length === 0) {
299
+ return pageRank(graph, options);
300
+ }
301
+
232
302
  const nodes = Array.from(graph.nodes()).map((node) => node.id);
233
303
  const personalization = new Map<NodeId, number>();
234
304
 
@@ -248,35 +318,39 @@ export function personalizedPageRank(
248
318
  }
249
319
 
250
320
  return pageRank(graph, {
251
- ... options,
321
+ ...options,
252
322
  personalization,
253
323
  });
254
324
  }
255
325
 
256
326
  /**
257
327
  * Calculate PageRank centrality (normalized PageRank scores)
328
+ * @param graph - The directed input graph to analyze
329
+ * @param options - Algorithm configuration options
330
+ * @returns PageRank scores for each node keyed by node ID
258
331
  */
259
- export function pageRankCentrality(
260
- graph: Graph,
261
- options: PageRankOptions = {},
262
- ): Record<string, number> {
332
+ export function pageRankCentrality(graph: Graph, options: PageRankOptions = {}): Record<string, number> {
263
333
  const result = pageRank(graph, options);
264
334
  return result.ranks;
265
335
  }
266
336
 
267
337
  /**
268
338
  * Get the top-k nodes by PageRank score
339
+ * @param graph - The directed input graph to analyze
340
+ * @param k - Number of top nodes to return
341
+ * @param options - Algorithm configuration options
342
+ * @returns Array of top-k nodes with their PageRank scores, sorted descending
269
343
  */
270
344
  export function topPageRankNodes(
271
345
  graph: Graph,
272
346
  k: number,
273
347
  options: PageRankOptions = {},
274
- ): {node: NodeId, rank: number}[] {
348
+ ): { node: NodeId; rank: number }[] {
275
349
  const result = pageRank(graph, options);
276
350
 
277
- const nodeRanks: {node: NodeId, rank: number}[] = [];
351
+ const nodeRanks: { node: NodeId; rank: number }[] = [];
278
352
  for (const [nodeStr, rank] of Object.entries(result.ranks)) {
279
- nodeRanks.push({node: nodeStr as NodeId, rank});
353
+ nodeRanks.push({ node: nodeStr as NodeId, rank });
280
354
  }
281
355
 
282
356
  // Sort by rank in descending order
@@ -287,6 +361,7 @@ export function topPageRankNodes(
287
361
 
288
362
  /**
289
363
  * Normalize ranks so they sum to 1
364
+ * @param ranks - The ranks map to normalize in place
290
365
  */
291
366
  function normalizeRanks(ranks: Map<NodeId, number>): void {
292
367
  let sum = 0;
@@ -1,6 +1,6 @@
1
- import {Graph} from "../../core/graph.js";
2
- import type {CommunityResult, ComponentResult, GirvanNewmanOptions, NodeId} from "../../types/index.js";
3
- import {connectedComponents} from "../components/connected.js";
1
+ import { Graph } from "../../core/graph.js";
2
+ import type { CommunityResult, ComponentResult, GirvanNewmanOptions, NodeId } from "../../types/index.js";
3
+ import { connectedComponents } from "../components/connected.js";
4
4
 
5
5
  /**
6
6
  * Girvan-Newman community detection algorithm
@@ -14,22 +14,20 @@ import {connectedComponents} from "../components/connected.js";
14
14
  *
15
15
  * References:
16
16
  * - Girvan, M., & Newman, M. E. J. (2002). Community structure in social
17
- * and biological networks. Proceedings of the National Academy of Sciences,
18
- * 99(12), 7821-7826.
19
- *
17
+ * and biological networks. Proceedings of the National Academy of Sciences,
18
+ * 99(12), 7821-7826.
20
19
  * @param graph - The input graph
21
20
  * @param options - Algorithm options
22
21
  * @returns Array of community detection results representing the dendrogram
23
22
  */
24
- export function girvanNewman(
25
- graph: Graph,
26
- options: GirvanNewmanOptions = {},
27
- ): CommunityResult[] {
28
- const {maxCommunities} = options;
23
+ export function girvanNewman(graph: Graph, options: GirvanNewmanOptions = {}): CommunityResult[] {
24
+ const { maxCommunities } = options;
29
25
  const minCommunitySize = options.minCommunitySize ?? 1;
26
+ const maxIterations = options.maxIterations ?? 100; // Prevent infinite loops
30
27
 
31
28
  const dendrogram: CommunityResult[] = [];
32
- const workingGraph = cloneGraph(graph);
29
+ const workingGraph = graph.clone();
30
+ let iterations = 0;
33
31
 
34
32
  // Initial state: one large component
35
33
  let components = getConnectedComponentsResult(workingGraph);
@@ -38,7 +36,8 @@ export function girvanNewman(
38
36
  modularity: calculateModularity(graph, components.componentMap),
39
37
  });
40
38
 
41
- while (Array.from(workingGraph.edges()).length > 0) {
39
+ while (Array.from(workingGraph.edges()).length > 0 && iterations < maxIterations) {
40
+ iterations++;
42
41
  // Calculate edge betweenness centrality
43
42
  const edgeBetweenness = calculateEdgeBetweenness(workingGraph);
44
43
 
@@ -47,20 +46,20 @@ export function girvanNewman(
47
46
  }
48
47
 
49
48
  // Find edges with maximum betweenness
50
- const maxBetweenness = Math.max(... edgeBetweenness.values());
51
- const edgesToRemove: {source: NodeId, target: NodeId}[] = [];
49
+ const maxBetweenness = Math.max(...edgeBetweenness.values());
50
+ const edgesToRemove: { source: NodeId; target: NodeId }[] = [];
52
51
 
53
52
  for (const [edgeKey, centrality] of edgeBetweenness) {
54
53
  if (Math.abs(centrality - maxBetweenness) < 1e-10) {
55
54
  const [source, target] = edgeKey.split("|");
56
55
  if (source && target) {
57
- edgesToRemove.push({source, target});
56
+ edgesToRemove.push({ source, target });
58
57
  }
59
58
  }
60
59
  }
61
60
 
62
61
  // Remove edges with highest betweenness
63
- for (const {source, target} of edgesToRemove) {
62
+ for (const { source, target } of edgesToRemove) {
64
63
  workingGraph.removeEdge(source, target);
65
64
  }
66
65
 
@@ -68,9 +67,7 @@ export function girvanNewman(
68
67
  components = getConnectedComponentsResult(workingGraph);
69
68
 
70
69
  // Filter communities by minimum size
71
- const validCommunities = components.components.filter(
72
- (community) => community.length >= minCommunitySize,
73
- );
70
+ const validCommunities = components.components.filter((community) => community.length >= minCommunitySize);
74
71
 
75
72
  // Calculate modularity for the new community structure
76
73
  const modularity = calculateModularity(graph, components.componentMap);
@@ -99,6 +96,8 @@ export function girvanNewman(
99
96
  *
100
97
  * Edge betweenness is the fraction of shortest paths that pass through the edge.
101
98
  * We adapt node betweenness centrality calculation to work with edges.
99
+ * @param graph - The input graph to analyze
100
+ * @returns Map of edge keys to their betweenness centrality values
102
101
  */
103
102
  function calculateEdgeBetweenness(graph: Graph): Map<string, number> {
104
103
  const edgeBetweenness = new Map<string, number>();
@@ -114,7 +113,7 @@ function calculateEdgeBetweenness(graph: Graph): Map<string, number> {
114
113
  const source = sourceNode.id;
115
114
 
116
115
  // Run BFS to find all shortest paths from source
117
- const {distances, predecessors, pathCounts} = findAllShortestPaths(graph, source);
116
+ const { distances, predecessors, pathCounts } = findAllShortestPaths(graph, source);
118
117
 
119
118
  // Calculate dependency for each node and accumulate edge betweenness
120
119
  const dependency = new Map<NodeId, number>();
@@ -187,9 +186,15 @@ function calculateEdgeBetweenness(graph: Graph): Map<string, number> {
187
186
  }
188
187
 
189
188
  /**
190
- * Find all shortest paths from a source node using BFS
189
+ * Find all shortest paths from a source node using optimized BFS
190
+ * @param graph - The input graph to search
191
+ * @param source - The source node to compute shortest paths from
192
+ * @returns Object containing distances, predecessors, and path counts
191
193
  */
192
- function findAllShortestPaths(graph: Graph, source: NodeId): {
194
+ function findAllShortestPaths(
195
+ graph: Graph,
196
+ source: NodeId,
197
+ ): {
193
198
  distances: Map<NodeId, number>;
194
199
  predecessors: Map<NodeId, NodeId[]>;
195
200
  pathCounts: Map<NodeId, number>;
@@ -198,39 +203,43 @@ function findAllShortestPaths(graph: Graph, source: NodeId): {
198
203
  const predecessors = new Map<NodeId, NodeId[]>();
199
204
  const pathCounts = new Map<NodeId, number>();
200
205
  const queue: NodeId[] = [];
206
+ const visited = new Set<NodeId>();
201
207
 
202
- // Initialize
203
- for (const node of graph.nodes()) {
204
- distances.set(node.id, Infinity);
205
- predecessors.set(node.id, []);
206
- pathCounts.set(node.id, 0);
207
- }
208
-
208
+ // Only initialize for reachable nodes
209
209
  distances.set(source, 0);
210
+ predecessors.set(source, []);
210
211
  pathCounts.set(source, 1);
211
212
  queue.push(source);
212
213
 
213
- // BFS
214
- while (queue.length > 0) {
215
- const current = queue.shift();
216
- if (current === undefined) {
217
- break;
214
+ // Optimized BFS with early termination
215
+ let queueIndex = 0;
216
+ while (queueIndex < queue.length) {
217
+ const current = queue[queueIndex++];
218
+ if (!current) {
219
+ continue;
220
+ }
221
+
222
+ if (visited.has(current)) {
223
+ continue;
218
224
  }
219
225
 
226
+ visited.add(current);
227
+
220
228
  const currentDistance = distances.get(current);
221
229
  if (currentDistance === undefined) {
222
230
  continue;
223
231
  }
224
232
 
225
233
  for (const neighbor of graph.neighbors(current)) {
226
- const edge = graph.getEdge(current, neighbor);
227
- const edgeWeight = edge?.weight ?? 1;
228
- const newDistance = currentDistance + edgeWeight;
229
- const neighborDistance = distances.get(neighbor);
230
- if (neighborDistance === undefined) {
234
+ // Skip if already processed
235
+ if (visited.has(neighbor)) {
231
236
  continue;
232
237
  }
233
238
 
239
+ const edgeWeight = 1; // Unweighted for community detection
240
+ const newDistance = currentDistance + edgeWeight;
241
+ const neighborDistance = distances.get(neighbor) ?? Infinity;
242
+
234
243
  if (newDistance < neighborDistance) {
235
244
  // Found shorter path
236
245
  distances.set(neighbor, newDistance);
@@ -241,25 +250,28 @@ function findAllShortestPaths(graph: Graph, source: NodeId): {
241
250
  }
242
251
 
243
252
  queue.push(neighbor);
244
- } else if (Math.abs(newDistance - neighborDistance) < 1e-10) {
253
+ } else if (newDistance === neighborDistance) {
245
254
  // Found alternative shortest path
246
255
  const neighborPredecessors = predecessors.get(neighbor);
247
- const neighborPathCount = pathCounts.get(neighbor);
248
- const currentPathCount = pathCounts.get(current);
249
-
250
- if (neighborPredecessors && neighborPathCount !== undefined && currentPathCount !== undefined) {
256
+ if (neighborPredecessors) {
251
257
  neighborPredecessors.push(current);
252
- pathCounts.set(neighbor, neighborPathCount + currentPathCount);
258
+ const currentPathCount = pathCounts.get(current);
259
+ if (currentPathCount !== undefined) {
260
+ pathCounts.set(neighbor, (pathCounts.get(neighbor) ?? 0) + currentPathCount);
261
+ }
253
262
  }
254
263
  }
255
264
  }
256
265
  }
257
266
 
258
- return {distances, predecessors, pathCounts};
267
+ return { distances, predecessors, pathCounts };
259
268
  }
260
269
 
261
270
  /**
262
271
  * Generate a consistent edge key for undirected graphs
272
+ * @param source - The source node ID
273
+ * @param target - The target node ID
274
+ * @returns A consistent string key for the edge (ordered alphabetically)
263
275
  */
264
276
  function getEdgeKey(source: NodeId, target: NodeId): string {
265
277
  // For undirected graphs, ensure consistent ordering
@@ -274,31 +286,39 @@ function getEdgeKey(source: NodeId, target: NodeId): string {
274
286
  }
275
287
 
276
288
  /**
277
- * Calculate modularity for a given community structure
289
+ * Calculate modularity for a given community structure - optimized version
290
+ * @param graph - The original graph
291
+ * @param communityMap - Map from node IDs to community indices
292
+ * @returns The modularity score of the partition
278
293
  */
279
- function calculateModularity(
280
- graph: Graph,
281
- communityMap: Map<NodeId, number>,
282
- ): number {
294
+ function calculateModularity(graph: Graph, communityMap: Map<NodeId, number>): number {
283
295
  const totalEdgeWeight = getTotalEdgeWeight(graph);
284
296
  if (totalEdgeWeight === 0) {
285
297
  return 0;
286
298
  }
287
299
 
288
300
  let modularity = 0;
301
+ const degrees = new Map<NodeId, number>();
289
302
 
290
- // Calculate modularity: Q = (1/2m) * Σ[A_ij - (k_i * k_j)/(2m)] * δ(c_i, c_j)
291
- for (const nodeI of graph.nodes()) {
292
- for (const nodeJ of graph.nodes()) {
293
- if (communityMap.get(nodeI.id) === communityMap.get(nodeJ.id)) {
294
- const edge = graph.getEdge(nodeI.id, nodeJ.id);
295
- const edgeWeight = edge?.weight ?? 0;
296
-
297
- const degreeI = getNodeDegree(graph, nodeI.id);
298
- const degreeJ = getNodeDegree(graph, nodeJ.id);
303
+ // Pre-calculate all degrees
304
+ for (const node of graph.nodes()) {
305
+ degrees.set(node.id, getNodeDegree(graph, node.id));
306
+ }
299
307
 
300
- modularity += edgeWeight - ((degreeI * degreeJ) / (2 * totalEdgeWeight));
308
+ // Only iterate over existing edges
309
+ for (const edge of graph.edges()) {
310
+ const communityI = communityMap.get(edge.source);
311
+ const communityJ = communityMap.get(edge.target);
312
+
313
+ if (communityI === communityJ) {
314
+ const edgeWeight = edge.weight ?? 1;
315
+ const degreeI = degrees.get(edge.source);
316
+ const degreeJ = degrees.get(edge.target);
317
+ if (degreeI === undefined || degreeJ === undefined) {
318
+ continue;
301
319
  }
320
+
321
+ modularity += edgeWeight - (degreeI * degreeJ) / (2 * totalEdgeWeight);
302
322
  }
303
323
  }
304
324
 
@@ -307,6 +327,8 @@ function calculateModularity(
307
327
 
308
328
  /**
309
329
  * Calculate total edge weight in the graph
330
+ * @param graph - The input graph
331
+ * @returns Total sum of all edge weights
310
332
  */
311
333
  function getTotalEdgeWeight(graph: Graph): number {
312
334
  let totalWeight = 0;
@@ -320,6 +342,9 @@ function getTotalEdgeWeight(graph: Graph): number {
320
342
 
321
343
  /**
322
344
  * Get the total degree (sum of edge weights) for a node
345
+ * @param graph - The input graph
346
+ * @param nodeId - The node ID to compute degree for
347
+ * @returns The weighted degree of the node
323
348
  */
324
349
  function getNodeDegree(graph: Graph, nodeId: NodeId): number {
325
350
  let degree = 0;
@@ -334,6 +359,8 @@ function getNodeDegree(graph: Graph, nodeId: NodeId): number {
334
359
 
335
360
  /**
336
361
  * Convert connected components result to ComponentResult format
362
+ * @param graph - The input graph
363
+ * @returns Object containing components array and node-to-component map
337
364
  */
338
365
  function getConnectedComponentsResult(graph: Graph): ComponentResult {
339
366
  const components = connectedComponents(graph);
@@ -345,28 +372,5 @@ function getConnectedComponentsResult(graph: Graph): ComponentResult {
345
372
  });
346
373
  });
347
374
 
348
- return {components, componentMap};
349
- }
350
-
351
- /**
352
- * Create a deep clone of the graph
353
- */
354
- function cloneGraph(graph: Graph): Graph {
355
- const clone = new Graph({
356
- directed: graph.isDirected,
357
- allowSelfLoops: true,
358
- allowParallelEdges: false,
359
- });
360
-
361
- // Add all nodes
362
- for (const node of graph.nodes()) {
363
- clone.addNode(node.id, node.data);
364
- }
365
-
366
- // Add all edges
367
- for (const edge of graph.edges()) {
368
- clone.addEdge(edge.source, edge.target, edge.weight, edge.data);
369
- }
370
-
371
- return clone;
375
+ return { components, componentMap };
372
376
  }
@@ -6,8 +6,9 @@
6
6
  * than with the rest of the network.
7
7
  */
8
8
 
9
- export {girvanNewman} from "./girvan-newman.js";
10
- export {labelPropagation, labelPropagationAsync, labelPropagationSemiSupervised} from "./label-propagation.js";
11
- export {leiden} from "./leiden.js";
12
- export {louvain} from "./louvain.js";
13
-
9
+ export { girvanNewman } from "./girvan-newman.js";
10
+ export type { LabelPropagationOptions, LabelPropagationResult } from "./label-propagation.js";
11
+ export { labelPropagation, labelPropagationAsync, labelPropagationSemiSupervised } from "./label-propagation.js";
12
+ export type { LeidenOptions, LeidenResult } from "./leiden.js";
13
+ export { leiden } from "./leiden.js";
14
+ export { louvain } from "./louvain.js";