@graphty/algorithms 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1259 -61
- 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 +551 -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 +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- 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/research/grsbm.d.ts +83 -0
- package/dist/src/research/grsbm.d.ts.map +1 -0
- package/dist/src/research/grsbm.js +411 -0
- package/dist/src/research/grsbm.js.map +1 -0
- package/dist/src/research/index.d.ts +12 -0
- package/dist/src/research/index.d.ts.map +1 -0
- package/dist/src/research/index.js +14 -0
- package/dist/src/research/index.js.map +1 -0
- package/dist/src/research/sync.d.ts +49 -0
- package/dist/src/research/sync.d.ts.map +1 -0
- package/dist/src/research/sync.js +342 -0
- package/dist/src/research/sync.js.map +1 -0
- package/dist/src/research/terahac.d.ts +63 -0
- package/dist/src/research/terahac.d.ts.map +1 -0
- package/dist/src/research/terahac.js +375 -0
- package/dist/src/research/terahac.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 +13 -2
- 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 +672 -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 +5 -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/research/grsbm.ts +589 -0
- package/src/research/index.ts +17 -0
- package/src/research/sync.ts +469 -0
- package/src/research/terahac.ts +506 -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
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
/* eslint-disable dot-notation */
|
|
2
|
-
import { describe, expect, it } from "vitest";
|
|
3
|
-
import { betweennessCentrality, edgeBetweennessCentrality, nodeBetweennessCentrality } from "../../src/algorithms/centrality/betweenness.js";
|
|
4
|
-
import { Graph } from "../../src/core/graph.js";
|
|
5
|
-
describe("Betweenness Centrality", () => {
|
|
6
|
-
describe("betweennessCentrality", () => {
|
|
7
|
-
it("should calculate betweenness centrality for simple path graph", () => {
|
|
8
|
-
const graph = new Graph();
|
|
9
|
-
// Create a path: a - b - c - d
|
|
10
|
-
graph.addEdge("a", "b");
|
|
11
|
-
graph.addEdge("b", "c");
|
|
12
|
-
graph.addEdge("c", "d");
|
|
13
|
-
const centrality = betweennessCentrality(graph);
|
|
14
|
-
expect(centrality["a"]).toBe(0); // Endpoint
|
|
15
|
-
expect(centrality["b"]).toBe(2); // paths: a↔c, a↔d pass through b
|
|
16
|
-
expect(centrality["c"]).toBe(2); // paths: a↔d, b↔d pass through c
|
|
17
|
-
expect(centrality["d"]).toBe(0); // Endpoint
|
|
18
|
-
});
|
|
19
|
-
it("should calculate betweenness centrality for star graph", () => {
|
|
20
|
-
const graph = new Graph();
|
|
21
|
-
// Create a star: center connected to a, b, c
|
|
22
|
-
graph.addEdge("center", "a");
|
|
23
|
-
graph.addEdge("center", "b");
|
|
24
|
-
graph.addEdge("center", "c");
|
|
25
|
-
const centrality = betweennessCentrality(graph);
|
|
26
|
-
expect(centrality["center"]).toBe(3); // All paths between periphery nodes go through center
|
|
27
|
-
expect(centrality["a"]).toBe(0);
|
|
28
|
-
expect(centrality["b"]).toBe(0);
|
|
29
|
-
expect(centrality["c"]).toBe(0);
|
|
30
|
-
});
|
|
31
|
-
it("should calculate normalized betweenness centrality", () => {
|
|
32
|
-
const graph = new Graph();
|
|
33
|
-
// Create a path: a - b - c
|
|
34
|
-
graph.addEdge("a", "b");
|
|
35
|
-
graph.addEdge("b", "c");
|
|
36
|
-
const centrality = betweennessCentrality(graph, { normalized: true });
|
|
37
|
-
// For 3 nodes in undirected graph: normalization factor = (3-1)*(3-2)/2 = 1
|
|
38
|
-
expect(centrality["a"]).toBe(0);
|
|
39
|
-
expect(centrality["b"]).toBe(1); // 1 path / 1 = 1
|
|
40
|
-
expect(centrality["c"]).toBe(0);
|
|
41
|
-
});
|
|
42
|
-
it("should handle directed graphs", () => {
|
|
43
|
-
const graph = new Graph({ directed: true });
|
|
44
|
-
graph.addEdge("a", "b");
|
|
45
|
-
graph.addEdge("b", "c");
|
|
46
|
-
graph.addEdge("a", "c");
|
|
47
|
-
const centrality = betweennessCentrality(graph);
|
|
48
|
-
expect(centrality["a"]).toBe(0);
|
|
49
|
-
expect(centrality["b"]).toBe(0); // Direct path a->c exists
|
|
50
|
-
expect(centrality["c"]).toBe(0);
|
|
51
|
-
});
|
|
52
|
-
it("should handle single node graph", () => {
|
|
53
|
-
const graph = new Graph();
|
|
54
|
-
graph.addNode("only");
|
|
55
|
-
const centrality = betweennessCentrality(graph);
|
|
56
|
-
expect(centrality["only"]).toBe(0);
|
|
57
|
-
});
|
|
58
|
-
it("should handle empty graph", () => {
|
|
59
|
-
const graph = new Graph();
|
|
60
|
-
const centrality = betweennessCentrality(graph);
|
|
61
|
-
expect(Object.keys(centrality)).toHaveLength(0);
|
|
62
|
-
});
|
|
63
|
-
it("should handle disconnected components", () => {
|
|
64
|
-
const graph = new Graph();
|
|
65
|
-
// Two disconnected edges
|
|
66
|
-
graph.addEdge("a", "b");
|
|
67
|
-
graph.addEdge("c", "d");
|
|
68
|
-
const centrality = betweennessCentrality(graph);
|
|
69
|
-
expect(centrality["a"]).toBe(0);
|
|
70
|
-
expect(centrality["b"]).toBe(0);
|
|
71
|
-
expect(centrality["c"]).toBe(0);
|
|
72
|
-
expect(centrality["d"]).toBe(0);
|
|
73
|
-
});
|
|
74
|
-
it("should handle triangle graph", () => {
|
|
75
|
-
const graph = new Graph();
|
|
76
|
-
// Create a triangle
|
|
77
|
-
graph.addEdge("a", "b");
|
|
78
|
-
graph.addEdge("b", "c");
|
|
79
|
-
graph.addEdge("c", "a");
|
|
80
|
-
const centrality = betweennessCentrality(graph);
|
|
81
|
-
// In a triangle, all nodes have equal betweenness (all are equally central)
|
|
82
|
-
expect(centrality["a"]).toBe(0);
|
|
83
|
-
expect(centrality["b"]).toBe(0);
|
|
84
|
-
expect(centrality["c"]).toBe(0);
|
|
85
|
-
});
|
|
86
|
-
it("should handle bridge node correctly", () => {
|
|
87
|
-
const graph = new Graph();
|
|
88
|
-
// Create two triangles connected by a bridge
|
|
89
|
-
graph.addEdge("a", "b");
|
|
90
|
-
graph.addEdge("b", "c");
|
|
91
|
-
graph.addEdge("c", "a");
|
|
92
|
-
graph.addEdge("c", "d"); // Bridge
|
|
93
|
-
graph.addEdge("d", "e");
|
|
94
|
-
graph.addEdge("e", "f");
|
|
95
|
-
graph.addEdge("f", "d");
|
|
96
|
-
const centrality = betweennessCentrality(graph);
|
|
97
|
-
// c and d should have high betweenness as they bridge the two components
|
|
98
|
-
expect(centrality["c"]).toBeGreaterThan(centrality["a"] ?? 0);
|
|
99
|
-
expect(centrality["d"]).toBeGreaterThan(centrality["e"] ?? 0);
|
|
100
|
-
});
|
|
101
|
-
it("should convert node IDs to strings in result", () => {
|
|
102
|
-
const graph = new Graph();
|
|
103
|
-
graph.addEdge(1, 2);
|
|
104
|
-
graph.addEdge(2, 3);
|
|
105
|
-
const centrality = betweennessCentrality(graph);
|
|
106
|
-
expect(centrality["1"]).toBe(0);
|
|
107
|
-
expect(centrality["2"]).toBe(1);
|
|
108
|
-
expect(centrality["3"]).toBe(0);
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
describe("nodeBetweennessCentrality", () => {
|
|
112
|
-
it("should calculate centrality for specific node", () => {
|
|
113
|
-
const graph = new Graph();
|
|
114
|
-
graph.addEdge("a", "b");
|
|
115
|
-
graph.addEdge("b", "c");
|
|
116
|
-
graph.addEdge("c", "d");
|
|
117
|
-
const centralityB = nodeBetweennessCentrality(graph, "b");
|
|
118
|
-
const centralityA = nodeBetweennessCentrality(graph, "a");
|
|
119
|
-
expect(centralityB).toBe(2);
|
|
120
|
-
expect(centralityA).toBe(0);
|
|
121
|
-
});
|
|
122
|
-
it("should handle normalized centrality for specific node", () => {
|
|
123
|
-
const graph = new Graph();
|
|
124
|
-
graph.addEdge("a", "b");
|
|
125
|
-
graph.addEdge("b", "c");
|
|
126
|
-
const centrality = nodeBetweennessCentrality(graph, "b", { normalized: true });
|
|
127
|
-
expect(centrality).toBe(1);
|
|
128
|
-
});
|
|
129
|
-
it("should throw error for non-existent node", () => {
|
|
130
|
-
const graph = new Graph();
|
|
131
|
-
graph.addNode("a");
|
|
132
|
-
expect(() => nodeBetweennessCentrality(graph, "nonexistent")).toThrow("Node nonexistent not found");
|
|
133
|
-
});
|
|
134
|
-
it("should handle numeric node ID", () => {
|
|
135
|
-
const graph = new Graph();
|
|
136
|
-
graph.addEdge(1, 2);
|
|
137
|
-
graph.addEdge(2, 3);
|
|
138
|
-
const centrality = nodeBetweennessCentrality(graph, 2);
|
|
139
|
-
expect(centrality).toBe(1);
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
describe("edgeBetweennessCentrality", () => {
|
|
143
|
-
it("should calculate edge betweenness centrality", () => {
|
|
144
|
-
const graph = new Graph();
|
|
145
|
-
// Create a path: a - b - c
|
|
146
|
-
graph.addEdge("a", "b");
|
|
147
|
-
graph.addEdge("b", "c");
|
|
148
|
-
const centrality = edgeBetweennessCentrality(graph);
|
|
149
|
-
expect(centrality.get("a-b")).toBe(1);
|
|
150
|
-
expect(centrality.get("b-c")).toBe(1);
|
|
151
|
-
});
|
|
152
|
-
it("should calculate edge betweenness for star graph", () => {
|
|
153
|
-
const graph = new Graph();
|
|
154
|
-
// Create a star
|
|
155
|
-
graph.addEdge("center", "a");
|
|
156
|
-
graph.addEdge("center", "b");
|
|
157
|
-
graph.addEdge("center", "c");
|
|
158
|
-
const centrality = edgeBetweennessCentrality(graph);
|
|
159
|
-
// Each edge from center carries equal betweenness
|
|
160
|
-
expect(centrality.get("center-a")).toBe(1.5);
|
|
161
|
-
expect(centrality.get("center-b")).toBe(1.5);
|
|
162
|
-
expect(centrality.get("center-c")).toBe(1.5);
|
|
163
|
-
});
|
|
164
|
-
it("should handle normalized edge betweenness", () => {
|
|
165
|
-
const graph = new Graph();
|
|
166
|
-
graph.addEdge("a", "b");
|
|
167
|
-
graph.addEdge("b", "c");
|
|
168
|
-
const centrality = edgeBetweennessCentrality(graph, { normalized: true });
|
|
169
|
-
expect(centrality.get("a-b")).toBe(1);
|
|
170
|
-
expect(centrality.get("b-c")).toBe(1);
|
|
171
|
-
});
|
|
172
|
-
it("should handle directed graphs for edge betweenness", () => {
|
|
173
|
-
const graph = new Graph({ directed: true });
|
|
174
|
-
graph.addEdge("a", "b");
|
|
175
|
-
graph.addEdge("b", "c");
|
|
176
|
-
const centrality = edgeBetweennessCentrality(graph);
|
|
177
|
-
expect(centrality.get("a-b")).toBe(2);
|
|
178
|
-
expect(centrality.get("b-c")).toBe(2);
|
|
179
|
-
});
|
|
180
|
-
it("should handle bridge edges correctly", () => {
|
|
181
|
-
const graph = new Graph();
|
|
182
|
-
// Two components connected by a bridge
|
|
183
|
-
graph.addEdge("a", "b");
|
|
184
|
-
graph.addEdge("b", "bridge1");
|
|
185
|
-
graph.addEdge("bridge1", "bridge2");
|
|
186
|
-
graph.addEdge("bridge2", "c");
|
|
187
|
-
graph.addEdge("c", "d");
|
|
188
|
-
const centrality = edgeBetweennessCentrality(graph);
|
|
189
|
-
// Bridge edge should have highest betweenness
|
|
190
|
-
const bridgeEdgeCentrality = centrality.get("bridge1-bridge2");
|
|
191
|
-
const normalEdgeCentrality = centrality.get("a-b");
|
|
192
|
-
expect(bridgeEdgeCentrality).toBeGreaterThan(normalEdgeCentrality);
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
describe("edge cases", () => {
|
|
196
|
-
it("should handle self-loops", () => {
|
|
197
|
-
const graph = new Graph({ allowSelfLoops: true });
|
|
198
|
-
graph.addEdge("a", "a");
|
|
199
|
-
graph.addEdge("a", "b");
|
|
200
|
-
const centrality = betweennessCentrality(graph);
|
|
201
|
-
expect(centrality["a"]).toBe(0);
|
|
202
|
-
expect(centrality["b"]).toBe(0);
|
|
203
|
-
});
|
|
204
|
-
it("should handle complex network", () => {
|
|
205
|
-
const graph = new Graph();
|
|
206
|
-
// Create a more complex network
|
|
207
|
-
graph.addEdge("a", "b");
|
|
208
|
-
graph.addEdge("a", "c");
|
|
209
|
-
graph.addEdge("b", "d");
|
|
210
|
-
graph.addEdge("c", "d");
|
|
211
|
-
graph.addEdge("d", "e");
|
|
212
|
-
graph.addEdge("e", "f");
|
|
213
|
-
graph.addEdge("e", "g");
|
|
214
|
-
const centrality = betweennessCentrality(graph);
|
|
215
|
-
// Node e should have high betweenness as it connects to multiple end branches
|
|
216
|
-
expect(centrality["e"]).toBeGreaterThan(centrality["a"] ?? 0);
|
|
217
|
-
expect(centrality["e"]).toBeGreaterThan(centrality["f"] ?? 0);
|
|
218
|
-
});
|
|
219
|
-
it("should handle large star graph efficiently", () => {
|
|
220
|
-
const graph = new Graph();
|
|
221
|
-
const nodeCount = 100;
|
|
222
|
-
// Create a large star
|
|
223
|
-
for (let i = 1; i < nodeCount; i++) {
|
|
224
|
-
graph.addEdge("center", `node_${i}`);
|
|
225
|
-
}
|
|
226
|
-
const centrality = betweennessCentrality(graph);
|
|
227
|
-
expect(centrality["center"]).toBe((nodeCount - 1) * (nodeCount - 2) / 2);
|
|
228
|
-
expect(centrality["node_1"]).toBe(0);
|
|
229
|
-
});
|
|
230
|
-
it("should handle endpoints option correctly", () => {
|
|
231
|
-
const graph = new Graph();
|
|
232
|
-
graph.addEdge("a", "b");
|
|
233
|
-
graph.addEdge("b", "c");
|
|
234
|
-
const centralityWithEndpoints = betweennessCentrality(graph, { endpoints: true });
|
|
235
|
-
const centralityWithoutEndpoints = betweennessCentrality(graph, { endpoints: false });
|
|
236
|
-
// Without endpoints, values should be different (typically smaller)
|
|
237
|
-
expect(centralityWithEndpoints["b"]).toBeGreaterThanOrEqual(centralityWithoutEndpoints["b"] ?? 0);
|
|
238
|
-
});
|
|
239
|
-
it("should handle weighted graphs", () => {
|
|
240
|
-
const graph = new Graph();
|
|
241
|
-
graph.addEdge("a", "b", 1);
|
|
242
|
-
graph.addEdge("b", "c", 1);
|
|
243
|
-
graph.addEdge("c", "d", 1);
|
|
244
|
-
graph.addEdge("a", "d", 10);
|
|
245
|
-
const centrality = betweennessCentrality(graph);
|
|
246
|
-
// In this graph structure, b and c are on the shortest path
|
|
247
|
-
expect(centrality["b"]).toBeGreaterThan(0);
|
|
248
|
-
expect(centrality["c"]).toBeGreaterThan(0);
|
|
249
|
-
});
|
|
250
|
-
it("should handle null weights gracefully", () => {
|
|
251
|
-
const graph = new Graph();
|
|
252
|
-
graph.addEdge("a", "b");
|
|
253
|
-
graph.addEdge("b", "c");
|
|
254
|
-
const centrality = betweennessCentrality(graph);
|
|
255
|
-
// Basic betweenness should work
|
|
256
|
-
expect(centrality["b"]).toBeGreaterThan(0);
|
|
257
|
-
});
|
|
258
|
-
it("should handle zero shortest paths", () => {
|
|
259
|
-
const graph = new Graph({ directed: true });
|
|
260
|
-
// Create a directed graph where some nodes are unreachable
|
|
261
|
-
graph.addEdge("a", "b");
|
|
262
|
-
graph.addEdge("c", "d");
|
|
263
|
-
// No path from a,b to c,d
|
|
264
|
-
const centrality = betweennessCentrality(graph);
|
|
265
|
-
expect(centrality["a"]).toBe(0);
|
|
266
|
-
expect(centrality["b"]).toBe(0);
|
|
267
|
-
expect(centrality["c"]).toBe(0);
|
|
268
|
-
expect(centrality["d"]).toBe(0);
|
|
269
|
-
});
|
|
270
|
-
it("should handle weighted edge betweenness", () => {
|
|
271
|
-
const graph = new Graph();
|
|
272
|
-
graph.addEdge("a", "b", 1);
|
|
273
|
-
graph.addEdge("b", "c", 1);
|
|
274
|
-
graph.addEdge("a", "c", 3);
|
|
275
|
-
const edgeCentrality = edgeBetweennessCentrality(graph);
|
|
276
|
-
// Edge a-b and b-c should be used in shortest paths
|
|
277
|
-
expect(edgeCentrality.get("a-b")).toBeGreaterThan(0);
|
|
278
|
-
expect(edgeCentrality.get("b-c")).toBeGreaterThan(0);
|
|
279
|
-
});
|
|
280
|
-
it("should handle parallel edges correctly", () => {
|
|
281
|
-
const graph = new Graph({ allowParallelEdges: true });
|
|
282
|
-
graph.addEdge("a", "b");
|
|
283
|
-
graph.addEdge("a", "b"); // Parallel edge
|
|
284
|
-
graph.addEdge("b", "c");
|
|
285
|
-
const centrality = betweennessCentrality(graph);
|
|
286
|
-
// Should still calculate correctly despite parallel edges
|
|
287
|
-
expect(centrality["b"]).toBeGreaterThan(0);
|
|
288
|
-
});
|
|
289
|
-
it("should handle directed graph with cycles", () => {
|
|
290
|
-
const graph = new Graph({ directed: true });
|
|
291
|
-
graph.addEdge("a", "b");
|
|
292
|
-
graph.addEdge("b", "c");
|
|
293
|
-
graph.addEdge("c", "a"); // Creates cycle
|
|
294
|
-
graph.addEdge("c", "d");
|
|
295
|
-
const centrality = betweennessCentrality(graph);
|
|
296
|
-
// c should have high betweenness as it's on paths to d
|
|
297
|
-
expect(centrality["c"]).toBeGreaterThan(0);
|
|
298
|
-
});
|
|
299
|
-
it("should handle weighted centrality with endpoints", () => {
|
|
300
|
-
const graph = new Graph();
|
|
301
|
-
graph.addEdge("a", "b", 1);
|
|
302
|
-
graph.addEdge("b", "c", 2);
|
|
303
|
-
const centrality = betweennessCentrality(graph, {
|
|
304
|
-
endpoints: true,
|
|
305
|
-
normalized: true,
|
|
306
|
-
});
|
|
307
|
-
expect(centrality["b"]).toBeGreaterThan(0);
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
});
|
|
311
|
-
//# sourceMappingURL=betweenness-centrality.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"betweenness-centrality.test.js","sourceRoot":"","sources":["../../../test/unit/betweenness-centrality.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bfs.test.d.ts","sourceRoot":"","sources":["../../../test/unit/bfs.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { breadthFirstSearch, isBipartite, shortestPathBFS, singleSourceShortestPathBFS } from "../../src/algorithms/traversal/bfs.js";
|
|
3
|
-
import { Graph } from "../../src/core/graph.js";
|
|
4
|
-
describe("BFS Algorithms", () => {
|
|
5
|
-
describe("breadthFirstSearch", () => {
|
|
6
|
-
it("should traverse graph in breadth-first order", () => {
|
|
7
|
-
const graph = new Graph();
|
|
8
|
-
// Create a simple tree: a -> b, c; b -> d, e
|
|
9
|
-
graph.addEdge("a", "b");
|
|
10
|
-
graph.addEdge("a", "c");
|
|
11
|
-
graph.addEdge("b", "d");
|
|
12
|
-
graph.addEdge("b", "e");
|
|
13
|
-
const result = breadthFirstSearch(graph, "a");
|
|
14
|
-
expect(result.visited.size).toBe(5);
|
|
15
|
-
expect(result.order).toHaveLength(5);
|
|
16
|
-
expect(result.order[0]).toBe("a"); // Start node first
|
|
17
|
-
// Level 1 nodes (b, c) should come before level 2 nodes (d, e)
|
|
18
|
-
const bIndex = result.order.indexOf("b");
|
|
19
|
-
const cIndex = result.order.indexOf("c");
|
|
20
|
-
const dIndex = result.order.indexOf("d");
|
|
21
|
-
const eIndex = result.order.indexOf("e");
|
|
22
|
-
expect(Math.max(bIndex, cIndex)).toBeLessThan(Math.min(dIndex, eIndex));
|
|
23
|
-
});
|
|
24
|
-
it("should build correct spanning tree", () => {
|
|
25
|
-
const graph = new Graph();
|
|
26
|
-
graph.addEdge("a", "b");
|
|
27
|
-
graph.addEdge("a", "c");
|
|
28
|
-
graph.addEdge("b", "d");
|
|
29
|
-
const result = breadthFirstSearch(graph, "a");
|
|
30
|
-
expect(result.tree.get("a")).toBeNull();
|
|
31
|
-
expect(result.tree.get("b")).toBe("a");
|
|
32
|
-
expect(result.tree.get("c")).toBe("a");
|
|
33
|
-
expect(result.tree.get("d")).toBe("b");
|
|
34
|
-
});
|
|
35
|
-
it("should handle early termination with target node", () => {
|
|
36
|
-
const graph = new Graph();
|
|
37
|
-
graph.addEdge("a", "b");
|
|
38
|
-
graph.addEdge("a", "c");
|
|
39
|
-
graph.addEdge("b", "d");
|
|
40
|
-
graph.addEdge("c", "e");
|
|
41
|
-
const result = breadthFirstSearch(graph, "a", { targetNode: "b" });
|
|
42
|
-
expect(result.visited.has("b")).toBe(true);
|
|
43
|
-
expect(result.order).toContain("b");
|
|
44
|
-
// Should not visit nodes beyond target if target is found early
|
|
45
|
-
expect(result.order.length).toBeLessThanOrEqual(3);
|
|
46
|
-
});
|
|
47
|
-
it("should call visitor callback with correct parameters", () => {
|
|
48
|
-
const graph = new Graph();
|
|
49
|
-
const visits = [];
|
|
50
|
-
graph.addEdge("a", "b");
|
|
51
|
-
graph.addEdge("a", "c");
|
|
52
|
-
breadthFirstSearch(graph, "a", {
|
|
53
|
-
visitCallback: (node, level) => {
|
|
54
|
-
visits.push({ node: node.toString(), level });
|
|
55
|
-
},
|
|
56
|
-
});
|
|
57
|
-
expect(visits).toHaveLength(3);
|
|
58
|
-
expect(visits[0]).toEqual({ node: "a", level: 0 });
|
|
59
|
-
const level1Visits = visits.filter((v) => v.level === 1);
|
|
60
|
-
expect(level1Visits).toHaveLength(2);
|
|
61
|
-
});
|
|
62
|
-
it("should throw error for non-existent start node", () => {
|
|
63
|
-
const graph = new Graph();
|
|
64
|
-
graph.addNode("a");
|
|
65
|
-
expect(() => breadthFirstSearch(graph, "nonexistent")).toThrow("Start node nonexistent not found");
|
|
66
|
-
});
|
|
67
|
-
it("should handle disconnected components", () => {
|
|
68
|
-
const graph = new Graph();
|
|
69
|
-
// Two disconnected components
|
|
70
|
-
graph.addEdge("a", "b");
|
|
71
|
-
graph.addEdge("c", "d");
|
|
72
|
-
const result = breadthFirstSearch(graph, "a");
|
|
73
|
-
expect(result.visited.has("a")).toBe(true);
|
|
74
|
-
expect(result.visited.has("b")).toBe(true);
|
|
75
|
-
expect(result.visited.has("c")).toBe(false);
|
|
76
|
-
expect(result.visited.has("d")).toBe(false);
|
|
77
|
-
});
|
|
78
|
-
it("should handle single node graph", () => {
|
|
79
|
-
const graph = new Graph();
|
|
80
|
-
graph.addNode("only");
|
|
81
|
-
const result = breadthFirstSearch(graph, "only");
|
|
82
|
-
expect(result.visited.size).toBe(1);
|
|
83
|
-
expect(result.order).toEqual(["only"]);
|
|
84
|
-
expect(result.tree.get("only")).toBeNull();
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
describe("shortestPathBFS", () => {
|
|
88
|
-
it("should find shortest path in unweighted graph", () => {
|
|
89
|
-
const graph = new Graph();
|
|
90
|
-
// Create a diamond graph: a -> b,c -> d
|
|
91
|
-
graph.addEdge("a", "b");
|
|
92
|
-
graph.addEdge("a", "c");
|
|
93
|
-
graph.addEdge("b", "d");
|
|
94
|
-
graph.addEdge("c", "d");
|
|
95
|
-
const result = shortestPathBFS(graph, "a", "d");
|
|
96
|
-
expect(result).not.toBeNull();
|
|
97
|
-
expect(result.distance).toBe(2);
|
|
98
|
-
expect(result.path).toHaveLength(3);
|
|
99
|
-
expect(result.path[0]).toBe("a");
|
|
100
|
-
expect(result.path[2]).toBe("d");
|
|
101
|
-
// Middle node should be either b or c
|
|
102
|
-
expect(["b", "c"]).toContain(result.path[1]);
|
|
103
|
-
});
|
|
104
|
-
it("should return null for unreachable target", () => {
|
|
105
|
-
const graph = new Graph();
|
|
106
|
-
// Two disconnected nodes
|
|
107
|
-
graph.addNode("a");
|
|
108
|
-
graph.addNode("b");
|
|
109
|
-
const result = shortestPathBFS(graph, "a", "b");
|
|
110
|
-
expect(result).toBeNull();
|
|
111
|
-
});
|
|
112
|
-
it("should handle same source and target", () => {
|
|
113
|
-
const graph = new Graph();
|
|
114
|
-
graph.addNode("a");
|
|
115
|
-
const result = shortestPathBFS(graph, "a", "a");
|
|
116
|
-
expect(result).not.toBeNull();
|
|
117
|
-
expect(result.distance).toBe(0);
|
|
118
|
-
expect(result.path).toEqual(["a"]);
|
|
119
|
-
});
|
|
120
|
-
it("should throw error for non-existent nodes", () => {
|
|
121
|
-
const graph = new Graph();
|
|
122
|
-
graph.addNode("a");
|
|
123
|
-
expect(() => shortestPathBFS(graph, "nonexistent", "a")).toThrow("Source node nonexistent not found");
|
|
124
|
-
expect(() => shortestPathBFS(graph, "a", "nonexistent")).toThrow("Target node nonexistent not found");
|
|
125
|
-
});
|
|
126
|
-
it("should find shortest path in complex graph", () => {
|
|
127
|
-
const graph = new Graph();
|
|
128
|
-
// Create a more complex graph
|
|
129
|
-
graph.addEdge("start", "a");
|
|
130
|
-
graph.addEdge("start", "b");
|
|
131
|
-
graph.addEdge("a", "c");
|
|
132
|
-
graph.addEdge("b", "c");
|
|
133
|
-
graph.addEdge("c", "end");
|
|
134
|
-
graph.addEdge("a", "end"); // Longer path
|
|
135
|
-
const result = shortestPathBFS(graph, "start", "end");
|
|
136
|
-
expect(result).not.toBeNull();
|
|
137
|
-
expect(result.distance).toBe(2); // start -> a -> end
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
describe("singleSourceShortestPathBFS", () => {
|
|
141
|
-
it("should find shortest paths to all reachable nodes", () => {
|
|
142
|
-
const graph = new Graph();
|
|
143
|
-
graph.addEdge("a", "b");
|
|
144
|
-
graph.addEdge("a", "c");
|
|
145
|
-
graph.addEdge("b", "d");
|
|
146
|
-
graph.addEdge("c", "d");
|
|
147
|
-
const results = singleSourceShortestPathBFS(graph, "a");
|
|
148
|
-
expect(results.size).toBe(4);
|
|
149
|
-
expect(results.get("a").distance).toBe(0);
|
|
150
|
-
expect(results.get("b").distance).toBe(1);
|
|
151
|
-
expect(results.get("c").distance).toBe(1);
|
|
152
|
-
expect(results.get("d").distance).toBe(2);
|
|
153
|
-
});
|
|
154
|
-
it("should only include reachable nodes", () => {
|
|
155
|
-
const graph = new Graph();
|
|
156
|
-
// Two disconnected components
|
|
157
|
-
graph.addEdge("a", "b");
|
|
158
|
-
graph.addEdge("c", "d");
|
|
159
|
-
const results = singleSourceShortestPathBFS(graph, "a");
|
|
160
|
-
expect(results.size).toBe(2);
|
|
161
|
-
expect(results.has("a")).toBe(true);
|
|
162
|
-
expect(results.has("b")).toBe(true);
|
|
163
|
-
expect(results.has("c")).toBe(false);
|
|
164
|
-
expect(results.has("d")).toBe(false);
|
|
165
|
-
});
|
|
166
|
-
it("should provide correct paths for all nodes", () => {
|
|
167
|
-
const graph = new Graph();
|
|
168
|
-
graph.addEdge("a", "b");
|
|
169
|
-
graph.addEdge("b", "c");
|
|
170
|
-
const results = singleSourceShortestPathBFS(graph, "a");
|
|
171
|
-
expect(results.get("a").path).toEqual(["a"]);
|
|
172
|
-
expect(results.get("b").path).toEqual(["a", "b"]);
|
|
173
|
-
expect(results.get("c").path).toEqual(["a", "b", "c"]);
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
describe("isBipartite", () => {
|
|
177
|
-
it("should return true for bipartite graph", () => {
|
|
178
|
-
const graph = new Graph();
|
|
179
|
-
// Create a simple bipartite graph
|
|
180
|
-
graph.addEdge("a1", "b1");
|
|
181
|
-
graph.addEdge("a1", "b2");
|
|
182
|
-
graph.addEdge("a2", "b1");
|
|
183
|
-
graph.addEdge("a2", "b2");
|
|
184
|
-
expect(isBipartite(graph)).toBe(true);
|
|
185
|
-
});
|
|
186
|
-
it("should return false for graph with odd cycle", () => {
|
|
187
|
-
const graph = new Graph();
|
|
188
|
-
// Create a triangle (odd cycle)
|
|
189
|
-
graph.addEdge("a", "b");
|
|
190
|
-
graph.addEdge("b", "c");
|
|
191
|
-
graph.addEdge("c", "a");
|
|
192
|
-
expect(isBipartite(graph)).toBe(false);
|
|
193
|
-
});
|
|
194
|
-
it("should return true for graph with even cycle", () => {
|
|
195
|
-
const graph = new Graph();
|
|
196
|
-
// Create a square (even cycle)
|
|
197
|
-
graph.addEdge("a", "b");
|
|
198
|
-
graph.addEdge("b", "c");
|
|
199
|
-
graph.addEdge("c", "d");
|
|
200
|
-
graph.addEdge("d", "a");
|
|
201
|
-
expect(isBipartite(graph)).toBe(true);
|
|
202
|
-
});
|
|
203
|
-
it("should handle disconnected components", () => {
|
|
204
|
-
const graph = new Graph();
|
|
205
|
-
// Two bipartite components
|
|
206
|
-
graph.addEdge("a1", "b1");
|
|
207
|
-
graph.addEdge("a1", "b2");
|
|
208
|
-
graph.addEdge("c1", "d1");
|
|
209
|
-
graph.addEdge("c1", "d2");
|
|
210
|
-
expect(isBipartite(graph)).toBe(true);
|
|
211
|
-
});
|
|
212
|
-
it("should handle single node", () => {
|
|
213
|
-
const graph = new Graph();
|
|
214
|
-
graph.addNode("only");
|
|
215
|
-
expect(isBipartite(graph)).toBe(true);
|
|
216
|
-
});
|
|
217
|
-
it("should handle empty graph", () => {
|
|
218
|
-
const graph = new Graph();
|
|
219
|
-
expect(isBipartite(graph)).toBe(true);
|
|
220
|
-
});
|
|
221
|
-
it("should throw error for directed graph", () => {
|
|
222
|
-
const graph = new Graph({ directed: true });
|
|
223
|
-
graph.addEdge("a", "b");
|
|
224
|
-
expect(() => isBipartite(graph)).toThrow("Bipartite test requires an undirected graph");
|
|
225
|
-
});
|
|
226
|
-
it("should detect non-bipartite in complex graph", () => {
|
|
227
|
-
const graph = new Graph();
|
|
228
|
-
// Create a graph with both bipartite and non-bipartite parts
|
|
229
|
-
graph.addEdge("a", "b"); // Bipartite part
|
|
230
|
-
graph.addEdge("c", "d"); // Another bipartite part
|
|
231
|
-
graph.addEdge("e", "f"); // Connect to triangle
|
|
232
|
-
graph.addEdge("f", "g");
|
|
233
|
-
graph.addEdge("g", "e"); // Triangle makes it non-bipartite
|
|
234
|
-
expect(isBipartite(graph)).toBe(false);
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
describe("edge cases", () => {
|
|
238
|
-
it("should handle self-loops correctly", () => {
|
|
239
|
-
const graph = new Graph({ allowSelfLoops: true });
|
|
240
|
-
graph.addEdge("a", "a");
|
|
241
|
-
const result = breadthFirstSearch(graph, "a");
|
|
242
|
-
expect(result.visited.has("a")).toBe(true);
|
|
243
|
-
expect(result.order).toEqual(["a"]);
|
|
244
|
-
});
|
|
245
|
-
it("should handle directed graphs", () => {
|
|
246
|
-
const graph = new Graph({ directed: true });
|
|
247
|
-
graph.addEdge("a", "b");
|
|
248
|
-
graph.addEdge("c", "a"); // a can't reach c in directed graph
|
|
249
|
-
const result = breadthFirstSearch(graph, "a");
|
|
250
|
-
expect(result.visited.has("a")).toBe(true);
|
|
251
|
-
expect(result.visited.has("b")).toBe(true);
|
|
252
|
-
expect(result.visited.has("c")).toBe(false);
|
|
253
|
-
});
|
|
254
|
-
it("should work with numeric node IDs", () => {
|
|
255
|
-
const graph = new Graph();
|
|
256
|
-
graph.addEdge(1, 2);
|
|
257
|
-
graph.addEdge(2, 3);
|
|
258
|
-
const result = shortestPathBFS(graph, 1, 3);
|
|
259
|
-
expect(result).not.toBeNull();
|
|
260
|
-
expect(result.distance).toBe(2);
|
|
261
|
-
expect(result.path).toEqual([1, 2, 3]);
|
|
262
|
-
});
|
|
263
|
-
it("should handle large graphs efficiently", () => {
|
|
264
|
-
const graph = new Graph();
|
|
265
|
-
const nodes = 1000;
|
|
266
|
-
// Create a path graph: 0 -> 1 -> 2 -> ... -> 999
|
|
267
|
-
for (let i = 0; i < nodes - 1; i++) {
|
|
268
|
-
graph.addEdge(i, i + 1);
|
|
269
|
-
}
|
|
270
|
-
const result = shortestPathBFS(graph, 0, nodes - 1);
|
|
271
|
-
expect(result).not.toBeNull();
|
|
272
|
-
expect(result.distance).toBe(nodes - 1);
|
|
273
|
-
expect(result.path).toHaveLength(nodes);
|
|
274
|
-
});
|
|
275
|
-
});
|
|
276
|
-
});
|
|
277
|
-
//# sourceMappingURL=bfs.test.js.map
|