@graphty/algorithms 1.3.1 → 1.5.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 +368 -422
- package/dist/algorithms.js +567 -264
- package/dist/algorithms.js.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.d.ts +10 -0
- package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.js +27 -6
- package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
- package/dist/src/algorithms/centrality/closeness.d.ts +11 -2
- package/dist/src/algorithms/centrality/closeness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/closeness.js +17 -3
- package/dist/src/algorithms/centrality/closeness.js.map +1 -1
- package/dist/src/algorithms/centrality/degree.d.ts +7 -0
- package/dist/src/algorithms/centrality/degree.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/degree.js +9 -6
- package/dist/src/algorithms/centrality/degree.js.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts +21 -3
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js +25 -7
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank.d.ts +28 -2
- package/dist/src/algorithms/centrality/delta-pagerank.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank.js +30 -4
- package/dist/src/algorithms/centrality/delta-pagerank.js.map +1 -1
- package/dist/src/algorithms/centrality/eigenvector.d.ts +10 -3
- package/dist/src/algorithms/centrality/eigenvector.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/eigenvector.js +11 -4
- package/dist/src/algorithms/centrality/eigenvector.js.map +1 -1
- package/dist/src/algorithms/centrality/hits.d.ts +10 -3
- package/dist/src/algorithms/centrality/hits.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/hits.js +11 -4
- package/dist/src/algorithms/centrality/hits.js.map +1 -1
- package/dist/src/algorithms/centrality/index.d.ts +1 -1
- package/dist/src/algorithms/centrality/index.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/index.js +1 -1
- package/dist/src/algorithms/centrality/index.js.map +1 -1
- package/dist/src/algorithms/centrality/katz.d.ts +10 -3
- package/dist/src/algorithms/centrality/katz.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/katz.js +13 -8
- package/dist/src/algorithms/centrality/katz.js.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.d.ts +14 -0
- package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.js +16 -1
- package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
- package/dist/src/algorithms/community/girvan-newman.d.ts +2 -3
- package/dist/src/algorithms/community/girvan-newman.d.ts.map +1 -1
- package/dist/src/algorithms/community/girvan-newman.js +21 -4
- package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
- package/dist/src/algorithms/community/index.d.ts.map +1 -1
- package/dist/src/algorithms/community/index.js.map +1 -1
- package/dist/src/algorithms/community/label-propagation.d.ts +0 -3
- package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -1
- package/dist/src/algorithms/community/label-propagation.js +13 -6
- package/dist/src/algorithms/community/label-propagation.js.map +1 -1
- package/dist/src/algorithms/community/leiden.d.ts +0 -1
- package/dist/src/algorithms/community/leiden.d.ts.map +1 -1
- package/dist/src/algorithms/community/leiden.js +37 -6
- package/dist/src/algorithms/community/leiden.js.map +1 -1
- package/dist/src/algorithms/community/louvain-optimized.d.ts +37 -0
- package/dist/src/algorithms/community/louvain-optimized.d.ts.map +1 -1
- package/dist/src/algorithms/community/louvain-optimized.js +42 -7
- package/dist/src/algorithms/community/louvain-optimized.js.map +1 -1
- package/dist/src/algorithms/community/louvain.d.ts +2 -3
- package/dist/src/algorithms/community/louvain.d.ts.map +1 -1
- package/dist/src/algorithms/community/louvain.js +19 -6
- package/dist/src/algorithms/community/louvain.js.map +1 -1
- package/dist/src/algorithms/community/modularity-utils.d.ts +0 -4
- package/dist/src/algorithms/community/modularity-utils.d.ts.map +1 -1
- package/dist/src/algorithms/community/modularity-utils.js +1 -5
- package/dist/src/algorithms/community/modularity-utils.js.map +1 -1
- package/dist/src/algorithms/components/connected.d.ts +23 -0
- package/dist/src/algorithms/components/connected.d.ts.map +1 -1
- package/dist/src/algorithms/components/connected.js +29 -3
- package/dist/src/algorithms/components/connected.js.map +1 -1
- package/dist/src/algorithms/matching/bipartite.d.ts +10 -0
- package/dist/src/algorithms/matching/bipartite.d.ts.map +1 -1
- package/dist/src/algorithms/matching/bipartite.js +10 -0
- package/dist/src/algorithms/matching/bipartite.js.map +1 -1
- package/dist/src/algorithms/matching/index.d.ts.map +1 -1
- package/dist/src/algorithms/matching/index.js.map +1 -1
- package/dist/src/algorithms/matching/isomorphism.d.ts +8 -0
- package/dist/src/algorithms/matching/isomorphism.d.ts.map +1 -1
- package/dist/src/algorithms/matching/isomorphism.js +36 -2
- package/dist/src/algorithms/matching/isomorphism.js.map +1 -1
- package/dist/src/algorithms/mst/index.d.ts.map +1 -1
- package/dist/src/algorithms/mst/index.js.map +1 -1
- package/dist/src/algorithms/mst/kruskal.d.ts +14 -0
- package/dist/src/algorithms/mst/kruskal.d.ts.map +1 -1
- package/dist/src/algorithms/mst/kruskal.js +17 -3
- package/dist/src/algorithms/mst/kruskal.js.map +1 -1
- package/dist/src/algorithms/mst/prim.d.ts +9 -0
- package/dist/src/algorithms/mst/prim.d.ts.map +1 -1
- package/dist/src/algorithms/mst/prim.js +9 -0
- package/dist/src/algorithms/mst/prim.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.d.ts +10 -0
- package/dist/src/algorithms/shortest-path/bellman-ford.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.js +10 -0
- package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts +12 -5
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +19 -17
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts +15 -0
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.js +15 -0
- package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
- package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts +17 -0
- package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/floyd-warshall.js +17 -0
- package/dist/src/algorithms/shortest-path/floyd-warshall.js.map +1 -1
- package/dist/src/algorithms/shortest-path/index.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/index.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs-unified.d.ts +13 -0
- package/dist/src/algorithms/traversal/bfs-unified.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs-unified.js +37 -0
- package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs-variants.d.ts +23 -0
- package/dist/src/algorithms/traversal/bfs-variants.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs-variants.js +34 -0
- package/dist/src/algorithms/traversal/bfs-variants.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs.d.ts +1 -1
- package/dist/src/algorithms/traversal/bfs.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs.js +1 -1
- package/dist/src/algorithms/traversal/bfs.js.map +1 -1
- package/dist/src/algorithms/traversal/dfs.d.ts +10 -0
- package/dist/src/algorithms/traversal/dfs.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/dfs.js +48 -0
- package/dist/src/algorithms/traversal/dfs.js.map +1 -1
- package/dist/src/algorithms/traversal/index.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/index.js.map +1 -1
- package/dist/src/benchmark-all-algorithms.d.ts +2 -0
- package/dist/src/benchmark-all-algorithms.d.ts.map +1 -1
- package/dist/src/benchmark-all-algorithms.js +32 -3
- package/dist/src/benchmark-all-algorithms.js.map +1 -1
- package/dist/src/clustering/hierarchical.d.ts +8 -1
- package/dist/src/clustering/hierarchical.d.ts.map +1 -1
- package/dist/src/clustering/hierarchical.js +22 -6
- package/dist/src/clustering/hierarchical.js.map +1 -1
- package/dist/src/clustering/index.d.ts.map +1 -1
- package/dist/src/clustering/index.js.map +1 -1
- package/dist/src/clustering/k-core.d.ts +2 -5
- package/dist/src/clustering/k-core.d.ts.map +1 -1
- package/dist/src/clustering/k-core.js +14 -12
- package/dist/src/clustering/k-core.js.map +1 -1
- package/dist/src/clustering/mcl.d.ts +6 -0
- package/dist/src/clustering/mcl.d.ts.map +1 -1
- package/dist/src/clustering/mcl.js +34 -3
- package/dist/src/clustering/mcl.js.map +1 -1
- package/dist/src/clustering/spectral.d.ts +4 -1
- package/dist/src/clustering/spectral.d.ts.map +1 -1
- package/dist/src/clustering/spectral.js +61 -28
- package/dist/src/clustering/spectral.js.map +1 -1
- package/dist/src/core/graph.d.ts +45 -0
- package/dist/src/core/graph.d.ts.map +1 -1
- package/dist/src/core/graph.js +45 -1
- package/dist/src/core/graph.js.map +1 -1
- package/dist/src/data-structures/index.d.ts.map +1 -1
- package/dist/src/data-structures/index.js.map +1 -1
- package/dist/src/data-structures/priority-queue.d.ts +18 -1
- package/dist/src/data-structures/priority-queue.d.ts.map +1 -1
- package/dist/src/data-structures/priority-queue.js +26 -5
- package/dist/src/data-structures/priority-queue.js.map +1 -1
- package/dist/src/data-structures/union-find.d.ts +21 -0
- package/dist/src/data-structures/union-find.d.ts.map +1 -1
- package/dist/src/data-structures/union-find.js +21 -0
- package/dist/src/data-structures/union-find.js.map +1 -1
- package/dist/src/flow/ford-fulkerson.d.ts +4 -2
- package/dist/src/flow/ford-fulkerson.d.ts.map +1 -1
- package/dist/src/flow/ford-fulkerson.js +31 -2
- package/dist/src/flow/ford-fulkerson.js.map +1 -1
- package/dist/src/flow/min-cut.d.ts +0 -3
- package/dist/src/flow/min-cut.d.ts.map +1 -1
- package/dist/src/flow/min-cut.js +17 -4
- package/dist/src/flow/min-cut.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/link-prediction/adamic-adar.d.ts +26 -0
- package/dist/src/link-prediction/adamic-adar.d.ts.map +1 -1
- package/dist/src/link-prediction/adamic-adar.js +36 -10
- package/dist/src/link-prediction/adamic-adar.js.map +1 -1
- package/dist/src/link-prediction/common-neighbors.d.ts +21 -0
- package/dist/src/link-prediction/common-neighbors.d.ts.map +1 -1
- package/dist/src/link-prediction/common-neighbors.js +27 -6
- package/dist/src/link-prediction/common-neighbors.js.map +1 -1
- package/dist/src/link-prediction/index.d.ts.map +1 -1
- package/dist/src/optimized/bit-packed.d.ts +103 -53
- package/dist/src/optimized/bit-packed.d.ts.map +1 -1
- package/dist/src/optimized/bit-packed.js +104 -54
- package/dist/src/optimized/bit-packed.js.map +1 -1
- package/dist/src/optimized/csr-graph.d.ts +87 -24
- package/dist/src/optimized/csr-graph.d.ts.map +1 -1
- package/dist/src/optimized/csr-graph.js +87 -24
- package/dist/src/optimized/csr-graph.js.map +1 -1
- package/dist/src/optimized/direction-optimized-bfs.d.ts +37 -16
- package/dist/src/optimized/direction-optimized-bfs.d.ts.map +1 -1
- package/dist/src/optimized/direction-optimized-bfs.js +39 -20
- package/dist/src/optimized/direction-optimized-bfs.js.map +1 -1
- package/dist/src/optimized/graph-adapter.d.ts +58 -9
- package/dist/src/optimized/graph-adapter.d.ts.map +1 -1
- package/dist/src/optimized/graph-adapter.js +58 -10
- package/dist/src/optimized/graph-adapter.js.map +1 -1
- package/dist/src/optimized/index.d.ts +1 -1
- package/dist/src/optimized/index.d.ts.map +1 -1
- package/dist/src/optimized/index.js +3 -1
- package/dist/src/optimized/index.js.map +1 -1
- package/dist/src/pathfinding/astar.d.ts +25 -9
- package/dist/src/pathfinding/astar.d.ts.map +1 -1
- package/dist/src/pathfinding/astar.js +25 -10
- package/dist/src/pathfinding/astar.js.map +1 -1
- package/dist/src/pathfinding/utils.d.ts +15 -6
- package/dist/src/pathfinding/utils.d.ts.map +1 -1
- package/dist/src/pathfinding/utils.js +19 -7
- package/dist/src/pathfinding/utils.js.map +1 -1
- package/dist/src/research/grsbm.d.ts +0 -1
- package/dist/src/research/grsbm.d.ts.map +1 -1
- package/dist/src/research/grsbm.js +23 -10
- package/dist/src/research/grsbm.js.map +1 -1
- package/dist/src/research/index.d.ts.map +1 -1
- package/dist/src/research/index.js.map +1 -1
- package/dist/src/research/sync.d.ts +0 -1
- package/dist/src/research/sync.d.ts.map +1 -1
- package/dist/src/research/sync.js +29 -8
- package/dist/src/research/sync.js.map +1 -1
- package/dist/src/research/terahac.d.ts +0 -1
- package/dist/src/research/terahac.d.ts.map +1 -1
- package/dist/src/research/terahac.js +32 -4
- package/dist/src/research/terahac.js.map +1 -1
- package/dist/src/utils/graph-converters.d.ts +31 -0
- package/dist/src/utils/graph-converters.d.ts.map +1 -1
- package/dist/src/utils/graph-converters.js +31 -0
- package/dist/src/utils/graph-converters.js.map +1 -1
- package/dist/src/utils/graph-utilities.d.ts.map +1 -1
- package/dist/src/utils/graph-utilities.js.map +1 -1
- package/dist/src/utils/math-utilities.d.ts +11 -0
- package/dist/src/utils/math-utilities.d.ts.map +1 -1
- package/dist/src/utils/math-utilities.js +14 -5
- package/dist/src/utils/math-utilities.js.map +1 -1
- package/dist/src/utils/optimization-helpers.d.ts +9 -0
- package/dist/src/utils/optimization-helpers.d.ts.map +1 -1
- package/dist/src/utils/optimization-helpers.js +12 -0
- package/dist/src/utils/optimization-helpers.js.map +1 -1
- package/dist/src/utils/priorityQueue.d.ts +24 -0
- package/dist/src/utils/priorityQueue.d.ts.map +1 -1
- package/dist/src/utils/priorityQueue.js +34 -4
- package/dist/src/utils/priorityQueue.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +56 -65
- package/src/algorithms/centrality/betweenness.ts +34 -17
- package/src/algorithms/centrality/closeness.ts +34 -17
- package/src/algorithms/centrality/degree.ts +15 -19
- package/src/algorithms/centrality/delta-pagerank-simple.ts +36 -28
- package/src/algorithms/centrality/delta-pagerank.ts +34 -11
- package/src/algorithms/centrality/eigenvector.ts +14 -15
- package/src/algorithms/centrality/hits.ts +17 -17
- package/src/algorithms/centrality/index.ts +20 -15
- package/src/algorithms/centrality/katz.ts +17 -25
- package/src/algorithms/centrality/pagerank.ts +26 -17
- package/src/algorithms/community/girvan-newman.ts +39 -28
- package/src/algorithms/community/index.ts +6 -7
- package/src/algorithms/community/label-propagation.ts +20 -28
- package/src/algorithms/community/leiden.ts +61 -37
- package/src/algorithms/community/louvain-optimized.ts +49 -20
- package/src/algorithms/community/louvain.ts +35 -25
- package/src/algorithms/community/modularity-utils.ts +5 -17
- package/src/algorithms/components/connected.ts +40 -17
- package/src/algorithms/matching/bipartite.ts +17 -10
- package/src/algorithms/matching/index.ts +4 -4
- package/src/algorithms/matching/isomorphism.ts +53 -23
- package/src/algorithms/mst/index.ts +3 -4
- package/src/algorithms/mst/kruskal.ts +21 -6
- package/src/algorithms/mst/prim.ts +13 -4
- package/src/algorithms/shortest-path/bellman-ford.ts +16 -15
- package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +29 -29
- package/src/algorithms/shortest-path/dijkstra.ts +23 -17
- package/src/algorithms/shortest-path/floyd-warshall.ts +21 -4
- package/src/algorithms/shortest-path/index.ts +5 -5
- package/src/algorithms/traversal/bfs-unified.ts +64 -60
- package/src/algorithms/traversal/bfs-variants.ts +61 -37
- package/src/algorithms/traversal/bfs.ts +1 -7
- package/src/algorithms/traversal/dfs.ts +61 -42
- package/src/algorithms/traversal/index.ts +3 -3
- package/src/benchmark-all-algorithms.ts +57 -25
- package/src/clustering/hierarchical.ts +40 -34
- package/src/clustering/index.ts +8 -8
- package/src/clustering/k-core.ts +26 -42
- package/src/clustering/mcl.ts +53 -23
- package/src/clustering/spectral.ts +91 -57
- package/src/core/graph.ts +54 -14
- package/src/data-structures/index.ts +2 -2
- package/src/data-structures/priority-queue.ts +36 -11
- package/src/data-structures/union-find.ts +22 -1
- package/src/flow/ford-fulkerson.ts +62 -35
- package/src/flow/min-cut.ts +43 -45
- package/src/index.ts +3 -2
- package/src/link-prediction/adamic-adar.ts +65 -51
- package/src/link-prediction/common-neighbors.ts +45 -36
- package/src/link-prediction/index.ts +1 -1
- package/src/optimized/bit-packed.ts +106 -56
- package/src/optimized/csr-graph.ts +93 -30
- package/src/optimized/direction-optimized-bfs.ts +44 -25
- package/src/optimized/graph-adapter.ts +64 -16
- package/src/optimized/index.ts +7 -9
- package/src/pathfinding/astar.ts +40 -25
- package/src/pathfinding/utils.ts +20 -13
- package/src/research/grsbm.ts +31 -25
- package/src/research/index.ts +4 -4
- package/src/research/sync.ts +40 -24
- package/src/research/terahac.ts +54 -20
- package/src/utils/graph-converters.ts +42 -14
- package/src/utils/graph-utilities.ts +11 -37
- package/src/utils/math-utilities.ts +17 -8
- package/src/utils/optimization-helpers.ts +27 -21
- package/src/utils/priorityQueue.ts +40 -6
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {Graph} from "../../core/graph.js";
|
|
2
|
-
import type {NodeId} from "../../types/index.js";
|
|
1
|
+
import type { Graph } from "../../core/graph.js";
|
|
2
|
+
import type { NodeId } from "../../types/index.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Graph Isomorphism (VF2) algorithm implementation
|
|
@@ -37,19 +37,19 @@ interface VF2State {
|
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* Check if two graphs are isomorphic using VF2 algorithm
|
|
40
|
+
* @param graph1 - The first graph to compare
|
|
41
|
+
* @param graph2 - The second graph to compare
|
|
42
|
+
* @param options - Optional configuration for node and edge matching predicates
|
|
43
|
+
* @returns An object indicating if the graphs are isomorphic and an optional mapping between nodes
|
|
40
44
|
*/
|
|
41
|
-
export function isGraphIsomorphic(
|
|
42
|
-
graph1: Graph,
|
|
43
|
-
graph2: Graph,
|
|
44
|
-
options: IsomorphismOptions = {},
|
|
45
|
-
): IsomorphismResult {
|
|
45
|
+
export function isGraphIsomorphic(graph1: Graph, graph2: Graph, options: IsomorphismOptions = {}): IsomorphismResult {
|
|
46
46
|
// Quick checks
|
|
47
47
|
if (graph1.nodeCount !== graph2.nodeCount || graph1.totalEdgeCount !== graph2.totalEdgeCount) {
|
|
48
|
-
return {isIsomorphic: false};
|
|
48
|
+
return { isIsomorphic: false };
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
if (graph1.isDirected !== graph2.isDirected) {
|
|
52
|
-
return {isIsomorphic: false};
|
|
52
|
+
return { isIsomorphic: false };
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
const nodes1 = Array.from(graph1.nodes()).map((n) => n.id);
|
|
@@ -61,7 +61,7 @@ export function isGraphIsomorphic(
|
|
|
61
61
|
|
|
62
62
|
for (let i = 0; i < degrees1.length; i++) {
|
|
63
63
|
if (degrees1[i] !== degrees2[i]) {
|
|
64
|
-
return {isIsomorphic: false};
|
|
64
|
+
return { isIsomorphic: false };
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -87,11 +87,19 @@ export function isGraphIsomorphic(
|
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
return {isIsomorphic: false};
|
|
90
|
+
return { isIsomorphic: false };
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
94
|
* VF2 recursive search
|
|
95
|
+
* @param g1 - The first graph being compared
|
|
96
|
+
* @param g2 - The second graph being compared
|
|
97
|
+
* @param state - The current VF2 algorithm state containing mappings and terminal sets
|
|
98
|
+
* @param nodes1 - Array of node IDs from the first graph
|
|
99
|
+
* @param nodes2 - Array of node IDs from the second graph
|
|
100
|
+
* @param options - Configuration options for matching predicates
|
|
101
|
+
* @param mappings - Array to collect found isomorphism mappings
|
|
102
|
+
* @returns True if an isomorphism was found and search should stop, false otherwise
|
|
95
103
|
*/
|
|
96
104
|
function vf2Recurse(
|
|
97
105
|
g1: Graph,
|
|
@@ -127,6 +135,12 @@ function vf2Recurse(
|
|
|
127
135
|
|
|
128
136
|
/**
|
|
129
137
|
* Get candidate pairs for the next mapping
|
|
138
|
+
* @param g1 - The first graph being compared
|
|
139
|
+
* @param g2 - The second graph being compared
|
|
140
|
+
* @param state - The current VF2 algorithm state containing mappings and terminal sets
|
|
141
|
+
* @param nodes1 - Array of node IDs from the first graph
|
|
142
|
+
* @param nodes2 - Array of node IDs from the second graph
|
|
143
|
+
* @returns Array of candidate node pairs to try matching
|
|
130
144
|
*/
|
|
131
145
|
function getCandidatePairs(
|
|
132
146
|
g1: Graph,
|
|
@@ -187,6 +201,13 @@ function getCandidatePairs(
|
|
|
187
201
|
|
|
188
202
|
/**
|
|
189
203
|
* Check if a pair is feasible
|
|
204
|
+
* @param g1 - The first graph being compared
|
|
205
|
+
* @param g2 - The second graph being compared
|
|
206
|
+
* @param state - The current VF2 algorithm state containing mappings and terminal sets
|
|
207
|
+
* @param node1 - The candidate node from the first graph
|
|
208
|
+
* @param node2 - The candidate node from the second graph
|
|
209
|
+
* @param options - Configuration options for matching predicates
|
|
210
|
+
* @returns True if the node pair can be feasibly matched, false otherwise
|
|
190
211
|
*/
|
|
191
212
|
function isFeasible(
|
|
192
213
|
g1: Graph,
|
|
@@ -222,8 +243,14 @@ function isFeasible(
|
|
|
222
243
|
}
|
|
223
244
|
|
|
224
245
|
// Check terminal set sizes
|
|
225
|
-
let new1In = 0;
|
|
226
|
-
let
|
|
246
|
+
let new1In = 0;
|
|
247
|
+
let new1Out = 0;
|
|
248
|
+
let term1In = 0;
|
|
249
|
+
let term1Out = 0;
|
|
250
|
+
let new2In = 0;
|
|
251
|
+
let new2Out = 0;
|
|
252
|
+
let term2In = 0;
|
|
253
|
+
let term2Out = 0;
|
|
227
254
|
|
|
228
255
|
for (const neighbor of neighbors1) {
|
|
229
256
|
if (state.core1.has(neighbor)) {
|
|
@@ -271,20 +298,19 @@ function isFeasible(
|
|
|
271
298
|
}
|
|
272
299
|
}
|
|
273
300
|
|
|
274
|
-
return term1In === term2In && term1Out === term2Out &&
|
|
275
|
-
new1In === new2In && new1Out === new2Out;
|
|
301
|
+
return term1In === term2In && term1Out === term2Out && new1In === new2In && new1Out === new2Out;
|
|
276
302
|
}
|
|
277
303
|
|
|
278
304
|
/**
|
|
279
305
|
* Add a pair to the mapping and update terminal sets
|
|
306
|
+
* @param g1 - The first graph being compared
|
|
307
|
+
* @param g2 - The second graph being compared
|
|
308
|
+
* @param state - The current VF2 algorithm state containing mappings and terminal sets
|
|
309
|
+
* @param node1 - The node from the first graph to add to the mapping
|
|
310
|
+
* @param node2 - The node from the second graph to add to the mapping
|
|
311
|
+
* @returns A new VF2 state with the pair added and terminal sets updated
|
|
280
312
|
*/
|
|
281
|
-
function addPair(
|
|
282
|
-
g1: Graph,
|
|
283
|
-
g2: Graph,
|
|
284
|
-
state: VF2State,
|
|
285
|
-
node1: NodeId,
|
|
286
|
-
node2: NodeId,
|
|
287
|
-
): VF2State {
|
|
313
|
+
function addPair(g1: Graph, g2: Graph, state: VF2State, node1: NodeId, node2: NodeId): VF2State {
|
|
288
314
|
const newState: VF2State = {
|
|
289
315
|
core1: new Map(state.core1),
|
|
290
316
|
core2: new Map(state.core2),
|
|
@@ -340,6 +366,10 @@ function addPair(
|
|
|
340
366
|
|
|
341
367
|
/**
|
|
342
368
|
* Find all isomorphisms between two graphs
|
|
369
|
+
* @param graph1 - The first graph to compare
|
|
370
|
+
* @param graph2 - The second graph to compare
|
|
371
|
+
* @param options - Optional configuration for node and edge matching predicates
|
|
372
|
+
* @returns An array of all possible node mappings between the graphs
|
|
343
373
|
*/
|
|
344
374
|
export function findAllIsomorphisms(
|
|
345
375
|
graph1: Graph,
|
|
@@ -386,7 +416,7 @@ export function findAllIsomorphisms(
|
|
|
386
416
|
|
|
387
417
|
// Find all isomorphisms
|
|
388
418
|
const mappings: Map<NodeId, NodeId>[] = [];
|
|
389
|
-
vf2Recurse(graph1, graph2, state, nodes1, nodes2, {...
|
|
419
|
+
vf2Recurse(graph1, graph2, state, nodes1, nodes2, { ...options, findAllMappings: true }, mappings);
|
|
390
420
|
|
|
391
421
|
return mappings;
|
|
392
422
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export type {MSTResult} from "./kruskal.js";
|
|
2
|
-
export {kruskalMST, minimumSpanningTree} from "./kruskal.js";
|
|
3
|
-
export {primMST} from "./prim.js";
|
|
4
|
-
|
|
1
|
+
export type { MSTResult } from "./kruskal.js";
|
|
2
|
+
export { kruskalMST, minimumSpanningTree } from "./kruskal.js";
|
|
3
|
+
export { primMST } from "./prim.js";
|
|
@@ -1,12 +1,20 @@
|
|
|
1
|
-
import {Graph} from "../../core/graph.js";
|
|
2
|
-
import {UnionFind} from "../../data-structures/union-find.js";
|
|
3
|
-
import type {Edge} from "../../types/index.js";
|
|
1
|
+
import { Graph } from "../../core/graph.js";
|
|
2
|
+
import { UnionFind } from "../../data-structures/union-find.js";
|
|
3
|
+
import type { Edge } from "../../types/index.js";
|
|
4
4
|
|
|
5
5
|
export interface MSTResult {
|
|
6
6
|
edges: Edge[];
|
|
7
7
|
totalWeight: number;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Computes the minimum spanning tree of an undirected graph using Kruskal's algorithm.
|
|
12
|
+
* The algorithm sorts edges by weight and greedily adds edges that don't create cycles,
|
|
13
|
+
* using a union-find data structure to efficiently detect cycles.
|
|
14
|
+
* @param graph - The undirected graph to compute the MST for
|
|
15
|
+
* @returns The minimum spanning tree as a set of edges and the total weight
|
|
16
|
+
* @throws Error if the graph is directed or not connected
|
|
17
|
+
*/
|
|
10
18
|
export function kruskalMST(graph: Graph): MSTResult {
|
|
11
19
|
if (graph.isDirected) {
|
|
12
20
|
throw new Error("Kruskal's algorithm requires an undirected graph");
|
|
@@ -16,9 +24,10 @@ export function kruskalMST(graph: Graph): MSTResult {
|
|
|
16
24
|
const visitedEdges = new Set<string>();
|
|
17
25
|
|
|
18
26
|
for (const edge of Array.from(graph.edges())) {
|
|
19
|
-
const edgeKey =
|
|
20
|
-
|
|
21
|
-
|
|
27
|
+
const edgeKey =
|
|
28
|
+
edge.source < edge.target
|
|
29
|
+
? `${String(edge.source)}-${String(edge.target)}`
|
|
30
|
+
: `${String(edge.target)}-${String(edge.source)}`;
|
|
22
31
|
|
|
23
32
|
if (!visitedEdges.has(edgeKey)) {
|
|
24
33
|
visitedEdges.add(edgeKey);
|
|
@@ -56,6 +65,12 @@ export function kruskalMST(graph: Graph): MSTResult {
|
|
|
56
65
|
};
|
|
57
66
|
}
|
|
58
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Alias for kruskalMST. Computes the minimum spanning tree of an undirected graph.
|
|
70
|
+
* @param graph - The undirected graph to compute the MST for
|
|
71
|
+
* @returns The minimum spanning tree as a set of edges and the total weight
|
|
72
|
+
* @throws Error if the graph is directed or not connected
|
|
73
|
+
*/
|
|
59
74
|
export function minimumSpanningTree(graph: Graph): MSTResult {
|
|
60
75
|
return kruskalMST(graph);
|
|
61
76
|
}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import {Graph} from "../../core/graph.js";
|
|
2
|
-
import {PriorityQueue} from "../../data-structures/priority-queue.js";
|
|
3
|
-
import type {Edge, NodeId} from "../../types/index.js";
|
|
4
|
-
import type {MSTResult} from "./kruskal.js";
|
|
1
|
+
import { Graph } from "../../core/graph.js";
|
|
2
|
+
import { PriorityQueue } from "../../data-structures/priority-queue.js";
|
|
3
|
+
import type { Edge, NodeId } from "../../types/index.js";
|
|
4
|
+
import type { MSTResult } from "./kruskal.js";
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Computes the minimum spanning tree of an undirected graph using Prim's algorithm.
|
|
8
|
+
* The algorithm grows the MST from a starting node by repeatedly adding the minimum
|
|
9
|
+
* weight edge that connects a node in the tree to a node outside the tree.
|
|
10
|
+
* @param graph - The undirected graph to compute the MST for
|
|
11
|
+
* @param startNode - Optional starting node; if not provided, uses the first node in the graph
|
|
12
|
+
* @returns The minimum spanning tree as a set of edges and the total weight
|
|
13
|
+
* @throws Error if the graph is directed, the start node is not found, or the graph is not connected
|
|
14
|
+
*/
|
|
6
15
|
export function primMST(graph: Graph, startNode?: NodeId): MSTResult {
|
|
7
16
|
if (graph.isDirected) {
|
|
8
17
|
throw new Error("Prim's algorithm requires an undirected graph");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {Graph} from "../../core/graph.js";
|
|
2
|
-
import type {NodeId, ShortestPathResult} from "../../types/index.js";
|
|
3
|
-
import {reconstructPath} from "../../utils/graph-utilities.js";
|
|
1
|
+
import type { Graph } from "../../core/graph.js";
|
|
2
|
+
import type { NodeId, ShortestPathResult } from "../../types/index.js";
|
|
3
|
+
import { reconstructPath } from "../../utils/graph-utilities.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Bellman-Ford algorithm implementation for single-source shortest paths
|
|
@@ -44,12 +44,12 @@ export interface BellmanFordResult {
|
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Find shortest paths from source using Bellman-Ford algorithm
|
|
47
|
+
* @param graph - The graph to search
|
|
48
|
+
* @param source - The starting node for the search
|
|
49
|
+
* @param options - Algorithm options including optional target for early termination
|
|
50
|
+
* @returns The distances, predecessors, and negative cycle information
|
|
47
51
|
*/
|
|
48
|
-
export function bellmanFord(
|
|
49
|
-
graph: Graph,
|
|
50
|
-
source: NodeId,
|
|
51
|
-
options: BellmanFordOptions = {},
|
|
52
|
-
): BellmanFordResult {
|
|
52
|
+
export function bellmanFord(graph: Graph, source: NodeId, options: BellmanFordOptions = {}): BellmanFordResult {
|
|
53
53
|
if (!graph.hasNode(source)) {
|
|
54
54
|
throw new Error(`Source node ${String(source)} not found in graph`);
|
|
55
55
|
}
|
|
@@ -130,12 +130,12 @@ export function bellmanFord(
|
|
|
130
130
|
|
|
131
131
|
/**
|
|
132
132
|
* Find shortest path between two specific nodes using Bellman-Ford
|
|
133
|
+
* @param graph - The graph to search
|
|
134
|
+
* @param source - The starting node for the path
|
|
135
|
+
* @param target - The destination node for the path
|
|
136
|
+
* @returns The shortest path result or null if no path exists
|
|
133
137
|
*/
|
|
134
|
-
export function bellmanFordPath(
|
|
135
|
-
graph: Graph,
|
|
136
|
-
source: NodeId,
|
|
137
|
-
target: NodeId,
|
|
138
|
-
): ShortestPathResult | null {
|
|
138
|
+
export function bellmanFordPath(graph: Graph, source: NodeId, target: NodeId): ShortestPathResult | null {
|
|
139
139
|
if (!graph.hasNode(source)) {
|
|
140
140
|
throw new Error(`Source node ${String(source)} not found in graph`);
|
|
141
141
|
}
|
|
@@ -144,7 +144,7 @@ export function bellmanFordPath(
|
|
|
144
144
|
throw new Error(`Target node ${String(target)} not found in graph`);
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
const result = bellmanFord(graph, source, {target});
|
|
147
|
+
const result = bellmanFord(graph, source, { target });
|
|
148
148
|
|
|
149
149
|
if (result.hasNegativeCycle) {
|
|
150
150
|
throw new Error("Graph contains a negative cycle");
|
|
@@ -168,6 +168,8 @@ export function bellmanFordPath(
|
|
|
168
168
|
|
|
169
169
|
/**
|
|
170
170
|
* Check if graph has negative cycles using Bellman-Ford
|
|
171
|
+
* @param graph - The graph to check for negative cycles
|
|
172
|
+
* @returns True if the graph contains a negative cycle
|
|
171
173
|
*/
|
|
172
174
|
export function hasNegativeCycle(graph: Graph): boolean {
|
|
173
175
|
const nodes = Array.from(graph.nodes());
|
|
@@ -198,4 +200,3 @@ export function hasNegativeCycle(graph: Graph): boolean {
|
|
|
198
200
|
|
|
199
201
|
return false;
|
|
200
202
|
}
|
|
201
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {Graph} from "../../core/graph.js";
|
|
2
|
-
import {PriorityQueue} from "../../data-structures/priority-queue.js";
|
|
3
|
-
import type {NodeId, ShortestPathResult} from "../../types/index.js";
|
|
1
|
+
import type { Graph } from "../../core/graph.js";
|
|
2
|
+
import { PriorityQueue } from "../../data-structures/priority-queue.js";
|
|
3
|
+
import type { NodeId, ShortestPathResult } from "../../types/index.js";
|
|
4
4
|
|
|
5
5
|
interface SearchState {
|
|
6
6
|
distances: Map<NodeId, number>;
|
|
@@ -30,6 +30,10 @@ export class BidirectionalDijkstra {
|
|
|
30
30
|
private meetingNode: NodeId | null = null;
|
|
31
31
|
private shortestDistance = Infinity;
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Creates a new BidirectionalDijkstra instance
|
|
35
|
+
* @param graph - The graph to search for shortest paths
|
|
36
|
+
*/
|
|
33
37
|
constructor(graph: Graph) {
|
|
34
38
|
this.graph = graph;
|
|
35
39
|
this.forwardSearch = this.initSearchState();
|
|
@@ -46,10 +50,13 @@ export class BidirectionalDijkstra {
|
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
/**
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
* Find shortest path between source and target nodes
|
|
54
|
+
* @param source - The starting node for the path
|
|
55
|
+
* @param target - The destination node for the path
|
|
56
|
+
* @returns The shortest path result or null if no path exists
|
|
57
|
+
*/
|
|
51
58
|
public findShortestPath(source: NodeId, target: NodeId): ShortestPathResult | null {
|
|
52
|
-
|
|
59
|
+
// Reset state for new search
|
|
53
60
|
this.reset();
|
|
54
61
|
if (!this.graph.hasNode(source)) {
|
|
55
62
|
throw new Error(`Source node ${String(source)} not found in graph`);
|
|
@@ -79,15 +86,16 @@ export class BidirectionalDijkstra {
|
|
|
79
86
|
this.backwardSearch.frontier.enqueue(target, 0);
|
|
80
87
|
|
|
81
88
|
// Main search loop
|
|
82
|
-
while (!this.forwardSearch.frontier.isEmpty() ||
|
|
83
|
-
!this.backwardSearch.frontier.isEmpty()) {
|
|
89
|
+
while (!this.forwardSearch.frontier.isEmpty() || !this.backwardSearch.frontier.isEmpty()) {
|
|
84
90
|
// Alternate between forward and backward search
|
|
85
91
|
// Choose the search with smaller frontier for better performance
|
|
86
92
|
let searchExpanded = false;
|
|
87
93
|
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
|
|
94
|
+
if (
|
|
95
|
+
!this.forwardSearch.frontier.isEmpty() &&
|
|
96
|
+
(this.backwardSearch.frontier.isEmpty() ||
|
|
97
|
+
this.forwardSearch.frontier.size() <= this.backwardSearch.frontier.size())
|
|
98
|
+
) {
|
|
91
99
|
if (this.expandSearch(this.forwardSearch, this.backwardSearch, true)) {
|
|
92
100
|
break;
|
|
93
101
|
}
|
|
@@ -102,8 +110,7 @@ export class BidirectionalDijkstra {
|
|
|
102
110
|
}
|
|
103
111
|
|
|
104
112
|
// Continue until both frontiers are empty or we've found an optimal path
|
|
105
|
-
if (this.forwardSearch.frontier.isEmpty() &&
|
|
106
|
-
this.backwardSearch.frontier.isEmpty()) {
|
|
113
|
+
if (this.forwardSearch.frontier.isEmpty() && this.backwardSearch.frontier.isEmpty()) {
|
|
107
114
|
break;
|
|
108
115
|
}
|
|
109
116
|
}
|
|
@@ -119,11 +126,7 @@ export class BidirectionalDijkstra {
|
|
|
119
126
|
};
|
|
120
127
|
}
|
|
121
128
|
|
|
122
|
-
private expandSearch(
|
|
123
|
-
search: SearchState,
|
|
124
|
-
oppositeSearch: SearchState,
|
|
125
|
-
isForward: boolean,
|
|
126
|
-
): boolean {
|
|
129
|
+
private expandSearch(search: SearchState, oppositeSearch: SearchState, isForward: boolean): boolean {
|
|
127
130
|
const current = search.frontier.dequeue();
|
|
128
131
|
if (current === undefined) {
|
|
129
132
|
return false;
|
|
@@ -150,18 +153,16 @@ export class BidirectionalDijkstra {
|
|
|
150
153
|
}
|
|
151
154
|
|
|
152
155
|
// Explore neighbors
|
|
153
|
-
const neighbors = isForward
|
|
154
|
-
Array.from(this.graph.neighbors(current))
|
|
155
|
-
Array.from(this.graph.inNeighbors(current));
|
|
156
|
+
const neighbors = isForward
|
|
157
|
+
? Array.from(this.graph.neighbors(current))
|
|
158
|
+
: Array.from(this.graph.inNeighbors(current));
|
|
156
159
|
|
|
157
160
|
for (const neighbor of neighbors) {
|
|
158
161
|
if (search.visited.has(neighbor)) {
|
|
159
162
|
continue;
|
|
160
163
|
}
|
|
161
164
|
|
|
162
|
-
const edge = isForward ?
|
|
163
|
-
this.graph.getEdge(current, neighbor) :
|
|
164
|
-
this.graph.getEdge(neighbor, current);
|
|
165
|
+
const edge = isForward ? this.graph.getEdge(current, neighbor) : this.graph.getEdge(neighbor, current);
|
|
165
166
|
|
|
166
167
|
if (!edge) {
|
|
167
168
|
continue;
|
|
@@ -175,8 +176,7 @@ export class BidirectionalDijkstra {
|
|
|
175
176
|
const newDistance = distance + edgeWeight;
|
|
176
177
|
const currentNeighborDistance = search.distances.get(neighbor);
|
|
177
178
|
|
|
178
|
-
if (!search.distances.has(neighbor) ||
|
|
179
|
-
newDistance < (currentNeighborDistance ?? Infinity)) {
|
|
179
|
+
if (!search.distances.has(neighbor) || newDistance < (currentNeighborDistance ?? Infinity)) {
|
|
180
180
|
search.distances.set(neighbor, newDistance);
|
|
181
181
|
search.previous.set(neighbor, current);
|
|
182
182
|
search.frontier.enqueue(neighbor, newDistance);
|
|
@@ -186,7 +186,7 @@ export class BidirectionalDijkstra {
|
|
|
186
186
|
return false;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
private
|
|
189
|
+
private _getMinDistance(frontier: PriorityQueue<NodeId>): number {
|
|
190
190
|
if (frontier.isEmpty()) {
|
|
191
191
|
return Infinity;
|
|
192
192
|
}
|
|
@@ -237,8 +237,8 @@ export class BidirectionalDijkstra {
|
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
/**
|
|
240
|
-
|
|
241
|
-
|
|
240
|
+
* Reset the search state for reuse
|
|
241
|
+
*/
|
|
242
242
|
public reset(): void {
|
|
243
243
|
this.forwardSearch = this.initSearchState();
|
|
244
244
|
this.backwardSearch = this.initSearchState();
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type {Graph} from "../../core/graph.js";
|
|
2
|
-
import {PriorityQueue} from "../../data-structures/priority-queue.js";
|
|
3
|
-
import type {DijkstraOptions, NodeId, ShortestPathResult} from "../../types/index.js";
|
|
4
|
-
import {reconstructPath} from "../../utils/graph-utilities.js";
|
|
5
|
-
import {BidirectionalDijkstra} from "./bidirectional-dijkstra.js";
|
|
1
|
+
import type { Graph } from "../../core/graph.js";
|
|
2
|
+
import { PriorityQueue } from "../../data-structures/priority-queue.js";
|
|
3
|
+
import type { DijkstraOptions, NodeId, ShortestPathResult } from "../../types/index.js";
|
|
4
|
+
import { reconstructPath } from "../../utils/graph-utilities.js";
|
|
5
|
+
import { BidirectionalDijkstra } from "./bidirectional-dijkstra.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Dijkstra's algorithm implementation for single-source shortest paths
|
|
@@ -13,12 +13,12 @@ import {BidirectionalDijkstra} from "./bidirectional-dijkstra.js";
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Find shortest paths from source to all reachable nodes using Dijkstra's algorithm
|
|
16
|
+
* @param graph - The graph to search
|
|
17
|
+
* @param source - The starting node for the search
|
|
18
|
+
* @param options - Algorithm options including optional target for early termination
|
|
19
|
+
* @returns A map of node IDs to their shortest path results
|
|
16
20
|
*/
|
|
17
|
-
export function dijkstra(
|
|
18
|
-
graph: Graph,
|
|
19
|
-
source: NodeId,
|
|
20
|
-
options: DijkstraOptions = {},
|
|
21
|
-
): Map<NodeId, ShortestPathResult> {
|
|
21
|
+
export function dijkstra(graph: Graph, source: NodeId, options: DijkstraOptions = {}): Map<NodeId, ShortestPathResult> {
|
|
22
22
|
if (!graph.hasNode(source)) {
|
|
23
23
|
throw new Error(`Source node ${String(source)} not found in graph`);
|
|
24
24
|
}
|
|
@@ -119,6 +119,11 @@ export function dijkstra(
|
|
|
119
119
|
*
|
|
120
120
|
* Uses bidirectional search by default for improved performance on point-to-point queries.
|
|
121
121
|
* Automatically falls back to standard Dijkstra for very small graphs or when explicitly disabled.
|
|
122
|
+
* @param graph - The graph to search
|
|
123
|
+
* @param source - The starting node for the path
|
|
124
|
+
* @param target - The destination node for the path
|
|
125
|
+
* @param options - Algorithm options including bidirectional search toggle
|
|
126
|
+
* @returns The shortest path result or null if no path exists
|
|
122
127
|
*/
|
|
123
128
|
export function dijkstraPath(
|
|
124
129
|
graph: Graph,
|
|
@@ -153,18 +158,18 @@ export function dijkstraPath(
|
|
|
153
158
|
}
|
|
154
159
|
|
|
155
160
|
// Fallback to standard dijkstra
|
|
156
|
-
const results = dijkstra(graph, source, {target});
|
|
161
|
+
const results = dijkstra(graph, source, { target });
|
|
157
162
|
return results.get(target) ?? null;
|
|
158
163
|
}
|
|
159
164
|
|
|
160
165
|
/**
|
|
161
166
|
* Single-source shortest paths with early termination optimization
|
|
167
|
+
* @param graph - The graph to search
|
|
168
|
+
* @param source - The starting node for the search
|
|
169
|
+
* @param cutoff - Optional maximum distance to search
|
|
170
|
+
* @returns A map of node IDs to their distances from the source
|
|
162
171
|
*/
|
|
163
|
-
export function singleSourceShortestPath(
|
|
164
|
-
graph: Graph,
|
|
165
|
-
source: NodeId,
|
|
166
|
-
cutoff?: number,
|
|
167
|
-
): Map<NodeId, number> {
|
|
172
|
+
export function singleSourceShortestPath(graph: Graph, source: NodeId, cutoff?: number): Map<NodeId, number> {
|
|
168
173
|
if (!graph.hasNode(source)) {
|
|
169
174
|
throw new Error(`Source node ${String(source)} not found in graph`);
|
|
170
175
|
}
|
|
@@ -244,6 +249,8 @@ export function singleSourceShortestPath(
|
|
|
244
249
|
/**
|
|
245
250
|
* All-pairs shortest paths using repeated Dijkstra
|
|
246
251
|
* Note: For dense graphs, consider Floyd-Warshall algorithm instead
|
|
252
|
+
* @param graph - The graph to compute all-pairs shortest paths for
|
|
253
|
+
* @returns A nested map of source to target to distance
|
|
247
254
|
*/
|
|
248
255
|
export function allPairsShortestPath(graph: Graph): Map<NodeId, Map<NodeId, number>> {
|
|
249
256
|
const results = new Map<NodeId, Map<NodeId, number>>();
|
|
@@ -255,4 +262,3 @@ export function allPairsShortestPath(graph: Graph): Map<NodeId, Map<NodeId, numb
|
|
|
255
262
|
|
|
256
263
|
return results;
|
|
257
264
|
}
|
|
258
|
-
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {Graph} from "../../core/graph.js";
|
|
2
|
-
import type {NodeId} from "../../types/index.js";
|
|
1
|
+
import { Graph } from "../../core/graph.js";
|
|
2
|
+
import type { NodeId } from "../../types/index.js";
|
|
3
3
|
|
|
4
4
|
export interface FloydWarshallResult {
|
|
5
5
|
distances: Map<NodeId, Map<NodeId, number>>;
|
|
@@ -7,6 +7,11 @@ export interface FloydWarshallResult {
|
|
|
7
7
|
hasNegativeCycle: boolean;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Computes all-pairs shortest paths using the Floyd-Warshall algorithm
|
|
12
|
+
* @param graph - The graph to compute shortest paths for
|
|
13
|
+
* @returns The distances, predecessors, and negative cycle detection result
|
|
14
|
+
*/
|
|
10
15
|
export function floydWarshall(graph: Graph): FloydWarshallResult {
|
|
11
16
|
const nodes = Array.from(graph.nodes()).map((n) => n.id);
|
|
12
17
|
const distances = new Map<NodeId, Map<NodeId, number>>();
|
|
@@ -105,11 +110,18 @@ export function floydWarshall(graph: Graph): FloydWarshallResult {
|
|
|
105
110
|
};
|
|
106
111
|
}
|
|
107
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Finds the shortest path between two nodes using Floyd-Warshall
|
|
115
|
+
* @param graph - The graph to search
|
|
116
|
+
* @param source - The starting node for the path
|
|
117
|
+
* @param target - The destination node for the path
|
|
118
|
+
* @returns The path and distance or null if no path exists
|
|
119
|
+
*/
|
|
108
120
|
export function floydWarshallPath(
|
|
109
121
|
graph: Graph,
|
|
110
122
|
source: NodeId,
|
|
111
123
|
target: NodeId,
|
|
112
|
-
): {path: NodeId[]
|
|
124
|
+
): { path: NodeId[]; distance: number } | null {
|
|
113
125
|
const result = floydWarshall(graph);
|
|
114
126
|
|
|
115
127
|
if (!graph.hasNode(source) || !graph.hasNode(target)) {
|
|
@@ -146,12 +158,17 @@ export function floydWarshallPath(
|
|
|
146
158
|
|
|
147
159
|
if (current === source) {
|
|
148
160
|
path.unshift(source);
|
|
149
|
-
return {path, distance};
|
|
161
|
+
return { path, distance };
|
|
150
162
|
}
|
|
151
163
|
|
|
152
164
|
return null;
|
|
153
165
|
}
|
|
154
166
|
|
|
167
|
+
/**
|
|
168
|
+
* Computes the transitive closure of a graph using Floyd-Warshall
|
|
169
|
+
* @param graph - The graph to compute transitive closure for
|
|
170
|
+
* @returns A map of each node to the set of nodes reachable from it
|
|
171
|
+
*/
|
|
155
172
|
export function transitiveClosure(graph: Graph): Map<NodeId, Set<NodeId>> {
|
|
156
173
|
const result = floydWarshall(graph);
|
|
157
174
|
const closure = new Map<NodeId, Set<NodeId>>();
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Shortest path algorithms
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export type {BellmanFordOptions, BellmanFordResult} from "./bellman-ford.js";
|
|
6
|
-
export {bellmanFord, bellmanFordPath, hasNegativeCycle} from "./bellman-ford.js";
|
|
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";
|
|
5
|
+
export type { BellmanFordOptions, BellmanFordResult } from "./bellman-ford.js";
|
|
6
|
+
export { bellmanFord, bellmanFordPath, hasNegativeCycle } from "./bellman-ford.js";
|
|
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";
|