@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,458 @@
1
+ import type { Graph } from "../../core/graph.js";
2
+ import { PriorityQueue } from "../../data-structures/priority-queue.js";
3
+ import type { NodeId } from "../../types/index.js";
4
+
5
+ /**
6
+ * Delta-based PageRank implementation for faster convergence
7
+ *
8
+ * This algorithm tracks changes (deltas) between iterations and only processes
9
+ * nodes with significant changes, dramatically reducing computation for graphs
10
+ * where only some nodes are actively changing their PageRank values.
11
+ *
12
+ * Key optimizations:
13
+ * - Only active nodes (with significant deltas) are processed
14
+ * - Early termination for converged vertices
15
+ * - Priority queue processing for high-impact updates
16
+ * - Adaptive convergence detection per vertex
17
+ *
18
+ * Expected speedup: 10-100x for incremental updates on large graphs
19
+ */
20
+
21
+ export interface DeltaPageRankOptions {
22
+ /**
23
+ * Damping factor (probability of following a link) (default: 0.85)
24
+ */
25
+ dampingFactor?: number;
26
+ /**
27
+ * Convergence tolerance (default: 1e-6)
28
+ */
29
+ tolerance?: number;
30
+ /**
31
+ * Maximum number of iterations (default: 100)
32
+ */
33
+ maxIterations?: number;
34
+ /**
35
+ * Minimum delta to keep vertex active (default: tolerance / 10)
36
+ */
37
+ deltaThreshold?: number;
38
+ /**
39
+ * Personalization vector for Personalized PageRank (default: null)
40
+ */
41
+ personalization?: Map<NodeId, number>;
42
+ /**
43
+ * Weight attribute for weighted PageRank (default: null = unweighted)
44
+ */
45
+ weight?: string;
46
+ }
47
+
48
+ /**
49
+ * Delta-based PageRank class that tracks changes between iterations
50
+ * and only processes nodes with significant changes for improved performance.
51
+ */
52
+ export class DeltaPageRank {
53
+ private graph: Graph;
54
+ private scores: Map<NodeId, number>;
55
+ private deltas: Map<NodeId, number>;
56
+ private activeNodes: Set<NodeId>;
57
+ private outDegrees: Map<NodeId, number>;
58
+ private outWeights: Map<NodeId, number>;
59
+ private danglingNodes: Set<NodeId>;
60
+ private nodeCount: number;
61
+
62
+ /**
63
+ * Creates a new DeltaPageRank instance for the given graph.
64
+ * @param graph - The directed graph to compute PageRank on
65
+ */
66
+ constructor(graph: Graph) {
67
+ if (!graph.isDirected) {
68
+ throw new Error("DeltaPageRank requires a directed graph");
69
+ }
70
+
71
+ this.graph = graph;
72
+ this.scores = new Map();
73
+ this.deltas = new Map();
74
+ this.activeNodes = new Set();
75
+ this.outDegrees = new Map();
76
+ this.outWeights = new Map();
77
+ this.danglingNodes = new Set();
78
+ this.nodeCount = graph.nodeCount;
79
+
80
+ this.initialize();
81
+ }
82
+
83
+ private initialize(): void {
84
+ const initialValue = 1.0 / this.nodeCount;
85
+
86
+ // Initialize data structures
87
+ for (const node of this.graph.nodes()) {
88
+ const nodeId = node.id;
89
+ this.scores.set(nodeId, 0); // Start with zero, will add initial value as delta
90
+ this.deltas.set(nodeId, initialValue);
91
+ this.activeNodes.add(nodeId);
92
+
93
+ // Precompute out-degrees and weights
94
+ let outDegree = 0;
95
+ let totalOutWeight = 0;
96
+
97
+ for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {
98
+ outDegree++;
99
+ const edge = this.graph.getEdge(nodeId, neighbor);
100
+ totalOutWeight += edge?.weight ?? 1;
101
+ }
102
+
103
+ this.outDegrees.set(nodeId, outDegree);
104
+ this.outWeights.set(nodeId, totalOutWeight);
105
+
106
+ if (outDegree === 0) {
107
+ this.danglingNodes.add(nodeId);
108
+ }
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Computes PageRank scores using delta-based iteration for faster convergence.
114
+ * @param options - Configuration options for PageRank computation
115
+ * @returns Map of node IDs to their PageRank scores
116
+ */
117
+ public compute(options: DeltaPageRankOptions = {}): Map<NodeId, number> {
118
+ const {
119
+ dampingFactor = 0.85,
120
+ tolerance = 1e-6,
121
+ maxIterations = 100,
122
+ deltaThreshold = tolerance / 10,
123
+ personalization,
124
+ weight,
125
+ } = options;
126
+
127
+ if (dampingFactor < 0 || dampingFactor > 1) {
128
+ throw new Error("Damping factor must be between 0 and 1");
129
+ }
130
+
131
+ if (this.nodeCount === 0) {
132
+ return new Map();
133
+ }
134
+
135
+ // Normalize personalization vector if provided
136
+ let personalVector: Map<NodeId, number> | null = null;
137
+ if (personalization) {
138
+ personalVector = new Map(personalization);
139
+ this.normalizeMap(personalVector);
140
+ }
141
+
142
+ const randomJump = (1 - dampingFactor) / this.nodeCount;
143
+ let iteration = 0;
144
+
145
+ while (this.activeNodes.size > 0 && iteration < maxIterations) {
146
+ iteration++;
147
+
148
+ // Create next iteration's deltas
149
+ const nextDeltas = new Map<NodeId, number>();
150
+
151
+ // Initialize all nodes with zero delta
152
+ for (const node of this.graph.nodes()) {
153
+ nextDeltas.set(node.id, 0);
154
+ }
155
+
156
+ // Handle dangling nodes contribution
157
+ let danglingSum = 0;
158
+ for (const danglingNode of this.danglingNodes) {
159
+ const currentScore = this.scores.get(danglingNode) ?? 0;
160
+ const delta = this.deltas.get(danglingNode) ?? 0;
161
+ danglingSum += currentScore + delta;
162
+ }
163
+
164
+ if (danglingSum > 0) {
165
+ const danglingContribution = (dampingFactor * danglingSum) / this.nodeCount;
166
+ for (const node of this.graph.nodes()) {
167
+ const nodeId = node.id;
168
+ const currentDelta = nextDeltas.get(nodeId) ?? 0;
169
+ if (personalVector) {
170
+ const personalContrib = danglingContribution * (personalVector.get(nodeId) ?? 0);
171
+ nextDeltas.set(nodeId, currentDelta + personalContrib);
172
+ } else {
173
+ nextDeltas.set(nodeId, currentDelta + danglingContribution);
174
+ }
175
+ }
176
+ }
177
+
178
+ // Process only active nodes
179
+ for (const nodeId of this.activeNodes) {
180
+ const delta = this.deltas.get(nodeId) ?? 0;
181
+
182
+ // Skip if delta is too small
183
+ if (Math.abs(delta) < deltaThreshold) {
184
+ continue;
185
+ }
186
+
187
+ // Apply delta to score
188
+ const currentScore = this.scores.get(nodeId) ?? 0;
189
+ this.scores.set(nodeId, currentScore + delta);
190
+
191
+ const outWeight = this.outWeights.get(nodeId) ?? 0;
192
+ if (outWeight > 0) {
193
+ // Distribute delta to neighbors
194
+ for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {
195
+ let edgeWeight = 1;
196
+ if (weight) {
197
+ const edge = this.graph.getEdge(nodeId, neighbor);
198
+ edgeWeight = edge?.weight ?? 1;
199
+ }
200
+
201
+ const contribution = dampingFactor * delta * (edgeWeight / outWeight);
202
+ const currentDelta = nextDeltas.get(neighbor) ?? 0;
203
+ nextDeltas.set(neighbor, currentDelta + contribution);
204
+ }
205
+ }
206
+ }
207
+
208
+ // Add teleportation probability as delta
209
+ for (const node of this.graph.nodes()) {
210
+ const nodeId = node.id;
211
+ const currentDelta = nextDeltas.get(nodeId) ?? 0;
212
+ if (personalVector) {
213
+ nextDeltas.set(nodeId, currentDelta + (1 - dampingFactor) * (personalVector.get(nodeId) ?? 0));
214
+ } else {
215
+ nextDeltas.set(nodeId, currentDelta + randomJump);
216
+ }
217
+ }
218
+
219
+ // Find active nodes for next iteration
220
+ const nextActive = new Set<NodeId>();
221
+ let maxDelta = 0;
222
+
223
+ for (const [nodeId, delta] of nextDeltas) {
224
+ maxDelta = Math.max(maxDelta, Math.abs(delta));
225
+ if (Math.abs(delta) >= deltaThreshold) {
226
+ nextActive.add(nodeId);
227
+ }
228
+ }
229
+
230
+ // Update for next iteration
231
+ this.deltas = nextDeltas;
232
+ this.activeNodes = nextActive;
233
+
234
+ // Global convergence check
235
+ if (maxDelta < tolerance) {
236
+ break;
237
+ }
238
+ }
239
+
240
+ // Normalize final scores
241
+ this.normalizeMap(this.scores);
242
+
243
+ return new Map(this.scores);
244
+ }
245
+
246
+ /**
247
+ * Update PageRank scores after graph modification.
248
+ * This is where delta-based approach really shines.
249
+ * @param modifiedNodes - Set of nodes that were modified (edges added/removed)
250
+ * @param options - Configuration options for PageRank computation
251
+ * @returns Updated PageRank scores
252
+ */
253
+ public update(modifiedNodes: Set<NodeId>, options: DeltaPageRankOptions = {}): Map<NodeId, number> {
254
+ // Mark modified nodes and their neighbors as active
255
+ this.activeNodes.clear();
256
+
257
+ for (const nodeId of modifiedNodes) {
258
+ this.activeNodes.add(nodeId);
259
+
260
+ // Add incoming neighbors
261
+ for (const neighbor of Array.from(this.graph.inNeighbors(nodeId))) {
262
+ this.activeNodes.add(neighbor);
263
+ }
264
+
265
+ // Add outgoing neighbors
266
+ for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {
267
+ this.activeNodes.add(neighbor);
268
+ }
269
+ }
270
+
271
+ // Recompute only for active nodes
272
+ return this.compute(options);
273
+ }
274
+
275
+ private normalizeMap(map: Map<NodeId, number>): void {
276
+ let sum = 0;
277
+ for (const value of map.values()) {
278
+ sum += value;
279
+ }
280
+
281
+ if (sum > 0) {
282
+ for (const [key, value] of Array.from(map)) {
283
+ map.set(key, value / sum);
284
+ }
285
+ }
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Priority queue based implementation for even better performance
291
+ * Processes nodes in order of their delta magnitude
292
+ */
293
+ export class PriorityDeltaPageRank {
294
+ private graph: Graph;
295
+ private scores: Map<NodeId, number>;
296
+ private priorityQueue: PriorityQueue<NodeId>;
297
+ private nodeDeltas: Map<NodeId, number>;
298
+ private outWeights: Map<NodeId, number>;
299
+ private danglingNodes: Set<NodeId>;
300
+ private nodeCount: number;
301
+
302
+ /**
303
+ * Creates a new PriorityDeltaPageRank instance for the given graph.
304
+ * @param graph - The directed graph to compute PageRank on
305
+ */
306
+ constructor(graph: Graph) {
307
+ if (!graph.isDirected) {
308
+ throw new Error("PriorityDeltaPageRank requires a directed graph");
309
+ }
310
+
311
+ this.graph = graph;
312
+ this.scores = new Map();
313
+ this.nodeDeltas = new Map();
314
+ this.outWeights = new Map();
315
+ this.danglingNodes = new Set();
316
+ this.nodeCount = graph.nodeCount;
317
+
318
+ // Priority queue ordered by delta magnitude (larger deltas have higher priority)
319
+ this.priorityQueue = new PriorityQueue<NodeId>((a, b) => b - a);
320
+
321
+ this.initialize();
322
+ }
323
+
324
+ private initialize(): void {
325
+ const initialValue = 1.0 / this.nodeCount;
326
+
327
+ // Initialize all nodes with initial delta
328
+ for (const node of this.graph.nodes()) {
329
+ const nodeId = node.id;
330
+ this.scores.set(nodeId, 0); // Start with zero scores
331
+ this.nodeDeltas.set(nodeId, initialValue);
332
+ this.priorityQueue.enqueue(nodeId, initialValue);
333
+
334
+ // Precompute out-weights
335
+ let totalOutWeight = 0;
336
+ let outDegree = 0;
337
+
338
+ for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {
339
+ outDegree++;
340
+ const edge = this.graph.getEdge(nodeId, neighbor);
341
+ totalOutWeight += edge?.weight ?? 1;
342
+ }
343
+
344
+ this.outWeights.set(nodeId, totalOutWeight);
345
+
346
+ if (outDegree === 0) {
347
+ this.danglingNodes.add(nodeId);
348
+ }
349
+ }
350
+ }
351
+
352
+ /**
353
+ * Computes PageRank scores using priority queue-based delta iteration.
354
+ * Processes nodes in order of their delta magnitude for optimal convergence.
355
+ * @param options - Configuration options for PageRank computation
356
+ * @returns Map of node IDs to their PageRank scores
357
+ */
358
+ public computeWithPriority(options: DeltaPageRankOptions = {}): Map<NodeId, number> {
359
+ const {
360
+ dampingFactor = 0.85,
361
+ tolerance = 1e-6,
362
+ maxIterations = 100,
363
+ deltaThreshold = tolerance / 10,
364
+ weight,
365
+ } = options;
366
+
367
+ let iteration = 0;
368
+ let processedCount = 0;
369
+
370
+ while (!this.priorityQueue.isEmpty() && iteration < maxIterations) {
371
+ const nodeId = this.priorityQueue.dequeue();
372
+ if (nodeId === undefined) {
373
+ break;
374
+ }
375
+
376
+ const delta = this.nodeDeltas.get(nodeId) ?? 0;
377
+
378
+ // Skip if delta is too small
379
+ if (Math.abs(delta) < deltaThreshold) {
380
+ continue;
381
+ }
382
+
383
+ // Apply delta to node's score
384
+ const currentScore = this.scores.get(nodeId) ?? 0;
385
+ this.scores.set(nodeId, currentScore + delta);
386
+ this.nodeDeltas.set(nodeId, 0);
387
+
388
+ // Distribute delta to neighbors
389
+ const outWeight = this.outWeights.get(nodeId) ?? 0;
390
+ if (outWeight > 0) {
391
+ for (const neighbor of Array.from(this.graph.neighbors(nodeId))) {
392
+ let edgeWeight = 1;
393
+ if (weight) {
394
+ const edge = this.graph.getEdge(nodeId, neighbor);
395
+ edgeWeight = edge?.weight ?? 1;
396
+ }
397
+
398
+ const contribution = dampingFactor * delta * (edgeWeight / outWeight);
399
+ const currentNeighborDelta = this.nodeDeltas.get(neighbor) ?? 0;
400
+ const newDelta = currentNeighborDelta + contribution;
401
+ this.nodeDeltas.set(neighbor, newDelta);
402
+
403
+ // Re-enqueue neighbor with updated priority
404
+ if (Math.abs(newDelta) >= deltaThreshold) {
405
+ this.priorityQueue.enqueue(neighbor, Math.abs(newDelta));
406
+ }
407
+ }
408
+ }
409
+
410
+ processedCount++;
411
+
412
+ // Periodic convergence check
413
+ if (processedCount % 1000 === 0) {
414
+ let maxDelta = 0;
415
+ for (const d of this.nodeDeltas.values()) {
416
+ maxDelta = Math.max(maxDelta, Math.abs(d));
417
+ }
418
+ if (maxDelta < tolerance) {
419
+ break;
420
+ }
421
+ }
422
+
423
+ iteration++;
424
+ }
425
+
426
+ // Apply any remaining deltas
427
+ for (const [nodeId, delta] of this.nodeDeltas) {
428
+ if (Math.abs(delta) >= deltaThreshold) {
429
+ const currentScore = this.scores.get(nodeId) ?? 0;
430
+ this.scores.set(nodeId, currentScore + delta);
431
+ }
432
+ }
433
+
434
+ // Add teleportation probability
435
+ const teleport = (1 - dampingFactor) / this.nodeCount;
436
+ for (const [nodeId, score] of this.scores) {
437
+ this.scores.set(nodeId, score + teleport);
438
+ }
439
+
440
+ // Normalize final scores
441
+ this.normalizeMap(this.scores);
442
+
443
+ return new Map(this.scores);
444
+ }
445
+
446
+ private normalizeMap(map: Map<NodeId, number>): void {
447
+ let sum = 0;
448
+ for (const value of map.values()) {
449
+ sum += value;
450
+ }
451
+
452
+ if (sum > 0) {
453
+ for (const [key, value] of Array.from(map)) {
454
+ map.set(key, value / sum);
455
+ }
456
+ }
457
+ }
458
+ }
@@ -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
  * Eigenvector centrality implementation
@@ -19,19 +19,14 @@ export interface EigenvectorCentralityOptions extends CentralityOptions {
19
19
  }
20
20
 
21
21
  /**
22
- * Calculate eigenvector centrality for all nodes in the graph
23
- * Uses the power iteration method to find the dominant eigenvector
22
+ * Calculate eigenvector centrality for all nodes in the graph.
23
+ * Uses the power iteration method to find the dominant eigenvector.
24
+ * @param graph - The graph to compute eigenvector centrality on
25
+ * @param options - Configuration options for the computation
26
+ * @returns Object mapping node IDs to their eigenvector centrality scores
24
27
  */
25
- export function eigenvectorCentrality(
26
- graph: Graph,
27
- options: EigenvectorCentralityOptions = {},
28
- ): CentralityResult {
29
- const {
30
- maxIterations = 100,
31
- tolerance = 1e-6,
32
- normalized = true,
33
- startVector,
34
- } = options;
28
+ export function eigenvectorCentrality(graph: Graph, options: EigenvectorCentralityOptions = {}): CentralityResult {
29
+ const { maxIterations = 100, tolerance = 1e-6, normalized = true, startVector } = options;
35
30
 
36
31
  const centrality: CentralityResult = {};
37
32
  const nodes = Array.from(graph.nodes());
@@ -146,7 +141,11 @@ export function eigenvectorCentrality(
146
141
  }
147
142
 
148
143
  /**
149
- * Calculate eigenvector centrality for a specific node
144
+ * Calculate eigenvector centrality for a specific node.
145
+ * @param graph - The graph to compute eigenvector centrality on
146
+ * @param nodeId - The ID of the node to calculate centrality for
147
+ * @param options - Configuration options for the computation
148
+ * @returns The eigenvector centrality score for the specified node
150
149
  */
151
150
  export function nodeEigenvectorCentrality(
152
151
  graph: Graph,
@@ -1,5 +1,5 @@
1
- import type {Graph} from "../../core/graph.js";
2
- import type {CentralityOptions} from "../../types/index.js";
1
+ import type { Graph } from "../../core/graph.js";
2
+ import type { CentralityOptions } from "../../types/index.js";
3
3
 
4
4
  /**
5
5
  * HITS (Hyperlink-Induced Topic Search) algorithm implementation
@@ -25,18 +25,14 @@ export interface HITSOptions extends CentralityOptions {
25
25
  }
26
26
 
27
27
  /**
28
- * Calculate HITS hub and authority scores for all nodes in the graph
29
- * Uses iterative method with normalization
28
+ * Calculate HITS hub and authority scores for all nodes in the graph.
29
+ * Uses iterative method with normalization.
30
+ * @param graph - The graph to compute HITS scores on
31
+ * @param options - Configuration options for the computation
32
+ * @returns Object containing hub and authority scores for all nodes
30
33
  */
31
- export function hits(
32
- graph: Graph,
33
- options: HITSOptions = {},
34
- ): HITSResult {
35
- const {
36
- maxIterations = 100,
37
- tolerance = 1e-6,
38
- normalized = true,
39
- } = options;
34
+ export function hits(graph: Graph, options: HITSOptions = {}): HITSResult {
35
+ const { maxIterations = 100, tolerance = 1e-6, normalized = true } = options;
40
36
 
41
37
  const hubs: Record<string, number> = {};
42
38
  const authorities: Record<string, number> = {};
@@ -45,7 +41,7 @@ export function hits(
45
41
  const nodeIds = nodes.map((node) => node.id);
46
42
 
47
43
  if (nodeIds.length === 0) {
48
- return {hubs, authorities};
44
+ return { hubs, authorities };
49
45
  }
50
46
 
51
47
  // Initialize scores
@@ -185,17 +181,21 @@ export function hits(
185
181
  }
186
182
  }
187
183
 
188
- return {hubs, authorities};
184
+ return { hubs, authorities };
189
185
  }
190
186
 
191
187
  /**
192
- * Calculate HITS scores for a specific node
188
+ * Calculate HITS scores for a specific node.
189
+ * @param graph - The graph to compute HITS scores on
190
+ * @param nodeId - The ID of the node to calculate scores for
191
+ * @param options - Configuration options for the computation
192
+ * @returns Object containing hub and authority scores for the specified node
193
193
  */
194
194
  export function nodeHITS(
195
195
  graph: Graph,
196
196
  nodeId: string | number,
197
197
  options: HITSOptions = {},
198
- ): {hub: number, authority: number} {
198
+ ): { hub: number; authority: number } {
199
199
  if (!graph.hasNode(nodeId)) {
200
200
  throw new Error(`Node ${String(nodeId)} not found in graph`);
201
201
  }
@@ -2,16 +2,23 @@
2
2
  * Centrality algorithms
3
3
  */
4
4
 
5
- export type {BetweennessCentralityOptions} from "./betweenness.js";
6
- export {betweennessCentrality, edgeBetweennessCentrality, nodeBetweennessCentrality} from "./betweenness.js";
7
- export type {ClosenessCentralityOptions} from "./closeness.js";
8
- export {closenessCentrality, nodeClosenessCentrality, nodeWeightedClosenessCentrality, weightedClosenessCentrality} from "./closeness.js";
9
- export {degreeCentrality, nodeDegreeCentrality} from "./degree.js";
10
- export type {EigenvectorCentralityOptions} from "./eigenvector.js";
11
- export {eigenvectorCentrality, nodeEigenvectorCentrality} from "./eigenvector.js";
12
- export type {HITSOptions, HITSResult} from "./hits.js";
13
- export {hits, nodeHITS} from "./hits.js";
14
- export type {KatzCentralityOptions} from "./katz.js";
15
- export {katzCentrality, nodeKatzCentrality} from "./katz.js";
16
- export type {PageRankOptions, PageRankResult} from "./pagerank.js";
17
- export {pageRank, pageRankCentrality, personalizedPageRank, topPageRankNodes} from "./pagerank.js";
5
+ export type { BetweennessCentralityOptions } from "./betweenness.js";
6
+ export { betweennessCentrality, edgeBetweennessCentrality, nodeBetweennessCentrality } from "./betweenness.js";
7
+ export type { ClosenessCentralityOptions } from "./closeness.js";
8
+ export {
9
+ closenessCentrality,
10
+ nodeClosenessCentrality,
11
+ nodeWeightedClosenessCentrality,
12
+ weightedClosenessCentrality,
13
+ } from "./closeness.js";
14
+ export { degreeCentrality, nodeDegreeCentrality } from "./degree.js";
15
+ export type { DeltaPageRankOptions } from "./delta-pagerank.js";
16
+ export { DeltaPageRank, PriorityDeltaPageRank } from "./delta-pagerank.js";
17
+ export type { EigenvectorCentralityOptions } from "./eigenvector.js";
18
+ export { eigenvectorCentrality, nodeEigenvectorCentrality } from "./eigenvector.js";
19
+ export type { HITSOptions, HITSResult } from "./hits.js";
20
+ export { hits, nodeHITS } from "./hits.js";
21
+ export type { KatzCentralityOptions } from "./katz.js";
22
+ export { katzCentrality, nodeKatzCentrality } from "./katz.js";
23
+ export type { PageRankOptions, PageRankResult } from "./pagerank.js";
24
+ export { pageRank, pageRankCentrality, personalizedPageRank, topPageRankNodes } from "./pagerank.js";
@@ -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
  * Katz centrality implementation
@@ -22,20 +22,14 @@ export interface KatzCentralityOptions extends CentralityOptions {
22
22
  }
23
23
 
24
24
  /**
25
- * Calculate Katz centrality for all nodes in the graph
26
- * Uses iterative method to compute centrality scores
25
+ * Calculate Katz centrality for all nodes in the graph.
26
+ * Uses iterative method to compute centrality scores.
27
+ * @param graph - The graph to compute Katz centrality on
28
+ * @param options - Configuration options for the computation
29
+ * @returns Object mapping node IDs to their Katz centrality scores
27
30
  */
28
- export function katzCentrality(
29
- graph: Graph,
30
- options: KatzCentralityOptions = {},
31
- ): CentralityResult {
32
- const {
33
- alpha = 0.1,
34
- beta = 1.0,
35
- maxIterations = 100,
36
- tolerance = 1e-6,
37
- normalized = true,
38
- } = options;
31
+ export function katzCentrality(graph: Graph, options: KatzCentralityOptions = {}): CentralityResult {
32
+ const { alpha = 0.1, beta = 1.0, maxIterations = 100, tolerance = 1e-6, normalized = true } = options;
39
33
 
40
34
  const centrality: CentralityResult = {};
41
35
  const nodes = Array.from(graph.nodes());
@@ -68,16 +62,14 @@ export function katzCentrality(
68
62
 
69
63
  // For directed graphs, use in-neighbors
70
64
  // For undirected graphs, use all neighbors
71
- const neighbors = graph.isDirected ?
72
- Array.from(graph.inNeighbors(nodeId)) :
73
- graph.neighbors(nodeId);
65
+ const neighbors = graph.isDirected ? Array.from(graph.inNeighbors(nodeId)) : graph.neighbors(nodeId);
74
66
 
75
67
  for (const neighbor of neighbors) {
76
68
  const neighborKey = neighbor.toString();
77
69
  sum += previousScores.get(neighborKey) ?? 0;
78
70
  }
79
71
 
80
- currentScores.set(nodeId.toString(), (alpha * sum) + beta);
72
+ currentScores.set(nodeId.toString(), alpha * sum + beta);
81
73
  }
82
74
 
83
75
  // Check for convergence
@@ -123,13 +115,13 @@ export function katzCentrality(
123
115
  }
124
116
 
125
117
  /**
126
- * Calculate Katz centrality for a specific node
118
+ * Calculate Katz centrality for a specific node.
119
+ * @param graph - The graph to compute Katz centrality on
120
+ * @param nodeId - The ID of the node to calculate centrality for
121
+ * @param options - Configuration options for the computation
122
+ * @returns The Katz centrality score for the specified node
127
123
  */
128
- export function nodeKatzCentrality(
129
- graph: Graph,
130
- nodeId: string | number,
131
- options: KatzCentralityOptions = {},
132
- ): number {
124
+ export function nodeKatzCentrality(graph: Graph, nodeId: string | number, options: KatzCentralityOptions = {}): number {
133
125
  if (!graph.hasNode(nodeId)) {
134
126
  throw new Error(`Node ${String(nodeId)} not found in graph`);
135
127
  }