@graphty/algorithms 1.0.1 → 1.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 (294) hide show
  1. package/README.md +1259 -61
  2. package/dist/algorithms.d.ts +2 -0
  3. package/dist/algorithms.d.ts.map +1 -0
  4. package/dist/algorithms.js +2 -0
  5. package/dist/algorithms.js.map +1 -0
  6. package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
  7. package/dist/src/algorithms/centrality/betweenness.js +22 -7
  8. package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
  9. package/dist/src/algorithms/centrality/closeness.js +7 -7
  10. package/dist/src/algorithms/centrality/closeness.js.map +1 -1
  11. package/dist/src/algorithms/centrality/degree.js +1 -1
  12. package/dist/src/algorithms/centrality/degree.js.map +1 -1
  13. package/dist/src/algorithms/centrality/eigenvector.d.ts +27 -0
  14. package/dist/src/algorithms/centrality/eigenvector.d.ts.map +1 -0
  15. package/dist/src/algorithms/centrality/eigenvector.js +113 -0
  16. package/dist/src/algorithms/centrality/eigenvector.js.map +1 -0
  17. package/dist/src/algorithms/centrality/hits.d.ts +35 -0
  18. package/dist/src/algorithms/centrality/hits.d.ts.map +1 -0
  19. package/dist/src/algorithms/centrality/hits.js +146 -0
  20. package/dist/src/algorithms/centrality/hits.js.map +1 -0
  21. package/dist/src/algorithms/centrality/index.d.ts +6 -0
  22. package/dist/src/algorithms/centrality/index.d.ts.map +1 -1
  23. package/dist/src/algorithms/centrality/index.js +3 -0
  24. package/dist/src/algorithms/centrality/index.js.map +1 -1
  25. package/dist/src/algorithms/centrality/katz.d.ts +30 -0
  26. package/dist/src/algorithms/centrality/katz.d.ts.map +1 -0
  27. package/dist/src/algorithms/centrality/katz.js +85 -0
  28. package/dist/src/algorithms/centrality/katz.js.map +1 -0
  29. package/dist/src/algorithms/centrality/pagerank.js +3 -3
  30. package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
  31. package/dist/src/algorithms/community/girvan-newman.d.ts +23 -0
  32. package/dist/src/algorithms/community/girvan-newman.d.ts.map +1 -0
  33. package/dist/src/algorithms/community/girvan-newman.js +297 -0
  34. package/dist/src/algorithms/community/girvan-newman.js.map +1 -0
  35. package/dist/src/algorithms/community/index.d.ts +12 -0
  36. package/dist/src/algorithms/community/index.d.ts.map +1 -0
  37. package/dist/src/algorithms/community/index.js +12 -0
  38. package/dist/src/algorithms/community/index.js.map +1 -0
  39. package/dist/src/algorithms/community/label-propagation.d.ts +42 -0
  40. package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -0
  41. package/dist/src/algorithms/community/label-propagation.js +307 -0
  42. package/dist/src/algorithms/community/label-propagation.js.map +1 -0
  43. package/dist/src/algorithms/community/leiden.d.ts +33 -0
  44. package/dist/src/algorithms/community/leiden.d.ts.map +1 -0
  45. package/dist/src/algorithms/community/leiden.js +434 -0
  46. package/dist/src/algorithms/community/leiden.js.map +1 -0
  47. package/dist/src/algorithms/community/louvain.d.ts +19 -0
  48. package/dist/src/algorithms/community/louvain.d.ts.map +1 -0
  49. package/dist/src/algorithms/community/louvain.js +219 -0
  50. package/dist/src/algorithms/community/louvain.js.map +1 -0
  51. package/dist/src/algorithms/components/connected.js +7 -7
  52. package/dist/src/algorithms/components/connected.js.map +1 -1
  53. package/dist/src/algorithms/index.d.ts +7 -0
  54. package/dist/src/algorithms/index.d.ts.map +1 -1
  55. package/dist/src/algorithms/index.js +14 -0
  56. package/dist/src/algorithms/index.js.map +1 -1
  57. package/dist/src/algorithms/matching/bipartite.d.ts +37 -0
  58. package/dist/src/algorithms/matching/bipartite.d.ts.map +1 -0
  59. package/dist/src/algorithms/matching/bipartite.js +127 -0
  60. package/dist/src/algorithms/matching/bipartite.js.map +1 -0
  61. package/dist/src/algorithms/matching/index.d.ts +8 -0
  62. package/dist/src/algorithms/matching/index.d.ts.map +1 -0
  63. package/dist/src/algorithms/matching/index.js +6 -0
  64. package/dist/src/algorithms/matching/index.js.map +1 -0
  65. package/dist/src/algorithms/matching/isomorphism.d.ts +32 -0
  66. package/dist/src/algorithms/matching/isomorphism.d.ts.map +1 -0
  67. package/dist/src/algorithms/matching/isomorphism.js +291 -0
  68. package/dist/src/algorithms/matching/isomorphism.js.map +1 -0
  69. package/dist/src/algorithms/mst/index.d.ts +4 -0
  70. package/dist/src/algorithms/mst/index.d.ts.map +1 -0
  71. package/dist/src/algorithms/mst/index.js +3 -0
  72. package/dist/src/algorithms/mst/index.js.map +1 -0
  73. package/dist/src/algorithms/mst/kruskal.d.ts +9 -0
  74. package/dist/src/algorithms/mst/kruskal.d.ts.map +1 -0
  75. package/dist/src/algorithms/mst/kruskal.js +43 -0
  76. package/dist/src/algorithms/mst/kruskal.js.map +1 -0
  77. package/dist/src/algorithms/mst/prim.d.ts +5 -0
  78. package/dist/src/algorithms/mst/prim.d.ts.map +1 -0
  79. package/dist/src/algorithms/mst/prim.js +63 -0
  80. package/dist/src/algorithms/mst/prim.js.map +1 -0
  81. package/dist/src/algorithms/shortest-path/bellman-ford.js +2 -2
  82. package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
  83. package/dist/src/algorithms/shortest-path/dijkstra.js +5 -5
  84. package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
  85. package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts +14 -0
  86. package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts.map +1 -0
  87. package/dist/src/algorithms/shortest-path/floyd-warshall.js +129 -0
  88. package/dist/src/algorithms/shortest-path/floyd-warshall.js.map +1 -0
  89. package/dist/src/algorithms/shortest-path/index.d.ts +2 -0
  90. package/dist/src/algorithms/shortest-path/index.d.ts.map +1 -1
  91. package/dist/src/algorithms/shortest-path/index.js +1 -0
  92. package/dist/src/algorithms/shortest-path/index.js.map +1 -1
  93. package/dist/src/algorithms/traversal/bfs.js +2 -2
  94. package/dist/src/algorithms/traversal/bfs.js.map +1 -1
  95. package/dist/src/algorithms/traversal/dfs.js +11 -11
  96. package/dist/src/algorithms/traversal/dfs.js.map +1 -1
  97. package/dist/src/clustering/hierarchical.d.ts +48 -0
  98. package/dist/src/clustering/hierarchical.d.ts.map +1 -0
  99. package/dist/src/clustering/hierarchical.js +439 -0
  100. package/dist/src/clustering/hierarchical.js.map +1 -0
  101. package/dist/src/clustering/index.d.ts +7 -0
  102. package/dist/src/clustering/index.d.ts.map +1 -0
  103. package/dist/src/clustering/index.js +5 -0
  104. package/dist/src/clustering/index.js.map +1 -0
  105. package/dist/src/clustering/k-core.d.ts +63 -0
  106. package/dist/src/clustering/k-core.d.ts.map +1 -0
  107. package/dist/src/clustering/k-core.js +377 -0
  108. package/dist/src/clustering/k-core.js.map +1 -0
  109. package/dist/src/clustering/mcl.d.ts +36 -0
  110. package/dist/src/clustering/mcl.d.ts.map +1 -0
  111. package/dist/src/clustering/mcl.js +343 -0
  112. package/dist/src/clustering/mcl.js.map +1 -0
  113. package/dist/src/clustering/spectral.d.ts +28 -0
  114. package/dist/src/clustering/spectral.d.ts.map +1 -0
  115. package/dist/src/clustering/spectral.js +551 -0
  116. package/dist/src/clustering/spectral.js.map +1 -0
  117. package/dist/src/core/graph.d.ts +9 -0
  118. package/dist/src/core/graph.d.ts.map +1 -1
  119. package/dist/src/core/graph.js +31 -11
  120. package/dist/src/core/graph.js.map +1 -1
  121. package/dist/src/data-structures/priority-queue.js +0 -2
  122. package/dist/src/data-structures/priority-queue.js.map +1 -1
  123. package/dist/src/data-structures/union-find.js +2 -5
  124. package/dist/src/data-structures/union-find.js.map +1 -1
  125. package/dist/src/flow/ford-fulkerson.d.ts +53 -0
  126. package/dist/src/flow/ford-fulkerson.d.ts.map +1 -0
  127. package/dist/src/flow/ford-fulkerson.js +355 -0
  128. package/dist/src/flow/ford-fulkerson.js.map +1 -0
  129. package/dist/src/flow/index.d.ts +3 -0
  130. package/dist/src/flow/index.d.ts.map +1 -0
  131. package/dist/src/flow/index.js +3 -0
  132. package/dist/src/flow/index.js.map +1 -0
  133. package/dist/src/flow/min-cut.d.ts +49 -0
  134. package/dist/src/flow/min-cut.d.ts.map +1 -0
  135. package/dist/src/flow/min-cut.js +383 -0
  136. package/dist/src/flow/min-cut.js.map +1 -0
  137. package/dist/src/index.d.ts +2 -1
  138. package/dist/src/index.d.ts.map +1 -1
  139. package/dist/src/index.js +2 -0
  140. package/dist/src/index.js.map +1 -1
  141. package/dist/src/link-prediction/adamic-adar.d.ts +56 -0
  142. package/dist/src/link-prediction/adamic-adar.d.ts.map +1 -0
  143. package/dist/src/link-prediction/adamic-adar.js +256 -0
  144. package/dist/src/link-prediction/adamic-adar.js.map +1 -0
  145. package/dist/src/link-prediction/common-neighbors.d.ts +50 -0
  146. package/dist/src/link-prediction/common-neighbors.d.ts.map +1 -0
  147. package/dist/src/link-prediction/common-neighbors.js +155 -0
  148. package/dist/src/link-prediction/common-neighbors.js.map +1 -0
  149. package/dist/src/link-prediction/index.d.ts +7 -0
  150. package/dist/src/link-prediction/index.d.ts.map +1 -0
  151. package/dist/src/link-prediction/index.js +6 -0
  152. package/dist/src/link-prediction/index.js.map +1 -0
  153. package/dist/src/pathfinding/astar.d.ts +50 -0
  154. package/dist/src/pathfinding/astar.d.ts.map +1 -0
  155. package/dist/src/pathfinding/astar.js +180 -0
  156. package/dist/src/pathfinding/astar.js.map +1 -0
  157. package/dist/src/pathfinding/index.d.ts +3 -0
  158. package/dist/src/pathfinding/index.d.ts.map +1 -0
  159. package/dist/src/pathfinding/index.js +3 -0
  160. package/dist/src/pathfinding/index.js.map +1 -0
  161. package/dist/src/pathfinding/utils.d.ts +18 -0
  162. package/dist/src/pathfinding/utils.d.ts.map +1 -0
  163. package/dist/src/pathfinding/utils.js +68 -0
  164. package/dist/src/pathfinding/utils.js.map +1 -0
  165. package/dist/src/research/grsbm.d.ts +83 -0
  166. package/dist/src/research/grsbm.d.ts.map +1 -0
  167. package/dist/src/research/grsbm.js +411 -0
  168. package/dist/src/research/grsbm.js.map +1 -0
  169. package/dist/src/research/index.d.ts +12 -0
  170. package/dist/src/research/index.d.ts.map +1 -0
  171. package/dist/src/research/index.js +14 -0
  172. package/dist/src/research/index.js.map +1 -0
  173. package/dist/src/research/sync.d.ts +49 -0
  174. package/dist/src/research/sync.d.ts.map +1 -0
  175. package/dist/src/research/sync.js +342 -0
  176. package/dist/src/research/sync.js.map +1 -0
  177. package/dist/src/research/terahac.d.ts +63 -0
  178. package/dist/src/research/terahac.d.ts.map +1 -0
  179. package/dist/src/research/terahac.js +375 -0
  180. package/dist/src/research/terahac.js.map +1 -0
  181. package/dist/src/types/index.d.ts +9 -0
  182. package/dist/src/types/index.d.ts.map +1 -1
  183. package/dist/src/utils/graphNode.d.ts +8 -0
  184. package/dist/src/utils/graphNode.d.ts.map +1 -0
  185. package/dist/src/utils/graphNode.js +2 -0
  186. package/dist/src/utils/graphNode.js.map +1 -0
  187. package/dist/src/utils/priorityQueue.d.ts +21 -0
  188. package/dist/src/utils/priorityQueue.d.ts.map +1 -0
  189. package/dist/src/utils/priorityQueue.js +101 -0
  190. package/dist/src/utils/priorityQueue.js.map +1 -0
  191. package/package.json +13 -2
  192. package/src/algorithms/centrality/betweenness.ts +25 -7
  193. package/src/algorithms/centrality/closeness.ts +7 -7
  194. package/src/algorithms/centrality/degree.ts +1 -1
  195. package/src/algorithms/centrality/eigenvector.ts +162 -0
  196. package/src/algorithms/centrality/hits.ts +210 -0
  197. package/src/algorithms/centrality/index.ts +6 -0
  198. package/src/algorithms/centrality/katz.ts +139 -0
  199. package/src/algorithms/centrality/pagerank.ts +3 -3
  200. package/src/algorithms/community/girvan-newman.ts +372 -0
  201. package/src/algorithms/community/index.ts +13 -0
  202. package/src/algorithms/community/label-propagation.ts +392 -0
  203. package/src/algorithms/community/leiden.ts +572 -0
  204. package/src/algorithms/community/louvain.ts +298 -0
  205. package/src/algorithms/components/connected.ts +7 -7
  206. package/src/algorithms/index.ts +21 -0
  207. package/src/algorithms/matching/bipartite.ts +179 -0
  208. package/src/algorithms/matching/index.ts +8 -0
  209. package/src/algorithms/matching/isomorphism.ts +392 -0
  210. package/src/algorithms/mst/index.ts +4 -0
  211. package/src/algorithms/mst/kruskal.ts +61 -0
  212. package/src/algorithms/mst/prim.ts +80 -0
  213. package/src/algorithms/shortest-path/bellman-ford.ts +2 -2
  214. package/src/algorithms/shortest-path/dijkstra.ts +5 -5
  215. package/src/algorithms/shortest-path/floyd-warshall.ts +170 -0
  216. package/src/algorithms/shortest-path/index.ts +2 -0
  217. package/src/algorithms/traversal/bfs.ts +2 -2
  218. package/src/algorithms/traversal/dfs.ts +11 -11
  219. package/src/clustering/hierarchical.ts +555 -0
  220. package/src/clustering/index.ts +6 -0
  221. package/src/clustering/k-core.ts +460 -0
  222. package/src/clustering/mcl.ts +454 -0
  223. package/src/clustering/spectral.ts +672 -0
  224. package/src/core/graph.ts +34 -6
  225. package/src/data-structures/union-find.ts +2 -2
  226. package/src/flow/ford-fulkerson.ts +459 -0
  227. package/src/flow/index.ts +2 -0
  228. package/src/flow/min-cut.ts +482 -0
  229. package/src/index.ts +5 -0
  230. package/src/link-prediction/adamic-adar.ts +353 -0
  231. package/src/link-prediction/common-neighbors.ts +252 -0
  232. package/src/link-prediction/index.ts +20 -0
  233. package/src/pathfinding/astar.ts +229 -0
  234. package/src/pathfinding/index.ts +2 -0
  235. package/src/pathfinding/utils.ts +87 -0
  236. package/src/research/grsbm.ts +589 -0
  237. package/src/research/index.ts +17 -0
  238. package/src/research/sync.ts +469 -0
  239. package/src/research/terahac.ts +506 -0
  240. package/src/types/index.ts +11 -0
  241. package/src/utils/graphNode.ts +7 -0
  242. package/src/utils/priorityQueue.ts +120 -0
  243. package/dist/test/browser/basic.test.d.ts +0 -2
  244. package/dist/test/browser/basic.test.d.ts.map +0 -1
  245. package/dist/test/browser/basic.test.js +0 -70
  246. package/dist/test/browser/basic.test.js.map +0 -1
  247. package/dist/test/unit/bellman-ford.test.d.ts +0 -2
  248. package/dist/test/unit/bellman-ford.test.d.ts.map +0 -1
  249. package/dist/test/unit/bellman-ford.test.js +0 -231
  250. package/dist/test/unit/bellman-ford.test.js.map +0 -1
  251. package/dist/test/unit/betweenness-centrality.test.d.ts +0 -2
  252. package/dist/test/unit/betweenness-centrality.test.d.ts.map +0 -1
  253. package/dist/test/unit/betweenness-centrality.test.js +0 -311
  254. package/dist/test/unit/betweenness-centrality.test.js.map +0 -1
  255. package/dist/test/unit/bfs.test.d.ts +0 -2
  256. package/dist/test/unit/bfs.test.d.ts.map +0 -1
  257. package/dist/test/unit/bfs.test.js +0 -277
  258. package/dist/test/unit/bfs.test.js.map +0 -1
  259. package/dist/test/unit/closeness.test.d.ts +0 -2
  260. package/dist/test/unit/closeness.test.d.ts.map +0 -1
  261. package/dist/test/unit/closeness.test.js +0 -266
  262. package/dist/test/unit/closeness.test.js.map +0 -1
  263. package/dist/test/unit/connected-components.test.d.ts +0 -2
  264. package/dist/test/unit/connected-components.test.d.ts.map +0 -1
  265. package/dist/test/unit/connected-components.test.js +0 -355
  266. package/dist/test/unit/connected-components.test.js.map +0 -1
  267. package/dist/test/unit/degree-centrality.test.d.ts +0 -2
  268. package/dist/test/unit/degree-centrality.test.d.ts.map +0 -1
  269. package/dist/test/unit/degree-centrality.test.js +0 -260
  270. package/dist/test/unit/degree-centrality.test.js.map +0 -1
  271. package/dist/test/unit/dfs.test.d.ts +0 -2
  272. package/dist/test/unit/dfs.test.d.ts.map +0 -1
  273. package/dist/test/unit/dfs.test.js +0 -350
  274. package/dist/test/unit/dfs.test.js.map +0 -1
  275. package/dist/test/unit/dijkstra.test.d.ts +0 -2
  276. package/dist/test/unit/dijkstra.test.d.ts.map +0 -1
  277. package/dist/test/unit/dijkstra.test.js +0 -311
  278. package/dist/test/unit/dijkstra.test.js.map +0 -1
  279. package/dist/test/unit/graph.test.d.ts +0 -2
  280. package/dist/test/unit/graph.test.d.ts.map +0 -1
  281. package/dist/test/unit/graph.test.js +0 -175
  282. package/dist/test/unit/graph.test.js.map +0 -1
  283. package/dist/test/unit/pagerank.test.d.ts +0 -2
  284. package/dist/test/unit/pagerank.test.d.ts.map +0 -1
  285. package/dist/test/unit/pagerank.test.js +0 -281
  286. package/dist/test/unit/pagerank.test.js.map +0 -1
  287. package/dist/test/unit/priority-queue.test.d.ts +0 -2
  288. package/dist/test/unit/priority-queue.test.d.ts.map +0 -1
  289. package/dist/test/unit/priority-queue.test.js +0 -189
  290. package/dist/test/unit/priority-queue.test.js.map +0 -1
  291. package/dist/test/unit/union-find.test.d.ts +0 -2
  292. package/dist/test/unit/union-find.test.d.ts.map +0 -1
  293. package/dist/test/unit/union-find.test.js +0 -245
  294. package/dist/test/unit/union-find.test.js.map +0 -1
