@graphty/algorithms 1.0.1 → 1.1.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.
- package/README.md +827 -60
- package/dist/algorithms.d.ts +2 -0
- package/dist/algorithms.d.ts.map +1 -0
- package/dist/algorithms.js +2 -0
- package/dist/algorithms.js.map +1 -0
- package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.js +22 -7
- package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
- package/dist/src/algorithms/centrality/closeness.js +7 -7
- package/dist/src/algorithms/centrality/closeness.js.map +1 -1
- package/dist/src/algorithms/centrality/degree.js +1 -1
- package/dist/src/algorithms/centrality/degree.js.map +1 -1
- package/dist/src/algorithms/centrality/eigenvector.d.ts +27 -0
- package/dist/src/algorithms/centrality/eigenvector.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/eigenvector.js +113 -0
- package/dist/src/algorithms/centrality/eigenvector.js.map +1 -0
- package/dist/src/algorithms/centrality/hits.d.ts +35 -0
- package/dist/src/algorithms/centrality/hits.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/hits.js +146 -0
- package/dist/src/algorithms/centrality/hits.js.map +1 -0
- package/dist/src/algorithms/centrality/index.d.ts +6 -0
- package/dist/src/algorithms/centrality/index.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/index.js +3 -0
- package/dist/src/algorithms/centrality/index.js.map +1 -1
- package/dist/src/algorithms/centrality/katz.d.ts +30 -0
- package/dist/src/algorithms/centrality/katz.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/katz.js +85 -0
- package/dist/src/algorithms/centrality/katz.js.map +1 -0
- package/dist/src/algorithms/centrality/pagerank.js +3 -3
- package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
- package/dist/src/algorithms/community/girvan-newman.d.ts +23 -0
- package/dist/src/algorithms/community/girvan-newman.d.ts.map +1 -0
- package/dist/src/algorithms/community/girvan-newman.js +297 -0
- package/dist/src/algorithms/community/girvan-newman.js.map +1 -0
- package/dist/src/algorithms/community/index.d.ts +12 -0
- package/dist/src/algorithms/community/index.d.ts.map +1 -0
- package/dist/src/algorithms/community/index.js +12 -0
- package/dist/src/algorithms/community/index.js.map +1 -0
- package/dist/src/algorithms/community/label-propagation.d.ts +42 -0
- package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -0
- package/dist/src/algorithms/community/label-propagation.js +307 -0
- package/dist/src/algorithms/community/label-propagation.js.map +1 -0
- package/dist/src/algorithms/community/leiden.d.ts +33 -0
- package/dist/src/algorithms/community/leiden.d.ts.map +1 -0
- package/dist/src/algorithms/community/leiden.js +434 -0
- package/dist/src/algorithms/community/leiden.js.map +1 -0
- package/dist/src/algorithms/community/louvain.d.ts +19 -0
- package/dist/src/algorithms/community/louvain.d.ts.map +1 -0
- package/dist/src/algorithms/community/louvain.js +219 -0
- package/dist/src/algorithms/community/louvain.js.map +1 -0
- package/dist/src/algorithms/components/connected.js +7 -7
- package/dist/src/algorithms/components/connected.js.map +1 -1
- package/dist/src/algorithms/index.d.ts +7 -0
- package/dist/src/algorithms/index.d.ts.map +1 -1
- package/dist/src/algorithms/index.js +14 -0
- package/dist/src/algorithms/index.js.map +1 -1
- package/dist/src/algorithms/matching/bipartite.d.ts +37 -0
- package/dist/src/algorithms/matching/bipartite.d.ts.map +1 -0
- package/dist/src/algorithms/matching/bipartite.js +127 -0
- package/dist/src/algorithms/matching/bipartite.js.map +1 -0
- package/dist/src/algorithms/matching/index.d.ts +8 -0
- package/dist/src/algorithms/matching/index.d.ts.map +1 -0
- package/dist/src/algorithms/matching/index.js +6 -0
- package/dist/src/algorithms/matching/index.js.map +1 -0
- package/dist/src/algorithms/matching/isomorphism.d.ts +32 -0
- package/dist/src/algorithms/matching/isomorphism.d.ts.map +1 -0
- package/dist/src/algorithms/matching/isomorphism.js +291 -0
- package/dist/src/algorithms/matching/isomorphism.js.map +1 -0
- package/dist/src/algorithms/mst/index.d.ts +4 -0
- package/dist/src/algorithms/mst/index.d.ts.map +1 -0
- package/dist/src/algorithms/mst/index.js +3 -0
- package/dist/src/algorithms/mst/index.js.map +1 -0
- package/dist/src/algorithms/mst/kruskal.d.ts +9 -0
- package/dist/src/algorithms/mst/kruskal.d.ts.map +1 -0
- package/dist/src/algorithms/mst/kruskal.js +43 -0
- package/dist/src/algorithms/mst/kruskal.js.map +1 -0
- package/dist/src/algorithms/mst/prim.d.ts +5 -0
- package/dist/src/algorithms/mst/prim.d.ts.map +1 -0
- package/dist/src/algorithms/mst/prim.js +63 -0
- package/dist/src/algorithms/mst/prim.js.map +1 -0
- package/dist/src/algorithms/shortest-path/bellman-ford.js +2 -2
- package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.js +5 -5
- package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
- package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts +14 -0
- package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts.map +1 -0
- package/dist/src/algorithms/shortest-path/floyd-warshall.js +129 -0
- package/dist/src/algorithms/shortest-path/floyd-warshall.js.map +1 -0
- package/dist/src/algorithms/shortest-path/index.d.ts +2 -0
- package/dist/src/algorithms/shortest-path/index.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/index.js +1 -0
- package/dist/src/algorithms/shortest-path/index.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs.js +2 -2
- package/dist/src/algorithms/traversal/bfs.js.map +1 -1
- package/dist/src/algorithms/traversal/dfs.js +11 -11
- package/dist/src/algorithms/traversal/dfs.js.map +1 -1
- package/dist/src/clustering/hierarchical.d.ts +48 -0
- package/dist/src/clustering/hierarchical.d.ts.map +1 -0
- package/dist/src/clustering/hierarchical.js +439 -0
- package/dist/src/clustering/hierarchical.js.map +1 -0
- package/dist/src/clustering/index.d.ts +7 -0
- package/dist/src/clustering/index.d.ts.map +1 -0
- package/dist/src/clustering/index.js +5 -0
- package/dist/src/clustering/index.js.map +1 -0
- package/dist/src/clustering/k-core.d.ts +63 -0
- package/dist/src/clustering/k-core.d.ts.map +1 -0
- package/dist/src/clustering/k-core.js +377 -0
- package/dist/src/clustering/k-core.js.map +1 -0
- package/dist/src/clustering/mcl.d.ts +36 -0
- package/dist/src/clustering/mcl.d.ts.map +1 -0
- package/dist/src/clustering/mcl.js +343 -0
- package/dist/src/clustering/mcl.js.map +1 -0
- package/dist/src/clustering/spectral.d.ts +28 -0
- package/dist/src/clustering/spectral.d.ts.map +1 -0
- package/dist/src/clustering/spectral.js +447 -0
- package/dist/src/clustering/spectral.js.map +1 -0
- package/dist/src/core/graph.d.ts +9 -0
- package/dist/src/core/graph.d.ts.map +1 -1
- package/dist/src/core/graph.js +31 -11
- package/dist/src/core/graph.js.map +1 -1
- package/dist/src/data-structures/priority-queue.js +0 -2
- package/dist/src/data-structures/priority-queue.js.map +1 -1
- package/dist/src/data-structures/union-find.js +2 -5
- package/dist/src/data-structures/union-find.js.map +1 -1
- package/dist/src/flow/ford-fulkerson.d.ts +53 -0
- package/dist/src/flow/ford-fulkerson.d.ts.map +1 -0
- package/dist/src/flow/ford-fulkerson.js +355 -0
- package/dist/src/flow/ford-fulkerson.js.map +1 -0
- package/dist/src/flow/index.d.ts +3 -0
- package/dist/src/flow/index.d.ts.map +1 -0
- package/dist/src/flow/index.js +3 -0
- package/dist/src/flow/index.js.map +1 -0
- package/dist/src/flow/min-cut.d.ts +49 -0
- package/dist/src/flow/min-cut.d.ts.map +1 -0
- package/dist/src/flow/min-cut.js +383 -0
- package/dist/src/flow/min-cut.js.map +1 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/link-prediction/adamic-adar.d.ts +56 -0
- package/dist/src/link-prediction/adamic-adar.d.ts.map +1 -0
- package/dist/src/link-prediction/adamic-adar.js +256 -0
- package/dist/src/link-prediction/adamic-adar.js.map +1 -0
- package/dist/src/link-prediction/common-neighbors.d.ts +50 -0
- package/dist/src/link-prediction/common-neighbors.d.ts.map +1 -0
- package/dist/src/link-prediction/common-neighbors.js +155 -0
- package/dist/src/link-prediction/common-neighbors.js.map +1 -0
- package/dist/src/link-prediction/index.d.ts +7 -0
- package/dist/src/link-prediction/index.d.ts.map +1 -0
- package/dist/src/link-prediction/index.js +6 -0
- package/dist/src/link-prediction/index.js.map +1 -0
- package/dist/src/pathfinding/astar.d.ts +50 -0
- package/dist/src/pathfinding/astar.d.ts.map +1 -0
- package/dist/src/pathfinding/astar.js +180 -0
- package/dist/src/pathfinding/astar.js.map +1 -0
- package/dist/src/pathfinding/index.d.ts +3 -0
- package/dist/src/pathfinding/index.d.ts.map +1 -0
- package/dist/src/pathfinding/index.js +3 -0
- package/dist/src/pathfinding/index.js.map +1 -0
- package/dist/src/pathfinding/utils.d.ts +18 -0
- package/dist/src/pathfinding/utils.d.ts.map +1 -0
- package/dist/src/pathfinding/utils.js +68 -0
- package/dist/src/pathfinding/utils.js.map +1 -0
- package/dist/src/types/index.d.ts +9 -0
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/utils/graphNode.d.ts +8 -0
- package/dist/src/utils/graphNode.d.ts.map +1 -0
- package/dist/src/utils/graphNode.js +2 -0
- package/dist/src/utils/graphNode.js.map +1 -0
- package/dist/src/utils/priorityQueue.d.ts +21 -0
- package/dist/src/utils/priorityQueue.d.ts.map +1 -0
- package/dist/src/utils/priorityQueue.js +101 -0
- package/dist/src/utils/priorityQueue.js.map +1 -0
- package/package.json +3 -1
- package/src/algorithms/centrality/betweenness.ts +25 -7
- package/src/algorithms/centrality/closeness.ts +7 -7
- package/src/algorithms/centrality/degree.ts +1 -1
- package/src/algorithms/centrality/eigenvector.ts +162 -0
- package/src/algorithms/centrality/hits.ts +210 -0
- package/src/algorithms/centrality/index.ts +6 -0
- package/src/algorithms/centrality/katz.ts +139 -0
- package/src/algorithms/centrality/pagerank.ts +3 -3
- package/src/algorithms/community/girvan-newman.ts +372 -0
- package/src/algorithms/community/index.ts +13 -0
- package/src/algorithms/community/label-propagation.ts +392 -0
- package/src/algorithms/community/leiden.ts +572 -0
- package/src/algorithms/community/louvain.ts +298 -0
- package/src/algorithms/components/connected.ts +7 -7
- package/src/algorithms/index.ts +21 -0
- package/src/algorithms/matching/bipartite.ts +179 -0
- package/src/algorithms/matching/index.ts +8 -0
- package/src/algorithms/matching/isomorphism.ts +392 -0
- package/src/algorithms/mst/index.ts +4 -0
- package/src/algorithms/mst/kruskal.ts +61 -0
- package/src/algorithms/mst/prim.ts +80 -0
- package/src/algorithms/shortest-path/bellman-ford.ts +2 -2
- package/src/algorithms/shortest-path/dijkstra.ts +5 -5
- package/src/algorithms/shortest-path/floyd-warshall.ts +170 -0
- package/src/algorithms/shortest-path/index.ts +2 -0
- package/src/algorithms/traversal/bfs.ts +2 -2
- package/src/algorithms/traversal/dfs.ts +11 -11
- package/src/clustering/hierarchical.ts +555 -0
- package/src/clustering/index.ts +6 -0
- package/src/clustering/k-core.ts +460 -0
- package/src/clustering/mcl.ts +454 -0
- package/src/clustering/spectral.ts +545 -0
- package/src/core/graph.ts +34 -6
- package/src/data-structures/union-find.ts +2 -2
- package/src/flow/ford-fulkerson.ts +459 -0
- package/src/flow/index.ts +2 -0
- package/src/flow/min-cut.ts +482 -0
- package/src/index.ts +2 -0
- package/src/link-prediction/adamic-adar.ts +353 -0
- package/src/link-prediction/common-neighbors.ts +252 -0
- package/src/link-prediction/index.ts +20 -0
- package/src/pathfinding/astar.ts +229 -0
- package/src/pathfinding/index.ts +2 -0
- package/src/pathfinding/utils.ts +87 -0
- package/src/types/index.ts +11 -0
- package/src/utils/graphNode.ts +7 -0
- package/src/utils/priorityQueue.ts +120 -0
- package/dist/test/browser/basic.test.d.ts +0 -2
- package/dist/test/browser/basic.test.d.ts.map +0 -1
- package/dist/test/browser/basic.test.js +0 -70
- package/dist/test/browser/basic.test.js.map +0 -1
- package/dist/test/unit/bellman-ford.test.d.ts +0 -2
- package/dist/test/unit/bellman-ford.test.d.ts.map +0 -1
- package/dist/test/unit/bellman-ford.test.js +0 -231
- package/dist/test/unit/bellman-ford.test.js.map +0 -1
- package/dist/test/unit/betweenness-centrality.test.d.ts +0 -2
- package/dist/test/unit/betweenness-centrality.test.d.ts.map +0 -1
- package/dist/test/unit/betweenness-centrality.test.js +0 -311
- package/dist/test/unit/betweenness-centrality.test.js.map +0 -1
- package/dist/test/unit/bfs.test.d.ts +0 -2
- package/dist/test/unit/bfs.test.d.ts.map +0 -1
- package/dist/test/unit/bfs.test.js +0 -277
- package/dist/test/unit/bfs.test.js.map +0 -1
- package/dist/test/unit/closeness.test.d.ts +0 -2
- package/dist/test/unit/closeness.test.d.ts.map +0 -1
- package/dist/test/unit/closeness.test.js +0 -266
- package/dist/test/unit/closeness.test.js.map +0 -1
- package/dist/test/unit/connected-components.test.d.ts +0 -2
- package/dist/test/unit/connected-components.test.d.ts.map +0 -1
- package/dist/test/unit/connected-components.test.js +0 -355
- package/dist/test/unit/connected-components.test.js.map +0 -1
- package/dist/test/unit/degree-centrality.test.d.ts +0 -2
- package/dist/test/unit/degree-centrality.test.d.ts.map +0 -1
- package/dist/test/unit/degree-centrality.test.js +0 -260
- package/dist/test/unit/degree-centrality.test.js.map +0 -1
- package/dist/test/unit/dfs.test.d.ts +0 -2
- package/dist/test/unit/dfs.test.d.ts.map +0 -1
- package/dist/test/unit/dfs.test.js +0 -350
- package/dist/test/unit/dfs.test.js.map +0 -1
- package/dist/test/unit/dijkstra.test.d.ts +0 -2
- package/dist/test/unit/dijkstra.test.d.ts.map +0 -1
- package/dist/test/unit/dijkstra.test.js +0 -311
- package/dist/test/unit/dijkstra.test.js.map +0 -1
- package/dist/test/unit/graph.test.d.ts +0 -2
- package/dist/test/unit/graph.test.d.ts.map +0 -1
- package/dist/test/unit/graph.test.js +0 -175
- package/dist/test/unit/graph.test.js.map +0 -1
- package/dist/test/unit/pagerank.test.d.ts +0 -2
- package/dist/test/unit/pagerank.test.d.ts.map +0 -1
- package/dist/test/unit/pagerank.test.js +0 -281
- package/dist/test/unit/pagerank.test.js.map +0 -1
- package/dist/test/unit/priority-queue.test.d.ts +0 -2
- package/dist/test/unit/priority-queue.test.d.ts.map +0 -1
- package/dist/test/unit/priority-queue.test.js +0 -189
- package/dist/test/unit/priority-queue.test.js.map +0 -1
- package/dist/test/unit/union-find.test.d.ts +0 -2
- package/dist/test/unit/union-find.test.d.ts.map +0 -1
- package/dist/test/unit/union-find.test.js +0 -245
- 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
|
|