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