@@ -0,0 +1,170 @@
1
+ import {Graph} from "../../core/graph.js";
2
+ import type {NodeId} from "../../types/index.js";
3
+
4
+ export interface FloydWarshallResult {
5
+ distances: Map<NodeId, Map<NodeId, number>>;
6
+ predecessors: Map<NodeId, Map<NodeId, NodeId | null>>;
7
+ hasNegativeCycle: boolean;
8
+ }
9
+
10
+ export function floydWarshall(graph: Graph): FloydWarshallResult {
11
+ const nodes = Array.from(graph.nodes()).map((n) => n.id);
12
+ const distances = new Map<NodeId, Map<NodeId, number>>();
13
+ const predecessors = new Map<NodeId, Map<NodeId, NodeId | null>>();
14
+
15
+ for (const node of nodes) {
16
+ distances.set(node, new Map());
17
+ predecessors.set(node, new Map());
18
+
19
+ const nodeDistances = distances.get(node);
20
+ const nodePredecessors = predecessors.get(node);
21
+
22
+ if (!nodeDistances || !nodePredecessors) {
23
+ continue;
24
+ }
25
+
26
+ for (const other of nodes) {
27
+ if (node === other) {
28
+ nodeDistances.set(other, 0);
29
+ nodePredecessors.set(other, null);
30
+ } else {
31
+ nodeDistances.set(other, Infinity);
32
+ nodePredecessors.set(other, null);
33
+ }
34
+ }
35
+ }
36
+
37
+ for (const edge of Array.from(graph.edges())) {
38
+ const weight = edge.weight ?? 1;
39
+ const sourceDistances = distances.get(edge.source);
40
+ const sourcePredecessors = predecessors.get(edge.source);
41
+
42
+ if (sourceDistances && sourcePredecessors) {
43
+ sourceDistances.set(edge.target, weight);
44
+ sourcePredecessors.set(edge.target, edge.source);
45
+ }
46
+
47
+ if (!graph.isDirected) {
48
+ const targetDistances = distances.get(edge.target);
49
+ const targetPredecessors = predecessors.get(edge.target);
50
+
51
+ if (targetDistances && targetPredecessors) {
52
+ targetDistances.set(edge.source, weight);
53
+ targetPredecessors.set(edge.source, edge.target);
54
+ }
55
+ }
56
+ }
57
+
58
+ for (const k of nodes) {
59
+ for (const i of nodes) {
60
+ for (const j of nodes) {
61
+ const distancesI = distances.get(i);
62
+ const distancesK = distances.get(k);
63
+ const predecessorsI = predecessors.get(i);
64
+ const predecessorsK = predecessors.get(k);
65
+
66
+ if (!distancesI || !distancesK || !predecessorsI || !predecessorsK) {
67
+ continue;
68
+ }
69
+
70
+ const distIK = distancesI.get(k);
71
+ const distKJ = distancesK.get(j);
72
+ const distIJ = distancesI.get(j);
73
+
74
+ if (distIK === undefined || distKJ === undefined || distIJ === undefined) {
75
+ continue;
76
+ }
77
+
78
+ if (distIK + distKJ < distIJ) {
79
+ distancesI.set(j, distIK + distKJ);
80
+ const predKJ = predecessorsK.get(j);
81
+ predecessorsI.set(j, predKJ ?? null);
82
+ }
83
+ }
84
+ }
85
+ }
86
+
87
+ let hasNegativeCycle = false;
88
+ for (const node of nodes) {
89
+ const nodeDistances = distances.get(node);
90
+ if (!nodeDistances) {
91
+ continue;
92
+ }
93
+
94
+ const selfDistance = nodeDistances.get(node);
95
+ if (selfDistance !== undefined && selfDistance < 0) {
96
+ hasNegativeCycle = true;
97
+ break;
98
+ }
99
+ }
100
+
101
+ return {
102
+ distances,
103
+ predecessors,
104
+ hasNegativeCycle,
105
+ };
106
+ }
107
+
108
+ export function floydWarshallPath(
109
+ graph: Graph,
110
+ source: NodeId,
111
+ target: NodeId,
112
+ ): {path: NodeId[], distance: number} | null {
113
+ const result = floydWarshall(graph);
114
+
115
+ if (!graph.hasNode(source) || !graph.hasNode(target)) {
116
+ return null;
117
+ }
118
+
119
+ const sourceDistances = result.distances.get(source);
120
+ if (!sourceDistances) {
121
+ return null;
122
+ }
123
+
124
+ const distance = sourceDistances.get(target);
125
+ if (distance === undefined || distance === Infinity) {
126
+ return null;
127
+ }
128
+
129
+ const path: NodeId[] = [];
130
+ let current: NodeId | null = target;
131
+
132
+ while (current !== null && current !== source) {
133
+ path.unshift(current);
134
+
135
+ const sourcePredecessors = result.predecessors.get(source);
136
+ if (!sourcePredecessors) {
137
+ return null;
138
+ }
139
+
140
+ current = sourcePredecessors.get(current) ?? null;
141
+
142
+ if (path.length > graph.nodeCount) {
143
+ return null;
144
+ }
145
+ }
146
+
147
+ if (current === source) {
148
+ path.unshift(source);
149
+ return {path, distance};
150
+ }
151
+
152
+ return null;
153
+ }
154
+
155
+ export function transitiveClosure(graph: Graph): Map<NodeId, Set<NodeId>> {
156
+ const result = floydWarshall(graph);
157
+ const closure = new Map<NodeId, Set<NodeId>>();
158
+
159
+ for (const [source, distances] of Array.from(result.distances)) {
160
+ const reachable = new Set<NodeId>();
161
+ for (const [target, distance] of Array.from(distances)) {
162
+ if (distance < Infinity) {
163
+ reachable.add(target);
164
+ }
165
+ }
166
+ closure.set(source, reachable);
167
+ }
168
+
169
+ return closure;
170
+ }
@@ -5,3 +5,5 @@
5
5
  export type {BellmanFordOptions, BellmanFordResult} from "./bellman-ford.js";
