@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
@@ -4,19 +4,20 @@
4
4
  * Various algorithms for finding minimum cuts in graphs
5
5
  */
6
6
 
7
- import {fordFulkerson} from "./ford-fulkerson.js";
7
+ import type { Graph } from "../core/graph.js";
8
+ import { graphToMap } from "../utils/graph-converters.js";
9
+ import { fordFulkerson } from "./ford-fulkerson.js";
8
10
 
9
11
  export interface MinCutResult {
10
12
  cutValue: number;
11
13
  partition1: Set<string>;
12
14
  partition2: Set<string>;
13
- cutEdges: {from: string, to: string, weight: number}[];
15
+ cutEdges: { from: string; to: string; weight: number }[];
14
16
  }
15
17
 
16
18
  /**
17
19
  * Find minimum s-t cut using max flow
18
20
  * The minimum cut value equals the maximum flow value (max-flow min-cut theorem)
19
- *
20
21
  * @param graph - Weighted graph
21
22
  * @param source - Source node
22
23
  * @param sink - Sink node
@@ -24,11 +25,7 @@ export interface MinCutResult {
24
25
  *
25
26
  * Time Complexity: Same as max flow algorithm used
26
27
  */
27
- export function minSTCut(
28
- graph: Map<string, Map<string, number>>,
29
- source: string,
30
- sink: string,
31
- ): MinCutResult {
28
+ export function minSTCut(graph: Graph, source: string, sink: string): MinCutResult {
32
29
  const flowResult = fordFulkerson(graph, source, sink);
33
30
 
34
31
  if (!flowResult.minCut) {
@@ -40,13 +37,14 @@ export function minSTCut(
40
37
  };
41
38
  }
42
39
 
43
- const cutEdges: {from: string, to: string, weight: number}[] = [];
40
+ const cutEdges: { from: string; to: string; weight: number }[] = [];
44
41
 
45
42
  // Find actual cut edges and their weights
46
43
  for (const [u, v] of flowResult.minCut.edges) {
47
- const weight = graph.get(u)?.get(v) ?? 0;
44
+ const edge = graph.getEdge(u, v);
45
+ const weight = edge?.weight ?? 0;
48
46
  if (weight > 0) {
49
- cutEdges.push({from: u, to: v, weight});
47
+ cutEdges.push({ from: u, to: v, weight });
50
48
  }
51
49
  }
52
50
 
@@ -61,17 +59,18 @@ export function minSTCut(
61
59
  /**
62
60
  * Stoer-Wagner algorithm for finding global minimum cut
63
61
  * Finds the minimum cut that separates the graph into two parts
64
- *
65
- * @param graph - Undirected weighted graph
62
+ * @param graph - Undirected weighted graph - accepts Graph class or Map representation
66
63
  * @returns Global minimum cut
67
64
  *
68
65
  * Time Complexity: O(V³) or O(VE + V² log V) with heap
69
66
  */
70
- export function stoerWagner(
71
- graph: Map<string, Map<string, number>>,
72
- ): MinCutResult {
67
+ export function stoerWagner(graph: Graph | Map<string, Map<string, number>>): MinCutResult {
68
+ // Convert Graph to Map representation if needed
69
+ const graphMap = graph instanceof Map ? graph : graphToMap(graph);
73
70
  // Convert to undirected if necessary
74
- const undirectedGraph = makeUndirected(graph);
71
+ const undirectedGraph = makeUndirected(graphMap);
72
+ // Keep a copy for finding cut edges later
73
+ const originalGraph = makeUndirected(graphMap);
75
74
 
76
75
  if (undirectedGraph.size < 2) {
77
76
  return {
@@ -84,6 +83,7 @@ export function stoerWagner(
84
83
 
85
84
  // Initialize
86
85
  const nodes = Array.from(undirectedGraph.keys());
86
+ const originalNodes = new Set(nodes); // Keep track of original nodes
87
87
  let minCutValue = Infinity;
88
88
  let bestPartition = new Set<string>();
89
89
  const contractionMap = new Map<string, Set<string>>();
@@ -125,20 +125,20 @@ export function stoerWagner(
125
125
  const partition1 = bestPartition;
126
126
  const partition2 = new Set<string>();
127
127
 
128
- for (const node of graph.keys()) {
128
+ for (const node of originalNodes) {
129
129
  if (!partition1.has(node)) {
130
130
  partition2.add(node);
131
131
  }
132
132
  }
133
133
 
134
134
  // Find cut edges
135
- const cutEdges: {from: string, to: string, weight: number}[] = [];
135
+ const cutEdges: { from: string; to: string; weight: number }[] = [];
136
136
  for (const u of partition1) {
137
- const neighbors = graph.get(u);
137
+ const neighbors = originalGraph.get(u);
138
138
  if (neighbors) {
139
139
  for (const [v, weight] of neighbors) {
140
140
  if (partition2.has(v)) {
141
- cutEdges.push({from: u, to: v, weight});
141
+ cutEdges.push({ from: u, to: v, weight });
142
142
  }
143
143
  }
144
144
  }
@@ -154,11 +154,14 @@ export function stoerWagner(
154
154
 
155
155
  /**
156
156
  * Minimum cut phase of Stoer-Wagner algorithm
157
+ * @param graph - The undirected weighted graph
158
+ * @param nodes - Array of remaining nodes in the graph
159
+ * @returns The cut result with last two nodes, cut value, and partition
157
160
  */
158
161
  function minimumCutPhase(
159
162
  graph: Map<string, Map<string, number>>,
160
163
  nodes: string[],
161
- ): {s: string, t: string, value: number, partition: string[]} {
164
+ ): { s: string; t: string; value: number; partition: string[] } {
162
165
  const n = nodes.length;
163
166
  const weight = new Map<string, number>();
164
167
  const added = new Set<string>();
@@ -172,7 +175,7 @@ function minimumCutPhase(
172
175
  // Start with arbitrary node
173
176
  let lastAdded = nodes[0];
174
177
  if (!lastAdded) {
175
- return {s: "", t: "", value: 0, partition: []};
178
+ return { s: "", t: "", value: 0, partition: [] };
176
179
  }
177
180
 
178
181
  added.add(lastAdded);
@@ -180,7 +183,7 @@ function minimumCutPhase(
180
183
 
181
184
  // Add remaining nodes
182
185
  for (let i = 1; i < n; i++) {
183
- // Update weights
186
+ // Update weights
184
187
  if (!lastAdded) {
185
188
  continue;
186
189
  }
@@ -217,7 +220,7 @@ function minimumCutPhase(
217
220
  const s = order[order.length - 2];
218
221
  const t = order[order.length - 1];
219
222
  if (!s || !t) {
220
- return {s: "", t: "", value: 0, partition: []};
223
+ return { s: "", t: "", value: 0, partition: [] };
221
224
  }
222
225
 
223
226
  const cutValue = weight.get(t) ?? 0;
@@ -225,18 +228,17 @@ function minimumCutPhase(
225
228
  // Partition is all nodes except t
226
229
  const partition = order.slice(0, -1);
227
230
 
228
- return {s, t, value: cutValue, partition};
231
+ return { s, t, value: cutValue, partition };
229
232
  }
230
233
 
231
234
  /**
232
235
  * Contract two nodes in the graph
236
+ * @param graph - The graph to modify by contracting nodes
237
+ * @param nodes - Array of nodes to update after contraction
238
+ * @param s - The node to keep after contraction
239
+ * @param t - The node to merge into s
233
240
  */
234
- function contractNodes(
235
- graph: Map<string, Map<string, number>>,
236
- nodes: string[],
237
- s: string,
238
- t: string,
239
- ): void {
241
+ function contractNodes(graph: Map<string, Map<string, number>>, nodes: string[], s: string, t: string): void {
240
242
  // Merge t into s
241
243
  const sNeighbors = graph.get(s);
242
244
  const tNeighbors = graph.get(t);
@@ -271,10 +273,10 @@ function contractNodes(
271
273
 
272
274
  /**
273
275
  * Convert directed graph to undirected
276
+ * @param graph - The directed graph to convert
277
+ * @returns An undirected graph with edges in both directions
274
278
  */
275
- function makeUndirected(
276
- graph: Map<string, Map<string, number>>,
277
- ): Map<string, Map<string, number>> {
279
+ function makeUndirected(graph: Map<string, Map<string, number>>): Map<string, Map<string, number>> {
278
280
  const undirected = new Map<string, Map<string, number>>();
279
281
 
280
282
  // Initialize all nodes
@@ -307,23 +309,21 @@ function makeUndirected(
307
309
  /**
308
310
  * Karger's randomized min-cut algorithm
309
311
  * Probabilistic algorithm that finds min cut with high probability
310
- *
311
- * @param graph - Undirected graph
312
+ * @param graph - Undirected graph - accepts Graph class or Map representation
312
313
  * @param iterations - Number of iterations (higher = better accuracy)
313
314
  * @returns Minimum cut found
314
315
  *
315
316
  * Time Complexity: O(V² * iterations)
316
317
  */
317
- export function kargerMinCut(
318
- graph: Map<string, Map<string, number>>,
319
- iterations = 100,
320
- ): MinCutResult {
318
+ export function kargerMinCut(graph: Graph | Map<string, Map<string, number>>, iterations = 100): MinCutResult {
319
+ // Convert Graph to Map representation if needed
320
+ const graphMap = graph instanceof Map ? graph : graphToMap(graph);
321
321
  let minCutValue = Infinity;
322
322
  let bestPartition1 = new Set<string>();
323
323
  let bestPartition2 = new Set<string>();
324
324
 
325
325
  for (let i = 0; i < iterations; i++) {
326
- const result = kargerSingleRun(graph);
326
+ const result = kargerSingleRun(graphMap);
327
327
 
328
328
  if (result.cutValue < minCutValue) {
329
329
  minCutValue = result.cutValue;
@@ -333,13 +333,13 @@ export function kargerMinCut(
333
333
  }
334
334
 
335
335
  // Find cut edges
336
- const cutEdges: {from: string, to: string, weight: number}[] = [];
336
+ const cutEdges: { from: string; to: string; weight: number }[] = [];
337
337
  for (const u of bestPartition1) {
338
- const neighbors = graph.get(u);
338
+ const neighbors = graphMap.get(u);
339
339
  if (neighbors) {
340
340
  for (const [v, weight] of neighbors) {
341
341
  if (bestPartition2.has(v)) {
342
- cutEdges.push({from: u, to: v, weight});
342
+ cutEdges.push({ from: u, to: v, weight });
343
343
  }
344
344
  }
345
345
  }
@@ -355,10 +355,14 @@ export function kargerMinCut(
355
355
 
356
356
  /**
357
357
  * Single run of Karger's algorithm
358
+ * @param graph - The undirected weighted graph
359
+ * @returns The cut result with cut value and two partitions
358
360
  */
359
- function kargerSingleRun(
360
- graph: Map<string, Map<string, number>>,
361
- ): {cutValue: number, partition1: Set<string>, partition2: Set<string>} {
361
+ function kargerSingleRun(graph: Map<string, Map<string, number>>): {
362
+ cutValue: number;
363
+ partition1: Set<string>;
364
+ partition2: Set<string>;
365
+ } {
362
366
  // Create a copy of the graph
363
367
  const workGraph = new Map<string, Map<string, number>>();
364
368
  const superNodes = new Map<string, Set<string>>();
@@ -371,11 +375,12 @@ function kargerSingleRun(
371
375
 
372
376
  // Contract until 2 nodes remain
373
377
  while (workGraph.size > 2) {
374
- // Pick random edge
378
+ // Pick random edge
375
379
  const edges: [string, string, number][] = [];
376
380
  for (const [u, neighbors] of workGraph) {
377
381
  for (const [v, weight] of neighbors) {
378
- if (u < v) { // Avoid duplicates
382
+ if (u < v) {
383
+ // Avoid duplicates
379
384
  edges.push([u, v, weight]);
380
385
  }
381
386
  }
@@ -430,6 +435,10 @@ function kargerSingleRun(
430
435
 
431
436
  /**
432
437
  * Contract edge in Karger's algorithm
438
+ * @param graph - The working graph to modify
439
+ * @param superNodes - Map tracking which original nodes are in each super node
440
+ * @param u - First endpoint of the edge to contract
441
+ * @param v - Second endpoint of the edge to contract (merged into u)
433
442
  */
434
443
  function contractKarger(
435
444
  graph: Map<string, Map<string, number>>,
@@ -479,4 +488,3 @@ function contractKarger(
479
488
  graph.delete(v);
480
489
  superNodes.delete(v);
481
490
  }
482
-
package/src/index.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  /**
2
- * @graphty/algorithms - Graph algorithms library for browser environments
2
+ * graphty/algorithms - Graph algorithms library for browser environments
3
3
  *
4
4
  * A comprehensive TypeScript library implementing fundamental graph algorithms
5
5
  * optimized for browser environments and visualization applications.
6
+ * @module
6
7
  */
7
8
 
8
9
  // Core exports
9
- export {Graph} from "./core/graph.js";
10
+ export { Graph } from "./core/graph.js";
10
11
 
11
12
  // Type exports
12
13
  export type {
@@ -38,3 +39,9 @@ export * from "./research/index.js";
38
39
 
39
40
  // Data structure exports
40
41
  export * from "./data-structures/index.js";
42
+
43
+ // Optimized algorithm exports
44
+ export * from "./optimized/index.js";
45
+
46
+ // Note: Configuration exports have been removed.
47
+ // The library now automatically optimizes based on graph size.
@@ -1,6 +1,7 @@
1
- import type {Graph} from "../core/graph.js";
2
- import type {NodeId} from "../types/index.js";
3
- import type {LinkPredictionOptions, LinkPredictionScore} from "./common-neighbors.js";
1
+ import type { Graph } from "../core/graph.js";
2
+ import type { NodeId } from "../types/index.js";
3
+ import { getCommonNeighbors, getIntermediateNodes } from "../utils/graph-utilities.js";
4
+ import type { LinkPredictionOptions, LinkPredictionScore } from "./common-neighbors.js";
4
5
 
5
6
  /**
6
7
  * Adamic-Adar Index link prediction implementation
@@ -18,6 +19,11 @@ import type {LinkPredictionOptions, LinkPredictionScore} from "./common-neighbor
18
19
 
19
20
  /**
20
21
  * Calculate Adamic-Adar index for a pair of nodes
22
+ * @param graph - The input graph
23
+ * @param source - The source node ID
24
+ * @param target - The target node ID
25
+ * @param options - Link prediction options
26
+ * @returns The Adamic-Adar score for the node pair
21
27
  */
22
28
  export function adamicAdarScore(
23
29
  graph: Graph,
@@ -29,30 +35,26 @@ export function adamicAdarScore(
29
35
  return 0;
30
36
  }
31
37
 
32
- const {directed = false} = options;
38
+ const { directed = false } = options;
33
39
 
34
- // Get neighbors
35
- const sourceNeighbors = new Set(
36
- directed ? Array.from(graph.outNeighbors(source)) : Array.from(graph.neighbors(source)),
37
- );
38
- const targetNeighbors = new Set(
39
- directed ? Array.from(graph.inNeighbors(target)) : Array.from(graph.neighbors(target)),
40
- );
40
+ // Use utility function to get common neighbors
41
+ // For directed graphs, we want intermediate nodes that form paths source->X->target
42
+ const commonNeighborsSet = directed
43
+ ? getIntermediateNodes(graph, source, target)
44
+ : getCommonNeighbors(graph, source, target, false);
41
45
 
42
46
  // Calculate Adamic-Adar score
43
47
  let score = 0;
44
- for (const neighbor of sourceNeighbors) {
45
- if (targetNeighbors.has(neighbor)) {
46
- const degree = directed ?
47
- graph.outDegree(neighbor) : // Use out-degree for directed graphs
48
- graph.degree(neighbor); // Use total degree for undirected graphs
49
-
50
- if (degree > 1) {
51
- score += 1 / Math.log(degree);
52
- } else if (degree === 1) {
53
- // For degree 1, we can't use log(1) = 0, so use a small constant
54
- score += 1; // or some other reasonable value
55
- }
48
+ for (const neighbor of commonNeighborsSet) {
49
+ const degree = directed
50
+ ? graph.outDegree(neighbor) // Use out-degree for directed graphs
51
+ : graph.degree(neighbor); // Use total degree for undirected graphs
52
+
53
+ if (degree > 1) {
54
+ score += 1 / Math.log(degree);
55
+ } else if (degree === 1) {
56
+ // For degree 1, we can't use log(1) = 0, so use a small constant
57
+ score += 1; // or some other reasonable value
56
58
  }
57
59
  }
58
60
 
@@ -61,16 +63,12 @@ export function adamicAdarScore(
61
63
 
62
64
  /**
63
65
  * Calculate Adamic-Adar scores for all possible node pairs
66
+ * @param graph - The input graph
67
+ * @param options - Link prediction options
68
+ * @returns Array of link prediction scores sorted by score descending
64
69
  */
65
- export function adamicAdarPrediction(
66
- graph: Graph,
67
- options: LinkPredictionOptions = {},
68
- ): LinkPredictionScore[] {
69
- const {
70
- directed = false,
71
- includeExisting = false,
72
- topK,
73
- } = options;
70
+ export function adamicAdarPrediction(graph: Graph, options: LinkPredictionOptions = {}): LinkPredictionScore[] {
71
+ const { directed = false, includeExisting = false, topK } = options;
74
72
 
75
73
  const scores: LinkPredictionScore[] = [];
76
74
  const nodes = Array.from(graph.nodes()).map((n) => n.id);
@@ -89,14 +87,14 @@ export function adamicAdarPrediction(
89
87
  continue;
90
88
  }
91
89
 
92
- const score = adamicAdarScore(graph, source, target, {directed});
90
+ const score = adamicAdarScore(graph, source, target, { directed });
93
91
 
94
92
  if (score > 0) {
95
- scores.push({source, target, score});
93
+ scores.push({ source, target, score });
96
94
 
97
95
  // For undirected graphs, also add the reverse pair
98
96
  if (!directed && source !== target) {
99
- scores.push({source: target, target: source, score});
97
+ scores.push({ source: target, target: source, score });
100
98
  }
101
99
  }
102
100
  }
@@ -115,6 +113,10 @@ export function adamicAdarPrediction(
115
113
 
116
114
  /**
117
115
  * Calculate Adamic-Adar scores for specific node pairs
116
+ * @param graph - The input graph
117
+ * @param pairs - Array of node ID pairs to calculate scores for
118
+ * @param options - Link prediction options
119
+ * @returns Array of link prediction scores for the specified pairs
118
120
  */
119
121
  export function adamicAdarForPairs(
120
122
  graph: Graph,
@@ -130,22 +132,21 @@ export function adamicAdarForPairs(
130
132
 
131
133
  /**
132
134
  * Get top Adamic-Adar candidates for link prediction for a specific node
135
+ * @param graph - The input graph
136
+ * @param node - The node ID to get candidates for
137
+ * @param options - Link prediction options with optional candidate list
138
+ * @returns Array of top link prediction candidates sorted by score descending
133
139
  */
134
140
  export function getTopAdamicAdarCandidatesForNode(
135
141
  graph: Graph,
136
142
  node: NodeId,
137
- options: LinkPredictionOptions & {candidates?: NodeId[]} = {},
143
+ options: LinkPredictionOptions & { candidates?: NodeId[] } = {},
138
144
  ): LinkPredictionScore[] {
139
145
  if (!graph.hasNode(node)) {
140
146
  return [];
141
147
  }
142
148
 
143
- const {
144
- directed = false,
145
- includeExisting = false,
146
- topK = 10,
147
- candidates,
148
- } = options;
149
+ const { directed = false, includeExisting = false, topK = 10, candidates } = options;
149
150
 
150
151
  const scores: LinkPredictionScore[] = [];
151
152
  const targetNodes = candidates ?? Array.from(graph.nodes()).map((n) => n.id);
@@ -160,10 +161,10 @@ export function getTopAdamicAdarCandidatesForNode(
160
161
  continue;
161
162
  }
162
163
 
163
- const score = adamicAdarScore(graph, node, target, {directed});
164
+ const score = adamicAdarScore(graph, node, target, { directed });
164
165
 
165
166
  if (score > 0) {
166
- scores.push({source: node, target, score});
167
+ scores.push({ source: node, target, score });
167
168
  }
168
169
  }
169
170
 
@@ -175,6 +176,11 @@ export function getTopAdamicAdarCandidatesForNode(
175
176
 
176
177
  /**
177
178
  * Calculate precision and recall for Adamic-Adar link prediction evaluation
179
+ * @param trainingGraph - The training graph without test edges
180
+ * @param testEdges - Array of node pairs that are actual edges
181
+ * @param nonEdges - Array of node pairs that are not edges
182
+ * @param options - Link prediction options
183
+ * @returns Evaluation metrics including precision, recall, F1 score, and AUC
178
184
  */
179
185
  export function evaluateAdamicAdar(
180
186
  trainingGraph: Graph,
@@ -182,19 +188,19 @@ export function evaluateAdamicAdar(
182
188
  nonEdges: [NodeId, NodeId][],
183
189
  options: LinkPredictionOptions = {},
184
190
  ): {
185
- precision: number;
186
- recall: number;
187
- f1Score: number;
188
- auc: number;
189
- } {
191
+ precision: number;
192
+ recall: number;
193
+ f1Score: number;
194
+ auc: number;
195
+ } {
190
196
  // Get scores for test edges and non-edges
191
197
  const testScores = adamicAdarForPairs(trainingGraph, testEdges, options);
192
198
  const nonEdgeScores = adamicAdarForPairs(trainingGraph, nonEdges, options);
193
199
 
194
200
  // Combine and sort all scores
195
201
  const allScores = [
196
- ... testScores.map((s) => ({... s, isActualEdge: true})),
197
- ... nonEdgeScores.map((s) => ({... s, isActualEdge: false})),
202
+ ...testScores.map((s) => ({ ...s, isActualEdge: true })),
203
+ ...nonEdgeScores.map((s) => ({ ...s, isActualEdge: false })),
198
204
  ].sort((a, b) => b.score - a.score);
199
205
 
200
206
  // Calculate precision and recall at different thresholds
@@ -215,7 +221,7 @@ export function evaluateAdamicAdar(
215
221
 
216
222
  const precision = truePositives / (truePositives + falsePositives);
217
223
  const recall = truePositives / totalPositives;
218
- const f1 = precision + recall > 0 ? 2 * (precision * recall) / (precision + recall) : 0;
224
+ const f1 = precision + recall > 0 ? (2 * (precision * recall)) / (precision + recall) : 0;
219
225
 
220
226
  if (f1 > bestF1) {
221
227
  bestF1 = f1;
@@ -254,6 +260,11 @@ export function evaluateAdamicAdar(
254
260
 
255
261
  /**
256
262
  * Compare Adamic-Adar with Common Neighbors for the same dataset
263
+ * @param graph - The input graph
264
+ * @param testEdges - Array of node pairs that are actual edges
265
+ * @param nonEdges - Array of node pairs that are not edges
266
+ * @param options - Link prediction options
267
+ * @returns Comparison of evaluation metrics for both algorithms
257
268
  */
258
269
  export function compareAdamicAdarWithCommonNeighbors(
259
270
  graph: Graph,
@@ -261,39 +272,29 @@ export function compareAdamicAdarWithCommonNeighbors(
261
272
  nonEdges: [NodeId, NodeId][],
262
273
  options: LinkPredictionOptions = {},
263
274
  ): {
264
- adamicAdar: ReturnType<typeof evaluateAdamicAdar>;
265
- commonNeighbors: {
266
- precision: number;
267
- recall: number;
268
- f1Score: number;
269
- auc: number;
270
- };
271
- } {
275
+ adamicAdar: ReturnType<typeof evaluateAdamicAdar>;
276
+ commonNeighbors: {
277
+ precision: number;
278
+ recall: number;
279
+ f1Score: number;
280
+ auc: number;
281
+ };
282
+ } {
272
283
  // Import common neighbors evaluation function
273
284
  // Since we're using ES modules, we can't use require. Instead, we'll implement a simple version here
274
285
  const commonNeighborsPairs = (pairs: [NodeId, NodeId][]): LinkPredictionScore[] =>
275
286
  pairs.map(([source, target]) => ({
276
287
  source,
277
288
  target,
278
- score: (() => {
279
- const sourceNeighbors = new Set(Array.from(graph.neighbors(source)));
280
- const targetNeighbors = new Set(Array.from(graph.neighbors(target)));
281
- let count = 0;
282
- for (const n of sourceNeighbors) {
283
- if (targetNeighbors.has(n)) {
284
- count++;
285
- }
286
- }
287
- return count;
288
- })(),
289
+ score: getCommonNeighbors(graph, source, target, options.directed).size,
289
290
  }));
290
291
 
291
292
  const testScores = commonNeighborsPairs(testEdges);
292
293
  const nonEdgeScores = commonNeighborsPairs(nonEdges);
293
294
 
294
295
  const allScores = [
295
- ... testScores.map((s) => ({... s, isActualEdge: true})),
296
- ... nonEdgeScores.map((s) => ({... s, isActualEdge: false})),
296
+ ...testScores.map((s) => ({ ...s, isActualEdge: true })),
297
+ ...nonEdgeScores.map((s) => ({ ...s, isActualEdge: false })),
297
298
  ].sort((a, b) => b.score - a.score);
298
299
 
299
300
  let truePositives = 0;
@@ -312,7 +313,7 @@ export function compareAdamicAdarWithCommonNeighbors(
312
313
 
313
314
  const precision = truePositives / (truePositives + falsePositives);
314
315
  const recall = truePositives / totalPositives;
315
- const f1 = precision + recall > 0 ? 2 * (precision * recall) / (precision + recall) : 0;
316
+ const f1 = precision + recall > 0 ? (2 * (precision * recall)) / (precision + recall) : 0;
316
317
  if (f1 > bestF1) {
317
318
  bestF1 = f1;
318
319
  bestPrecision = precision;