@graphty/algorithms 2.1.2 → 2.2.0

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 (355) hide show
  1. package/README.md +139 -50
  2. package/dist/algorithms.js +15260 -10390
  3. package/dist/algorithms.js.map +1 -1
  4. package/dist/algorithms.standalone.js +26675 -21542
  5. package/dist/algorithms.standalone.js.map +1 -1
  6. package/dist/src/algorithms/centrality/betweenness.d.ts +18 -0
  7. package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
  8. package/dist/src/algorithms/centrality/betweenness.js +40 -1
  9. package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
  10. package/dist/src/algorithms/centrality/closeness.d.ts +20 -0
  11. package/dist/src/algorithms/centrality/closeness.d.ts.map +1 -1
  12. package/dist/src/algorithms/centrality/closeness.js +93 -8
  13. package/dist/src/algorithms/centrality/closeness.js.map +1 -1
  14. package/dist/src/algorithms/centrality/degree.d.ts +9 -0
  15. package/dist/src/algorithms/centrality/degree.d.ts.map +1 -1
  16. package/dist/src/algorithms/centrality/degree.js +18 -0
  17. package/dist/src/algorithms/centrality/degree.js.map +1 -1
  18. package/dist/src/algorithms/centrality/eigenvector.d.ts +10 -0
  19. package/dist/src/algorithms/centrality/eigenvector.d.ts.map +1 -1
  20. package/dist/src/algorithms/centrality/eigenvector.js +29 -0
  21. package/dist/src/algorithms/centrality/eigenvector.js.map +1 -1
  22. package/dist/src/algorithms/centrality/hits.d.ts +9 -0
  23. package/dist/src/algorithms/centrality/hits.d.ts.map +1 -1
  24. package/dist/src/algorithms/centrality/hits.js +23 -0
  25. package/dist/src/algorithms/centrality/hits.js.map +1 -1
  26. package/dist/src/algorithms/centrality/katz.d.ts +9 -0
  27. package/dist/src/algorithms/centrality/katz.d.ts.map +1 -1
  28. package/dist/src/algorithms/centrality/katz.js +31 -0
  29. package/dist/src/algorithms/centrality/katz.js.map +1 -1
  30. package/dist/src/algorithms/centrality/pagerank.d.ts +13 -13
  31. package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -1
  32. package/dist/src/algorithms/centrality/pagerank.js +47 -10
  33. package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
  34. package/dist/src/algorithms/community/girvan-newman-legacy.d.ts +27 -0
  35. package/dist/src/algorithms/community/girvan-newman-legacy.d.ts.map +1 -0
  36. package/dist/src/algorithms/community/girvan-newman-legacy.js +335 -0
  37. package/dist/src/algorithms/community/girvan-newman-legacy.js.map +1 -0
  38. package/dist/src/algorithms/community/girvan-newman.d.ts +5 -3
  39. package/dist/src/algorithms/community/girvan-newman.d.ts.map +1 -1
  40. package/dist/src/algorithms/community/girvan-newman.js +34 -308
  41. package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
  42. package/dist/src/algorithms/community/label-propagation.d.ts +9 -6
  43. package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -1
  44. package/dist/src/algorithms/community/label-propagation.js +24 -110
  45. package/dist/src/algorithms/community/label-propagation.js.map +1 -1
  46. package/dist/src/algorithms/components/connected.d.ts.map +1 -1
  47. package/dist/src/algorithms/components/connected.js +28 -77
  48. package/dist/src/algorithms/components/connected.js.map +1 -1
  49. package/dist/src/algorithms/mst/kruskal.d.ts.map +1 -1
  50. package/dist/src/algorithms/mst/kruskal.js +59 -3
  51. package/dist/src/algorithms/mst/kruskal.js.map +1 -1
  52. package/dist/src/algorithms/shortest-path/bellman-ford.d.ts.map +1 -1
  53. package/dist/src/algorithms/shortest-path/bellman-ford.js +46 -0
  54. package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
  55. package/dist/src/algorithms/shortest-path/dijkstra.d.ts.map +1 -1
  56. package/dist/src/algorithms/shortest-path/dijkstra.js +27 -0
  57. package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
  58. package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts +15 -5
  59. package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts.map +1 -1
  60. package/dist/src/algorithms/shortest-path/floyd-warshall.js +97 -107
  61. package/dist/src/algorithms/shortest-path/floyd-warshall.js.map +1 -1
  62. package/dist/src/algorithms/traversal/bfs-unified.d.ts +2 -12
  63. package/dist/src/algorithms/traversal/bfs-unified.d.ts.map +1 -1
  64. package/dist/src/algorithms/traversal/bfs-unified.js +47 -308
  65. package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -1
  66. package/dist/src/algorithms/traversal/bfs-variants.d.ts.map +1 -1
  67. package/dist/src/algorithms/traversal/bfs-variants.js +5 -25
  68. package/dist/src/algorithms/traversal/bfs-variants.js.map +1 -1
  69. package/dist/src/algorithms/traversal/bfs.d.ts +0 -3
  70. package/dist/src/algorithms/traversal/bfs.d.ts.map +1 -1
  71. package/dist/src/algorithms/traversal/bfs.js +0 -4
  72. package/dist/src/algorithms/traversal/bfs.js.map +1 -1
  73. package/dist/src/algorithms/traversal/dfs.d.ts.map +1 -1
  74. package/dist/src/algorithms/traversal/dfs.js +33 -154
  75. package/dist/src/algorithms/traversal/dfs.js.map +1 -1
  76. package/dist/src/clustering/hierarchical-legacy.d.ts +56 -0
  77. package/dist/src/clustering/hierarchical-legacy.d.ts.map +1 -0
  78. package/dist/src/clustering/hierarchical-legacy.js +441 -0
  79. package/dist/src/clustering/hierarchical-legacy.js.map +1 -0
  80. package/dist/src/clustering/hierarchical.d.ts +7 -39
  81. package/dist/src/clustering/hierarchical.d.ts.map +1 -1
  82. package/dist/src/clustering/hierarchical.js +56 -417
  83. package/dist/src/clustering/hierarchical.js.map +1 -1
  84. package/dist/src/clustering/k-core-legacy.d.ts +30 -0
  85. package/dist/src/clustering/k-core-legacy.d.ts.map +1 -0
  86. package/dist/src/clustering/k-core-legacy.js +191 -0
  87. package/dist/src/clustering/k-core-legacy.js.map +1 -0
  88. package/dist/src/clustering/k-core.d.ts +8 -7
  89. package/dist/src/clustering/k-core.d.ts.map +1 -1
  90. package/dist/src/clustering/k-core.js +33 -174
  91. package/dist/src/clustering/k-core.js.map +1 -1
  92. package/dist/src/clustering/mcl-legacy.d.ts +42 -0
  93. package/dist/src/clustering/mcl-legacy.d.ts.map +1 -0
  94. package/dist/src/clustering/mcl-legacy.js +386 -0
  95. package/dist/src/clustering/mcl-legacy.js.map +1 -0
  96. package/dist/src/clustering/mcl.d.ts +9 -32
  97. package/dist/src/clustering/mcl.d.ts.map +1 -1
  98. package/dist/src/clustering/mcl.js +48 -374
  99. package/dist/src/clustering/mcl.js.map +1 -1
  100. package/dist/src/index.d.ts +29 -3
  101. package/dist/src/index.d.ts.map +1 -1
  102. package/dist/src/index.js +2 -1
  103. package/dist/src/index.js.map +1 -1
  104. package/dist/src/indexed/accelerator.d.ts +141 -11
  105. package/dist/src/indexed/accelerator.d.ts.map +1 -1
  106. package/dist/src/indexed/accelerator.js +319 -5
  107. package/dist/src/indexed/accelerator.js.map +1 -1
  108. package/dist/src/indexed/all-pairs.d.ts +59 -0
  109. package/dist/src/indexed/all-pairs.d.ts.map +1 -0
  110. package/dist/src/indexed/all-pairs.js +274 -0
  111. package/dist/src/indexed/all-pairs.js.map +1 -0
  112. package/dist/src/indexed/bellman-ford.d.ts +25 -0
  113. package/dist/src/indexed/bellman-ford.d.ts.map +1 -0
  114. package/dist/src/indexed/bellman-ford.js +59 -0
  115. package/dist/src/indexed/bellman-ford.js.map +1 -0
  116. package/dist/src/indexed/betweenness.d.ts +85 -0
  117. package/dist/src/indexed/betweenness.d.ts.map +1 -0
  118. package/dist/src/indexed/betweenness.js +188 -0
  119. package/dist/src/indexed/betweenness.js.map +1 -0
  120. package/dist/src/indexed/bfs.d.ts +69 -2
  121. package/dist/src/indexed/bfs.d.ts.map +1 -1
  122. package/dist/src/indexed/bfs.js +148 -1
  123. package/dist/src/indexed/bfs.js.map +1 -1
  124. package/dist/src/indexed/bipartite.d.ts +37 -0
  125. package/dist/src/indexed/bipartite.d.ts.map +1 -0
  126. package/dist/src/indexed/bipartite.js +54 -0
  127. package/dist/src/indexed/bipartite.js.map +1 -0
  128. package/dist/src/indexed/closeness.d.ts +49 -0
  129. package/dist/src/indexed/closeness.d.ts.map +1 -0
  130. package/dist/src/indexed/closeness.js +127 -0
  131. package/dist/src/indexed/closeness.js.map +1 -0
  132. package/dist/src/indexed/common-neighbors.d.ts +14 -1
  133. package/dist/src/indexed/common-neighbors.d.ts.map +1 -1
  134. package/dist/src/indexed/common-neighbors.js +24 -14
  135. package/dist/src/indexed/common-neighbors.js.map +1 -1
  136. package/dist/src/indexed/degree.d.ts +19 -0
  137. package/dist/src/indexed/degree.d.ts.map +1 -0
  138. package/dist/src/indexed/degree.js +45 -0
  139. package/dist/src/indexed/degree.js.map +1 -0
  140. package/dist/src/indexed/delta-pagerank.d.ts +145 -0
  141. package/dist/src/indexed/delta-pagerank.d.ts.map +1 -0
  142. package/dist/src/indexed/delta-pagerank.js +428 -0
  143. package/dist/src/indexed/delta-pagerank.js.map +1 -0
  144. package/dist/src/indexed/dfs.d.ts +55 -0
  145. package/dist/src/indexed/dfs.d.ts.map +1 -0
  146. package/dist/src/indexed/dfs.js +146 -0
  147. package/dist/src/indexed/dfs.js.map +1 -0
  148. package/dist/src/indexed/eigenvector.d.ts +48 -0
  149. package/dist/src/indexed/eigenvector.d.ts.map +1 -0
  150. package/dist/src/indexed/eigenvector.js +162 -0
  151. package/dist/src/indexed/eigenvector.js.map +1 -0
  152. package/dist/src/indexed/facade.d.ts +109 -0
  153. package/dist/src/indexed/facade.d.ts.map +1 -0
  154. package/dist/src/indexed/facade.js +204 -0
  155. package/dist/src/indexed/facade.js.map +1 -0
  156. package/dist/src/indexed/flow.d.ts +120 -0
  157. package/dist/src/indexed/flow.d.ts.map +1 -0
  158. package/dist/src/indexed/flow.js +377 -0
  159. package/dist/src/indexed/flow.js.map +1 -0
  160. package/dist/src/indexed/girvan-newman.d.ts +42 -0
  161. package/dist/src/indexed/girvan-newman.d.ts.map +1 -0
  162. package/dist/src/indexed/girvan-newman.js +90 -0
  163. package/dist/src/indexed/girvan-newman.js.map +1 -0
  164. package/dist/src/indexed/grsbm.d.ts +85 -0
  165. package/dist/src/indexed/grsbm.d.ts.map +1 -0
  166. package/dist/src/indexed/grsbm.js +287 -0
  167. package/dist/src/indexed/grsbm.js.map +1 -0
  168. package/dist/src/indexed/hierarchical.d.ts +69 -0
  169. package/dist/src/indexed/hierarchical.d.ts.map +1 -0
  170. package/dist/src/indexed/hierarchical.js +245 -0
  171. package/dist/src/indexed/hierarchical.js.map +1 -0
  172. package/dist/src/indexed/index.d.ts +29 -3
  173. package/dist/src/indexed/index.d.ts.map +1 -1
  174. package/dist/src/indexed/index.js +29 -3
  175. package/dist/src/indexed/index.js.map +1 -1
  176. package/dist/src/indexed/isomorphism.d.ts +42 -0
  177. package/dist/src/indexed/isomorphism.d.ts.map +1 -0
  178. package/dist/src/indexed/isomorphism.js +269 -0
  179. package/dist/src/indexed/isomorphism.js.map +1 -0
  180. package/dist/src/indexed/label-propagation.d.ts +134 -0
  181. package/dist/src/indexed/label-propagation.d.ts.map +1 -0
  182. package/dist/src/indexed/label-propagation.js +486 -0
  183. package/dist/src/indexed/label-propagation.js.map +1 -0
  184. package/dist/src/indexed/leiden.d.ts +52 -0
  185. package/dist/src/indexed/leiden.d.ts.map +1 -0
  186. package/dist/src/indexed/leiden.js +384 -0
  187. package/dist/src/indexed/leiden.js.map +1 -0
  188. package/dist/src/indexed/link-prediction.d.ts +147 -0
  189. package/dist/src/indexed/link-prediction.d.ts.map +1 -0
  190. package/dist/src/indexed/link-prediction.js +317 -0
  191. package/dist/src/indexed/link-prediction.js.map +1 -0
  192. package/dist/src/indexed/markov.d.ts +54 -0
  193. package/dist/src/indexed/markov.d.ts.map +1 -0
  194. package/dist/src/indexed/markov.js +284 -0
  195. package/dist/src/indexed/markov.js.map +1 -0
  196. package/dist/src/indexed/matching.d.ts +53 -0
  197. package/dist/src/indexed/matching.d.ts.map +1 -0
  198. package/dist/src/indexed/matching.js +139 -0
  199. package/dist/src/indexed/matching.js.map +1 -0
  200. package/dist/src/indexed/min-cut.d.ts +48 -0
  201. package/dist/src/indexed/min-cut.d.ts.map +1 -0
  202. package/dist/src/indexed/min-cut.js +175 -0
  203. package/dist/src/indexed/min-cut.js.map +1 -0
  204. package/dist/src/indexed/modularity.d.ts +34 -0
  205. package/dist/src/indexed/modularity.d.ts.map +1 -0
  206. package/dist/src/indexed/modularity.js +74 -0
  207. package/dist/src/indexed/modularity.js.map +1 -0
  208. package/dist/src/indexed/mst.d.ts +29 -1
  209. package/dist/src/indexed/mst.d.ts.map +1 -1
  210. package/dist/src/indexed/mst.js +62 -0
  211. package/dist/src/indexed/mst.js.map +1 -1
  212. package/dist/src/indexed/pagerank.d.ts +29 -6
  213. package/dist/src/indexed/pagerank.d.ts.map +1 -1
  214. package/dist/src/indexed/pagerank.js +107 -11
  215. package/dist/src/indexed/pagerank.js.map +1 -1
  216. package/dist/src/indexed/point-to-point.d.ts +53 -0
  217. package/dist/src/indexed/point-to-point.d.ts.map +1 -0
  218. package/dist/src/indexed/point-to-point.js +173 -0
  219. package/dist/src/indexed/point-to-point.js.map +1 -0
  220. package/dist/src/indexed/scc.d.ts +53 -0
  221. package/dist/src/indexed/scc.d.ts.map +1 -0
  222. package/dist/src/indexed/scc.js +110 -0
  223. package/dist/src/indexed/scc.js.map +1 -0
  224. package/dist/src/indexed/spectral.d.ts +61 -0
  225. package/dist/src/indexed/spectral.d.ts.map +1 -0
  226. package/dist/src/indexed/spectral.js +476 -0
  227. package/dist/src/indexed/spectral.js.map +1 -0
  228. package/dist/src/indexed/structures/bit-set.d.ts +45 -0
  229. package/dist/src/indexed/structures/bit-set.d.ts.map +1 -0
  230. package/dist/src/indexed/structures/bit-set.js +57 -0
  231. package/dist/src/indexed/structures/bit-set.js.map +1 -0
  232. package/dist/src/indexed/structures/max-heap.d.ts +52 -0
  233. package/dist/src/indexed/structures/max-heap.d.ts.map +1 -0
  234. package/dist/src/indexed/structures/max-heap.js +66 -0
  235. package/dist/src/indexed/structures/max-heap.js.map +1 -0
  236. package/dist/src/indexed/structures/min-heap.d.ts +30 -1
  237. package/dist/src/indexed/structures/min-heap.d.ts.map +1 -1
  238. package/dist/src/indexed/structures/min-heap.js +46 -6
  239. package/dist/src/indexed/structures/min-heap.js.map +1 -1
  240. package/dist/src/indexed/structures/ring-queue.d.ts +41 -0
  241. package/dist/src/indexed/structures/ring-queue.d.ts.map +1 -0
  242. package/dist/src/indexed/structures/ring-queue.js +64 -0
  243. package/dist/src/indexed/structures/ring-queue.js.map +1 -0
  244. package/dist/src/indexed/sync.d.ts +50 -0
  245. package/dist/src/indexed/sync.d.ts.map +1 -0
  246. package/dist/src/indexed/sync.js +175 -0
  247. package/dist/src/indexed/sync.js.map +1 -0
  248. package/dist/src/indexed/terahac.d.ts +58 -0
  249. package/dist/src/indexed/terahac.d.ts.map +1 -0
  250. package/dist/src/indexed/terahac.js +244 -0
  251. package/dist/src/indexed/terahac.js.map +1 -0
  252. package/dist/src/indexed/to-snapshot.d.ts +45 -2
  253. package/dist/src/indexed/to-snapshot.d.ts.map +1 -1
  254. package/dist/src/indexed/to-snapshot.js +140 -6
  255. package/dist/src/indexed/to-snapshot.js.map +1 -1
  256. package/dist/src/link-prediction/common-neighbors-legacy.d.ts +71 -0
  257. package/dist/src/link-prediction/common-neighbors-legacy.d.ts.map +1 -0
  258. package/dist/src/link-prediction/common-neighbors-legacy.js +172 -0
  259. package/dist/src/link-prediction/common-neighbors-legacy.js.map +1 -0
  260. package/dist/src/link-prediction/common-neighbors.d.ts +11 -19
  261. package/dist/src/link-prediction/common-neighbors.d.ts.map +1 -1
  262. package/dist/src/link-prediction/common-neighbors.js +56 -123
  263. package/dist/src/link-prediction/common-neighbors.js.map +1 -1
  264. package/dist/src/optimized/direction-optimized-bfs.d.ts +6 -0
  265. package/dist/src/optimized/direction-optimized-bfs.d.ts.map +1 -1
  266. package/dist/src/optimized/direction-optimized-bfs.js +6 -0
  267. package/dist/src/optimized/direction-optimized-bfs.js.map +1 -1
  268. package/dist/src/research/grsbm-legacy.d.ts +82 -0
  269. package/dist/src/research/grsbm-legacy.d.ts.map +1 -0
  270. package/dist/src/research/grsbm-legacy.js +416 -0
  271. package/dist/src/research/grsbm-legacy.js.map +1 -0
  272. package/dist/src/research/grsbm.d.ts +9 -66
  273. package/dist/src/research/grsbm.d.ts.map +1 -1
  274. package/dist/src/research/grsbm.js +67 -391
  275. package/dist/src/research/grsbm.js.map +1 -1
  276. package/dist/src/research/sync-legacy.d.ts +48 -0
  277. package/dist/src/research/sync-legacy.d.ts.map +1 -0
  278. package/dist/src/research/sync-legacy.js +337 -0
  279. package/dist/src/research/sync-legacy.js.map +1 -0
  280. package/dist/src/research/sync.d.ts +10 -32
  281. package/dist/src/research/sync.d.ts.map +1 -1
  282. package/dist/src/research/sync.js +28 -316
  283. package/dist/src/research/sync.js.map +1 -1
  284. package/package.json +4 -3
  285. package/src/algorithms/centrality/betweenness.ts +51 -1
  286. package/src/algorithms/centrality/closeness.ts +112 -12
  287. package/src/algorithms/centrality/degree.ts +19 -0
  288. package/src/algorithms/centrality/eigenvector.ts +34 -0
  289. package/src/algorithms/centrality/hits.ts +24 -0
  290. package/src/algorithms/centrality/katz.ts +32 -0
  291. package/src/algorithms/centrality/pagerank.ts +53 -13
  292. package/src/algorithms/community/girvan-newman-legacy.ts +414 -0
  293. package/src/algorithms/community/girvan-newman.ts +36 -386
  294. package/src/algorithms/community/label-propagation.ts +24 -133
  295. package/src/algorithms/components/connected.ts +28 -95
  296. package/src/algorithms/mst/kruskal.ts +65 -4
  297. package/src/algorithms/shortest-path/bellman-ford.ts +49 -0
  298. package/src/algorithms/shortest-path/dijkstra.ts +29 -0
  299. package/src/algorithms/shortest-path/floyd-warshall.ts +106 -136
  300. package/src/algorithms/traversal/bfs-unified.ts +52 -366
  301. package/src/algorithms/traversal/bfs-variants.ts +5 -28
  302. package/src/algorithms/traversal/bfs.ts +0 -4
  303. package/src/algorithms/traversal/dfs.ts +39 -182
  304. package/src/clustering/hierarchical-legacy.ts +551 -0
  305. package/src/clustering/hierarchical.ts +64 -520
  306. package/src/clustering/k-core-legacy.ts +229 -0
  307. package/src/clustering/k-core.ts +38 -209
  308. package/src/clustering/mcl-legacy.ts +498 -0
  309. package/src/clustering/mcl.ts +46 -479
  310. package/src/index.ts +90 -3
  311. package/src/indexed/accelerator.ts +502 -16
  312. package/src/indexed/all-pairs.ts +342 -0
  313. package/src/indexed/bellman-ford.ts +72 -0
  314. package/src/indexed/betweenness.ts +258 -0
  315. package/src/indexed/bfs.ts +189 -3
  316. package/src/indexed/bipartite.ts +77 -0
  317. package/src/indexed/closeness.ts +160 -0
  318. package/src/indexed/common-neighbors.ts +31 -14
  319. package/src/indexed/degree.ts +55 -0
  320. package/src/indexed/delta-pagerank.ts +513 -0
  321. package/src/indexed/dfs.ts +189 -0
  322. package/src/indexed/eigenvector.ts +202 -0
  323. package/src/indexed/facade.ts +229 -0
  324. package/src/indexed/flow.ts +500 -0
  325. package/src/indexed/girvan-newman.ts +120 -0
  326. package/src/indexed/grsbm.ts +390 -0
  327. package/src/indexed/hierarchical.ts +295 -0
  328. package/src/indexed/index.ts +94 -3
  329. package/src/indexed/isomorphism.ts +305 -0
  330. package/src/indexed/label-propagation.ts +582 -0
  331. package/src/indexed/leiden.ts +436 -0
  332. package/src/indexed/link-prediction.ts +399 -0
  333. package/src/indexed/markov.ts +324 -0
  334. package/src/indexed/matching.ts +192 -0
  335. package/src/indexed/min-cut.ts +201 -0
  336. package/src/indexed/modularity.ts +81 -0
  337. package/src/indexed/mst.ts +79 -1
  338. package/src/indexed/pagerank.ts +128 -15
  339. package/src/indexed/point-to-point.ts +220 -0
  340. package/src/indexed/scc.ts +132 -0
  341. package/src/indexed/spectral.ts +550 -0
  342. package/src/indexed/structures/bit-set.ts +65 -0
  343. package/src/indexed/structures/max-heap.ts +74 -0
  344. package/src/indexed/structures/min-heap.ts +51 -6
  345. package/src/indexed/structures/ring-queue.ts +70 -0
  346. package/src/indexed/sync.ts +229 -0
  347. package/src/indexed/terahac.ts +290 -0
  348. package/src/indexed/to-snapshot.ts +156 -6
  349. package/src/link-prediction/common-neighbors-legacy.ts +252 -0
  350. package/src/link-prediction/common-neighbors.ts +65 -168
  351. package/src/optimized/direction-optimized-bfs.ts +6 -1
  352. package/src/research/grsbm-legacy.ts +586 -0
  353. package/src/research/grsbm.ts +76 -555
  354. package/src/research/sync-legacy.ts +456 -0
  355. package/src/research/sync.ts +30 -431