6
6
  export {bellmanFord, bellmanFordPath, hasNegativeCycle} from "./bellman-ford.js";
7
7
  export {allPairsShortestPath, dijkstra, dijkstraPath, singleSourceShortestPath} from "./dijkstra.js";
8
+ export type {FloydWarshallResult} from "./floyd-warshall.js";
9
+ export {floydWarshall, floydWarshallPath, transitiveClosure} from "./floyd-warshall.js";
@@ -185,7 +185,7 @@ export function isBipartite(graph: Graph): boolean {
185
185
  const visited = new Set<NodeId>();
186
186
 
187
187
  // Check each connected component
188
- for (const node of graph.nodes()) {
188
+ for (const node of Array.from(graph.nodes())) {
189
189
  if (!visited.has(node.id)) {
190
190
  const queue: NodeId[] = [node.id];
191
191
  color.set(node.id, 0);
@@ -202,7 +202,7 @@ export function isBipartite(graph: Graph): boolean {
202
202
  continue;
203
203
  }
204
204
 
205
- for (const neighbor of graph.neighbors(current)) {
205
+ for (const neighbor of Array.from(graph.neighbors(current))) {
206
206
  if (!visited.has(neighbor)) {
207
207
  // Color with opposite color
208
208
  color.set(neighbor, currentColor === 0 ? 1 : 0);
@@ -127,7 +127,7 @@ function dfsRecursive(
127
127
  }
128
128
 
129
129
  // Recursively visit neighbors
130
- for (const neighbor of graph.neighbors(node)) {
130
+ for (const neighbor of Array.from(graph.neighbors(node))) {
131
131
  if (!visited.has(neighbor)) {
132
132
  dfsRecursive(graph, neighbor, visited, order, tree, options, depth + 1, node);
133
133
  }
@@ -150,7 +150,7 @@ export function hasCycleDFS(graph: Graph): boolean {
150
150
  const visited = new Set<NodeId>();
151
151
 
152
152
  // Check each unvisited node for cycles
153
- for (const node of graph.nodes()) {
153
+ for (const node of Array.from(graph.nodes())) {
154
154
  if (!visited.has(node.id)) {
155
155
  if (graph.isDirected) {
156
156
  const recursionStack = new Set<NodeId>();
@@ -181,7 +181,7 @@ function hasCycleUtilDirected(
181
181
  recursionStack.add(node);
182
182
 
183
183
  // Check all neighbors
184
- for (const neighbor of graph.neighbors(node)) {
184
+ for (const neighbor of Array.from(graph.neighbors(node))) {
185
185
  if (!visited.has(neighbor)) {
186
186
  if (hasCycleUtilDirected(graph, neighbor, visited, recursionStack)) {
187
187
  return true;
@@ -208,7 +208,7 @@ function hasCycleUtilUndirected(
208
208
  visited.add(node);
209
209
 
210
210
  // Check all neighbors
211
- for (const neighbor of graph.neighbors(node)) {
211
+ for (const neighbor of Array.from(graph.neighbors(node))) {
212
212
  if (!visited.has(neighbor)) {
213
213
  if (hasCycleUtilUndirected(graph, neighbor, visited, node)) {
214
214
  return true;
@@ -239,7 +239,7 @@ export function topologicalSort(graph: Graph): NodeId[] | null {
239
239
  const stack: NodeId[] = [];
240
240
 
241
241
  // Perform DFS from each unvisited node
242
- for (const node of graph.nodes()) {
242
+ for (const node of Array.from(graph.nodes())) {
243
243
  if (!visited.has(node.id)) {
244
244
  topologicalSortUtil(graph, node.id, visited, stack);
245
245
  }
@@ -261,7 +261,7 @@ function topologicalSortUtil(
261
261
  visited.add(node);
262
262
 
263
263
  // Visit all neighbors first
264
- for (const neighbor of graph.neighbors(node)) {
264
+ for (const neighbor of Array.from(graph.neighbors(node))) {
265
265
  if (!visited.has(neighbor)) {
266
266
  topologicalSortUtil(graph, neighbor, visited, stack);
267
267
  }
@@ -283,7 +283,7 @@ export function findStronglyConnectedComponents(graph: Graph): NodeId[][] {
283
283
  const finishOrder: NodeId[] = [];
284
284
 
285
285
  // Step 1: Get nodes in order of finishing times
286
- for (const node of graph.nodes()) {
286
+ for (const node of Array.from(graph.nodes())) {
287
287
  if (!visited.has(node.id)) {
288
288
  dfsFinishOrder(graph, node.id, visited, finishOrder);
289
289
  }
@@ -319,7 +319,7 @@ function dfsFinishOrder(
319
319
  ): void {
320
320
  visited.add(node);
321
321
 
322
- for (const neighbor of graph.neighbors(node)) {
322
+ for (const neighbor of Array.from(graph.neighbors(node))) {
323
323
  if (!visited.has(neighbor)) {
324
324
  dfsFinishOrder(graph, neighbor, visited, finishOrder);
325
325
  }
@@ -340,7 +340,7 @@ function dfsCollectComponent(
340
340
  visited.add(node);
341
341
  component.push(node);
342
342
 
343
- for (const neighbor of graph.neighbors(node)) {
343
+ for (const neighbor of Array.from(graph.neighbors(node))) {
344
344
  if (!visited.has(neighbor)) {
345
345
  dfsCollectComponent(graph, neighbor, visited, component);
346
346
  }
@@ -354,12 +354,12 @@ function createTransposeGraph(graph: Graph): Graph {
354
354
  const transpose = new Graph({directed: true});
355
355
 
356
356
  // Add all nodes
357
- for (const node of graph.nodes()) {
357
+ for (const node of Array.from(graph.nodes())) {
358
358
  transpose.addNode(node.id, node.data);
359
359
  }
360
360
 
361
361
  // Add reverse edges
362
- for (const edge of graph.edges()) {
362
+ for (const edge of Array.from(graph.edges())) {
363
363
  transpose.addEdge(edge.target, edge.source, edge.weight, edge.data);
364
364
  }
365
365