@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,120 @@
1
+ import { type GraphSnapshot, type NodeId, type NodeMask, type NumericVector, type U32 } from "@graphty/graph-format";
2
+ /** Options of {@link maxFlow} and {@link minSTCut}. @public */
3
+ export interface MaxFlowOptions {
4
+ /**
5
+ * How augmenting paths are found: `"edmonds-karp"` (breadth-first, shortest paths first,
6
+ * O(V E^2)) or `"ford-fulkerson"` (depth-first, O(E f)). Default `"edmonds-karp"` for
7
+ * {@link maxFlow} and `"ford-fulkerson"` for {@link minSTCut}. Both give the same source side
8
+ * and the same flow value up to floating-point rounding; the per-edge flows can differ where
9
+ * the maximum flow is not unique.
10
+ */
11
+ readonly algorithm?: "edmonds-karp" | "ford-fulkerson" | undefined;
12
+ /**
13
+ * Per-arc capacity override, arcCount long -- the facade passes `expandEdges(s, shadow.data)`
14
+ * for exact f64 capacities. Without it the snapshot's arc weights are the capacities, and an
15
+ * unweighted snapshot gives every edge capacity 1.
16
+ */
17
+ readonly weights?: NumericVector | undefined;
18
+ }
19
+ /** Result of {@link maxFlow}. @public */
20
+ export interface MaxFlowResult {
21
+ /** The value of the maximum flow. */
22
+ readonly maxFlow: number;
23
+ /**
24
+ * Net flow per logical edge in its declared orientation. On an undirected snapshot a negative
25
+ * value is flow from the declared target to the declared source.
26
+ */
27
+ readonly flow: Float64Array;
28
+ /** The nodes reachable from the source in the final residual graph: the source side of a minimum cut. */
29
+ readonly sourceSide: NodeMask;
30
+ /**
31
+ * Logical edges with positive capacity that cross the cut, in edge order: from the source side
32
+ * to the other on a directed snapshot, with exactly one endpoint on the source side on an
33
+ * undirected one.
34
+ */
35
+ readonly cutEdges: U32;
36
+ }
37
+ /** Result of the index-based minimum cuts ({@link minSTCut}, `stoerWagner`, `kargerMinCut`). @public */
38
+ export interface MinCutResult {
39
+ /** The total weight of the cut. */
40
+ readonly cutValue: number;
41
+ /** One side of the cut; every other node is on the other side. */
42
+ readonly side: NodeMask;
43
+ /** Logical edges with one endpoint on each side, in edge order. */
44
+ readonly cutEdges: U32;
45
+ }
46
+ /**
47
+ * The capacity of every logical edge: the override's value at the edge's declared arc, else the
48
+ * snapshot's per-edge weight, else 1.
49
+ * @param s - The snapshot
50
+ * @param weights - The optional per-arc override
51
+ * @returns One capacity per logical edge
52
+ */
53
+ export declare function edgeCapacities(s: GraphSnapshot, weights: NumericVector | undefined): Float64Array;
54
+ /**
55
+ * The logical edges whose endpoints lie on different sides of `side` -- leaving it, when
56
+ * `directed` -- with positive capacity when `positiveOnly` is set.
57
+ * @param s - The snapshot
58
+ * @param side - One side of the cut
59
+ * @param directed - Whether only edges from `side` to the other side count
60
+ * @param capacity - Per-edge capacities, consulted only with `positiveOnly`
61
+ * @param positiveOnly - Whether to leave out edges of capacity zero or less
62
+ * @returns Edge indices in edge order
63
+ */
64
+ export declare function crossingEdges(s: GraphSnapshot, side: NodeMask, directed: boolean, capacity: Float64Array, positiveOnly: boolean): U32;
65
+ /**
66
+ * Maximum flow from `source` to `sink` by augmenting paths.
67
+ *
68
+ * Paths, bottlenecks and per-edge flows equal the legacy `edmondsKarp` / `fordFulkerson` on a
69
+ * graph with no parallel edges and no two opposite directed edges: the residual is kept per node
70
+ * pair and searched in the legacy row order (see {@link buildResidual}). Where two opposite
71
+ * directed edges carry flow, legacy records every push on the edge in the push's direction, so
72
+ * one edge can show more flow than its capacity; this port reports the net flow of the pair on
73
+ * the edges in its direction instead, each within its capacity.
74
+ * @param s - The snapshot
75
+ * @param source - The source node index
76
+ * @param sink - The sink node index
77
+ * @param options - The path search and the capacity override
78
+ * @returns The flow value, the per-edge flows, the source side and the cut edges
79
+ * @throws RangeError when `source` or `sink` is not a node index, or they are the same node
80
+ * @public
81
+ */
82
+ export declare function maxFlow(s: GraphSnapshot, source: number, sink: number, options?: MaxFlowOptions): MaxFlowResult;
83
+ /**
84
+ * Minimum s-t cut: the source side and value of a maximum flow (max-flow min-cut theorem). The
85
+ * side is the set reachable from the source in the final residual graph, which is the same for
86
+ * every maximum flow, so the path search does not change it. The search defaults to
87
+ * `"ford-fulkerson"`, as the legacy `minSTCut` uses: on weights that are not binary fractions
88
+ * another search adds the bottlenecks in another order and the value can differ in its last bits.
89
+ * @param s - The snapshot
90
+ * @param source - The source node index
91
+ * @param sink - The sink node index
92
+ * @param options - The path search and the capacity override
93
+ * @returns The cut value, the source side and the cut edges
94
+ * @throws RangeError as {@link maxFlow} does
95
+ * @public
96
+ */
97
+ export declare function minSTCut(s: GraphSnapshot, source: number, sink: number, options?: MaxFlowOptions): MinCutResult;
98
+ /** Result of {@link bipartiteFlowNetwork}. @public */
99
+ export interface BipartiteFlowNetwork {
100
+ /** The directed, unit-capacity (unweighted) flow network. */
101
+ readonly snapshot: GraphSnapshot;
102
+ /** The index of the added source node, id `"__source__"`. */
103
+ readonly source: number;
104
+ /** The index of the added sink node, id `"__sink__"`. */
105
+ readonly sink: number;
106
+ }
107
+ /**
108
+ * The unit-capacity flow network whose maximum flow is a maximum bipartite matching: a source with
109
+ * an edge to every left node, every given left-right edge, and an edge from every right node to a
110
+ * sink. Nodes are numbered source, left nodes, left endpoints of `edges` not already listed, right
111
+ * nodes, right endpoints not already listed, sink; a repeated edge is kept once.
112
+ * @param left - The left side's node ids
113
+ * @param right - The right side's node ids
114
+ * @param edges - Left-to-right edges as `[left id, right id]`
115
+ * @returns The network and the indices of its source and sink
116
+ * @throws RangeError when a given id is `"__source__"` or `"__sink__"`
117
+ * @public
118
+ */
119
+ export declare function bipartiteFlowNetwork(left: readonly NodeId[], right: readonly NodeId[], edges: readonly (readonly [NodeId, NodeId])[]): BipartiteFlowNetwork;
120
+ //# sourceMappingURL=flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../../src/indexed/flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,KAAK,aAAa,EAKlB,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,GAAG,EACX,MAAM,uBAAuB,CAAC;AAE/B,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,GAAG,gBAAgB,GAAG,SAAS,CAAC;IACnE;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAChD;AAED,yCAAyC;AACzC,MAAM,WAAW,aAAa;IAC1B,qCAAqC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,yGAAyG;IACzG,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC;CAC1B;AAED,wGAAwG;AACxG,MAAM,WAAW,YAAY;IACzB,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,aAAa,GAAG,SAAS,GAAG,YAAY,CAOjG;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CACzB,CAAC,EAAE,aAAa,EAChB,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,OAAO,EACjB,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,OAAO,GACtB,GAAG,CAWL;AAkGD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,aAAa,CAgDnH;AAqDD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,YAAY,CAGnH;AA6GD,sDAAsD;AACtD,MAAM,WAAW,oBAAoB;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAKD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAChC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,GAC9C,oBAAoB,CAwBtB"}
@@ -0,0 +1,377 @@
1
+ import { fromEdgeArrays, GraphBuilder, INVALID_INDEX, makeMask, maskSet, maskTest, } from "@graphty/graph-format";
2
+ /**
3
+ * The capacity of every logical edge: the override's value at the edge's declared arc, else the
4
+ * snapshot's per-edge weight, else 1.
5
+ * @param s - The snapshot
6
+ * @param weights - The optional per-arc override
7
+ * @returns One capacity per logical edge
8
+ */
9
+ export function edgeCapacities(s, weights) {
10
+ const el = s.edgeList();
11
+ const out = new Float64Array(s.edgeCount);
12
+ for (let e = 0; e < s.edgeCount; e++) {
13
+ out[e] = weights !== undefined ? weights[el.arc[e]] : (el.weights?.[e] ?? 1);
14
+ }
15
+ return out;
16
+ }
17
+ /**
18
+ * The logical edges whose endpoints lie on different sides of `side` -- leaving it, when
19
+ * `directed` -- with positive capacity when `positiveOnly` is set.
20
+ * @param s - The snapshot
21
+ * @param side - One side of the cut
22
+ * @param directed - Whether only edges from `side` to the other side count
23
+ * @param capacity - Per-edge capacities, consulted only with `positiveOnly`
24
+ * @param positiveOnly - Whether to leave out edges of capacity zero or less
25
+ * @returns Edge indices in edge order
26
+ */
27
+ export function crossingEdges(s, side, directed, capacity, positiveOnly) {
28
+ const { src, dst } = s.edgeList();
29
+ const out = [];
30
+ for (let e = 0; e < s.edgeCount; e++) {
31
+ const inSrc = maskTest(side, src[e]);
32
+ const crosses = directed ? inSrc && !maskTest(side, dst[e]) : inSrc !== maskTest(side, dst[e]);
33
+ if (crosses && (!positiveOnly || capacity[e] > 0)) {
34
+ out.push(e);
35
+ }
36
+ }
37
+ return Uint32Array.from(out);
38
+ }
39
+ /**
40
+ * Build the pair-keyed residual graph of `s`. The visiting order starts as the legacy
41
+ * `graphToMap` row order -- each neighbour at the first edge that joins it -- and a group with no
42
+ * real arc is appended to its row when flow first reaches it, where the legacy residual Map
43
+ * inserts the key.
44
+ * @param s - The snapshot
45
+ * @param capacity - Per-edge capacities
46
+ * @returns The residual graph
47
+ */
48
+ function buildResidual(s, capacity) {
49
+ const n = s.nodeCount;
50
+ const E = s.edgeCount;
51
+ const { src, dst } = s.edgeList();
52
+ const rSrc = new Uint32Array(2 * E);
53
+ const rDst = new Uint32Array(2 * E);
54
+ rSrc.set(src);
55
+ rSrc.set(dst, E);
56
+ rDst.set(dst);
57
+ rDst.set(src, E);
58
+ const r = fromEdgeArrays({ directed: true, nodeCount: n, src: rSrc, dst: rDst });
59
+ const { rowPtr, colIdx, arcToEdge, edgeToArc } = r;
60
+ const A = r.arcCount;
61
+ const residual = new Float64Array(A);
62
+ const groupOf = new Uint32Array(A);
63
+ const real = new Uint8Array(A);
64
+ for (let u = 0; u < n; u++) {
65
+ for (let a = rowPtr[u]; a < rowPtr[u + 1]; a++) {
66
+ const g = a > rowPtr[u] && colIdx[a] === colIdx[a - 1] ? groupOf[a - 1] : a;
67
+ groupOf[a] = g;
68
+ const re = arcToEdge[a];
69
+ if (re < E || !s.directed) {
70
+ real[g] = 1;
71
+ residual[g] += Math.max(capacity[re < E ? re : re - E], 0);
72
+ }
73
+ }
74
+ }
75
+ const twin = new Uint32Array(A);
76
+ for (let a = 0; a < A; a++) {
77
+ if (groupOf[a] === a) {
78
+ const re = arcToEdge[a];
79
+ twin[a] = groupOf[edgeToArc[re < E ? re + E : re - E]];
80
+ }
81
+ }
82
+ const order = new Uint32Array(A);
83
+ const placed = new Uint32Array(n);
84
+ const inOrder = new Uint8Array(A);
85
+ const place = (u, g) => {
86
+ if (inOrder[g] === 0) {
87
+ inOrder[g] = 1;
88
+ order[rowPtr[u] + placed[u]++] = g;
89
+ }
90
+ };
91
+ for (let e = 0; e < E; e++) {
92
+ place(src[e], groupOf[edgeToArc[e]]);
93
+ if (!s.directed) {
94
+ place(dst[e], groupOf[edgeToArc[e + E]]);
95
+ }
96
+ }
97
+ return { rowPtr, colIdx, arcToEdge, capacity: residual, groupOf, twin, order, placed, inOrder, real };
98
+ }
99
+ /**
100
+ * Maximum flow from `source` to `sink` by augmenting paths.
101
+ *
102
+ * Paths, bottlenecks and per-edge flows equal the legacy `edmondsKarp` / `fordFulkerson` on a
103
+ * graph with no parallel edges and no two opposite directed edges: the residual is kept per node
104
+ * pair and searched in the legacy row order (see {@link buildResidual}). Where two opposite
105
+ * directed edges carry flow, legacy records every push on the edge in the push's direction, so
106
+ * one edge can show more flow than its capacity; this port reports the net flow of the pair on
107
+ * the edges in its direction instead, each within its capacity.
108
+ * @param s - The snapshot
109
+ * @param source - The source node index
110
+ * @param sink - The sink node index
111
+ * @param options - The path search and the capacity override
112
+ * @returns The flow value, the per-edge flows, the source side and the cut edges
113
+ * @throws RangeError when `source` or `sink` is not a node index, or they are the same node
114
+ * @public
115
+ */
116
+ export function maxFlow(s, source, sink, options = {}) {
117
+ const n = s.nodeCount;
118
+ if (!(Number.isInteger(source) && source >= 0 && source < n && Number.isInteger(sink) && sink >= 0 && sink < n)) {
119
+ throw new RangeError(`source ${String(source)} and sink ${String(sink)} must be node indices below ${n}`);
120
+ }
121
+ if (source === sink) {
122
+ throw new RangeError(`source and sink are the same node (${source})`);
123
+ }
124
+ const capacity = edgeCapacities(s, options.weights);
125
+ const r = buildResidual(s, capacity);
126
+ const { colIdx, twin } = r;
127
+ // Flow pushed per real group, accumulated as the legacy flow Map accumulates it: a push along
128
+ // a pair with a real arc adds to that pair, a push along a reverse-only pair subtracts from
129
+ // the opposite one.
130
+ const pushed = new Float64Array(colIdx.length);
131
+ const predGroup = new Uint32Array(n);
132
+ const findPath = options.algorithm === "ford-fulkerson" ? depthFirstPath : breadthFirstPath;
133
+ let total = 0;
134
+ while (findPath(r, source, sink, predGroup)) {
135
+ let bottleneck = Infinity;
136
+ for (let v = sink; v !== source; v = colIdx[twin[predGroup[v]]]) {
137
+ bottleneck = Math.min(bottleneck, r.capacity[predGroup[v]]);
138
+ }
139
+ for (let v = sink; v !== source;) {
140
+ const g = predGroup[v];
141
+ const t = twin[g];
142
+ r.capacity[g] -= bottleneck;
143
+ r.capacity[t] += bottleneck;
144
+ if (r.inOrder[t] === 0) {
145
+ r.inOrder[t] = 1;
146
+ r.order[r.rowPtr[v] + r.placed[v]++] = t;
147
+ }
148
+ if (r.real[g] === 1) {
149
+ pushed[g] += bottleneck;
150
+ }
151
+ else {
152
+ pushed[t] -= bottleneck;
153
+ }
154
+ v = colIdx[t];
155
+ }
156
+ total += bottleneck;
157
+ }
158
+ const sourceSide = reachable(r, source);
159
+ return {
160
+ maxFlow: total,
161
+ flow: edgeFlows(s, r, capacity, pushed),
162
+ sourceSide,
163
+ cutEdges: crossingEdges(s, sourceSide, s.directed, capacity, true),
164
+ };
165
+ }
166
+ /**
167
+ * Spread each pair's net flow over its logical edges: all of it on the pair's only edge in the
168
+ * flow's direction, and in arc order up to capacity where there are several (the last one takes
169
+ * the remainder, so rounding never drops flow).
170
+ * @param s - The snapshot
171
+ * @param r - The residual graph after the last augmentation
172
+ * @param capacity - Per-edge capacities
173
+ * @param pushed - Flow pushed per real group
174
+ * @returns Net flow per logical edge in its declared orientation
175
+ */
176
+ function edgeFlows(s, r, capacity, pushed) {
177
+ const E = s.edgeCount;
178
+ const flow = new Float64Array(E);
179
+ const { rowPtr, colIdx, arcToEdge, groupOf } = r;
180
+ for (let u = 0; u < s.nodeCount; u++) {
181
+ for (let g = rowPtr[u]; g < rowPtr[u + 1]; g++) {
182
+ const v = colIdx[g];
183
+ if (groupOf[g] !== g || v <= u) {
184
+ continue;
185
+ }
186
+ const net = pushed[g] - pushed[r.twin[g]];
187
+ if (net === 0) {
188
+ continue;
189
+ }
190
+ // Walk the arcs of the group the flow runs along: u to v, or v to u.
191
+ const along = net > 0 ? g : r.twin[g];
192
+ const end = rowPtr[colIdx[r.twin[along]] + 1];
193
+ let remaining = Math.abs(net);
194
+ let lastEdge = -1;
195
+ let lastSign = 1;
196
+ for (let a = along; a < end && groupOf[a] === along; a++) {
197
+ const re = arcToEdge[a];
198
+ if (re >= E && s.directed) {
199
+ continue; // a reverse arc carries no edge
200
+ }
201
+ if (lastEdge >= 0) {
202
+ const x = Math.min(remaining, Math.max(capacity[lastEdge], 0));
203
+ flow[lastEdge] += lastSign * x;
204
+ remaining -= x;
205
+ }
206
+ lastEdge = re < E ? re : re - E;
207
+ lastSign = re < E ? 1 : -1;
208
+ }
209
+ if (lastEdge >= 0) {
210
+ flow[lastEdge] += lastSign * remaining;
211
+ }
212
+ }
213
+ }
214
+ return flow;
215
+ }
216
+ /**
217
+ * Minimum s-t cut: the source side and value of a maximum flow (max-flow min-cut theorem). The
218
+ * side is the set reachable from the source in the final residual graph, which is the same for
219
+ * every maximum flow, so the path search does not change it. The search defaults to
220
+ * `"ford-fulkerson"`, as the legacy `minSTCut` uses: on weights that are not binary fractions
221
+ * another search adds the bottlenecks in another order and the value can differ in its last bits.
222
+ * @param s - The snapshot
223
+ * @param source - The source node index
224
+ * @param sink - The sink node index
225
+ * @param options - The path search and the capacity override
226
+ * @returns The cut value, the source side and the cut edges
227
+ * @throws RangeError as {@link maxFlow} does
228
+ * @public
229
+ */
230
+ export function minSTCut(s, source, sink, options = {}) {
231
+ const r = maxFlow(s, source, sink, { ...options, algorithm: options.algorithm ?? "ford-fulkerson" });
232
+ return { cutValue: r.maxFlow, side: r.sourceSide, cutEdges: r.cutEdges };
233
+ }
234
+ /**
235
+ * Breadth-first search for a source-to-sink path over groups with residual capacity, stopping when
236
+ * the sink is discovered (its parent is fixed then, as in the legacy search that stops when it
237
+ * dequeues the sink).
238
+ * @param r - The residual graph
239
+ * @param source - The source node index
240
+ * @param sink - The sink node index
241
+ * @param predGroup - Receives the group that discovered each node on the path
242
+ * @returns Whether the sink was reached
243
+ */
244
+ function breadthFirstPath(r, source, sink, predGroup) {
245
+ const { rowPtr, colIdx, order, placed, capacity } = r;
246
+ predGroup.fill(INVALID_INDEX);
247
+ const queue = new Uint32Array(predGroup.length);
248
+ let head = 0;
249
+ let tail = 0;
250
+ queue[tail++] = source;
251
+ while (head < tail) {
252
+ const u = queue[head++];
253
+ const end = rowPtr[u] + placed[u];
254
+ for (let k = rowPtr[u]; k < end; k++) {
255
+ const g = order[k];
256
+ const v = colIdx[g];
257
+ if (capacity[g] > 0 && v !== source && predGroup[v] === INVALID_INDEX) {
258
+ predGroup[v] = g;
259
+ if (v === sink) {
260
+ return true;
261
+ }
262
+ queue[tail++] = v;
263
+ }
264
+ }
265
+ }
266
+ return false;
267
+ }
268
+ /**
269
+ * Depth-first search for a source-to-sink path over groups with residual capacity, in the order a
270
+ * recursive search takes: the first group with capacity to an unvisited node is followed to its
271
+ * end before the next is tried.
272
+ * @param r - The residual graph
273
+ * @param source - The source node index
274
+ * @param sink - The sink node index
275
+ * @param predGroup - Receives the group that entered each node on the path
276
+ * @returns Whether the sink was reached
277
+ */
278
+ function depthFirstPath(r, source, sink, predGroup) {
279
+ const { rowPtr, colIdx, order, placed, capacity } = r;
280
+ const n = predGroup.length;
281
+ predGroup.fill(INVALID_INDEX);
282
+ const visited = new Uint8Array(n);
283
+ const stack = new Uint32Array(n);
284
+ const cursor = new Uint32Array(n);
285
+ let depth = 0;
286
+ stack[depth++] = source;
287
+ visited[source] = 1;
288
+ cursor[source] = rowPtr[source];
289
+ while (depth > 0) {
290
+ const u = stack[depth - 1];
291
+ const k = cursor[u]++;
292
+ if (k >= rowPtr[u] + placed[u]) {
293
+ depth--;
294
+ continue;
295
+ }
296
+ const g = order[k];
297
+ const v = colIdx[g];
298
+ if (capacity[g] > 0 && visited[v] === 0) {
299
+ predGroup[v] = g;
300
+ if (v === sink) {
301
+ return true;
302
+ }
303
+ visited[v] = 1;
304
+ cursor[v] = rowPtr[v];
305
+ stack[depth++] = v;
306
+ }
307
+ }
308
+ return false;
309
+ }
310
+ /**
311
+ * The nodes reachable from `source` over groups with residual capacity.
312
+ * @param r - The residual graph
313
+ * @param source - The source node index
314
+ * @returns The reachable set as a node mask
315
+ */
316
+ function reachable(r, source) {
317
+ const { rowPtr, colIdx, order, placed, capacity } = r;
318
+ const n = rowPtr.length - 1;
319
+ const mask = makeMask(n);
320
+ const queue = new Uint32Array(n);
321
+ let head = 0;
322
+ let tail = 0;
323
+ queue[tail++] = source;
324
+ maskSet(mask, source, true);
325
+ while (head < tail) {
326
+ const u = queue[head++];
327
+ const end = rowPtr[u] + placed[u];
328
+ for (let k = rowPtr[u]; k < end; k++) {
329
+ const v = colIdx[order[k]];
330
+ if (capacity[order[k]] > 0 && !maskTest(mask, v)) {
331
+ maskSet(mask, v, true);
332
+ queue[tail++] = v;
333
+ }
334
+ }
335
+ }
336
+ return mask;
337
+ }
338
+ const SOURCE_ID = "__source__";
339
+ const SINK_ID = "__sink__";
340
+ /**
341
+ * The unit-capacity flow network whose maximum flow is a maximum bipartite matching: a source with
342
+ * an edge to every left node, every given left-right edge, and an edge from every right node to a
343
+ * sink. Nodes are numbered source, left nodes, left endpoints of `edges` not already listed, right
344
+ * nodes, right endpoints not already listed, sink; a repeated edge is kept once.
345
+ * @param left - The left side's node ids
346
+ * @param right - The right side's node ids
347
+ * @param edges - Left-to-right edges as `[left id, right id]`
348
+ * @returns The network and the indices of its source and sink
349
+ * @throws RangeError when a given id is `"__source__"` or `"__sink__"`
350
+ * @public
351
+ */
352
+ export function bipartiteFlowNetwork(left, right, edges) {
353
+ const b = new GraphBuilder({ directed: true, duplicateEdges: "first" });
354
+ const add = (id) => {
355
+ if (id === SOURCE_ID || id === SINK_ID) {
356
+ throw new RangeError(`node id "${id}" is reserved for the flow network's source or sink`);
357
+ }
358
+ return b.addNode(id);
359
+ };
360
+ const source = b.addNode(SOURCE_ID);
361
+ const leftIndex = left.map(add);
362
+ const edgeLeft = edges.map(([u]) => add(u));
363
+ const rightIndex = right.map(add);
364
+ const edgeRight = edges.map(([, v]) => add(v));
365
+ const sink = b.addNode(SINK_ID);
366
+ for (const u of leftIndex) {
367
+ b.addEdgeByIndex(source, u);
368
+ }
369
+ for (let e = 0; e < edges.length; e++) {
370
+ b.addEdgeByIndex(edgeLeft[e], edgeRight[e]);
371
+ }
372
+ for (const v of rightIndex) {
373
+ b.addEdgeByIndex(v, sink);
374
+ }
375
+ return { snapshot: b.freeze({ label: "algorithms.bipartiteFlowNetwork" }), source, sink };
376
+ }
377
+ //# sourceMappingURL=flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.js","sourceRoot":"","sources":["../../../src/indexed/flow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { type F64, type GraphSnapshot, type U32 } from "@graphty/graph-format";
2
+ /** Options of the index-based Girvan-Newman, matching the legacy `girvanNewman`. @public */
3
+ export interface GirvanNewmanOptions {
4
+ /** Stop once a level has at least this many communities of `minCommunitySize` or more nodes. */
5
+ readonly maxCommunities?: number | undefined;
6
+ /** Communities smaller than this do not count towards `maxCommunities`; default 1. */
7
+ readonly minCommunitySize?: number | undefined;
8
+ /** Cap on rounds of edge removal; default 100. */
9
+ readonly maxIterations?: number | undefined;
10
+ }
11
+ /** The Girvan-Newman dendrogram: one partition per level, the uncut graph first. @public */
12
+ export interface GirvanNewmanResult {
13
+ /** Dense community label per node index at each level, in first-seen order. */
14
+ readonly levels: U32[];
15
+ /** Modularity of each level's partition over the original graph. */
16
+ readonly modularity: F64;
17
+ }
18
+ /**
19
+ * Girvan-Newman divisive community detection (PNAS 99:7821, 2002) over an undirected snapshot:
20
+ * repeatedly delete every edge whose betweenness is the maximum (within 1e-10), recording the
21
+ * connected components after each round as one level of a dendrogram.
22
+ *
23
+ * Edges are deleted by clearing bits of an alive mask over logical edges that the edge betweenness
24
+ * reads, so no graph is rebuilt. Betweenness is unweighted, as in the legacy function; a pair of
25
+ * nodes joined by parallel edges is one neighbour relation whose share goes to the first alive
26
+ * parallel, so the parallels are deleted one round at a time. Modularity reads the edge weights,
27
+ * the exact f64 ones when the snapshot keeps them, with graph-format's `weightedDegree()` rule (a
28
+ * self-loop counts twice); on a graph without self-loops it equals the legacy function's.
29
+ *
30
+ * The run stops when no edge is left, after `maxIterations` rounds, when a level has
31
+ * `maxCommunities` communities of at least `minCommunitySize` nodes, or when that count reaches
32
+ * the node count. Every level is returned whole: the legacy function drops communities below
33
+ * `minCommunitySize` from the lists it returns, which a caller does with `levels[i]` and a size
34
+ * count.
35
+ * @param s - An undirected snapshot
36
+ * @param options - Stopping rules
37
+ * @returns The levels and their modularity
38
+ * @throws Error on a directed snapshot
39
+ * @public
40
+ */
41
+ export declare function girvanNewman(s: GraphSnapshot, options?: GirvanNewmanOptions): GirvanNewmanResult;
42
+ //# sourceMappingURL=girvan-newman.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"girvan-newman.d.ts","sourceRoot":"","sources":["../../../src/indexed/girvan-newman.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,GAAG,EACR,KAAK,aAAa,EAKlB,KAAK,GAAG,EACX,MAAM,uBAAuB,CAAC;AAO/B,4FAA4F;AAC5F,MAAM,WAAW,mBAAmB;IAChC,gGAAgG;IAChG,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7C,sFAAsF;IACtF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,kDAAkD;IAClD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/C;AAED,4FAA4F;AAC5F,MAAM,WAAW,kBAAkB;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC;IACvB,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC;CAC5B;AAsBD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,GAAE,mBAAwB,GAAG,kBAAkB,CA0CpG"}
@@ -0,0 +1,90 @@
1
+ import { makeMask, maskCount, maskSet, maskTest, } from "@graphty/graph-format";
2
+ import { edgeBetweennessCentrality } from "./betweenness.js";
3
+ import { arcWeightsOf, exactEdgeWeights } from "./label-propagation.js";
4
+ import { modularity } from "./modularity.js";
5
+ import { IntUnionFind } from "./structures/union-find.js";
6
+ /** Scores this close to the maximum are removed together, as the legacy function does. */
7
+ const TIE = 1e-10;
8
+ /**
9
+ * Connected components over the edges still alive.
10
+ * @param s - The snapshot
11
+ * @param alive - Kept edges
12
+ * @returns Dense labels and their count
13
+ */
14
+ function aliveComponents(s, alive) {
15
+ const uf = new IntUnionFind(s.nodeCount);
16
+ const el = s.edgeList();
17
+ for (let e = 0; e < s.edgeCount; e++) {
18
+ if (maskTest(alive, e)) {
19
+ uf.union(el.src[e], el.dst[e]);
20
+ }
21
+ }
22
+ return uf.toLabels();
23
+ }
24
+ /**
25
+ * Girvan-Newman divisive community detection (PNAS 99:7821, 2002) over an undirected snapshot:
26
+ * repeatedly delete every edge whose betweenness is the maximum (within 1e-10), recording the
27
+ * connected components after each round as one level of a dendrogram.
28
+ *
29
+ * Edges are deleted by clearing bits of an alive mask over logical edges that the edge betweenness
30
+ * reads, so no graph is rebuilt. Betweenness is unweighted, as in the legacy function; a pair of
31
+ * nodes joined by parallel edges is one neighbour relation whose share goes to the first alive
32
+ * parallel, so the parallels are deleted one round at a time. Modularity reads the edge weights,
33
+ * the exact f64 ones when the snapshot keeps them, with graph-format's `weightedDegree()` rule (a
34
+ * self-loop counts twice); on a graph without self-loops it equals the legacy function's.
35
+ *
36
+ * The run stops when no edge is left, after `maxIterations` rounds, when a level has
37
+ * `maxCommunities` communities of at least `minCommunitySize` nodes, or when that count reaches
38
+ * the node count. Every level is returned whole: the legacy function drops communities below
39
+ * `minCommunitySize` from the lists it returns, which a caller does with `levels[i]` and a size
40
+ * count.
41
+ * @param s - An undirected snapshot
42
+ * @param options - Stopping rules
43
+ * @returns The levels and their modularity
44
+ * @throws Error on a directed snapshot
45
+ * @public
46
+ */
47
+ export function girvanNewman(s, options = {}) {
48
+ if (s.directed) {
49
+ throw new Error("Girvan-Newman requires an undirected graph. Pass s.toUndirected().snapshot.");
50
+ }
51
+ const maxCommunities = options.maxCommunities ?? 0;
52
+ const minCommunitySize = options.minCommunitySize ?? 1;
53
+ const maxIterations = options.maxIterations ?? 100;
54
+ const { nodeCount: n, edgeCount } = s;
55
+ const weights = arcWeightsOf(s, exactEdgeWeights(s));
56
+ const alive = makeMask(edgeCount, true);
57
+ const levels = [];
58
+ const scores = [];
59
+ const record = () => {
60
+ const { labels, count } = aliveComponents(s, alive);
61
+ levels.push(labels);
62
+ scores.push(modularity(s, labels, weights === null ? {} : { weights }));
63
+ const sizes = new Uint32Array(count);
64
+ for (let u = 0; u < n; u++) {
65
+ sizes[labels[u]]++;
66
+ }
67
+ return sizes.filter((size) => size >= minCommunitySize).length;
68
+ };
69
+ record();
70
+ for (let round = 0; round < maxIterations && maskCount(alive, edgeCount) > 0; round++) {
71
+ const betweenness = edgeBetweennessCentrality(s, { alive }).scores;
72
+ let max = -Infinity;
73
+ for (let e = 0; e < edgeCount; e++) {
74
+ if (maskTest(alive, e) && betweenness[e] > max) {
75
+ max = betweenness[e];
76
+ }
77
+ }
78
+ for (let e = 0; e < edgeCount; e++) {
79
+ if (maskTest(alive, e) && Math.abs(betweenness[e] - max) < TIE) {
80
+ maskSet(alive, e, false);
81
+ }
82
+ }
83
+ const valid = record();
84
+ if ((maxCommunities > 0 && valid >= maxCommunities) || valid === n) {
85
+ break;
86
+ }
87
+ }
88
+ return { levels, modularity: Float64Array.from(scores) };
89
+ }
90
+ //# sourceMappingURL=girvan-newman.js.map