@graphty/algorithms 1.2.0 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +375 -276
- package/dist/algorithms.d.ts +42 -2
- package/dist/algorithms.js +11402 -2
- package/dist/algorithms.js.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.d.ts +14 -0
- package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.js +144 -169
- package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
- package/dist/src/algorithms/centrality/closeness.d.ts +35 -1
- package/dist/src/algorithms/centrality/closeness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/closeness.js +70 -149
- 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 +12 -9
- package/dist/src/algorithms/centrality/degree.js.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts +57 -0
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js +304 -0
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js.map +1 -0
- package/dist/src/algorithms/centrality/delta-pagerank.d.ts +106 -0
- package/dist/src/algorithms/centrality/delta-pagerank.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/delta-pagerank.js +320 -0
- package/dist/src/algorithms/centrality/delta-pagerank.js.map +1 -0
- 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 +3 -1
- package/dist/src/algorithms/centrality/index.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/index.js +2 -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 +31 -0
- package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.js +61 -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 +67 -57
- package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
- package/dist/src/algorithms/community/index.d.ts +2 -0
- 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 +11 -4
- package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -1
- package/dist/src/algorithms/community/label-propagation.js +60 -38
- package/dist/src/algorithms/community/label-propagation.js.map +1 -1
- package/dist/src/algorithms/community/leiden.d.ts +3 -3
- package/dist/src/algorithms/community/leiden.d.ts.map +1 -1
- package/dist/src/algorithms/community/leiden.js +70 -44
- package/dist/src/algorithms/community/leiden.js.map +1 -1
- package/dist/src/algorithms/community/louvain-optimized.d.ts +149 -0
- package/dist/src/algorithms/community/louvain-optimized.d.ts.map +1 -0
- package/dist/src/algorithms/community/louvain-optimized.js +338 -0
- package/dist/src/algorithms/community/louvain-optimized.js.map +1 -0
- 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 +35 -81
- package/dist/src/algorithms/community/louvain.js.map +1 -1
- package/dist/src/algorithms/community/modularity-utils.d.ts +55 -0
- package/dist/src/algorithms/community/modularity-utils.d.ts.map +1 -0
- package/dist/src/algorithms/community/modularity-utils.js +108 -0
- package/dist/src/algorithms/community/modularity-utils.js.map +1 -0
- 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 +18 -40
- 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 +11 -12
- package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts +44 -0
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts.map +1 -0
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +195 -0
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js.map +1 -0
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts +20 -2
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.js +30 -14
- 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 +42 -0
- package/dist/src/algorithms/traversal/bfs-unified.d.ts.map +1 -0
- package/dist/src/algorithms/traversal/bfs-unified.js +370 -0
- package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -0
- package/dist/src/algorithms/traversal/bfs-variants.d.ts +77 -0
- package/dist/src/algorithms/traversal/bfs-variants.d.ts.map +1 -0
- package/dist/src/algorithms/traversal/bfs-variants.js +402 -0
- package/dist/src/algorithms/traversal/bfs-variants.js.map +1 -0
- package/dist/src/algorithms/traversal/bfs.d.ts +4 -18
- package/dist/src/algorithms/traversal/bfs.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs.js +5 -182
- 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 +25 -0
- package/dist/src/benchmark-all-algorithms.d.ts.map +1 -0
- package/dist/src/benchmark-all-algorithms.js +491 -0
- package/dist/src/benchmark-all-algorithms.js.map +1 -0
- package/dist/src/clustering/hierarchical.d.ts +23 -15
- package/dist/src/clustering/hierarchical.d.ts.map +1 -1
- package/dist/src/clustering/hierarchical.js +226 -224
- package/dist/src/clustering/hierarchical.js.map +1 -1
- package/dist/src/clustering/index.d.ts +4 -2
- package/dist/src/clustering/index.d.ts.map +1 -1
- package/dist/src/clustering/index.js +2 -2
- package/dist/src/clustering/index.js.map +1 -1
- package/dist/src/clustering/k-core.d.ts +17 -19
- package/dist/src/clustering/k-core.d.ts.map +1 -1
- package/dist/src/clustering/k-core.js +68 -30
- 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 +11 -0
- package/dist/src/clustering/spectral.d.ts.map +1 -1
- package/dist/src/clustering/spectral.js +99 -47
- 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 +49 -5
- 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 +20 -12
- package/dist/src/flow/ford-fulkerson.d.ts.map +1 -1
- package/dist/src/flow/ford-fulkerson.js +170 -217
- package/dist/src/flow/ford-fulkerson.js.map +1 -1
- package/dist/src/flow/min-cut.d.ts +6 -8
- package/dist/src/flow/min-cut.d.ts.map +1 -1
- package/dist/src/flow/min-cut.js +34 -12
- package/dist/src/flow/min-cut.js.map +1 -1
- package/dist/src/index.d.ts +3 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -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 +47 -30
- 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 +31 -14
- 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 +193 -0
- package/dist/src/optimized/bit-packed.d.ts.map +1 -0
- package/dist/src/optimized/bit-packed.js +342 -0
- package/dist/src/optimized/bit-packed.js.map +1 -0
- package/dist/src/optimized/csr-graph.d.ts +149 -0
- package/dist/src/optimized/csr-graph.d.ts.map +1 -0
- package/dist/src/optimized/csr-graph.js +404 -0
- package/dist/src/optimized/csr-graph.js.map +1 -0
- package/dist/src/optimized/direction-optimized-bfs.d.ts +95 -0
- package/dist/src/optimized/direction-optimized-bfs.d.ts.map +1 -0
- package/dist/src/optimized/direction-optimized-bfs.js +242 -0
- package/dist/src/optimized/direction-optimized-bfs.js.map +1 -0
- package/dist/src/optimized/graph-adapter.d.ts +111 -0
- package/dist/src/optimized/graph-adapter.d.ts.map +1 -0
- package/dist/src/optimized/graph-adapter.js +194 -0
- package/dist/src/optimized/graph-adapter.js.map +1 -0
- package/dist/src/optimized/index.d.ts +14 -0
- package/dist/src/optimized/index.d.ts.map +1 -0
- package/dist/src/optimized/index.js +30 -0
- package/dist/src/optimized/index.js.map +1 -0
- 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 +28 -23
- 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 +31 -36
- package/dist/src/research/sync.js.map +1 -1
- package/dist/src/research/terahac.d.ts +2 -1
- package/dist/src/research/terahac.d.ts.map +1 -1
- package/dist/src/research/terahac.js +39 -7
- package/dist/src/research/terahac.js.map +1 -1
- package/dist/src/types/index.d.ts +8 -0
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/utils/algorithm-utilities.d.ts +2 -0
- package/dist/src/utils/algorithm-utilities.d.ts.map +1 -0
- package/dist/src/utils/algorithm-utilities.js +2 -0
- package/dist/src/utils/algorithm-utilities.js.map +1 -0
- package/dist/src/utils/graph-converters.d.ts +110 -0
- package/dist/src/utils/graph-converters.d.ts.map +1 -0
- package/dist/src/utils/graph-converters.js +227 -0
- package/dist/src/utils/graph-converters.js.map +1 -0
- package/dist/src/utils/graph-utilities.d.ts +62 -0
- package/dist/src/utils/graph-utilities.d.ts.map +1 -0
- package/dist/src/utils/graph-utilities.js +148 -0
- package/dist/src/utils/graph-utilities.js.map +1 -0
- package/dist/src/utils/index.d.ts +5 -0
- package/dist/src/utils/index.d.ts.map +1 -0
- package/dist/src/utils/index.js +5 -0
- package/dist/src/utils/index.js.map +1 -0
- package/dist/src/utils/math-utilities.d.ts +63 -0
- package/dist/src/utils/math-utilities.d.ts.map +1 -0
- package/dist/src/utils/math-utilities.js +132 -0
- package/dist/src/utils/math-utilities.js.map +1 -0
- package/dist/src/utils/matrix-utilities.d.ts +2 -0
- package/dist/src/utils/matrix-utilities.d.ts.map +1 -0
- package/dist/src/utils/matrix-utilities.js +2 -0
- package/dist/src/utils/matrix-utilities.js.map +1 -0
- package/dist/src/utils/optimization-helpers.d.ts +42 -0
- package/dist/src/utils/optimization-helpers.d.ts.map +1 -0
- package/dist/src/utils/optimization-helpers.js +59 -0
- package/dist/src/utils/optimization-helpers.js.map +1 -0
- 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/package.json +58 -39
- package/src/algorithms/centrality/betweenness.ts +185 -200
- package/src/algorithms/centrality/closeness.ts +93 -194
- package/src/algorithms/centrality/degree.ts +18 -22
- package/src/algorithms/centrality/delta-pagerank-simple.ts +374 -0
- package/src/algorithms/centrality/delta-pagerank.ts +458 -0
- package/src/algorithms/centrality/eigenvector.ts +14 -15
- package/src/algorithms/centrality/hits.ts +17 -17
- package/src/algorithms/centrality/index.ts +20 -13
- package/src/algorithms/centrality/katz.ts +17 -25
- package/src/algorithms/centrality/pagerank.ts +91 -16
- package/src/algorithms/community/girvan-newman.ts +90 -86
- package/src/algorithms/community/index.ts +6 -5
- package/src/algorithms/community/label-propagation.ts +69 -48
- package/src/algorithms/community/leiden.ts +88 -65
- package/src/algorithms/community/louvain-optimized.ts +474 -0
- package/src/algorithms/community/louvain.ts +52 -122
- package/src/algorithms/community/modularity-utils.ts +134 -0
- package/src/algorithms/components/connected.ts +40 -17
- package/src/algorithms/matching/bipartite.ts +24 -53
- 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 -28
- package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +248 -0
- package/src/algorithms/shortest-path/dijkstra.ts +38 -30
- 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 +437 -0
- package/src/algorithms/traversal/bfs-variants.ts +520 -0
- package/src/algorithms/traversal/bfs.ts +5 -229
- package/src/algorithms/traversal/dfs.ts +61 -42
- package/src/algorithms/traversal/index.ts +3 -3
- package/src/benchmark-all-algorithms.ts +580 -0
- package/src/clustering/hierarchical.ts +268 -272
- package/src/clustering/index.ts +8 -6
- package/src/clustering/k-core.ts +93 -61
- package/src/clustering/mcl.ts +53 -23
- package/src/clustering/spectral.ts +130 -72
- package/src/core/graph.ts +58 -18
- 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 +221 -262
- package/src/flow/min-cut.ts +59 -51
- package/src/index.ts +9 -2
- package/src/link-prediction/adamic-adar.ts +75 -74
- package/src/link-prediction/common-neighbors.ts +49 -49
- package/src/link-prediction/index.ts +1 -1
- package/src/optimized/bit-packed.ts +390 -0
- package/src/optimized/csr-graph.ts +518 -0
- package/src/optimized/direction-optimized-bfs.ts +310 -0
- package/src/optimized/graph-adapter.ts +248 -0
- package/src/optimized/index.ts +34 -0
- package/src/pathfinding/astar.ts +40 -25
- package/src/pathfinding/utils.ts +20 -13
- package/src/research/grsbm.ts +36 -39
- package/src/research/index.ts +4 -4
- package/src/research/sync.ts +41 -54
- package/src/research/terahac.ts +63 -21
- package/src/types/index.ts +8 -0
- package/src/utils/algorithm-utilities.ts +2 -0
- package/src/utils/graph-converters.ts +269 -0
- package/src/utils/graph-utilities.ts +173 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/math-utilities.ts +149 -0
- package/src/utils/matrix-utilities.ts +2 -0
- package/src/utils/optimization-helpers.ts +87 -0
- package/src/utils/priorityQueue.ts +40 -6
|
@@ -1,236 +1,12 @@
|
|
|
1
|
-
import type {Graph} from "../../core/graph.js";
|
|
2
|
-
import type {NodeId, ShortestPathResult, TraversalOptions, TraversalResult} from "../../types/index.js";
|
|
3
|
-
|
|
4
1
|
/**
|
|
5
2
|
* Breadth-First Search (BFS) implementation
|
|
6
3
|
*
|
|
7
4
|
* Explores graph level by level from a starting node. Guarantees shortest path
|
|
8
5
|
* in unweighted graphs and can be used for various graph analysis tasks.
|
|
6
|
+
*
|
|
7
|
+
* Automatically uses optimized implementations for large graphs (>10k nodes)
|
|
8
|
+
* to provide the best performance without requiring manual configuration.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
*/
|
|
14
|
-
export function breadthFirstSearch(
|
|
15
|
-
graph: Graph,
|
|
16
|
-
startNode: NodeId,
|
|
17
|
-
options: TraversalOptions = {},
|
|
18
|
-
): TraversalResult {
|
|
19
|
-
if (!graph.hasNode(startNode)) {
|
|
20
|
-
throw new Error(`Start node ${String(startNode)} not found in graph`);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const visited = new Set<NodeId>();
|
|
24
|
-
const queue: {node: NodeId, level: number}[] = [];
|
|
25
|
-
const order: NodeId[] = [];
|
|
26
|
-
const tree = new Map<NodeId, NodeId | null>();
|
|
27
|
-
|
|
28
|
-
// Initialize with start node
|
|
29
|
-
queue.push({node: startNode, level: 0});
|
|
30
|
-
visited.add(startNode);
|
|
31
|
-
tree.set(startNode, null);
|
|
32
|
-
|
|
33
|
-
while (queue.length > 0) {
|
|
34
|
-
const current = queue.shift();
|
|
35
|
-
if (!current) {
|
|
36
|
-
break;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
order.push(current.node);
|
|
40
|
-
|
|
41
|
-
// Call visitor callback if provided
|
|
42
|
-
if (options.visitCallback) {
|
|
43
|
-
options.visitCallback(current.node, current.level);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Early termination if target found
|
|
47
|
-
if (options.targetNode && current.node === options.targetNode) {
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Explore neighbors
|
|
52
|
-
for (const neighbor of graph.neighbors(current.node)) {
|
|
53
|
-
if (!visited.has(neighbor)) {
|
|
54
|
-
visited.add(neighbor);
|
|
55
|
-
tree.set(neighbor, current.node);
|
|
56
|
-
queue.push({node: neighbor, level: current.level + 1});
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return {visited, order, tree};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Find shortest path between two nodes in an unweighted graph using BFS
|
|
66
|
-
*/
|
|
67
|
-
export function shortestPathBFS(
|
|
68
|
-
graph: Graph,
|
|
69
|
-
source: NodeId,
|
|
70
|
-
target: NodeId,
|
|
71
|
-
): ShortestPathResult | null {
|
|
72
|
-
if (!graph.hasNode(source)) {
|
|
73
|
-
throw new Error(`Source node ${String(source)} not found in graph`);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (!graph.hasNode(target)) {
|
|
77
|
-
throw new Error(`Target node ${String(target)} not found in graph`);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Special case: source equals target
|
|
81
|
-
if (source === target) {
|
|
82
|
-
return {
|
|
83
|
-
distance: 0,
|
|
84
|
-
path: [source],
|
|
85
|
-
predecessor: new Map([[source, null]]),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const visited = new Set<NodeId>();
|
|
90
|
-
const queue: {node: NodeId, distance: number}[] = [];
|
|
91
|
-
const predecessor = new Map<NodeId, NodeId | null>();
|
|
92
|
-
|
|
93
|
-
// Initialize BFS
|
|
94
|
-
queue.push({node: source, distance: 0});
|
|
95
|
-
visited.add(source);
|
|
96
|
-
predecessor.set(source, null);
|
|
97
|
-
|
|
98
|
-
while (queue.length > 0) {
|
|
99
|
-
const current = queue.shift();
|
|
100
|
-
if (!current) {
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Target found
|
|
105
|
-
if (current.node === target) {
|
|
106
|
-
const path = reconstructPath(target, predecessor);
|
|
107
|
-
return {
|
|
108
|
-
distance: current.distance,
|
|
109
|
-
path,
|
|
110
|
-
predecessor,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Explore neighbors
|
|
115
|
-
for (const neighbor of graph.neighbors(current.node)) {
|
|
116
|
-
if (!visited.has(neighbor)) {
|
|
117
|
-
visited.add(neighbor);
|
|
118
|
-
predecessor.set(neighbor, current.node);
|
|
119
|
-
queue.push({node: neighbor, distance: current.distance + 1});
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// No path found
|
|
125
|
-
return null;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Find shortest paths from source to all reachable nodes using BFS
|
|
130
|
-
*/
|
|
131
|
-
export function singleSourceShortestPathBFS(
|
|
132
|
-
graph: Graph,
|
|
133
|
-
source: NodeId,
|
|
134
|
-
): Map<NodeId, ShortestPathResult> {
|
|
135
|
-
if (!graph.hasNode(source)) {
|
|
136
|
-
throw new Error(`Source node ${String(source)} not found in graph`);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const results = new Map<NodeId, ShortestPathResult>();
|
|
140
|
-
const visited = new Set<NodeId>();
|
|
141
|
-
const queue: {node: NodeId, distance: number}[] = [];
|
|
142
|
-
const predecessor = new Map<NodeId, NodeId | null>();
|
|
143
|
-
|
|
144
|
-
// Initialize BFS
|
|
145
|
-
queue.push({node: source, distance: 0});
|
|
146
|
-
visited.add(source);
|
|
147
|
-
predecessor.set(source, null);
|
|
148
|
-
|
|
149
|
-
while (queue.length > 0) {
|
|
150
|
-
const current = queue.shift();
|
|
151
|
-
if (!current) {
|
|
152
|
-
break;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Store result for current node
|
|
156
|
-
const path = reconstructPath(current.node, predecessor);
|
|
157
|
-
results.set(current.node, {
|
|
158
|
-
distance: current.distance,
|
|
159
|
-
path,
|
|
160
|
-
predecessor: new Map(predecessor),
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
// Explore neighbors
|
|
164
|
-
for (const neighbor of graph.neighbors(current.node)) {
|
|
165
|
-
if (!visited.has(neighbor)) {
|
|
166
|
-
visited.add(neighbor);
|
|
167
|
-
predecessor.set(neighbor, current.node);
|
|
168
|
-
queue.push({node: neighbor, distance: current.distance + 1});
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return results;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Check if the graph is bipartite using BFS coloring
|
|
178
|
-
*/
|
|
179
|
-
export function isBipartite(graph: Graph): boolean {
|
|
180
|
-
if (graph.isDirected) {
|
|
181
|
-
throw new Error("Bipartite test requires an undirected graph");
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const color = new Map<NodeId, 0 | 1>();
|
|
185
|
-
const visited = new Set<NodeId>();
|
|
186
|
-
|
|
187
|
-
// Check each connected component
|
|
188
|
-
for (const node of Array.from(graph.nodes())) {
|
|
189
|
-
if (!visited.has(node.id)) {
|
|
190
|
-
const queue: NodeId[] = [node.id];
|
|
191
|
-
color.set(node.id, 0);
|
|
192
|
-
visited.add(node.id);
|
|
193
|
-
|
|
194
|
-
while (queue.length > 0) {
|
|
195
|
-
const current = queue.shift();
|
|
196
|
-
if (!current) {
|
|
197
|
-
break;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const currentColor = color.get(current);
|
|
201
|
-
if (currentColor === undefined) {
|
|
202
|
-
continue;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
for (const neighbor of Array.from(graph.neighbors(current))) {
|
|
206
|
-
if (!visited.has(neighbor)) {
|
|
207
|
-
// Color with opposite color
|
|
208
|
-
color.set(neighbor, currentColor === 0 ? 1 : 0);
|
|
209
|
-
visited.add(neighbor);
|
|
210
|
-
queue.push(neighbor);
|
|
211
|
-
} else if (color.get(neighbor) === currentColor) {
|
|
212
|
-
// Same color as current node - not bipartite
|
|
213
|
-
return false;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return true;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Reconstruct path from predecessor map
|
|
225
|
-
*/
|
|
226
|
-
function reconstructPath(target: NodeId, predecessor: Map<NodeId, NodeId | null>): NodeId[] {
|
|
227
|
-
const path: NodeId[] = [];
|
|
228
|
-
let current: NodeId | null = target;
|
|
229
|
-
|
|
230
|
-
while (current !== null) {
|
|
231
|
-
path.unshift(current);
|
|
232
|
-
current = predecessor.get(current) ?? null;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
return path;
|
|
236
|
-
}
|
|
11
|
+
// Re-export unified implementations that automatically optimize for large graphs
|
|
12
|
+
export { breadthFirstSearch, isBipartite, shortestPathBFS, singleSourceShortestPathBFS } from "./bfs-unified.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {Graph} from "../../core/graph.js";
|
|
2
|
-
import type {NodeId, TraversalOptions, TraversalResult} from "../../types/index.js";
|
|
1
|
+
import { Graph } from "../../core/graph.js";
|
|
2
|
+
import type { NodeId, TraversalOptions, TraversalResult } from "../../types/index.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Depth-First Search (DFS) implementation
|
|
@@ -18,12 +18,12 @@ export interface DFSOptions extends TraversalOptions {
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Perform depth-first search starting from a given node
|
|
21
|
+
* @param graph - The input graph to traverse
|
|
22
|
+
* @param startNode - The node to start the DFS from
|
|
23
|
+
* @param options - DFS options (recursive mode, pre/post order, etc.)
|
|
24
|
+
* @returns Traversal result with visited nodes, order, and tree structure
|
|
21
25
|
*/
|
|
22
|
-
export function depthFirstSearch(
|
|
23
|
-
graph: Graph,
|
|
24
|
-
startNode: NodeId,
|
|
25
|
-
options: DFSOptions = {},
|
|
26
|
-
): TraversalResult {
|
|
26
|
+
export function depthFirstSearch(graph: Graph, startNode: NodeId, options: DFSOptions = {}): TraversalResult {
|
|
27
27
|
if (!graph.hasNode(startNode)) {
|
|
28
28
|
throw new Error(`Start node ${String(startNode)} not found in graph`);
|
|
29
29
|
}
|
|
@@ -38,11 +38,17 @@ export function depthFirstSearch(
|
|
|
38
38
|
dfsIterative(graph, startNode, visited, order, tree, options);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
return {visited, order, tree};
|
|
41
|
+
return { visited, order, tree };
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Iterative DFS implementation (safer for browsers)
|
|
46
|
+
* @param graph - The input graph to traverse
|
|
47
|
+
* @param startNode - The node to start the DFS from
|
|
48
|
+
* @param visited - Set to track visited nodes
|
|
49
|
+
* @param order - Array to store traversal order
|
|
50
|
+
* @param tree - Map to store parent relationships
|
|
51
|
+
* @param options - DFS options (recursive mode, pre/post order, etc.)
|
|
46
52
|
*/
|
|
47
53
|
function dfsIterative(
|
|
48
54
|
graph: Graph,
|
|
@@ -58,8 +64,8 @@ function dfsIterative(
|
|
|
58
64
|
return;
|
|
59
65
|
}
|
|
60
66
|
|
|
61
|
-
const stack: {node: NodeId
|
|
62
|
-
stack.push({node: startNode, parent: null, depth: 0});
|
|
67
|
+
const stack: { node: NodeId; parent: NodeId | null; depth: number }[] = [];
|
|
68
|
+
stack.push({ node: startNode, parent: null, depth: 0 });
|
|
63
69
|
|
|
64
70
|
while (stack.length > 0) {
|
|
65
71
|
const current = stack.pop();
|
|
@@ -89,7 +95,7 @@ function dfsIterative(
|
|
|
89
95
|
for (let i = neighbors.length - 1; i >= 0; i--) {
|
|
90
96
|
const neighbor = neighbors[i];
|
|
91
97
|
if (neighbor !== undefined && !visited.has(neighbor)) {
|
|
92
|
-
stack.push({node: neighbor, parent: current.node, depth: current.depth + 1});
|
|
98
|
+
stack.push({ node: neighbor, parent: current.node, depth: current.depth + 1 });
|
|
93
99
|
}
|
|
94
100
|
}
|
|
95
101
|
}
|
|
@@ -98,6 +104,14 @@ function dfsIterative(
|
|
|
98
104
|
|
|
99
105
|
/**
|
|
100
106
|
* Recursive DFS implementation
|
|
107
|
+
* @param graph - The input graph to traverse
|
|
108
|
+
* @param node - Current node being visited
|
|
109
|
+
* @param visited - Set to track visited nodes
|
|
110
|
+
* @param order - Array to store traversal order
|
|
111
|
+
* @param tree - Map to store parent relationships
|
|
112
|
+
* @param options - DFS options (recursive mode, pre/post order, etc.)
|
|
113
|
+
* @param depth - Current depth in the traversal tree
|
|
114
|
+
* @param parent - Parent node of the current node
|
|
101
115
|
*/
|
|
102
116
|
function dfsRecursive(
|
|
103
117
|
graph: Graph,
|
|
@@ -145,6 +159,8 @@ function dfsRecursive(
|
|
|
145
159
|
|
|
146
160
|
/**
|
|
147
161
|
* Detect cycles in a graph using DFS
|
|
162
|
+
* @param graph - The input graph to check for cycles
|
|
163
|
+
* @returns True if the graph contains a cycle, false otherwise
|
|
148
164
|
*/
|
|
149
165
|
export function hasCycleDFS(graph: Graph): boolean {
|
|
150
166
|
const visited = new Set<NodeId>();
|
|
@@ -170,13 +186,13 @@ export function hasCycleDFS(graph: Graph): boolean {
|
|
|
170
186
|
|
|
171
187
|
/**
|
|
172
188
|
* Utility function for cycle detection in directed graphs
|
|
189
|
+
* @param graph - The directed graph to check
|
|
190
|
+
* @param node - Current node being visited
|
|
191
|
+
* @param visited - Set of all visited nodes
|
|
192
|
+
* @param recursionStack - Set of nodes in the current recursion path
|
|
193
|
+
* @returns True if a cycle is found, false otherwise
|
|
173
194
|
*/
|
|
174
|
-
function hasCycleUtilDirected(
|
|
175
|
-
graph: Graph,
|
|
176
|
-
node: NodeId,
|
|
177
|
-
visited: Set<NodeId>,
|
|
178
|
-
recursionStack: Set<NodeId>,
|
|
179
|
-
): boolean {
|
|
195
|
+
function hasCycleUtilDirected(graph: Graph, node: NodeId, visited: Set<NodeId>, recursionStack: Set<NodeId>): boolean {
|
|
180
196
|
visited.add(node);
|
|
181
197
|
recursionStack.add(node);
|
|
182
198
|
|
|
@@ -198,13 +214,13 @@ function hasCycleUtilDirected(
|
|
|
198
214
|
|
|
199
215
|
/**
|
|
200
216
|
* Utility function for cycle detection in undirected graphs
|
|
217
|
+
* @param graph - The undirected graph to check
|
|
218
|
+
* @param node - Current node being visited
|
|
219
|
+
* @param visited - Set of all visited nodes
|
|
220
|
+
* @param parent - Parent node of the current node
|
|
221
|
+
* @returns True if a cycle is found, false otherwise
|
|
201
222
|
*/
|
|
202
|
-
function hasCycleUtilUndirected(
|
|
203
|
-
graph: Graph,
|
|
204
|
-
node: NodeId,
|
|
205
|
-
visited: Set<NodeId>,
|
|
206
|
-
parent: NodeId | null,
|
|
207
|
-
): boolean {
|
|
223
|
+
function hasCycleUtilUndirected(graph: Graph, node: NodeId, visited: Set<NodeId>, parent: NodeId | null): boolean {
|
|
208
224
|
visited.add(node);
|
|
209
225
|
|
|
210
226
|
// Check all neighbors
|
|
@@ -224,6 +240,8 @@ function hasCycleUtilUndirected(
|
|
|
224
240
|
|
|
225
241
|
/**
|
|
226
242
|
* Topological sorting using DFS (for directed acyclic graphs)
|
|
243
|
+
* @param graph - The directed acyclic graph to sort
|
|
244
|
+
* @returns Array of node IDs in topological order, or null if graph has cycles
|
|
227
245
|
*/
|
|
228
246
|
export function topologicalSort(graph: Graph): NodeId[] | null {
|
|
229
247
|
if (!graph.isDirected) {
|
|
@@ -251,13 +269,12 @@ export function topologicalSort(graph: Graph): NodeId[] | null {
|
|
|
251
269
|
|
|
252
270
|
/**
|
|
253
271
|
* Utility function for topological sorting
|
|
272
|
+
* @param graph - The directed graph being sorted
|
|
273
|
+
* @param node - Current node being visited
|
|
274
|
+
* @param visited - Set of visited nodes
|
|
275
|
+
* @param stack - Stack to store nodes in reverse topological order
|
|
254
276
|
*/
|
|
255
|
-
function topologicalSortUtil(
|
|
256
|
-
graph: Graph,
|
|
257
|
-
node: NodeId,
|
|
258
|
-
visited: Set<NodeId>,
|
|
259
|
-
stack: NodeId[],
|
|
260
|
-
): void {
|
|
277
|
+
function topologicalSortUtil(graph: Graph, node: NodeId, visited: Set<NodeId>, stack: NodeId[]): void {
|
|
261
278
|
visited.add(node);
|
|
262
279
|
|
|
263
280
|
// Visit all neighbors first
|
|
@@ -273,6 +290,8 @@ function topologicalSortUtil(
|
|
|
273
290
|
|
|
274
291
|
/**
|
|
275
292
|
* Find strongly connected components using DFS (for directed graphs)
|
|
293
|
+
* @param graph - The directed graph to analyze
|
|
294
|
+
* @returns Array of strongly connected components (each is an array of node IDs)
|
|
276
295
|
*/
|
|
277
296
|
export function findStronglyConnectedComponents(graph: Graph): NodeId[][] {
|
|
278
297
|
if (!graph.isDirected) {
|
|
@@ -310,13 +329,12 @@ export function findStronglyConnectedComponents(graph: Graph): NodeId[][] {
|
|
|
310
329
|
|
|
311
330
|
/**
|
|
312
331
|
* DFS to record finish order
|
|
332
|
+
* @param graph - The graph being traversed
|
|
333
|
+
* @param node - Current node being visited
|
|
334
|
+
* @param visited - Set of visited nodes
|
|
335
|
+
* @param finishOrder - Array to store nodes in order of completion
|
|
313
336
|
*/
|
|
314
|
-
function dfsFinishOrder(
|
|
315
|
-
graph: Graph,
|
|
316
|
-
node: NodeId,
|
|
317
|
-
visited: Set<NodeId>,
|
|
318
|
-
finishOrder: NodeId[],
|
|
319
|
-
): void {
|
|
337
|
+
function dfsFinishOrder(graph: Graph, node: NodeId, visited: Set<NodeId>, finishOrder: NodeId[]): void {
|
|
320
338
|
visited.add(node);
|
|
321
339
|
|
|
322
340
|
for (const neighbor of Array.from(graph.neighbors(node))) {
|
|
@@ -330,13 +348,12 @@ function dfsFinishOrder(
|
|
|
330
348
|
|
|
331
349
|
/**
|
|
332
350
|
* DFS to collect nodes in a component
|
|
351
|
+
* @param graph - The graph being traversed
|
|
352
|
+
* @param node - Current node being visited
|
|
353
|
+
* @param visited - Set of visited nodes
|
|
354
|
+
* @param component - Array to collect nodes in the current component
|
|
333
355
|
*/
|
|
334
|
-
function dfsCollectComponent(
|
|
335
|
-
graph: Graph,
|
|
336
|
-
node: NodeId,
|
|
337
|
-
visited: Set<NodeId>,
|
|
338
|
-
component: NodeId[],
|
|
339
|
-
): void {
|
|
356
|
+
function dfsCollectComponent(graph: Graph, node: NodeId, visited: Set<NodeId>, component: NodeId[]): void {
|
|
340
357
|
visited.add(node);
|
|
341
358
|
component.push(node);
|
|
342
359
|
|
|
@@ -349,9 +366,11 @@ function dfsCollectComponent(
|
|
|
349
366
|
|
|
350
367
|
/**
|
|
351
368
|
* Create transpose (reverse) of a directed graph
|
|
369
|
+
* @param graph - The directed graph to transpose
|
|
370
|
+
* @returns A new graph with all edges reversed
|
|
352
371
|
*/
|
|
353
372
|
function createTransposeGraph(graph: Graph): Graph {
|
|
354
|
-
const transpose = new Graph({directed: true});
|
|
373
|
+
const transpose = new Graph({ directed: true });
|
|
355
374
|
|
|
356
375
|
// Add all nodes
|
|
357
376
|
for (const node of Array.from(graph.nodes())) {
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* Graph traversal algorithms
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export {breadthFirstSearch, isBipartite, shortestPathBFS, singleSourceShortestPathBFS} from "./bfs.js";
|
|
6
|
-
export type {DFSOptions} from "./dfs.js";
|
|
7
|
-
export {depthFirstSearch, findStronglyConnectedComponents, hasCycleDFS, topologicalSort} from "./dfs.js";
|
|
5
|
+
export { breadthFirstSearch, isBipartite, shortestPathBFS, singleSourceShortestPathBFS } from "./bfs.js";
|
|
6
|
+
export type { DFSOptions } from "./dfs.js";
|
|
7
|
+
export { depthFirstSearch, findStronglyConnectedComponents, hasCycleDFS, topologicalSort } from "./dfs.js";
|