@@ -0,0 +1,202 @@
1
+ import type { F32, F64, GraphSnapshot, NumericVector } from "@graphty/graph-format";
2
+
3
+ import { ConvergenceError } from "../errors.js";
4
+
5
+ /** Options of the index-based eigenvector centrality, matching the legacy `eigenvectorCentrality`. @public */
6
+ export interface EigenvectorOptions {
7
+ /** Iteration cap; default 100. */
8
+ readonly maxIterations?: number | undefined;
9
+ /** Per-node tolerance: the run stops when the L1 change is below `n * tolerance`; default 1e-6. */
10
+ readonly tolerance?: number | undefined;
11
+ /** Rescale the unit-length vector to [0, 1] by min-max, as the legacy function does; default true. */
12
+ readonly normalized?: boolean | undefined;
13
+ /**
14
+ * On a directed snapshot, which arcs feed a node: `"in"` (default, as networkx) the nodes pointing
15
+ * at it, `"out"` the nodes it points at, `"total"` both. Ignored on an undirected snapshot.
16
+ */
17
+ readonly mode?: "in" | "out" | "total" | undefined;
18
+ /** Starting value per node index; default 1 for every node. */
19
+ readonly startVector?: F32 | F64 | undefined;
20
+ }
21
+
22
+ /** Result of the index-based eigenvector centrality. @public */
23
+ export interface EigenvectorResult {
24
+ /** Score per node index. */
25
+ readonly scores: F64;
26
+ /** Iterations actually run; 0 when the relation has no cycle and every score is 0. */
27
+ readonly iterations: number;
28
+ /** Always true: a run that does not converge throws `ConvergenceError` instead. */
29
+ readonly converged: boolean;
30
+ }
31
+
32
+ interface Relation {
33
+ readonly rowPtr: Uint32Array;
34
+ readonly colIdx: Uint32Array;
35
+ }
36
+
37
+ /**
38
+ * Eigenvector centrality by power iteration on `(A + I)`, as networkx does: the identity shift
39
+ * leaves the eigenvectors alone and makes the largest eigenvalue the only one of largest magnitude,
40
+ * so a bipartite or periodic graph converges instead of oscillating. Each node's neighbours are
41
+ * counted once however many parallel edges join them, as in the legacy neighbour sets. When the
42
+ * relation has no cycle (no arcs, or a directed acyclic graph) its matrix is nilpotent and every
43
+ * score is exactly 0.
44
+ * @param s - The snapshot
45
+ * @param o - Algorithm options
46
+ * @returns The scores, the iteration count and the convergence flag
47
+ * @throws {ConvergenceError} When `maxIterations` passes do not meet the tolerance
48
+ * @public
49
+ */
50
+ export function eigenvectorCentrality(s: GraphSnapshot, o: EigenvectorOptions = {}): EigenvectorResult {
51
+ const n = s.nodeCount;
52
+ const maxIter = o.maxIterations ?? 100;
53
+ const tol = o.tolerance ?? 1e-6;
54
+ const start = o.startVector;
55
+ if (start !== undefined && start.length !== n) {
56
+ throw new Error(
57
+ `eigenvectorCentrality: startVector has ${String(start.length)} entries for ${String(n)} nodes`,
58
+ );
59
+ }
60
+ let x = new Float64Array(n);
61
+ if (n === 0) {
62
+ return { scores: x, iterations: 0, converged: true };
63
+ }
64
+ const rel = feeders(s, o.mode ?? "in");
65
+ if (isAcyclic(rel, n)) {
66
+ return { scores: x, iterations: 0, converged: true };
67
+ }
68
+ // A node with nothing feeding it scores exactly 0 once the largest eigenvalue is positive.
69
+ for (let v = 0; v < n; v++) {
70
+ if (rel.rowPtr[v + 1] > rel.rowPtr[v]) {
71
+ x[v] = start === undefined ? 1 : start[v];
72
+ }
73
+ }
74
+ scaleToUnitLength(x);
75
+ let next = new Float64Array(n);
76
+ let it = 0;
77
+ let converged = false;
78
+ for (; it < maxIter && !converged; it++) {
79
+ for (let v = 0; v < n; v++) {
80
+ let sum = x[v];
81
+ const end = rel.rowPtr[v + 1];
82
+ for (let a = rel.rowPtr[v]; a < end; a++) {
83
+ sum += x[rel.colIdx[a]];
84
+ }
85
+ next[v] = sum;
86
+ }
87
+ scaleToUnitLength(next);
88
+ let change = 0;
89
+ for (let v = 0; v < n; v++) {
90
+ change += Math.abs(next[v] - x[v]);
91
+ }
92
+ [x, next] = [next, x];
93
+ converged = change < n * tol;
94
+ }
95
+ if (!converged) {
96
+ throw new ConvergenceError("eigenvectorCentrality", maxIter, tol);
97
+ }
98
+ if (o.normalized !== false) {
99
+ minMaxRescale(x);
100
+ }
101
+ return { scores: x, iterations: it, converged };
102
+ }
103
+
104
+ /**
105
+ * Rescale a score vector in place to [0, 1] by min-max, the legacy eigenvector rule: a flat vector
106
+ * becomes all 1, or all 0 when its maximum is not positive.
107
+ * @param x - The scores to rescale
108
+ * @internal
109
+ */
110
+ export function minMaxRescale(x: F64): void {
111
+ let min = Infinity;
112
+ let max = 0;
113
+ for (const value of x) {
114
+ min = Math.min(min, value);
115
+ max = Math.max(max, value);
116
+ }
117
+ const range = max - min;
118
+ const flat = max > 0 ? 1 : 0;
119
+ for (let v = 0; v < x.length; v++) {
120
+ x[v] = range > 0 ? (x[v] - min) / range : flat;
121
+ }
122
+ }
123
+
124
+ /**
125
+ * The feeding relation as a CSR with each neighbour once per row. Snapshot rows are sorted, so a
126
+ * parallel arc is the previous entry repeated, and the `"total"` row is a merge of two sorted rows.
127
+ * @param s - The snapshot
128
+ * @param mode - Which arcs feed a node on a directed snapshot
129
+ * @returns Row pointers and neighbour indices
130
+ */
131
+ function feeders(s: GraphSnapshot, mode: "in" | "out" | "total"): Relation {
132
+ const n = s.nodeCount;
133
+ const a = !s.directed || mode === "out" ? s : s.reverse();
134
+ // The second source of a "total" row; an empty row everywhere otherwise.
135
+ const total = s.directed && mode === "total";
136
+ const bRowPtr = total ? s.rowPtr : new Uint32Array(n + 1);
137
+ const bColIdx = total ? s.colIdx : new Uint32Array(0);
138
+ const rowPtr = new Uint32Array(n + 1);
139
+ const colIdx = new Uint32Array(a.colIdx.length + bColIdx.length);
140
+ let k = 0;
141
+ for (let v = 0; v < n; v++) {
142
+ let i = a.rowPtr[v];
143
+ const iEnd = a.rowPtr[v + 1];
144
+ let j = bRowPtr[v];
145
+ const jEnd = bRowPtr[v + 1];
146
+ const rowStart = k;
147
+ while (i < iEnd || j < jEnd) {
148
+ const u = j >= jEnd || (i < iEnd && a.colIdx[i] <= bColIdx[j]) ? a.colIdx[i++] : bColIdx[j++];
149
+ if (k === rowStart || colIdx[k - 1] !== u) {
150
+ colIdx[k++] = u;
151
+ }
152
+ }
153
+ rowPtr[v + 1] = k;
154
+ }
155
+ return { rowPtr, colIdx: colIdx.subarray(0, k) };
156
+ }
157
+
158
+ /**
159
+ * Whether the relation has no cycle (Kahn's algorithm), which makes its matrix nilpotent.
160
+ * @param rel - The relation
161
+ * @param n - The node count
162
+ * @returns True when every node peels off in topological order
163
+ */
164
+ function isAcyclic(rel: Relation, n: number): boolean {
165
+ const inDegree = new Uint32Array(n);
166
+ for (const u of rel.colIdx) {
167
+ inDegree[u]++;
168
+ }
169
+ const queue = new Uint32Array(n);
170
+ let tail = 0;
171
+ for (let v = 0; v < n; v++) {
172
+ if (inDegree[v] === 0) {
173
+ queue[tail++] = v;
174
+ }
175
+ }
176
+ for (let head = 0; head < tail; head++) {
177
+ const v = queue[head];
178
+ for (let a = rel.rowPtr[v]; a < rel.rowPtr[v + 1]; a++) {
179
+ if (--inDegree[rel.colIdx[a]] === 0) {
180
+ queue[tail++] = rel.colIdx[a];
181
+ }
182
+ }
183
+ }
184
+ return tail === n;
185
+ }
186
+
187
+ /**
188
+ * Scale a vector in place to unit Euclidean length; a zero vector is left alone.
189
+ * @param v - The vector
190
+ */
191
+ function scaleToUnitLength(v: NumericVector): void {
192
+ let norm = 0;
193
+ for (const value of v) {
194
+ norm += value * value;
195
+ }
196
+ norm = Math.sqrt(norm);
197
+ if (norm > 0) {
198
+ for (let i = 0; i < v.length; i++) {
199
+ v[i] /= norm;
200
+ }
201
+ }
202
+ }
@@ -0,0 +1,229 @@
1
+ /**
2
+ * The conversions a legacy function uses to delegate to its `indexed.*` port and keep its own
3
+ * signature and result shape (graph-format design 14.1 rule 1 and the 14.2 result table). Internal:
4
+ * nothing here is exported from the package, and nothing here takes a legacy `Graph` -- a facade
5
+ * gets its snapshot from `toSnapshot`, or from {@link fromAdjacencyMap} for a Map-of-Maps input.
6
+ * @module
7
+ */
8
+
9
+ import {
10
+ expandEdges,
11
+ type F64,
12
+ GraphBuilder,
13
+ type GraphSnapshot,
14
+ INVALID_INDEX,
15
+ maskToIndices,
16
+ type NodeIdMap,
17
+ type NodeMask,
18
+ type NumericVector,
19
+ type U32,
20
+ } from "@graphty/graph-format";
21
+
22
+ import type { Edge, NodeId, ShortestPathResult } from "../types/index.js";
23
+ import type { SsspResult } from "./dijkstra.js";
24
+
25
+ /**
26
+ * Resolve a legacy node argument to an index: the id itself first, then -- for a string only --
27
+ * its spelling, so `"5"` finds numeric id 5 the way the legacy string-typed parameters
28
+ * (flow `source` / `sink`, seed-label Maps) do today. A number never finds a string id: the
29
+ * legacy graph's `hasNode(5)` is false for a node `"5"`.
30
+ * @param ids - The snapshot's id map
31
+ * @param id - The caller's node argument
32
+ * @returns The node index, or `INVALID_INDEX` when absent; the facade throws its legacy message
33
+ */
34
+ export function resolveNode(ids: NodeIdMap, id: NodeId): number {
35
+ const index = ids.indexOf(id);
36
+ if (index !== INVALID_INDEX || typeof id !== "string") {
37
+ return index;
38
+ }
39
+ return ids.stringIndex().get(id) ?? INVALID_INDEX;
40
+ }
41
+
42
+ /**
43
+ * The snapshot's per-edge weights at full f64 precision: the role-`weight` f64 shadow column
44
+ * `toSnapshot` keeps when a legacy weight is not f32-exact, else the f32 per-edge weights (exact by
45
+ * definition then), else null for an unweighted snapshot.
46
+ * @param s - The snapshot
47
+ * @returns One weight per logical edge, or null
48
+ */
49
+ function exactEdgeWeights(s: GraphSnapshot): NumericVector | null {
50
+ const shadow = s.edges.byRole("weight");
51
+ if (shadow?.dtype === "f64") {
52
+ return shadow.data;
53
+ }
54
+ return s.edgeList().weights;
55
+ }
56
+
57
+ /**
58
+ * The per-arc `weights` override a weighted port needs to reproduce legacy f64 results exactly
59
+ * (design 14.1 rule 4). Undefined when the f32 arc weights are already exact, so the port reads
60
+ * its own arc array.
61
+ * @param s - The snapshot
62
+ * @returns arcCount f64 weights, or undefined
63
+ */
64
+ export function exactArcWeights(s: GraphSnapshot): NumericVector | undefined {
65
+ const shadow = s.edges.byRole("weight");
66
+ return shadow?.dtype === "f64" ? expandEdges(s, shadow.data) : undefined;
67
+ }
68
+
69
+ /**
70
+ * A traversal's visited nodes to the legacy tree (or predecessor) Map: node id to parent id, null for
71
+ * the start, in visit order -- the order a legacy walk set its entries in.
72
+ * @param ids - The snapshot's id map
73
+ * @param order - The visited node indices, in visit order
74
+ * @param parent - The parent of every node index, INVALID_INDEX for the start
75
+ * @returns The tree
76
+ */
77
+ export function orderToTree(ids: NodeIdMap, order: U32, parent: U32): Map<NodeId, NodeId | null> {
78
+ const tree = new Map<NodeId, NodeId | null>();
79
+ for (const i of order) {
80
+ tree.set(ids.idOf(i), parent[i] === INVALID_INDEX ? null : ids.idOf(parent[i]));
81
+ }
82
+ return tree;
83
+ }
84
+
85
+ /**
86
+ * Per-node scores to the legacy `Record<string, number>` keyed by `String(id)`, in index order. A
87
+ * plain object, as the legacy functions return: `ids.toRecord` gives a null-prototype one, which a
88
+ * caller's `result.hasOwnProperty(id)` cannot call.
89
+ * @param ids - The snapshot's id map
90
+ * @param scores - One score per node index
91
+ * @returns The keyed scores
92
+ */
93
+ export function scoresToRecord(ids: NodeIdMap, scores: ArrayLike<number>): Record<string, number> {
94
+ const out: Record<string, number> = {};
95
+ for (let i = 0; i < ids.size; i++) {
96
+ out[String(ids.idOf(i))] = scores[i];
97
+ }
98
+ return out;
99
+ }
100
+
101
+ /**
102
+ * Labels to the legacy `NodeId[][]` (components, communities): one group per label in label order,
103
+ * members in index order. A node labelled `INVALID_INDEX` belongs to no group.
104
+ * @param ids - The snapshot's id map
105
+ * @param labels - One label per node, in `[0, count)` or `INVALID_INDEX`
106
+ * @param count - The number of labels
107
+ * @returns The groups
108
+ */
109
+ export function labelsToGroups(ids: NodeIdMap, labels: U32, count: number): NodeId[][] {
110
+ const groups: NodeId[][] = Array.from({ length: count }, () => []);
111
+ for (let i = 0; i < labels.length; i++) {
112
+ if (labels[i] !== INVALID_INDEX) {
113
+ groups[labels[i]].push(ids.idOf(i));
114
+ }
115
+ }
116
+ return groups;
117
+ }
118
+
119
+ /**
120
+ * A node mask to the legacy `Set<string>` (`getKCore`, min-cut partitions), keyed by `String(id)`.
121
+ * @param ids - The snapshot's id map
122
+ * @param mask - A node mask over `ids.size` nodes
123
+ * @returns The included nodes' ids as strings
124
+ */
125
+ export function maskToStringSet(ids: NodeIdMap, mask: NodeMask): Set<string> {
126
+ const out = new Set<string>();
127
+ for (const i of maskToIndices(mask, ids.size)) {
128
+ out.add(String(ids.idOf(i)));
129
+ }
130
+ return out;
131
+ }
132
+
133
+ /**
134
+ * An `SsspResult` to the legacy `Map<NodeId, ShortestPathResult>`: an entry per reached node in
135
+ * index order. Each entry gets its own copy of the predecessor Map over every node (null for the
136
+ * source and the unreached), as legacy `dijkstra` does, so a caller that mutates one entry's Map
137
+ * does not change the others. That copy is O(n) per reached node, the legacy cost.
138
+ *
139
+ * It matches only a legacy `dijkstra` call WITHOUT the `target` option. With `target`, legacy stops
140
+ * once the target is settled and reports tentative, not final, distances for the nodes it had not
141
+ * settled; the port has no early stop, so a facade must not route a `target` call through here.
142
+ * @param s - The snapshot the search ran on
143
+ * @param result - The port's result
144
+ * @returns The legacy result
145
+ */
146
+ export function ssspToShortestPaths(s: GraphSnapshot, result: SsspResult): Map<NodeId, ShortestPathResult> {
147
+ const { ids } = s;
148
+ const predecessor = new Map<NodeId, NodeId | null>();
149
+ for (let v = 0; v < s.nodeCount; v++) {
150
+ const arc = result.predArc[v];
151
+ predecessor.set(ids.idOf(v), arc === INVALID_INDEX ? null : ids.idOf(s.arcSource(arc)));
152
+ }
153
+ const out = new Map<NodeId, ShortestPathResult>();
154
+ for (let v = 0; v < s.nodeCount; v++) {
155
+ const distance = result.dist[v];
156
+ if (distance < Infinity) {
157
+ const path = Array.from(result.pathTo(v), (i) => ids.idOf(i));
158
+ out.set(ids.idOf(v), { distance, path, predecessor: new Map(predecessor) });
159
+ }
160
+ }
161
+ return out;
162
+ }
163
+
164
+ /**
165
+ * Logical edge indices to legacy `Edge` objects, in the given order, each in the orientation the
166
+ * snapshot stores (the declared one) with its exact f64 weight (1 on an unweighted snapshot). That
167
+ * is the orientation legacy `kruskalMST` reports. Legacy `primMST` reports tree edges in traversal
168
+ * orientation instead, so a Prim facade must orient its edges itself.
169
+ * @param s - The snapshot
170
+ * @param edges - Logical edge indices
171
+ * @returns `{ source, target, weight }` per edge
172
+ */
173
+ export function edgesToLegacy(s: GraphSnapshot, edges: U32): Edge[] {
174
+ const { src, dst } = s.edgeList();
175
+ const weights = exactEdgeWeights(s);
176
+ return Array.from(edges, (e) => ({
177
+ source: s.ids.idOf(src[e]),
178
+ target: s.ids.idOf(dst[e]),
179
+ weight: weights === null ? 1 : weights[e],
180
+ }));
181
+ }
182
+
183
+ /**
184
+ * Per-edge scores to the legacy `Map<string, number>` keyed `"source-target"` (edge betweenness):
185
+ * every edge in declared orientation and edge order, then -- on an undirected snapshot -- every
186
+ * edge again reversed, with the same score, in edge order. Legacy `edgeBetweennessCentrality`
187
+ * returns both orientations of an undirected edge with equal values; it adds the reversed keys in
188
+ * the order its searches first cross them, which this converter does not reproduce.
189
+ * @param s - The snapshot
190
+ * @param scores - One score per logical edge
191
+ * @returns The keyed scores
192
+ */
193
+ export function edgeScoresToPairMap(s: GraphSnapshot, scores: F64): Map<string, number> {
194
+ const { src, dst } = s.edgeList();
195
+ const key = (from: number, to: number): string => `${String(s.ids.idOf(from))}-${String(s.ids.idOf(to))}`;
196
+ const out = new Map<string, number>();
197
+ for (let e = 0; e < s.edgeCount; e++) {
198
+ out.set(key(src[e], dst[e]), scores[e]);
199
+ }
200
+ if (!s.directed) {
201
+ for (let e = 0; e < s.edgeCount; e++) {
202
+ out.set(key(dst[e], src[e]), scores[e]);
203
+ }
204
+ }
205
+ return out;
206
+ }
207
+
208
+ /**
209
+ * A legacy Map-of-Maps adjacency (`astar`, `edmondsKarp`, `stoerWagner`, `kargerMinCut` inputs) to
210
+ * a DIRECTED snapshot: one arc per inner entry, weights kept exactly through the f64 shadow. Every
211
+ * key is a node in key order, then each target not already a key as it is first met. Not memoised:
212
+ * a Map has no mutation counter. The snapshot's `weights` view is f32 like every snapshot's, so a
213
+ * port reads rounded weights (0.1 + 0.2 comes back as 0.30000000447) unless the facade passes
214
+ * `{ weights: exactArcWeights(s) }`.
215
+ * @param adjacency - source id to (target id to weight)
216
+ * @returns The frozen snapshot
217
+ */
218
+ export function fromAdjacencyMap(adjacency: ReadonlyMap<string, ReadonlyMap<string, number>>): GraphSnapshot {
219
+ const builder = new GraphBuilder({ directed: true, weightDtype: "f64" });
220
+ for (const id of adjacency.keys()) {
221
+ builder.addNode(id);
222
+ }
223
+ for (const [source, row] of adjacency) {
224
+ for (const [target, weight] of row) {
225
+ builder.addEdge(source, target, weight);
226
+ }
227
+ }
228
+ return builder.freeze({ label: "algorithms.fromAdjacencyMap" });
229
+ }