@graphty/algorithms 1.3.1 → 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 +358 -413
- package/dist/algorithms.js +564 -261
- 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 +11 -4
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +18 -16
- 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 +22 -9
- 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 +28 -7
- 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/package.json +49 -45
- 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 +28 -28
- 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 +30 -24
- package/src/research/index.ts +4 -4
- package/src/research/sync.ts +39 -23
- 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
package/README.md
CHANGED
|
@@ -35,6 +35,7 @@ const result = breadthFirstSearch(largeGraph, startNode);
|
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
All BFS-based algorithms benefit from these optimizations:
|
|
38
|
+
|
|
38
39
|
- `breadthFirstSearch`, `shortestPathBFS`, `singleSourceShortestPathBFS`
|
|
39
40
|
- `betweennessCentrality`, `closenessCentrality`
|
|
40
41
|
- Connected component algorithms
|
|
@@ -42,12 +43,12 @@ All BFS-based algorithms benefit from these optimizations:
|
|
|
42
43
|
### Performance Benchmarks
|
|
43
44
|
|
|
44
45
|
| Graph Size | Standard BFS | Optimized BFS | Speedup |
|
|
45
|
-
|
|
46
|
-
| 10K nodes | 4.40ms
|
|
47
|
-
| 50K nodes | 158.64ms
|
|
48
|
-
| 100K nodes | 5,370ms
|
|
46
|
+
| ---------- | ------------ | ------------- | ------- |
|
|
47
|
+
| 10K nodes | 4.40ms | 6.34ms | 0.69x |
|
|
48
|
+
| 50K nodes | 158.64ms | 44.27ms | 3.58x |
|
|
49
|
+
| 100K nodes | 5,370ms | 126ms | 42.58x |
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
_Note: Optimizations activate automatically for graphs ≥10K nodes to avoid conversion overhead on smaller graphs._
|
|
51
52
|
|
|
52
53
|
### Learn More
|
|
53
54
|
|
|
@@ -64,31 +65,31 @@ npm install @graphty/algorithms
|
|
|
64
65
|
## Quick Start
|
|
65
66
|
|
|
66
67
|
```typescript
|
|
67
|
-
import { Graph, breadthFirstSearch, dijkstra } from
|
|
68
|
+
import { Graph, breadthFirstSearch, dijkstra } from "@graphty/algorithms";
|
|
68
69
|
|
|
69
70
|
// Create a new graph
|
|
70
|
-
const graph = new Graph()
|
|
71
|
+
const graph = new Graph();
|
|
71
72
|
|
|
72
73
|
// Add nodes and edges
|
|
73
|
-
graph.addNode(
|
|
74
|
-
graph.addNode(
|
|
75
|
-
graph.addNode(
|
|
76
|
-
graph.addEdge(
|
|
77
|
-
graph.addEdge(
|
|
74
|
+
graph.addNode("A");
|
|
75
|
+
graph.addNode("B");
|
|
76
|
+
graph.addNode("C");
|
|
77
|
+
graph.addEdge("A", "B", 1); // source, target, weight
|
|
78
|
+
graph.addEdge("B", "C", 2);
|
|
78
79
|
|
|
79
80
|
// Basic graph operations
|
|
80
|
-
console.log(graph.nodeCount) // 3
|
|
81
|
-
console.log(graph.totalEdgeCount) // 2
|
|
82
|
-
console.log(graph.hasEdge(
|
|
81
|
+
console.log(graph.nodeCount); // 3
|
|
82
|
+
console.log(graph.totalEdgeCount); // 2
|
|
83
|
+
console.log(graph.hasEdge("A", "B")); // true
|
|
83
84
|
|
|
84
85
|
// Run algorithms
|
|
85
|
-
const traversal = breadthFirstSearch(graph,
|
|
86
|
-
console.log(traversal.order) // ['A', 'B', 'C']
|
|
86
|
+
const traversal = breadthFirstSearch(graph, "A");
|
|
87
|
+
console.log(traversal.order); // ['A', 'B', 'C']
|
|
87
88
|
|
|
88
|
-
const shortestPaths = dijkstra(graph,
|
|
89
|
+
const shortestPaths = dijkstra(graph, "A");
|
|
89
90
|
// Get distance to C
|
|
90
|
-
const pathToC = shortestPaths.get(
|
|
91
|
-
console.log(pathToC?.distance) // 3
|
|
91
|
+
const pathToC = shortestPaths.get("C");
|
|
92
|
+
console.log(pathToC?.distance); // 3
|
|
92
93
|
```
|
|
93
94
|
|
|
94
95
|
## API Reference
|
|
@@ -99,7 +100,7 @@ The core data structure for representing graphs.
|
|
|
99
100
|
|
|
100
101
|
```typescript
|
|
101
102
|
class Graph {
|
|
102
|
-
|
|
103
|
+
constructor(config?: Partial<GraphConfig>);
|
|
103
104
|
}
|
|
104
105
|
```
|
|
105
106
|
|
|
@@ -107,9 +108,9 @@ class Graph {
|
|
|
107
108
|
|
|
108
109
|
```typescript
|
|
109
110
|
interface GraphConfig {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
directed: boolean; // Default: false
|
|
112
|
+
allowSelfLoops: boolean; // Default: false
|
|
113
|
+
allowParallelEdges: boolean; // Default: false
|
|
113
114
|
}
|
|
114
115
|
```
|
|
115
116
|
|
|
@@ -306,14 +307,10 @@ const allPairs = allPairsShortestPath(graph)
|
|
|
306
307
|
#### Bellman-Ford Algorithm
|
|
307
308
|
|
|
308
309
|
```typescript
|
|
309
|
-
import {
|
|
310
|
-
bellmanFord,
|
|
311
|
-
bellmanFordPath,
|
|
312
|
-
hasNegativeCycle
|
|
313
|
-
} from '@graphty/algorithms'
|
|
310
|
+
import { bellmanFord, bellmanFordPath, hasNegativeCycle } from "@graphty/algorithms";
|
|
314
311
|
|
|
315
312
|
// Single-source shortest paths (handles negative weights)
|
|
316
|
-
const result = bellmanFord(graph, source)
|
|
313
|
+
const result = bellmanFord(graph, source);
|
|
317
314
|
// Returns: BellmanFordResult {
|
|
318
315
|
// distances: Map<NodeId, number>,
|
|
319
316
|
// predecessors: Map<NodeId, NodeId | null>,
|
|
@@ -322,33 +319,29 @@ const result = bellmanFord(graph, source)
|
|
|
322
319
|
// }
|
|
323
320
|
|
|
324
321
|
// Get specific path
|
|
325
|
-
const path = bellmanFordPath(graph, source, target)
|
|
322
|
+
const path = bellmanFordPath(graph, source, target);
|
|
326
323
|
// Returns: ShortestPathResult | null
|
|
327
324
|
|
|
328
325
|
// Check for negative cycles
|
|
329
|
-
const result = hasNegativeCycle(graph)
|
|
326
|
+
const result = hasNegativeCycle(graph);
|
|
330
327
|
// Returns: BellmanFordResult with hasNegativeCycle boolean
|
|
331
328
|
```
|
|
332
329
|
|
|
333
330
|
#### Floyd-Warshall Algorithm
|
|
334
331
|
|
|
335
332
|
```typescript
|
|
336
|
-
import {
|
|
337
|
-
floydWarshall,
|
|
338
|
-
floydWarshallPath,
|
|
339
|
-
transitiveClosure
|
|
340
|
-
} from '@graphty/algorithms'
|
|
333
|
+
import { floydWarshall, floydWarshallPath, transitiveClosure } from "@graphty/algorithms";
|
|
341
334
|
|
|
342
335
|
// All pairs shortest paths
|
|
343
|
-
const result = floydWarshall(graph)
|
|
336
|
+
const result = floydWarshall(graph);
|
|
344
337
|
// Returns: { distances: Map<NodeId, Map<NodeId, number>>, next: Map<NodeId, Map<NodeId, NodeId | null>> }
|
|
345
338
|
|
|
346
339
|
// Get specific path between any pair
|
|
347
|
-
const path = floydWarshallPath(result, source, target)
|
|
340
|
+
const path = floydWarshallPath(result, source, target);
|
|
348
341
|
// Returns: NodeId[] | null
|
|
349
342
|
|
|
350
343
|
// Compute transitive closure
|
|
351
|
-
const closure = transitiveClosure(graph)
|
|
344
|
+
const closure = transitiveClosure(graph);
|
|
352
345
|
// Returns: Map<NodeId, Set<NodeId>>
|
|
353
346
|
```
|
|
354
347
|
|
|
@@ -357,169 +350,154 @@ const closure = transitiveClosure(graph)
|
|
|
357
350
|
#### Degree Centrality
|
|
358
351
|
|
|
359
352
|
```typescript
|
|
360
|
-
import { degreeCentrality, nodeDegreeCentrality } from
|
|
353
|
+
import { degreeCentrality, nodeDegreeCentrality } from "@graphty/algorithms";
|
|
361
354
|
|
|
362
355
|
// Calculate for all nodes
|
|
363
356
|
const centralities = degreeCentrality(graph, {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
})
|
|
357
|
+
normalized: boolean, // Default: false
|
|
358
|
+
weight: string, // Optional: edge property for weighted degree
|
|
359
|
+
});
|
|
367
360
|
// Returns: CentralityResult (Record<string, number>)
|
|
368
361
|
|
|
369
362
|
// Calculate for single node
|
|
370
|
-
const centrality = nodeDegreeCentrality(graph, nodeId, { normalized: boolean })
|
|
363
|
+
const centrality = nodeDegreeCentrality(graph, nodeId, { normalized: boolean });
|
|
371
364
|
// Returns: number
|
|
372
365
|
```
|
|
373
366
|
|
|
374
367
|
#### Betweenness Centrality
|
|
375
368
|
|
|
376
369
|
```typescript
|
|
377
|
-
import {
|
|
378
|
-
betweennessCentrality,
|
|
379
|
-
nodeBetweennessCentrality,
|
|
380
|
-
edgeBetweennessCentrality
|
|
381
|
-
} from '@graphty/algorithms'
|
|
370
|
+
import { betweennessCentrality, nodeBetweennessCentrality, edgeBetweennessCentrality } from "@graphty/algorithms";
|
|
382
371
|
|
|
383
372
|
// Node betweenness for all nodes
|
|
384
373
|
const centralities = betweennessCentrality(graph, {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
})
|
|
374
|
+
normalized: boolean, // Default: false
|
|
375
|
+
weight: string, // Optional: use weighted shortest paths
|
|
376
|
+
endpoints: boolean, // Default: false, include endpoints in paths
|
|
377
|
+
});
|
|
389
378
|
// Returns: CentralityResult (Record<string, number>)
|
|
390
379
|
|
|
391
380
|
// Single node betweenness
|
|
392
|
-
const centrality = nodeBetweennessCentrality(graph, nodeId, options)
|
|
381
|
+
const centrality = nodeBetweennessCentrality(graph, nodeId, options);
|
|
393
382
|
// Returns: number
|
|
394
383
|
|
|
395
384
|
// Edge betweenness
|
|
396
|
-
const edgeCentralities = edgeBetweennessCentrality(graph, options)
|
|
385
|
+
const edgeCentralities = edgeBetweennessCentrality(graph, options);
|
|
397
386
|
// Returns: Map<string, number> (edge ID to centrality)
|
|
398
387
|
```
|
|
399
388
|
|
|
400
389
|
#### Closeness Centrality
|
|
401
390
|
|
|
402
391
|
```typescript
|
|
403
|
-
import {
|
|
404
|
-
closenessCentrality,
|
|
405
|
-
nodeClosenessCentrality,
|
|
406
|
-
weightedClosenessCentrality
|
|
407
|
-
} from '@graphty/algorithms'
|
|
392
|
+
import { closenessCentrality, nodeClosenessCentrality, weightedClosenessCentrality } from "@graphty/algorithms";
|
|
408
393
|
|
|
409
394
|
// Closeness for all nodes
|
|
410
395
|
const centralities = closenessCentrality(graph, {
|
|
411
|
-
|
|
412
|
-
})
|
|
396
|
+
normalized: boolean, // Default: false
|
|
397
|
+
});
|
|
413
398
|
// Returns: CentralityResult (Record<string, number>)
|
|
414
399
|
|
|
415
400
|
// Single node closeness
|
|
416
401
|
const centrality = nodeClosenessCentrality(graph, nodeId, {
|
|
417
|
-
|
|
418
|
-
})
|
|
402
|
+
normalized: boolean,
|
|
403
|
+
});
|
|
419
404
|
// Returns: number
|
|
420
405
|
|
|
421
406
|
// Weighted closeness
|
|
422
407
|
const centralities = weightedClosenessCentrality(graph, {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
})
|
|
408
|
+
normalized: boolean,
|
|
409
|
+
weight: string, // Edge property for weights
|
|
410
|
+
});
|
|
426
411
|
// Returns: CentralityResult (Record<string, number>)
|
|
427
412
|
|
|
428
413
|
// Single node weighted closeness
|
|
429
414
|
const centrality = nodeWeightedClosenessCentrality(graph, nodeId, {
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
})
|
|
415
|
+
normalized: boolean,
|
|
416
|
+
weight: string, // Edge property for weights
|
|
417
|
+
});
|
|
433
418
|
// Returns: number
|
|
434
419
|
```
|
|
435
420
|
|
|
436
421
|
#### PageRank
|
|
437
422
|
|
|
438
423
|
```typescript
|
|
439
|
-
import {
|
|
440
|
-
pageRank,
|
|
441
|
-
personalizedPageRank,
|
|
442
|
-
topPageRankNodes
|
|
443
|
-
} from '@graphty/algorithms'
|
|
424
|
+
import { pageRank, personalizedPageRank, topPageRankNodes } from "@graphty/algorithms";
|
|
444
425
|
|
|
445
426
|
// Standard PageRank
|
|
446
427
|
const result = pageRank(graph, {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
})
|
|
428
|
+
dampingFactor: number, // Default: 0.85
|
|
429
|
+
maxIterations: number, // Default: 100
|
|
430
|
+
tolerance: number, // Default: 1e-6
|
|
431
|
+
initialRanks: Record<string, number>,
|
|
432
|
+
personalization: Record<string, number>,
|
|
433
|
+
});
|
|
453
434
|
// Returns: { ranks: Record<string, number>, iterations: number, converged: boolean }
|
|
454
435
|
|
|
455
436
|
// Personalized PageRank (with bias)
|
|
456
|
-
const ranks = personalizedPageRank(graph, personalization, options)
|
|
437
|
+
const ranks = personalizedPageRank(graph, personalization, options);
|
|
457
438
|
// personalization: Map<NodeId, number> - restart probabilities
|
|
458
439
|
// Returns: CentralityResult (Record<string, number>)
|
|
459
440
|
|
|
460
441
|
// Get top N nodes by PageRank
|
|
461
|
-
const topNodes = topPageRankNodes(graph, n, options)
|
|
442
|
+
const topNodes = topPageRankNodes(graph, n, options);
|
|
462
443
|
// Returns: Array<{ node: NodeId, rank: number }>
|
|
463
444
|
|
|
464
445
|
// Alternative PageRank that returns CentralityResult format
|
|
465
|
-
const centralities = pageRankCentrality(graph, options)
|
|
446
|
+
const centralities = pageRankCentrality(graph, options);
|
|
466
447
|
// Returns: CentralityResult (Record<string, number>)
|
|
467
448
|
```
|
|
468
449
|
|
|
469
450
|
#### Eigenvector Centrality
|
|
470
451
|
|
|
471
452
|
```typescript
|
|
472
|
-
import {
|
|
473
|
-
eigenvectorCentrality,
|
|
474
|
-
nodeEigenvectorCentrality
|
|
475
|
-
} from '@graphty/algorithms'
|
|
453
|
+
import { eigenvectorCentrality, nodeEigenvectorCentrality } from "@graphty/algorithms";
|
|
476
454
|
|
|
477
455
|
// Calculate eigenvector centrality for all nodes
|
|
478
456
|
const centralities = eigenvectorCentrality(graph, {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
})
|
|
457
|
+
maxIterations: number, // Default: 100
|
|
458
|
+
tolerance: number, // Default: 1e-6
|
|
459
|
+
});
|
|
482
460
|
// Returns: CentralityResult (Record<string, number>)
|
|
483
461
|
|
|
484
462
|
// Single node eigenvector centrality
|
|
485
|
-
const centrality = nodeEigenvectorCentrality(graph, nodeId, options)
|
|
463
|
+
const centrality = nodeEigenvectorCentrality(graph, nodeId, options);
|
|
486
464
|
// Returns: number
|
|
487
465
|
```
|
|
488
466
|
|
|
489
467
|
#### Katz Centrality
|
|
490
468
|
|
|
491
469
|
```typescript
|
|
492
|
-
import { katzCentrality, nodeKatzCentrality } from
|
|
470
|
+
import { katzCentrality, nodeKatzCentrality } from "@graphty/algorithms";
|
|
493
471
|
|
|
494
472
|
// Calculate Katz centrality for all nodes
|
|
495
473
|
const centralities = katzCentrality(graph, {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
})
|
|
474
|
+
alpha: number, // Attenuation factor (default: 0.1)
|
|
475
|
+
beta: number, // Weight for direct connections (default: 1.0)
|
|
476
|
+
maxIterations: number, // Default: 100
|
|
477
|
+
tolerance: number, // Default: 1e-6
|
|
478
|
+
normalized: boolean, // Default: true
|
|
479
|
+
});
|
|
502
480
|
// Returns: CentralityResult (Record<string, number>)
|
|
503
481
|
|
|
504
482
|
// Single node Katz centrality
|
|
505
|
-
const centrality = nodeKatzCentrality(graph, nodeId, options)
|
|
483
|
+
const centrality = nodeKatzCentrality(graph, nodeId, options);
|
|
506
484
|
// Returns: number
|
|
507
485
|
```
|
|
508
486
|
|
|
509
487
|
#### HITS Algorithm
|
|
510
488
|
|
|
511
489
|
```typescript
|
|
512
|
-
import { hits, nodeHITS } from
|
|
490
|
+
import { hits, nodeHITS } from "@graphty/algorithms";
|
|
513
491
|
|
|
514
492
|
// Calculate hub and authority scores
|
|
515
493
|
const result = hits(graph, {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
})
|
|
494
|
+
maxIterations: number, // Default: 100
|
|
495
|
+
tolerance: number, // Default: 1e-6
|
|
496
|
+
});
|
|
519
497
|
// Returns: HITSResult { hubs: CentralityResult, authorities: CentralityResult }
|
|
520
498
|
|
|
521
499
|
// Single node HITS scores
|
|
522
|
-
const scores = nodeHITS(graph, nodeId, options)
|
|
500
|
+
const scores = nodeHITS(graph, nodeId, options);
|
|
523
501
|
// Returns: { hub: number, authority: number }
|
|
524
502
|
```
|
|
525
503
|
|
|
@@ -529,31 +507,31 @@ const scores = nodeHITS(graph, nodeId, options)
|
|
|
529
507
|
|
|
530
508
|
```typescript
|
|
531
509
|
import {
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
} from
|
|
510
|
+
connectedComponents,
|
|
511
|
+
isConnected,
|
|
512
|
+
numberOfConnectedComponents,
|
|
513
|
+
largestConnectedComponent,
|
|
514
|
+
getConnectedComponent,
|
|
515
|
+
} from "@graphty/algorithms";
|
|
538
516
|
|
|
539
517
|
// Find all components
|
|
540
|
-
const components = connectedComponents(graph)
|
|
518
|
+
const components = connectedComponents(graph);
|
|
541
519
|
// Returns: NodeId[][] (array of component arrays)
|
|
542
520
|
|
|
543
521
|
// Check if graph is connected
|
|
544
|
-
const connected = isConnected(graph)
|
|
522
|
+
const connected = isConnected(graph);
|
|
545
523
|
// Returns: boolean
|
|
546
524
|
|
|
547
525
|
// Count components
|
|
548
|
-
const count = numberOfConnectedComponents(graph)
|
|
526
|
+
const count = numberOfConnectedComponents(graph);
|
|
549
527
|
// Returns: number
|
|
550
528
|
|
|
551
529
|
// Get largest component
|
|
552
|
-
const largest = largestConnectedComponent(graph)
|
|
530
|
+
const largest = largestConnectedComponent(graph);
|
|
553
531
|
// Returns: NodeId[]
|
|
554
532
|
|
|
555
533
|
// Get component containing a specific node
|
|
556
|
-
const component = getConnectedComponent(graph, nodeId)
|
|
534
|
+
const component = getConnectedComponent(graph, nodeId);
|
|
557
535
|
// Returns: Set<NodeId>
|
|
558
536
|
```
|
|
559
537
|
|
|
@@ -561,47 +539,44 @@ const component = getConnectedComponent(graph, nodeId)
|
|
|
561
539
|
|
|
562
540
|
```typescript
|
|
563
541
|
import {
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
} from
|
|
542
|
+
stronglyConnectedComponents,
|
|
543
|
+
findStronglyConnectedComponents,
|
|
544
|
+
isStronglyConnected,
|
|
545
|
+
condensationGraph,
|
|
546
|
+
} from "@graphty/algorithms";
|
|
569
547
|
|
|
570
548
|
// Find SCCs using Tarjan's algorithm
|
|
571
|
-
const sccs = stronglyConnectedComponents(graph)
|
|
549
|
+
const sccs = stronglyConnectedComponents(graph);
|
|
572
550
|
// Returns: ComponentResult
|
|
573
551
|
|
|
574
552
|
// Alternative: using DFS
|
|
575
|
-
const sccs = findStronglyConnectedComponents(graph)
|
|
553
|
+
const sccs = findStronglyConnectedComponents(graph);
|
|
576
554
|
// Returns: NodeId[][]
|
|
577
555
|
|
|
578
556
|
// Check if directed graph is strongly connected
|
|
579
|
-
const stronglyConnected = isStronglyConnected(graph)
|
|
557
|
+
const stronglyConnected = isStronglyConnected(graph);
|
|
580
558
|
// Returns: boolean
|
|
581
559
|
|
|
582
560
|
// Create condensation graph (DAG of SCCs)
|
|
583
|
-
const condensation = condensationGraph(graph)
|
|
561
|
+
const condensation = condensationGraph(graph);
|
|
584
562
|
// Returns: { graph: Graph, componentMap: Map<NodeId, number> }
|
|
585
563
|
|
|
586
564
|
// Alternative DFS-based connected components
|
|
587
|
-
const components = connectedComponentsDFS(graph)
|
|
565
|
+
const components = connectedComponentsDFS(graph);
|
|
588
566
|
// Returns: ComponentResult
|
|
589
567
|
```
|
|
590
568
|
|
|
591
569
|
#### Weakly Connected Components
|
|
592
570
|
|
|
593
571
|
```typescript
|
|
594
|
-
import {
|
|
595
|
-
weaklyConnectedComponents,
|
|
596
|
-
isWeaklyConnected
|
|
597
|
-
} from '@graphty/algorithms'
|
|
572
|
+
import { weaklyConnectedComponents, isWeaklyConnected } from "@graphty/algorithms";
|
|
598
573
|
|
|
599
574
|
// Find WCCs (ignoring edge direction)
|
|
600
|
-
const wccs = weaklyConnectedComponents(graph)
|
|
575
|
+
const wccs = weaklyConnectedComponents(graph);
|
|
601
576
|
// Returns: ComponentResult
|
|
602
577
|
|
|
603
578
|
// Check if directed graph is weakly connected
|
|
604
|
-
const weaklyConnected = isWeaklyConnected(graph)
|
|
579
|
+
const weaklyConnected = isWeaklyConnected(graph);
|
|
605
580
|
// Returns: boolean
|
|
606
581
|
```
|
|
607
582
|
|
|
@@ -612,16 +587,16 @@ const weaklyConnected = isWeaklyConnected(graph)
|
|
|
612
587
|
Min-heap implementation used internally by algorithms.
|
|
613
588
|
|
|
614
589
|
```typescript
|
|
615
|
-
import { PriorityQueue } from
|
|
590
|
+
import { PriorityQueue } from "@graphty/algorithms";
|
|
616
591
|
|
|
617
|
-
const pq = new PriorityQueue<T>((a, b) => a.priority - b.priority)
|
|
592
|
+
const pq = new PriorityQueue<T>((a, b) => a.priority - b.priority);
|
|
618
593
|
|
|
619
|
-
pq.enqueue(item)
|
|
620
|
-
pq.dequeue()
|
|
621
|
-
pq.peek()
|
|
622
|
-
pq.isEmpty()
|
|
623
|
-
pq.size
|
|
624
|
-
pq.clear()
|
|
594
|
+
pq.enqueue(item);
|
|
595
|
+
pq.dequeue();
|
|
596
|
+
pq.peek();
|
|
597
|
+
pq.isEmpty();
|
|
598
|
+
pq.size;
|
|
599
|
+
pq.clear();
|
|
625
600
|
```
|
|
626
601
|
|
|
627
602
|
#### Union-Find (Disjoint Set)
|
|
@@ -629,16 +604,16 @@ pq.clear()
|
|
|
629
604
|
Efficient data structure for tracking connected components.
|
|
630
605
|
|
|
631
606
|
```typescript
|
|
632
|
-
import { UnionFind } from
|
|
607
|
+
import { UnionFind } from "@graphty/algorithms";
|
|
633
608
|
|
|
634
|
-
const uf = new UnionFind<T>()
|
|
609
|
+
const uf = new UnionFind<T>();
|
|
635
610
|
|
|
636
|
-
uf.makeSet(item)
|
|
637
|
-
uf.find(item)
|
|
638
|
-
uf.union(item1, item2)
|
|
639
|
-
uf.connected(item1, item2)
|
|
640
|
-
uf.getSetSize(item)
|
|
641
|
-
uf.numberOfSets
|
|
611
|
+
uf.makeSet(item);
|
|
612
|
+
uf.find(item);
|
|
613
|
+
uf.union(item1, item2);
|
|
614
|
+
uf.connected(item1, item2);
|
|
615
|
+
uf.getSetSize(item);
|
|
616
|
+
uf.numberOfSets;
|
|
642
617
|
```
|
|
643
618
|
|
|
644
619
|
### Minimum Spanning Tree Algorithms
|
|
@@ -646,14 +621,14 @@ uf.numberOfSets
|
|
|
646
621
|
#### Kruskal's Algorithm
|
|
647
622
|
|
|
648
623
|
```typescript
|
|
649
|
-
import { kruskalMST, minimumSpanningTree } from
|
|
624
|
+
import { kruskalMST, minimumSpanningTree } from "@graphty/algorithms";
|
|
650
625
|
|
|
651
626
|
// Find MST using Kruskal's algorithm
|
|
652
|
-
const mst = kruskalMST(graph)
|
|
627
|
+
const mst = kruskalMST(graph);
|
|
653
628
|
// Returns: { edges: Edge[], weight: number }
|
|
654
629
|
|
|
655
630
|
// Alternative alias
|
|
656
|
-
const mst = minimumSpanningTree(graph)
|
|
631
|
+
const mst = minimumSpanningTree(graph);
|
|
657
632
|
```
|
|
658
633
|
|
|
659
634
|
#### Prim's Algorithm
|
|
@@ -671,61 +646,57 @@ const mst = primMST(graph, startNode?);
|
|
|
671
646
|
#### Louvain Method
|
|
672
647
|
|
|
673
648
|
```typescript
|
|
674
|
-
import { louvain } from
|
|
649
|
+
import { louvain } from "@graphty/algorithms";
|
|
675
650
|
|
|
676
651
|
// Detect communities using Louvain method
|
|
677
652
|
const communities = louvain(graph, {
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
})
|
|
653
|
+
resolution: number, // Default: 1.0
|
|
654
|
+
randomSeed: number,
|
|
655
|
+
});
|
|
681
656
|
// Returns: { communities: Map<NodeId, number>, modularity: number }
|
|
682
657
|
```
|
|
683
658
|
|
|
684
659
|
#### Leiden Algorithm
|
|
685
660
|
|
|
686
661
|
```typescript
|
|
687
|
-
import { leiden } from
|
|
662
|
+
import { leiden } from "@graphty/algorithms";
|
|
688
663
|
|
|
689
664
|
// Improved community detection
|
|
690
665
|
const communities = leiden(graph, {
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
})
|
|
666
|
+
resolution: number, // Default: 1.0
|
|
667
|
+
iterations: number, // Default: 10
|
|
668
|
+
randomSeed: number,
|
|
669
|
+
});
|
|
695
670
|
// Returns: { communities: Map<NodeId, number>, modularity: number }
|
|
696
671
|
```
|
|
697
672
|
|
|
698
673
|
#### Label Propagation
|
|
699
674
|
|
|
700
675
|
```typescript
|
|
701
|
-
import {
|
|
702
|
-
labelPropagation,
|
|
703
|
-
labelPropagationAsync,
|
|
704
|
-
labelPropagationSemiSupervised
|
|
705
|
-
} from '@graphty/algorithms'
|
|
676
|
+
import { labelPropagation, labelPropagationAsync, labelPropagationSemiSupervised } from "@graphty/algorithms";
|
|
706
677
|
|
|
707
678
|
// Basic label propagation
|
|
708
679
|
const labels = labelPropagation(graph, {
|
|
709
|
-
|
|
710
|
-
})
|
|
680
|
+
maxIterations: number, // Default: 100
|
|
681
|
+
});
|
|
711
682
|
// Returns: Map<NodeId, number>
|
|
712
683
|
|
|
713
684
|
// Asynchronous version
|
|
714
|
-
const labels = labelPropagationAsync(graph, options)
|
|
685
|
+
const labels = labelPropagationAsync(graph, options);
|
|
715
686
|
|
|
716
687
|
// Semi-supervised with seed communities
|
|
717
|
-
const labels = labelPropagationSemiSupervised(graph, seedLabels, options)
|
|
688
|
+
const labels = labelPropagationSemiSupervised(graph, seedLabels, options);
|
|
718
689
|
```
|
|
719
690
|
|
|
720
691
|
#### Girvan-Newman Algorithm
|
|
721
692
|
|
|
722
693
|
```typescript
|
|
723
|
-
import { girvanNewman } from
|
|
694
|
+
import { girvanNewman } from "@graphty/algorithms";
|
|
724
695
|
|
|
725
696
|
// Edge betweenness based community detection
|
|
726
697
|
const dendrogram = girvanNewman(graph, {
|
|
727
|
-
|
|
728
|
-
})
|
|
698
|
+
targetCommunities: number, // Stop at this many communities
|
|
699
|
+
});
|
|
729
700
|
// Returns: { levels: Array<{ modularity: number, communities: NodeId[][] }> }
|
|
730
701
|
```
|
|
731
702
|
|
|
@@ -734,15 +705,15 @@ const dendrogram = girvanNewman(graph, {
|
|
|
734
705
|
#### A\* Algorithm
|
|
735
706
|
|
|
736
707
|
```typescript
|
|
737
|
-
import { astar } from
|
|
708
|
+
import { astar } from "@graphty/algorithms";
|
|
738
709
|
|
|
739
710
|
// A* pathfinding with heuristic
|
|
740
711
|
const path = astar(
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
)
|
|
712
|
+
graph, // Map<T, Map<T, number>> adjacency list
|
|
713
|
+
start,
|
|
714
|
+
goal,
|
|
715
|
+
heuristic, // (node: T, goal: T) => number
|
|
716
|
+
);
|
|
746
717
|
// Returns: { path: T[], cost: number } | null
|
|
747
718
|
```
|
|
748
719
|
|
|
@@ -790,86 +761,77 @@ const cut = kargerMinCut(graph, iterations?);
|
|
|
790
761
|
#### Hierarchical Clustering
|
|
791
762
|
|
|
792
763
|
```typescript
|
|
793
|
-
import {
|
|
794
|
-
hierarchicalClustering,
|
|
795
|
-
cutDendrogram,
|
|
796
|
-
cutDendrogramKClusters
|
|
797
|
-
} from '@graphty/algorithms'
|
|
764
|
+
import { hierarchicalClustering, cutDendrogram, cutDendrogramKClusters } from "@graphty/algorithms";
|
|
798
765
|
|
|
799
766
|
// Agglomerative clustering
|
|
800
|
-
const result = hierarchicalClustering(graph, linkage)
|
|
767
|
+
const result = hierarchicalClustering(graph, linkage);
|
|
801
768
|
// graph: Map<NodeId, Set<NodeId>>
|
|
802
769
|
// linkage: 'single' | 'complete' | 'average' | 'ward' (default: 'single')
|
|
803
770
|
// Returns: HierarchicalClusteringResult { root: ClusterNode, dendrogram: ClusterNode[], clusters: Map<number, Set<NodeId>[]> }
|
|
804
771
|
|
|
805
772
|
// Cut at specific height
|
|
806
|
-
const clusters = cutDendrogram(result.root, height)
|
|
773
|
+
const clusters = cutDendrogram(result.root, height);
|
|
807
774
|
// Returns: Set<NodeId>[]
|
|
808
775
|
|
|
809
776
|
// Get exactly k clusters
|
|
810
|
-
const clusters = cutDendrogramKClusters(result.root, k)
|
|
777
|
+
const clusters = cutDendrogramKClusters(result.root, k);
|
|
811
778
|
// Returns: Set<NodeId>[]
|
|
812
779
|
```
|
|
813
780
|
|
|
814
781
|
#### K-Core Decomposition
|
|
815
782
|
|
|
816
783
|
```typescript
|
|
817
|
-
import {
|
|
818
|
-
kCoreDecomposition,
|
|
819
|
-
getKCore,
|
|
820
|
-
kTruss,
|
|
821
|
-
degeneracyOrdering
|
|
822
|
-
} from '@graphty/algorithms'
|
|
784
|
+
import { kCoreDecomposition, getKCore, kTruss, degeneracyOrdering } from "@graphty/algorithms";
|
|
823
785
|
|
|
824
786
|
// Find all k-cores
|
|
825
|
-
const result = kCoreDecomposition(graph)
|
|
787
|
+
const result = kCoreDecomposition(graph);
|
|
826
788
|
// graph: Map<NodeId, Set<NodeId>>
|
|
827
789
|
// Returns: KCoreResult { cores: Map<number, Set<NodeId>>, coreness: Map<NodeId, number>, maxCore: number }
|
|
828
790
|
|
|
829
791
|
// Extract specific k-core subgraph
|
|
830
|
-
const kCore = getKCore(graph, k)
|
|
792
|
+
const kCore = getKCore(graph, k);
|
|
831
793
|
// Returns: Set<NodeId>
|
|
832
794
|
|
|
833
795
|
// Find k-truss (triangular cores)
|
|
834
|
-
const truss = kTruss(graph, k)
|
|
796
|
+
const truss = kTruss(graph, k);
|
|
835
797
|
// Returns: Set<string> (edge strings)
|
|
836
798
|
|
|
837
799
|
// Degeneracy ordering
|
|
838
|
-
const ordering = degeneracyOrdering(graph)
|
|
800
|
+
const ordering = degeneracyOrdering(graph);
|
|
839
801
|
// Returns: NodeId[]
|
|
840
802
|
```
|
|
841
803
|
|
|
842
804
|
#### Spectral Clustering
|
|
843
805
|
|
|
844
806
|
```typescript
|
|
845
|
-
import { spectralClustering } from
|
|
807
|
+
import { spectralClustering } from "@graphty/algorithms";
|
|
846
808
|
|
|
847
809
|
// Spectral clustering using graph Laplacian
|
|
848
810
|
const result = spectralClustering(graph, {
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
})
|
|
811
|
+
k: number, // Number of clusters
|
|
812
|
+
laplacianType: "unnormalized" | "normalized" | "randomWalk", // Default: 'normalized'
|
|
813
|
+
maxIterations: number, // Default: 100
|
|
814
|
+
tolerance: number, // Default: 1e-4
|
|
815
|
+
});
|
|
854
816
|
// Returns: SpectralClusteringResult { communities: NodeId[][], clusterAssignments: Map<NodeId, number> }
|
|
855
817
|
```
|
|
856
818
|
|
|
857
819
|
#### Markov Clustering (MCL)
|
|
858
820
|
|
|
859
821
|
```typescript
|
|
860
|
-
import { markovClustering, calculateMCLModularity } from
|
|
822
|
+
import { markovClustering, calculateMCLModularity } from "@graphty/algorithms";
|
|
861
823
|
|
|
862
824
|
// MCL algorithm for network clustering
|
|
863
825
|
const result = markovClustering(graph, {
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
})
|
|
826
|
+
expansion: number, // Expansion parameter (default: 2)
|
|
827
|
+
inflation: number, // Inflation parameter (default: 2)
|
|
828
|
+
maxIterations: number, // Default: 100
|
|
829
|
+
tolerance: number, // Default: 1e-6
|
|
830
|
+
});
|
|
869
831
|
// Returns: MCLResult { communities: NodeId[][], attractors: Set<NodeId>, iterations: number, converged: boolean }
|
|
870
832
|
|
|
871
833
|
// Calculate modularity of MCL clustering result
|
|
872
|
-
const modularity = calculateMCLModularity(graph, result.communities)
|
|
834
|
+
const modularity = calculateMCLModularity(graph, result.communities);
|
|
873
835
|
// Returns: number
|
|
874
836
|
```
|
|
875
837
|
|
|
@@ -878,47 +840,38 @@ const modularity = calculateMCLModularity(graph, result.communities)
|
|
|
878
840
|
#### Bipartite Matching
|
|
879
841
|
|
|
880
842
|
```typescript
|
|
881
|
-
import {
|
|
882
|
-
maximumBipartiteMatching,
|
|
883
|
-
greedyBipartiteMatching,
|
|
884
|
-
bipartitePartition
|
|
885
|
-
} from '@graphty/algorithms'
|
|
843
|
+
import { maximumBipartiteMatching, greedyBipartiteMatching, bipartitePartition } from "@graphty/algorithms";
|
|
886
844
|
|
|
887
845
|
// Maximum bipartite matching (Hungarian algorithm)
|
|
888
846
|
const matching = maximumBipartiteMatching(graph, {
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
})
|
|
847
|
+
leftNodes: Set<NodeId>, // Optional: specify left partition
|
|
848
|
+
rightNodes: Set<NodeId>, // Optional: specify right partition
|
|
849
|
+
});
|
|
892
850
|
// Returns: BipartiteMatchingResult { matching: Map<NodeId, NodeId>, size: number }
|
|
893
851
|
|
|
894
852
|
// Greedy bipartite matching (faster, approximate)
|
|
895
|
-
const matching = greedyBipartiteMatching(graph, options)
|
|
853
|
+
const matching = greedyBipartiteMatching(graph, options);
|
|
896
854
|
|
|
897
855
|
// Partition graph into bipartite sets
|
|
898
|
-
const partition = bipartitePartition(graph)
|
|
856
|
+
const partition = bipartitePartition(graph);
|
|
899
857
|
// Returns: { left: Set<NodeId>, right: Set<NodeId> } | null
|
|
900
858
|
```
|
|
901
859
|
|
|
902
860
|
#### Graph Isomorphism
|
|
903
861
|
|
|
904
862
|
```typescript
|
|
905
|
-
import { isGraphIsomorphic, findAllIsomorphisms } from
|
|
863
|
+
import { isGraphIsomorphic, findAllIsomorphisms } from "@graphty/algorithms";
|
|
906
864
|
|
|
907
865
|
// Check if two graphs are isomorphic
|
|
908
866
|
const result = isGraphIsomorphic(graph1, graph2, {
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
g1: Graph,
|
|
914
|
-
g2: Graph
|
|
915
|
-
) => boolean,
|
|
916
|
-
findAllMappings: boolean // Find all possible isomorphisms
|
|
917
|
-
})
|
|
867
|
+
nodeMatch: (node1: NodeId, node2: NodeId, g1: Graph, g2: Graph) => boolean,
|
|
868
|
+
edgeMatch: (edge1: [NodeId, NodeId], edge2: [NodeId, NodeId], g1: Graph, g2: Graph) => boolean,
|
|
869
|
+
findAllMappings: boolean, // Find all possible isomorphisms
|
|
870
|
+
});
|
|
918
871
|
// Returns: IsomorphismResult { isIsomorphic: boolean, mapping?: Map<NodeId, NodeId> }
|
|
919
872
|
|
|
920
873
|
// Find all isomorphism mappings
|
|
921
|
-
const mappings = findAllIsomorphisms(graph1, graph2, options)
|
|
874
|
+
const mappings = findAllIsomorphisms(graph1, graph2, options);
|
|
922
875
|
// Returns: Array<Map<NodeId, NodeId>>
|
|
923
876
|
```
|
|
924
877
|
|
|
@@ -927,74 +880,66 @@ const mappings = findAllIsomorphisms(graph1, graph2, options)
|
|
|
927
880
|
#### Common Neighbors
|
|
928
881
|
|
|
929
882
|
```typescript
|
|
930
|
-
import {
|
|
931
|
-
commonNeighborsScore,
|
|
932
|
-
commonNeighborsPrediction,
|
|
933
|
-
commonNeighborsForPairs
|
|
934
|
-
} from '@graphty/algorithms'
|
|
883
|
+
import { commonNeighborsScore, commonNeighborsPrediction, commonNeighborsForPairs } from "@graphty/algorithms";
|
|
935
884
|
|
|
936
885
|
// Score for a specific pair
|
|
937
|
-
const score = commonNeighborsScore(graph, node1, node2)
|
|
886
|
+
const score = commonNeighborsScore(graph, node1, node2);
|
|
938
887
|
// Returns: number
|
|
939
888
|
|
|
940
889
|
// Predict links for all non-connected pairs
|
|
941
890
|
const predictions = commonNeighborsPrediction(graph, {
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
})
|
|
891
|
+
directed: boolean, // Consider direction
|
|
892
|
+
includeExisting: boolean, // Include existing edges
|
|
893
|
+
topK: number, // Return only top K predictions
|
|
894
|
+
});
|
|
946
895
|
// Returns: LinkPredictionScore[]
|
|
947
896
|
|
|
948
897
|
// Score multiple specific pairs
|
|
949
|
-
const scores = commonNeighborsForPairs(graph, pairs, options)
|
|
898
|
+
const scores = commonNeighborsForPairs(graph, pairs, options);
|
|
950
899
|
// Returns: LinkPredictionScore[]
|
|
951
900
|
|
|
952
901
|
// Evaluate prediction performance
|
|
953
|
-
const evaluation = evaluateCommonNeighbors(graph, testEdges)
|
|
902
|
+
const evaluation = evaluateCommonNeighbors(graph, testEdges);
|
|
954
903
|
// Returns: { precision, recall, f1Score }
|
|
955
904
|
|
|
956
905
|
// Get top candidates for a node
|
|
957
|
-
const candidates = getTopCandidatesForNode(graph, nodeId, { topK: number })
|
|
906
|
+
const candidates = getTopCandidatesForNode(graph, nodeId, { topK: number });
|
|
958
907
|
// Returns: LinkPredictionScore[]
|
|
959
908
|
```
|
|
960
909
|
|
|
961
910
|
#### Adamic-Adar Index
|
|
962
911
|
|
|
963
912
|
```typescript
|
|
964
|
-
import {
|
|
965
|
-
adamicAdarScore,
|
|
966
|
-
adamicAdarPrediction,
|
|
967
|
-
adamicAdarForPairs
|
|
968
|
-
} from '@graphty/algorithms'
|
|
913
|
+
import { adamicAdarScore, adamicAdarPrediction, adamicAdarForPairs } from "@graphty/algorithms";
|
|
969
914
|
|
|
970
915
|
// Adamic-Adar score for a pair (weighted by neighbor degrees)
|
|
971
|
-
const score = adamicAdarScore(graph, node1, node2)
|
|
916
|
+
const score = adamicAdarScore(graph, node1, node2);
|
|
972
917
|
// Returns: number
|
|
973
918
|
|
|
974
919
|
// Predict links using Adamic-Adar
|
|
975
920
|
const predictions = adamicAdarPrediction(graph, {
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
})
|
|
921
|
+
directed: boolean,
|
|
922
|
+
includeExisting: boolean,
|
|
923
|
+
topK: number,
|
|
924
|
+
});
|
|
980
925
|
// Returns: LinkPredictionScore[]
|
|
981
926
|
|
|
982
927
|
// Score multiple pairs
|
|
983
|
-
const scores = adamicAdarForPairs(graph, pairs, options)
|
|
928
|
+
const scores = adamicAdarForPairs(graph, pairs, options);
|
|
984
929
|
// Returns: LinkPredictionScore[]
|
|
985
930
|
|
|
986
931
|
// Compare Adamic-Adar with Common Neighbors
|
|
987
|
-
const comparison = compareAdamicAdarWithCommonNeighbors(graph, pairs)
|
|
932
|
+
const comparison = compareAdamicAdarWithCommonNeighbors(graph, pairs);
|
|
988
933
|
// Returns: Array<{ source, target, adamicAdar, commonNeighbors }>
|
|
989
934
|
|
|
990
935
|
// Evaluate prediction performance
|
|
991
|
-
const evaluation = evaluateAdamicAdar(graph, testEdges)
|
|
936
|
+
const evaluation = evaluateAdamicAdar(graph, testEdges);
|
|
992
937
|
// Returns: { precision, recall, f1Score }
|
|
993
938
|
|
|
994
939
|
// Get top candidates for a node
|
|
995
940
|
const candidates = getTopAdamicAdarCandidatesForNode(graph, nodeId, {
|
|
996
|
-
|
|
997
|
-
})
|
|
941
|
+
topK: number,
|
|
942
|
+
});
|
|
998
943
|
// Returns: LinkPredictionScore[]
|
|
999
944
|
```
|
|
1000
945
|
|
|
@@ -1005,16 +950,16 @@ Cutting-edge graph algorithms based on recent research.
|
|
|
1005
950
|
#### SynC - Synergistic Deep Graph Clustering
|
|
1006
951
|
|
|
1007
952
|
```typescript
|
|
1008
|
-
import { syncClustering } from
|
|
953
|
+
import { syncClustering } from "@graphty/algorithms";
|
|
1009
954
|
|
|
1010
955
|
// Deep learning based clustering
|
|
1011
956
|
const result = syncClustering(graph, {
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
})
|
|
957
|
+
k: number, // Number of clusters
|
|
958
|
+
maxIterations: number, // Default: 100
|
|
959
|
+
learningRate: number, // Default: 0.01
|
|
960
|
+
hiddenDim: number, // Default: 64
|
|
961
|
+
randomSeed: number,
|
|
962
|
+
});
|
|
1018
963
|
// Returns: SynCResult {
|
|
1019
964
|
// communities: NodeId[][],
|
|
1020
965
|
// clusterAssignments: Map<NodeId, number>,
|
|
@@ -1027,16 +972,16 @@ const result = syncClustering(graph, {
|
|
|
1027
972
|
#### TeraHAC - Scalable Hierarchical Agglomerative Clustering
|
|
1028
973
|
|
|
1029
974
|
```typescript
|
|
1030
|
-
import { teraHAC } from
|
|
975
|
+
import { teraHAC } from "@graphty/algorithms";
|
|
1031
976
|
|
|
1032
977
|
// Scalable hierarchical clustering
|
|
1033
978
|
const result = teraHAC(graph, {
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
})
|
|
979
|
+
linkage: "single" | "complete" | "average", // Default: 'average'
|
|
980
|
+
k: number, // Target number of clusters
|
|
981
|
+
threshold: number, // Distance threshold for merging
|
|
982
|
+
sampleSize: number, // Default: 1000
|
|
983
|
+
randomSeed: number,
|
|
984
|
+
});
|
|
1040
985
|
// Returns: TeraHACResult {
|
|
1041
986
|
// root: TeraHACClusterNode,
|
|
1042
987
|
// dendrogram: TeraHACClusterNode[],
|
|
@@ -1048,15 +993,15 @@ const result = teraHAC(graph, {
|
|
|
1048
993
|
#### GRSBM - Greedy Recursive Spectral Bisection with Modularity
|
|
1049
994
|
|
|
1050
995
|
```typescript
|
|
1051
|
-
import { grsbm } from
|
|
996
|
+
import { grsbm } from "@graphty/algorithms";
|
|
1052
997
|
|
|
1053
998
|
// Explainable community detection
|
|
1054
999
|
const result = grsbm(graph, {
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
})
|
|
1000
|
+
minClusterSize: number, // Default: 5
|
|
1001
|
+
maxDepth: number, // Default: 10
|
|
1002
|
+
modularityThreshold: number, // Default: 0.1
|
|
1003
|
+
explainClusters: boolean, // Default: true
|
|
1004
|
+
});
|
|
1060
1005
|
// Returns: GRSBMResult {
|
|
1061
1006
|
// clusters: GRSBMCluster[], // Each cluster has id, nodes, modularity, explanation
|
|
1062
1007
|
// hierarchy: Map<number, number[]>,
|
|
@@ -1156,97 +1101,97 @@ The library includes comprehensive examples demonstrating each algorithm. You ca
|
|
|
1156
1101
|
### Working with Weighted Graphs
|
|
1157
1102
|
|
|
1158
1103
|
```typescript
|
|
1159
|
-
const graph = new Graph()
|
|
1104
|
+
const graph = new Graph();
|
|
1160
1105
|
|
|
1161
1106
|
// Add weighted edges
|
|
1162
|
-
graph.addEdge(
|
|
1163
|
-
graph.addEdge(
|
|
1164
|
-
graph.addEdge(
|
|
1107
|
+
graph.addEdge("A", "B", 5);
|
|
1108
|
+
graph.addEdge("B", "C", 3);
|
|
1109
|
+
graph.addEdge("A", "C", 10);
|
|
1165
1110
|
|
|
1166
1111
|
// Find shortest path considering weights
|
|
1167
|
-
const result = dijkstra(graph,
|
|
1168
|
-
const pathToC = dijkstraPath(graph,
|
|
1169
|
-
console.log(pathToC) // { path: ['A', 'B', 'C'], distance: 8 }
|
|
1112
|
+
const result = dijkstra(graph, "A");
|
|
1113
|
+
const pathToC = dijkstraPath(graph, "A", "C");
|
|
1114
|
+
console.log(pathToC); // { path: ['A', 'B', 'C'], distance: 8 }
|
|
1170
1115
|
```
|
|
1171
1116
|
|
|
1172
1117
|
### Directed Graphs
|
|
1173
1118
|
|
|
1174
1119
|
```typescript
|
|
1175
|
-
const directedGraph = new Graph({ directed: true })
|
|
1120
|
+
const directedGraph = new Graph({ directed: true });
|
|
1176
1121
|
|
|
1177
|
-
directedGraph.addEdge(
|
|
1178
|
-
directedGraph.addEdge(
|
|
1179
|
-
directedGraph.addEdge(
|
|
1122
|
+
directedGraph.addEdge("A", "B");
|
|
1123
|
+
directedGraph.addEdge("B", "C");
|
|
1124
|
+
directedGraph.addEdge("C", "A");
|
|
1180
1125
|
|
|
1181
1126
|
// Check for cycles
|
|
1182
|
-
console.log(hasCycleDFS(directedGraph)) // true
|
|
1127
|
+
console.log(hasCycleDFS(directedGraph)); // true
|
|
1183
1128
|
|
|
1184
1129
|
// Find strongly connected components
|
|
1185
|
-
const sccs = stronglyConnectedComponents(directedGraph)
|
|
1186
|
-
console.log(sccs.components) // [['A', 'B', 'C']]
|
|
1130
|
+
const sccs = stronglyConnectedComponents(directedGraph);
|
|
1131
|
+
console.log(sccs.components); // [['A', 'B', 'C']]
|
|
1187
1132
|
```
|
|
1188
1133
|
|
|
1189
1134
|
### Network Analysis
|
|
1190
1135
|
|
|
1191
1136
|
```typescript
|
|
1192
1137
|
// Identify important nodes
|
|
1193
|
-
const graph = createSocialNetwork() // Your graph
|
|
1138
|
+
const graph = createSocialNetwork(); // Your graph
|
|
1194
1139
|
|
|
1195
1140
|
// Find influencers (high PageRank)
|
|
1196
|
-
const influencers = topPageRankNodes(graph, 10)
|
|
1141
|
+
const influencers = topPageRankNodes(graph, 10);
|
|
1197
1142
|
|
|
1198
1143
|
// Find bridges (high betweenness)
|
|
1199
1144
|
const bridgers = Array.from(betweennessCentrality(graph).entries())
|
|
1200
|
-
|
|
1201
|
-
|
|
1145
|
+
.sort((a, b) => b[1] - a[1])
|
|
1146
|
+
.slice(0, 10);
|
|
1202
1147
|
|
|
1203
1148
|
// Find communities (connected components)
|
|
1204
|
-
const communities = connectedComponents(graph)
|
|
1205
|
-
console.log(`Found ${communities.components.length} communities`)
|
|
1149
|
+
const communities = connectedComponents(graph);
|
|
1150
|
+
console.log(`Found ${communities.components.length} communities`);
|
|
1206
1151
|
```
|
|
1207
1152
|
|
|
1208
1153
|
### Custom Edge Properties
|
|
1209
1154
|
|
|
1210
1155
|
```typescript
|
|
1211
|
-
const graph = new Graph()
|
|
1156
|
+
const graph = new Graph();
|
|
1212
1157
|
|
|
1213
1158
|
// Add edges with custom data
|
|
1214
|
-
graph.addEdge(
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
})
|
|
1159
|
+
graph.addEdge("A", "B", 1, {
|
|
1160
|
+
type: "road",
|
|
1161
|
+
distance: 100,
|
|
1162
|
+
traffic: "heavy",
|
|
1163
|
+
});
|
|
1219
1164
|
|
|
1220
1165
|
// Use custom weight in algorithms
|
|
1221
|
-
const result = dijkstra(graph,
|
|
1222
|
-
|
|
1223
|
-
})
|
|
1166
|
+
const result = dijkstra(graph, "A", {
|
|
1167
|
+
weightKey: "distance", // Use 'distance' property as weight
|
|
1168
|
+
});
|
|
1224
1169
|
```
|
|
1225
1170
|
|
|
1226
1171
|
### Graph Visualization Preparation
|
|
1227
1172
|
|
|
1228
1173
|
```typescript
|
|
1229
1174
|
// Prepare data for visualization
|
|
1230
|
-
const graph = loadGraph()
|
|
1175
|
+
const graph = loadGraph();
|
|
1231
1176
|
|
|
1232
1177
|
// Calculate layout metrics
|
|
1233
|
-
const centralities = degreeCentrality(graph, { normalized: true })
|
|
1234
|
-
const ranks = pageRank(graph)
|
|
1178
|
+
const centralities = degreeCentrality(graph, { normalized: true });
|
|
1179
|
+
const ranks = pageRank(graph);
|
|
1235
1180
|
|
|
1236
1181
|
// Export for visualization
|
|
1237
|
-
const nodes = Array.from(graph.nodes()).map(node => ({
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
}))
|
|
1243
|
-
|
|
1244
|
-
const edges = Array.from(graph.edges()).map(edge => ({
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
}))
|
|
1182
|
+
const nodes = Array.from(graph.nodes()).map((node) => ({
|
|
1183
|
+
id: node.id,
|
|
1184
|
+
data: node.data,
|
|
1185
|
+
size: centralities.get(node.id) || 0,
|
|
1186
|
+
importance: ranks.get(node.id) || 0,
|
|
1187
|
+
}));
|
|
1188
|
+
|
|
1189
|
+
const edges = Array.from(graph.edges()).map((edge) => ({
|
|
1190
|
+
source: edge.source,
|
|
1191
|
+
target: edge.target,
|
|
1192
|
+
weight: edge.weight || 1,
|
|
1193
|
+
data: edge.data,
|
|
1194
|
+
}));
|
|
1250
1195
|
```
|
|
1251
1196
|
|
|
1252
1197
|
## Type Definitions
|
|
@@ -1254,19 +1199,19 @@ const edges = Array.from(graph.edges()).map(edge => ({
|
|
|
1254
1199
|
### Core Types
|
|
1255
1200
|
|
|
1256
1201
|
```typescript
|
|
1257
|
-
type NodeId = string | number
|
|
1202
|
+
type NodeId = string | number;
|
|
1258
1203
|
|
|
1259
1204
|
interface Node {
|
|
1260
|
-
|
|
1261
|
-
|
|
1205
|
+
id: NodeId;
|
|
1206
|
+
data?: Record<string, unknown>;
|
|
1262
1207
|
}
|
|
1263
1208
|
|
|
1264
1209
|
interface Edge {
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1210
|
+
source: NodeId;
|
|
1211
|
+
target: NodeId;
|
|
1212
|
+
weight?: number;
|
|
1213
|
+
id?: string;
|
|
1214
|
+
data?: Record<string, unknown>;
|
|
1270
1215
|
}
|
|
1271
1216
|
```
|
|
1272
1217
|
|
|
@@ -1274,106 +1219,106 @@ interface Edge {
|
|
|
1274
1219
|
|
|
1275
1220
|
```typescript
|
|
1276
1221
|
interface TraversalResult {
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1222
|
+
visited: Set<NodeId>;
|
|
1223
|
+
order: NodeId[];
|
|
1224
|
+
tree?: Map<NodeId, NodeId | null>;
|
|
1280
1225
|
}
|
|
1281
1226
|
|
|
1282
1227
|
interface ShortestPathResult {
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1228
|
+
distance: number;
|
|
1229
|
+
path: NodeId[];
|
|
1230
|
+
predecessor: Map<NodeId, NodeId | null>;
|
|
1286
1231
|
}
|
|
1287
1232
|
|
|
1288
1233
|
interface BellmanFordResult {
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1234
|
+
distances: Map<NodeId, number>;
|
|
1235
|
+
previous: Map<NodeId, NodeId | null>;
|
|
1236
|
+
hasNegativeCycle: boolean;
|
|
1237
|
+
negativeCycleNodes?: NodeId[];
|
|
1293
1238
|
}
|
|
1294
1239
|
|
|
1295
|
-
type CentralityResult = Record<string, number
|
|
1240
|
+
type CentralityResult = Record<string, number>;
|
|
1296
1241
|
|
|
1297
1242
|
interface PageRankResult {
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1243
|
+
ranks: Record<string, number>;
|
|
1244
|
+
iterations: number;
|
|
1245
|
+
converged: boolean;
|
|
1301
1246
|
}
|
|
1302
1247
|
|
|
1303
1248
|
interface CommunityResult {
|
|
1304
|
-
|
|
1305
|
-
|
|
1249
|
+
communities: Map<NodeId, number>;
|
|
1250
|
+
modularity: number;
|
|
1306
1251
|
}
|
|
1307
1252
|
|
|
1308
1253
|
interface ComponentResult {
|
|
1309
|
-
|
|
1310
|
-
|
|
1254
|
+
components: NodeId[][];
|
|
1255
|
+
componentMap: Map<NodeId, number>;
|
|
1311
1256
|
}
|
|
1312
1257
|
|
|
1313
1258
|
interface HITSResult {
|
|
1314
|
-
|
|
1315
|
-
|
|
1259
|
+
hubs: CentralityResult;
|
|
1260
|
+
authorities: CentralityResult;
|
|
1316
1261
|
}
|
|
1317
1262
|
|
|
1318
1263
|
interface SpectralClusteringResult {
|
|
1319
|
-
|
|
1320
|
-
|
|
1264
|
+
communities: NodeId[][];
|
|
1265
|
+
clusterAssignments: Map<NodeId, number>;
|
|
1321
1266
|
}
|
|
1322
1267
|
|
|
1323
1268
|
interface MCLResult {
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1269
|
+
communities: NodeId[][];
|
|
1270
|
+
attractors: Set<NodeId>;
|
|
1271
|
+
iterations: number;
|
|
1272
|
+
converged: boolean;
|
|
1328
1273
|
}
|
|
1329
1274
|
|
|
1330
1275
|
interface BipartiteMatchingResult {
|
|
1331
|
-
|
|
1332
|
-
|
|
1276
|
+
matching: Map<NodeId, NodeId>;
|
|
1277
|
+
size: number;
|
|
1333
1278
|
}
|
|
1334
1279
|
|
|
1335
1280
|
interface LinkPredictionScore {
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1281
|
+
source: NodeId;
|
|
1282
|
+
target: NodeId;
|
|
1283
|
+
score: number;
|
|
1339
1284
|
}
|
|
1340
1285
|
|
|
1341
1286
|
interface HierarchicalClusteringResult<T> {
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1287
|
+
root: ClusterNode<T>;
|
|
1288
|
+
dendrogram: ClusterNode<T>[];
|
|
1289
|
+
clusters: Map<number, Set<T>[]>;
|
|
1345
1290
|
}
|
|
1346
1291
|
|
|
1347
1292
|
interface KCoreResult<T> {
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1293
|
+
cores: Map<number, Set<T>>;
|
|
1294
|
+
coreness: Map<T, number>;
|
|
1295
|
+
maxCore: number;
|
|
1351
1296
|
}
|
|
1352
1297
|
|
|
1353
1298
|
interface IsomorphismResult {
|
|
1354
|
-
|
|
1355
|
-
|
|
1299
|
+
isIsomorphic: boolean;
|
|
1300
|
+
mapping?: Map<NodeId, NodeId>;
|
|
1356
1301
|
}
|
|
1357
1302
|
|
|
1358
1303
|
interface SynCResult {
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1304
|
+
communities: NodeId[][];
|
|
1305
|
+
clusterAssignments: Map<NodeId, number>;
|
|
1306
|
+
embeddings: Map<NodeId, number[]>;
|
|
1307
|
+
iterations: number;
|
|
1308
|
+
converged: boolean;
|
|
1364
1309
|
}
|
|
1365
1310
|
|
|
1366
1311
|
interface TeraHACResult {
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1312
|
+
root: TeraHACClusterNode;
|
|
1313
|
+
dendrogram: TeraHACClusterNode[];
|
|
1314
|
+
clusters: NodeId[][];
|
|
1315
|
+
mergeDistances: number[];
|
|
1371
1316
|
}
|
|
1372
1317
|
|
|
1373
1318
|
interface GRSBMResult {
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1319
|
+
clusters: GRSBMCluster[];
|
|
1320
|
+
hierarchy: Map<number, number[]>;
|
|
1321
|
+
totalModularity: number;
|
|
1377
1322
|
}
|
|
1378
1323
|
```
|
|
1379
1324
|
|
|
@@ -1381,22 +1326,22 @@ interface GRSBMResult {
|
|
|
1381
1326
|
|
|
1382
1327
|
- **Graph Representation**: Uses adjacency lists for O(1) neighbor access
|
|
1383
1328
|
- **Algorithm Complexity**:
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1329
|
+
- BFS/DFS: O(V + E)
|
|
1330
|
+
- Dijkstra: O((V + E) log V) with binary heap
|
|
1331
|
+
- Bellman-Ford: O(VE)
|
|
1332
|
+
- Floyd-Warshall: O(V³)
|
|
1333
|
+
- PageRank: O(k(V + E)) where k is iterations
|
|
1334
|
+
- Connected Components: O(V + E)
|
|
1335
|
+
- Kruskal's MST: O(E log E)
|
|
1336
|
+
- Prim's MST: O((V + E) log V)
|
|
1337
|
+
- A\*: O((V + E) log V) - depends on heuristic quality
|
|
1338
|
+
- Ford-Fulkerson: O(E \* f) where f is max flow
|
|
1339
|
+
- Edmonds-Karp: O(VE²)
|
|
1340
|
+
- Louvain/Leiden: O(n log n) average case
|
|
1341
|
+
- Hierarchical Clustering: O(n² log n)
|
|
1342
|
+
- SynC: O(kni) where k is clusters, n is nodes, i is iterations
|
|
1343
|
+
- TeraHAC: O(n log n) with sampling
|
|
1344
|
+
- GRSBM: O(m log n) where m is edges
|
|
1400
1345
|
- **Memory Usage**: O(V + E) for graph storage
|
|
1401
1346
|
- **Browser Optimization**: Algorithms use iterative approaches where possible to avoid stack overflow
|
|
1402
1347
|
- **Performance Benchmarks**: View detailed performance comparisons at [https://graphty-org.github.io/algorithms/benchmarks/](https://graphty-org.github.io/algorithms/benchmarks/)
|
|
@@ -1461,28 +1406,28 @@ The project includes interactive HTML examples demonstrating each algorithm. To
|
|
|
1461
1406
|
|
|
1462
1407
|
1. **Copy the environment configuration:**
|
|
1463
1408
|
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1409
|
+
```bash
|
|
1410
|
+
cp .env.example .env
|
|
1411
|
+
```
|
|
1467
1412
|
|
|
1468
1413
|
2. **Configure the server (optional):**
|
|
1469
1414
|
Edit `.env` to set your preferred host and port:
|
|
1470
1415
|
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1416
|
+
```bash
|
|
1417
|
+
# Server host (defaults to true for network exposure)
|
|
1418
|
+
HOST=localhost # For local-only access
|
|
1419
|
+
# HOST=0.0.0.0 # For network access
|
|
1420
|
+
# HOST=my.server.com # Custom domain
|
|
1476
1421
|
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1422
|
+
# Server port (defaults to 9000)
|
|
1423
|
+
PORT=9000 # Must be between 9000-9099
|
|
1424
|
+
```
|
|
1480
1425
|
|
|
1481
1426
|
3. **Start the development server:**
|
|
1482
1427
|
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1428
|
+
```bash
|
|
1429
|
+
npm run examples:html
|
|
1430
|
+
```
|
|
1486
1431
|
|
|
1487
1432
|
4. **Open your browser** to `http://localhost:9000` (or your configured host/port)
|
|
1488
1433
|
|