@graphty/algorithms 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1259 -61
- package/dist/algorithms.d.ts +2 -0
- package/dist/algorithms.d.ts.map +1 -0
- package/dist/algorithms.js +2 -0
- package/dist/algorithms.js.map +1 -0
- package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.js +22 -7
- package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
- package/dist/src/algorithms/centrality/closeness.js +7 -7
- package/dist/src/algorithms/centrality/closeness.js.map +1 -1
- package/dist/src/algorithms/centrality/degree.js +1 -1
- package/dist/src/algorithms/centrality/degree.js.map +1 -1
- package/dist/src/algorithms/centrality/eigenvector.d.ts +27 -0
- package/dist/src/algorithms/centrality/eigenvector.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/eigenvector.js +113 -0
- package/dist/src/algorithms/centrality/eigenvector.js.map +1 -0
- package/dist/src/algorithms/centrality/hits.d.ts +35 -0
- package/dist/src/algorithms/centrality/hits.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/hits.js +146 -0
- package/dist/src/algorithms/centrality/hits.js.map +1 -0
- package/dist/src/algorithms/centrality/index.d.ts +6 -0
- package/dist/src/algorithms/centrality/index.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/index.js +3 -0
- package/dist/src/algorithms/centrality/index.js.map +1 -1
- package/dist/src/algorithms/centrality/katz.d.ts +30 -0
- package/dist/src/algorithms/centrality/katz.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/katz.js +85 -0
- package/dist/src/algorithms/centrality/katz.js.map +1 -0
- package/dist/src/algorithms/centrality/pagerank.js +3 -3
- package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
- package/dist/src/algorithms/community/girvan-newman.d.ts +23 -0
- package/dist/src/algorithms/community/girvan-newman.d.ts.map +1 -0
- package/dist/src/algorithms/community/girvan-newman.js +297 -0
- package/dist/src/algorithms/community/girvan-newman.js.map +1 -0
- package/dist/src/algorithms/community/index.d.ts +12 -0
- package/dist/src/algorithms/community/index.d.ts.map +1 -0
- package/dist/src/algorithms/community/index.js +12 -0
- package/dist/src/algorithms/community/index.js.map +1 -0
- package/dist/src/algorithms/community/label-propagation.d.ts +42 -0
- package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -0
- package/dist/src/algorithms/community/label-propagation.js +307 -0
- package/dist/src/algorithms/community/label-propagation.js.map +1 -0
- package/dist/src/algorithms/community/leiden.d.ts +33 -0
- package/dist/src/algorithms/community/leiden.d.ts.map +1 -0
- package/dist/src/algorithms/community/leiden.js +434 -0
- package/dist/src/algorithms/community/leiden.js.map +1 -0
- package/dist/src/algorithms/community/louvain.d.ts +19 -0
- package/dist/src/algorithms/community/louvain.d.ts.map +1 -0
- package/dist/src/algorithms/community/louvain.js +219 -0
- package/dist/src/algorithms/community/louvain.js.map +1 -0
- package/dist/src/algorithms/components/connected.js +7 -7
- package/dist/src/algorithms/components/connected.js.map +1 -1
- package/dist/src/algorithms/index.d.ts +7 -0
- package/dist/src/algorithms/index.d.ts.map +1 -1
- package/dist/src/algorithms/index.js +14 -0
- package/dist/src/algorithms/index.js.map +1 -1
- package/dist/src/algorithms/matching/bipartite.d.ts +37 -0
- package/dist/src/algorithms/matching/bipartite.d.ts.map +1 -0
- package/dist/src/algorithms/matching/bipartite.js +127 -0
- package/dist/src/algorithms/matching/bipartite.js.map +1 -0
- package/dist/src/algorithms/matching/index.d.ts +8 -0
- package/dist/src/algorithms/matching/index.d.ts.map +1 -0
- package/dist/src/algorithms/matching/index.js +6 -0
- package/dist/src/algorithms/matching/index.js.map +1 -0
- package/dist/src/algorithms/matching/isomorphism.d.ts +32 -0
- package/dist/src/algorithms/matching/isomorphism.d.ts.map +1 -0
- package/dist/src/algorithms/matching/isomorphism.js +291 -0
- package/dist/src/algorithms/matching/isomorphism.js.map +1 -0
- package/dist/src/algorithms/mst/index.d.ts +4 -0
- package/dist/src/algorithms/mst/index.d.ts.map +1 -0
- package/dist/src/algorithms/mst/index.js +3 -0
- package/dist/src/algorithms/mst/index.js.map +1 -0
- package/dist/src/algorithms/mst/kruskal.d.ts +9 -0
- package/dist/src/algorithms/mst/kruskal.d.ts.map +1 -0
- package/dist/src/algorithms/mst/kruskal.js +43 -0
- package/dist/src/algorithms/mst/kruskal.js.map +1 -0
- package/dist/src/algorithms/mst/prim.d.ts +5 -0
- package/dist/src/algorithms/mst/prim.d.ts.map +1 -0
- package/dist/src/algorithms/mst/prim.js +63 -0
- package/dist/src/algorithms/mst/prim.js.map +1 -0
- package/dist/src/algorithms/shortest-path/bellman-ford.js +2 -2
- package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.js +5 -5
- package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
- package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts +14 -0
- package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts.map +1 -0
- package/dist/src/algorithms/shortest-path/floyd-warshall.js +129 -0
- package/dist/src/algorithms/shortest-path/floyd-warshall.js.map +1 -0
- package/dist/src/algorithms/shortest-path/index.d.ts +2 -0
- package/dist/src/algorithms/shortest-path/index.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/index.js +1 -0
- package/dist/src/algorithms/shortest-path/index.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs.js +2 -2
- package/dist/src/algorithms/traversal/bfs.js.map +1 -1
- package/dist/src/algorithms/traversal/dfs.js +11 -11
- package/dist/src/algorithms/traversal/dfs.js.map +1 -1
- package/dist/src/clustering/hierarchical.d.ts +48 -0
- package/dist/src/clustering/hierarchical.d.ts.map +1 -0
- package/dist/src/clustering/hierarchical.js +439 -0
- package/dist/src/clustering/hierarchical.js.map +1 -0
- package/dist/src/clustering/index.d.ts +7 -0
- package/dist/src/clustering/index.d.ts.map +1 -0
- package/dist/src/clustering/index.js +5 -0
- package/dist/src/clustering/index.js.map +1 -0
- package/dist/src/clustering/k-core.d.ts +63 -0
- package/dist/src/clustering/k-core.d.ts.map +1 -0
- package/dist/src/clustering/k-core.js +377 -0
- package/dist/src/clustering/k-core.js.map +1 -0
- package/dist/src/clustering/mcl.d.ts +36 -0
- package/dist/src/clustering/mcl.d.ts.map +1 -0
- package/dist/src/clustering/mcl.js +343 -0
- package/dist/src/clustering/mcl.js.map +1 -0
- package/dist/src/clustering/spectral.d.ts +28 -0
- package/dist/src/clustering/spectral.d.ts.map +1 -0
- package/dist/src/clustering/spectral.js +551 -0
- package/dist/src/clustering/spectral.js.map +1 -0
- package/dist/src/core/graph.d.ts +9 -0
- package/dist/src/core/graph.d.ts.map +1 -1
- package/dist/src/core/graph.js +31 -11
- package/dist/src/core/graph.js.map +1 -1
- package/dist/src/data-structures/priority-queue.js +0 -2
- package/dist/src/data-structures/priority-queue.js.map +1 -1
- package/dist/src/data-structures/union-find.js +2 -5
- package/dist/src/data-structures/union-find.js.map +1 -1
- package/dist/src/flow/ford-fulkerson.d.ts +53 -0
- package/dist/src/flow/ford-fulkerson.d.ts.map +1 -0
- package/dist/src/flow/ford-fulkerson.js +355 -0
- package/dist/src/flow/ford-fulkerson.js.map +1 -0
- package/dist/src/flow/index.d.ts +3 -0
- package/dist/src/flow/index.d.ts.map +1 -0
- package/dist/src/flow/index.js +3 -0
- package/dist/src/flow/index.js.map +1 -0
- package/dist/src/flow/min-cut.d.ts +49 -0
- package/dist/src/flow/min-cut.d.ts.map +1 -0
- package/dist/src/flow/min-cut.js +383 -0
- package/dist/src/flow/min-cut.js.map +1 -0
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/link-prediction/adamic-adar.d.ts +56 -0
- package/dist/src/link-prediction/adamic-adar.d.ts.map +1 -0
- package/dist/src/link-prediction/adamic-adar.js +256 -0
- package/dist/src/link-prediction/adamic-adar.js.map +1 -0
- package/dist/src/link-prediction/common-neighbors.d.ts +50 -0
- package/dist/src/link-prediction/common-neighbors.d.ts.map +1 -0
- package/dist/src/link-prediction/common-neighbors.js +155 -0
- package/dist/src/link-prediction/common-neighbors.js.map +1 -0
- package/dist/src/link-prediction/index.d.ts +7 -0
- package/dist/src/link-prediction/index.d.ts.map +1 -0
- package/dist/src/link-prediction/index.js +6 -0
- package/dist/src/link-prediction/index.js.map +1 -0
- package/dist/src/pathfinding/astar.d.ts +50 -0
- package/dist/src/pathfinding/astar.d.ts.map +1 -0
- package/dist/src/pathfinding/astar.js +180 -0
- package/dist/src/pathfinding/astar.js.map +1 -0
- package/dist/src/pathfinding/index.d.ts +3 -0
- package/dist/src/pathfinding/index.d.ts.map +1 -0
- package/dist/src/pathfinding/index.js +3 -0
- package/dist/src/pathfinding/index.js.map +1 -0
- package/dist/src/pathfinding/utils.d.ts +18 -0
- package/dist/src/pathfinding/utils.d.ts.map +1 -0
- package/dist/src/pathfinding/utils.js +68 -0
- package/dist/src/pathfinding/utils.js.map +1 -0
- package/dist/src/research/grsbm.d.ts +83 -0
- package/dist/src/research/grsbm.d.ts.map +1 -0
- package/dist/src/research/grsbm.js +411 -0
- package/dist/src/research/grsbm.js.map +1 -0
- package/dist/src/research/index.d.ts +12 -0
- package/dist/src/research/index.d.ts.map +1 -0
- package/dist/src/research/index.js +14 -0
- package/dist/src/research/index.js.map +1 -0
- package/dist/src/research/sync.d.ts +49 -0
- package/dist/src/research/sync.d.ts.map +1 -0
- package/dist/src/research/sync.js +342 -0
- package/dist/src/research/sync.js.map +1 -0
- package/dist/src/research/terahac.d.ts +63 -0
- package/dist/src/research/terahac.d.ts.map +1 -0
- package/dist/src/research/terahac.js +375 -0
- package/dist/src/research/terahac.js.map +1 -0
- package/dist/src/types/index.d.ts +9 -0
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/utils/graphNode.d.ts +8 -0
- package/dist/src/utils/graphNode.d.ts.map +1 -0
- package/dist/src/utils/graphNode.js +2 -0
- package/dist/src/utils/graphNode.js.map +1 -0
- package/dist/src/utils/priorityQueue.d.ts +21 -0
- package/dist/src/utils/priorityQueue.d.ts.map +1 -0
- package/dist/src/utils/priorityQueue.js +101 -0
- package/dist/src/utils/priorityQueue.js.map +1 -0
- package/package.json +13 -2
- package/src/algorithms/centrality/betweenness.ts +25 -7
- package/src/algorithms/centrality/closeness.ts +7 -7
- package/src/algorithms/centrality/degree.ts +1 -1
- package/src/algorithms/centrality/eigenvector.ts +162 -0
- package/src/algorithms/centrality/hits.ts +210 -0
- package/src/algorithms/centrality/index.ts +6 -0
- package/src/algorithms/centrality/katz.ts +139 -0
- package/src/algorithms/centrality/pagerank.ts +3 -3
- package/src/algorithms/community/girvan-newman.ts +372 -0
- package/src/algorithms/community/index.ts +13 -0
- package/src/algorithms/community/label-propagation.ts +392 -0
- package/src/algorithms/community/leiden.ts +572 -0
- package/src/algorithms/community/louvain.ts +298 -0
- package/src/algorithms/components/connected.ts +7 -7
- package/src/algorithms/index.ts +21 -0
- package/src/algorithms/matching/bipartite.ts +179 -0
- package/src/algorithms/matching/index.ts +8 -0
- package/src/algorithms/matching/isomorphism.ts +392 -0
- package/src/algorithms/mst/index.ts +4 -0
- package/src/algorithms/mst/kruskal.ts +61 -0
- package/src/algorithms/mst/prim.ts +80 -0
- package/src/algorithms/shortest-path/bellman-ford.ts +2 -2
- package/src/algorithms/shortest-path/dijkstra.ts +5 -5
- package/src/algorithms/shortest-path/floyd-warshall.ts +170 -0
- package/src/algorithms/shortest-path/index.ts +2 -0
- package/src/algorithms/traversal/bfs.ts +2 -2
- package/src/algorithms/traversal/dfs.ts +11 -11
- package/src/clustering/hierarchical.ts +555 -0
- package/src/clustering/index.ts +6 -0
- package/src/clustering/k-core.ts +460 -0
- package/src/clustering/mcl.ts +454 -0
- package/src/clustering/spectral.ts +672 -0
- package/src/core/graph.ts +34 -6
- package/src/data-structures/union-find.ts +2 -2
- package/src/flow/ford-fulkerson.ts +459 -0
- package/src/flow/index.ts +2 -0
- package/src/flow/min-cut.ts +482 -0
- package/src/index.ts +5 -0
- package/src/link-prediction/adamic-adar.ts +353 -0
- package/src/link-prediction/common-neighbors.ts +252 -0
- package/src/link-prediction/index.ts +20 -0
- package/src/pathfinding/astar.ts +229 -0
- package/src/pathfinding/index.ts +2 -0
- package/src/pathfinding/utils.ts +87 -0
- package/src/research/grsbm.ts +589 -0
- package/src/research/index.ts +17 -0
- package/src/research/sync.ts +469 -0
- package/src/research/terahac.ts +506 -0
- package/src/types/index.ts +11 -0
- package/src/utils/graphNode.ts +7 -0
- package/src/utils/priorityQueue.ts +120 -0
- package/dist/test/browser/basic.test.d.ts +0 -2
- package/dist/test/browser/basic.test.d.ts.map +0 -1
- package/dist/test/browser/basic.test.js +0 -70
- package/dist/test/browser/basic.test.js.map +0 -1
- package/dist/test/unit/bellman-ford.test.d.ts +0 -2
- package/dist/test/unit/bellman-ford.test.d.ts.map +0 -1
- package/dist/test/unit/bellman-ford.test.js +0 -231
- package/dist/test/unit/bellman-ford.test.js.map +0 -1
- package/dist/test/unit/betweenness-centrality.test.d.ts +0 -2
- package/dist/test/unit/betweenness-centrality.test.d.ts.map +0 -1
- package/dist/test/unit/betweenness-centrality.test.js +0 -311
- package/dist/test/unit/betweenness-centrality.test.js.map +0 -1
- package/dist/test/unit/bfs.test.d.ts +0 -2
- package/dist/test/unit/bfs.test.d.ts.map +0 -1
- package/dist/test/unit/bfs.test.js +0 -277
- package/dist/test/unit/bfs.test.js.map +0 -1
- package/dist/test/unit/closeness.test.d.ts +0 -2
- package/dist/test/unit/closeness.test.d.ts.map +0 -1
- package/dist/test/unit/closeness.test.js +0 -266
- package/dist/test/unit/closeness.test.js.map +0 -1
- package/dist/test/unit/connected-components.test.d.ts +0 -2
- package/dist/test/unit/connected-components.test.d.ts.map +0 -1
- package/dist/test/unit/connected-components.test.js +0 -355
- package/dist/test/unit/connected-components.test.js.map +0 -1
- package/dist/test/unit/degree-centrality.test.d.ts +0 -2
- package/dist/test/unit/degree-centrality.test.d.ts.map +0 -1
- package/dist/test/unit/degree-centrality.test.js +0 -260
- package/dist/test/unit/degree-centrality.test.js.map +0 -1
- package/dist/test/unit/dfs.test.d.ts +0 -2
- package/dist/test/unit/dfs.test.d.ts.map +0 -1
- package/dist/test/unit/dfs.test.js +0 -350
- package/dist/test/unit/dfs.test.js.map +0 -1
- package/dist/test/unit/dijkstra.test.d.ts +0 -2
- package/dist/test/unit/dijkstra.test.d.ts.map +0 -1
- package/dist/test/unit/dijkstra.test.js +0 -311
- package/dist/test/unit/dijkstra.test.js.map +0 -1
- package/dist/test/unit/graph.test.d.ts +0 -2
- package/dist/test/unit/graph.test.d.ts.map +0 -1
- package/dist/test/unit/graph.test.js +0 -175
- package/dist/test/unit/graph.test.js.map +0 -1
- package/dist/test/unit/pagerank.test.d.ts +0 -2
- package/dist/test/unit/pagerank.test.d.ts.map +0 -1
- package/dist/test/unit/pagerank.test.js +0 -281
- package/dist/test/unit/pagerank.test.js.map +0 -1
- package/dist/test/unit/priority-queue.test.d.ts +0 -2
- package/dist/test/unit/priority-queue.test.d.ts.map +0 -1
- package/dist/test/unit/priority-queue.test.js +0 -189
- package/dist/test/unit/priority-queue.test.js.map +0 -1
- package/dist/test/unit/union-find.test.d.ts +0 -2
- package/dist/test/unit/union-find.test.d.ts.map +0 -1
- package/dist/test/unit/union-find.test.js +0 -245
- package/dist/test/unit/union-find.test.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
# @graphty/algorithms
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/graphty-org/algorithms/actions/workflows/test.yml)
|
|
4
|
+
[](https://coveralls.io/github/graphty-org/algorithms)
|
|
5
|
+
[](https://www.npmjs.com/package/@graphty/algorithms)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
A comprehensive TypeScript graph algorithms library with 100+ algorithms optimized for browser environments and visualization applications.
|
|
4
9
|
|
|
5
10
|
## Features
|
|
6
11
|
|
|
7
12
|
- **TypeScript-first**: Full type safety with comprehensive type definitions
|
|
8
13
|
- **Browser-optimized**: Designed to run efficiently in web browsers
|
|
9
14
|
- **Modular**: Import only the algorithms you need
|
|
10
|
-
- **Comprehensive**:
|
|
15
|
+
- **Comprehensive**: 100+ graph algorithms including traversal, shortest paths, centrality, clustering, flow, matching, link prediction, and more
|
|
11
16
|
- **Well-tested**: Extensive test suite with high coverage
|
|
12
17
|
- **Standards-compliant**: Follows conventional commits and semantic versioning
|
|
13
18
|
|
|
@@ -20,7 +25,7 @@ npm install @graphty/algorithms
|
|
|
20
25
|
## Quick Start
|
|
21
26
|
|
|
22
27
|
```typescript
|
|
23
|
-
import { Graph } from '@graphty/algorithms';
|
|
28
|
+
import { Graph, breadthFirstSearch, dijkstra } from '@graphty/algorithms';
|
|
24
29
|
|
|
25
30
|
// Create a new graph
|
|
26
31
|
const graph = new Graph();
|
|
@@ -28,81 +33,1230 @@ const graph = new Graph();
|
|
|
28
33
|
// Add nodes and edges
|
|
29
34
|
graph.addNode('A');
|
|
30
35
|
graph.addNode('B');
|
|
36
|
+
graph.addNode('C');
|
|
31
37
|
graph.addEdge('A', 'B', 1); // source, target, weight
|
|
38
|
+
graph.addEdge('B', 'C', 2);
|
|
32
39
|
|
|
33
40
|
// Basic graph operations
|
|
34
|
-
console.log(graph.nodeCount); //
|
|
35
|
-
console.log(graph.totalEdgeCount); //
|
|
41
|
+
console.log(graph.nodeCount); // 3
|
|
42
|
+
console.log(graph.totalEdgeCount); // 2
|
|
36
43
|
console.log(graph.hasEdge('A', 'B')); // true
|
|
44
|
+
|
|
45
|
+
// Run algorithms
|
|
46
|
+
const traversal = breadthFirstSearch(graph, 'A');
|
|
47
|
+
console.log(traversal.order); // ['A', 'B', 'C']
|
|
48
|
+
|
|
49
|
+
const shortestPaths = dijkstra(graph, 'A');
|
|
50
|
+
// Get distance to C
|
|
51
|
+
const pathToC = shortestPaths.get('C');
|
|
52
|
+
console.log(pathToC?.distance); // 3
|
|
37
53
|
```
|
|
38
54
|
|
|
39
|
-
##
|
|
55
|
+
## API Reference
|
|
40
56
|
|
|
41
|
-
###
|
|
57
|
+
### Graph Class
|
|
42
58
|
|
|
43
|
-
|
|
44
|
-
- [x] **Graph Data Structure**: Core graph implementation with adjacency lists
|
|
45
|
-
- [ ] **Breadth-First Search (BFS)**: Level-by-level traversal and shortest paths
|
|
46
|
-
- [ ] **Depth-First Search (DFS)**: Deep traversal with cycle detection
|
|
59
|
+
The core data structure for representing graphs.
|
|
47
60
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
61
|
+
```typescript
|
|
62
|
+
class Graph {
|
|
63
|
+
constructor(config?: Partial<GraphConfig>)
|
|
64
|
+
}
|
|
65
|
+
```
|
|
51
66
|
|
|
52
|
-
####
|
|
53
|
-
- [ ] **Degree Centrality**: Node importance based on connections
|
|
54
|
-
- [ ] **Betweenness Centrality**: Node importance based on shortest path frequency
|
|
55
|
-
- [ ] **Closeness Centrality**: Node importance based on average distance
|
|
56
|
-
- [ ] **PageRank**: Google's web page ranking algorithm
|
|
67
|
+
#### Configuration Options
|
|
57
68
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
69
|
+
```typescript
|
|
70
|
+
interface GraphConfig {
|
|
71
|
+
directed: boolean; // Default: false
|
|
72
|
+
allowSelfLoops: boolean; // Default: false
|
|
73
|
+
allowParallelEdges: boolean; // Default: false
|
|
74
|
+
}
|
|
75
|
+
```
|
|
61
76
|
|
|
62
|
-
####
|
|
63
|
-
- [ ] **Connected Components**: Find connected subgraphs
|
|
64
|
-
- [ ] **Strongly Connected Components**: Tarjan's algorithm for directed graphs
|
|
77
|
+
#### Node Operations
|
|
65
78
|
|
|
66
|
-
|
|
79
|
+
```typescript
|
|
80
|
+
// Add a node with optional data
|
|
81
|
+
graph.addNode(id: NodeId, data?: Record<string, unknown>): void
|
|
67
82
|
|
|
68
|
-
|
|
83
|
+
// Remove a node and all its edges
|
|
84
|
+
graph.removeNode(id: NodeId): boolean
|
|
85
|
+
|
|
86
|
+
// Check if a node exists
|
|
87
|
+
graph.hasNode(id: NodeId): boolean
|
|
88
|
+
|
|
89
|
+
// Get node details
|
|
90
|
+
graph.getNode(id: NodeId): Node | undefined
|
|
91
|
+
|
|
92
|
+
// Get all nodes
|
|
93
|
+
graph.nodes(): IterableIterator<Node>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
#### Edge Operations
|
|
69
97
|
|
|
70
98
|
```typescript
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
// Add an edge with optional weight and data
|
|
100
|
+
graph.addEdge(
|
|
101
|
+
source: NodeId,
|
|
102
|
+
target: NodeId,
|
|
103
|
+
weight?: number,
|
|
104
|
+
data?: Record<string, unknown>
|
|
105
|
+
): void
|
|
106
|
+
|
|
107
|
+
// Remove an edge
|
|
108
|
+
graph.removeEdge(source: NodeId, target: NodeId): boolean
|
|
109
|
+
|
|
110
|
+
// Check if an edge exists
|
|
111
|
+
graph.hasEdge(source: NodeId, target: NodeId): boolean
|
|
112
|
+
|
|
113
|
+
// Get edge details
|
|
114
|
+
graph.getEdge(source: NodeId, target: NodeId): Edge | undefined
|
|
115
|
+
|
|
116
|
+
// Get all edges
|
|
117
|
+
graph.edges(): IterableIterator<Edge>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### Graph Properties
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// Number of nodes
|
|
124
|
+
graph.nodeCount: number
|
|
125
|
+
|
|
126
|
+
// Total number of edges (counts both directions for undirected)
|
|
127
|
+
graph.totalEdgeCount: number
|
|
128
|
+
|
|
129
|
+
// Number of unique edges
|
|
130
|
+
graph.uniqueEdgeCount: number
|
|
131
|
+
|
|
132
|
+
// Check if graph is directed
|
|
133
|
+
graph.isDirected: boolean
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Degree Operations
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
// Total degree (in + out for directed)
|
|
140
|
+
graph.degree(nodeId: NodeId): number
|
|
141
|
+
|
|
142
|
+
// In-degree (directed graphs only)
|
|
143
|
+
graph.inDegree(nodeId: NodeId): number
|
|
144
|
+
|
|
145
|
+
// Out-degree
|
|
146
|
+
graph.outDegree(nodeId: NodeId): number
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### Neighbor Operations
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// Get neighboring nodes
|
|
153
|
+
graph.neighbors(nodeId: NodeId): IterableIterator<NodeId>
|
|
154
|
+
|
|
155
|
+
// Get incoming neighbors (directed graphs)
|
|
156
|
+
graph.inNeighbors(nodeId: NodeId): IterableIterator<NodeId>
|
|
157
|
+
|
|
158
|
+
// Get outgoing neighbors
|
|
159
|
+
graph.outNeighbors(nodeId: NodeId): IterableIterator<NodeId>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Utility Methods
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// Create a deep copy
|
|
166
|
+
graph.clone(): Graph
|
|
167
|
+
|
|
168
|
+
// Clear all nodes and edges
|
|
169
|
+
graph.clear(): void
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Traversal Algorithms
|
|
173
|
+
|
|
174
|
+
#### Breadth-First Search (BFS)
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { breadthFirstSearch, shortestPathBFS, singleSourceShortestPathBFS, isBipartite } from '@graphty/algorithms';
|
|
178
|
+
|
|
179
|
+
// Basic BFS traversal
|
|
180
|
+
const result = breadthFirstSearch(graph, startNode, {
|
|
181
|
+
maxDepth?: number, // Optional: limit traversal depth
|
|
182
|
+
visitCallback?: (node: NodeId, depth: number) => void
|
|
183
|
+
});
|
|
184
|
+
// Returns: TraversalResult { visited: Set<NodeId>, order: NodeId[], tree?: Map<NodeId, NodeId> }
|
|
185
|
+
|
|
186
|
+
// Find shortest path between two nodes (unweighted)
|
|
187
|
+
const path = shortestPathBFS(graph, source, target);
|
|
188
|
+
// Returns: NodeId[] | null
|
|
189
|
+
|
|
190
|
+
// Find all shortest paths from a source
|
|
191
|
+
const paths = singleSourceShortestPathBFS(graph, source);
|
|
192
|
+
// Returns: Map<NodeId, NodeId[]>
|
|
193
|
+
|
|
194
|
+
// Check if graph is bipartite
|
|
195
|
+
const bipartite = isBipartite(graph);
|
|
196
|
+
// Returns: { isBipartite: boolean, coloring?: Map<NodeId, number> }
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### Depth-First Search (DFS)
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import { depthFirstSearch, topologicalSort, hasCycleDFS, findStronglyConnectedComponents } from '@graphty/algorithms';
|
|
203
|
+
|
|
204
|
+
// Basic DFS traversal
|
|
205
|
+
const result = depthFirstSearch(graph, startNode, {
|
|
206
|
+
previsitCallback?: (node: NodeId) => void,
|
|
207
|
+
postvisitCallback?: (node: NodeId) => void
|
|
208
|
+
});
|
|
209
|
+
// Returns: TraversalResult
|
|
210
|
+
|
|
211
|
+
// Topological sort (for DAGs)
|
|
212
|
+
const sorted = topologicalSort(graph);
|
|
213
|
+
// Returns: NodeId[] | null (null if cycle detected)
|
|
214
|
+
|
|
215
|
+
// Cycle detection
|
|
216
|
+
const hasCycle = hasCycleDFS(graph);
|
|
217
|
+
// Returns: boolean
|
|
218
|
+
|
|
219
|
+
// Find strongly connected components using DFS
|
|
220
|
+
const sccs = findStronglyConnectedComponents(graph);
|
|
221
|
+
// Returns: NodeId[][]
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Shortest Path Algorithms
|
|
225
|
+
|
|
226
|
+
#### Dijkstra's Algorithm
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
import { dijkstra, dijkstraPath, singleSourceShortestPath, allPairsShortestPath } from '@graphty/algorithms';
|
|
230
|
+
|
|
231
|
+
// Single-source shortest paths
|
|
232
|
+
const result = dijkstra(graph, source, {
|
|
233
|
+
target?: NodeId // Optional: stop when target is reached
|
|
234
|
+
});
|
|
235
|
+
// Returns: Map<NodeId, ShortestPathResult>
|
|
236
|
+
// ShortestPathResult = { distance: number, path: NodeId[], predecessor: Map<NodeId, NodeId | null> }
|
|
237
|
+
|
|
238
|
+
// Get specific path
|
|
239
|
+
const path = dijkstraPath(graph, source, target);
|
|
240
|
+
// Returns: ShortestPathResult | null
|
|
241
|
+
|
|
242
|
+
// All shortest paths from source
|
|
243
|
+
const paths = singleSourceShortestPath(graph, source);
|
|
244
|
+
// Returns: Map<NodeId, ShortestPathResult>
|
|
245
|
+
|
|
246
|
+
// All pairs shortest paths
|
|
247
|
+
const allPairs = allPairsShortestPath(graph);
|
|
248
|
+
// Returns: Map<NodeId, Map<NodeId, ShortestPathResult>>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
#### Bellman-Ford Algorithm
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
import { bellmanFord, bellmanFordPath, hasNegativeCycle } from '@graphty/algorithms';
|
|
255
|
+
|
|
256
|
+
// Single-source shortest paths (handles negative weights)
|
|
257
|
+
const result = bellmanFord(graph, source);
|
|
258
|
+
// Returns: BellmanFordResult {
|
|
259
|
+
// distances: Map<NodeId, number>,
|
|
260
|
+
// predecessors: Map<NodeId, NodeId | null>,
|
|
261
|
+
// hasNegativeCycle: boolean,
|
|
262
|
+
// negativeCycleNodes?: Set<NodeId>
|
|
263
|
+
// }
|
|
264
|
+
|
|
265
|
+
// Get specific path
|
|
266
|
+
const path = bellmanFordPath(graph, source, target);
|
|
267
|
+
// Returns: ShortestPathResult | null
|
|
268
|
+
|
|
269
|
+
// Check for negative cycles
|
|
270
|
+
const result = hasNegativeCycle(graph);
|
|
271
|
+
// Returns: BellmanFordResult with hasNegativeCycle boolean
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
#### Floyd-Warshall Algorithm
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
import { floydWarshall, floydWarshallPath, transitiveClosure } from '@graphty/algorithms';
|
|
278
|
+
|
|
279
|
+
// All pairs shortest paths
|
|
280
|
+
const result = floydWarshall(graph);
|
|
281
|
+
// Returns: { distances: Map<NodeId, Map<NodeId, number>>, next: Map<NodeId, Map<NodeId, NodeId | null>> }
|
|
282
|
+
|
|
283
|
+
// Get specific path between any pair
|
|
284
|
+
const path = floydWarshallPath(result, source, target);
|
|
285
|
+
// Returns: NodeId[] | null
|
|
286
|
+
|
|
287
|
+
// Compute transitive closure
|
|
288
|
+
const closure = transitiveClosure(graph);
|
|
289
|
+
// Returns: Map<NodeId, Set<NodeId>>
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Centrality Algorithms
|
|
293
|
+
|
|
294
|
+
#### Degree Centrality
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
import { degreeCentrality, nodeDegreeCentrality } from '@graphty/algorithms';
|
|
298
|
+
|
|
299
|
+
// Calculate for all nodes
|
|
300
|
+
const centralities = degreeCentrality(graph, {
|
|
301
|
+
normalized?: boolean, // Default: false
|
|
302
|
+
weight?: string // Optional: edge property for weighted degree
|
|
303
|
+
});
|
|
304
|
+
// Returns: CentralityResult (Record<string, number>)
|
|
305
|
+
|
|
306
|
+
// Calculate for single node
|
|
307
|
+
const centrality = nodeDegreeCentrality(graph, nodeId, { normalized?: boolean });
|
|
308
|
+
// Returns: number
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
#### Betweenness Centrality
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
import { betweennessCentrality, nodeBetweennessCentrality, edgeBetweennessCentrality } from '@graphty/algorithms';
|
|
315
|
+
|
|
316
|
+
// Node betweenness for all nodes
|
|
317
|
+
const centralities = betweennessCentrality(graph, {
|
|
318
|
+
normalized?: boolean, // Default: false
|
|
319
|
+
weight?: string, // Optional: use weighted shortest paths
|
|
320
|
+
endpoints?: boolean // Default: false, include endpoints in paths
|
|
321
|
+
});
|
|
322
|
+
// Returns: CentralityResult (Record<string, number>)
|
|
323
|
+
|
|
324
|
+
// Single node betweenness
|
|
325
|
+
const centrality = nodeBetweennessCentrality(graph, nodeId, options);
|
|
326
|
+
// Returns: number
|
|
327
|
+
|
|
328
|
+
// Edge betweenness
|
|
329
|
+
const edgeCentralities = edgeBetweennessCentrality(graph, options);
|
|
330
|
+
// Returns: Map<string, number> (edge ID to centrality)
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
#### Closeness Centrality
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
import { closenessCentrality, nodeClosenessCentrality, weightedClosenessCentrality } from '@graphty/algorithms';
|
|
337
|
+
|
|
338
|
+
// Closeness for all nodes
|
|
339
|
+
const centralities = closenessCentrality(graph, {
|
|
340
|
+
normalized?: boolean // Default: false
|
|
341
|
+
});
|
|
342
|
+
// Returns: CentralityResult (Record<string, number>)
|
|
343
|
+
|
|
344
|
+
// Single node closeness
|
|
345
|
+
const centrality = nodeClosenessCentrality(graph, nodeId, { normalized?: boolean });
|
|
346
|
+
// Returns: number
|
|
347
|
+
|
|
348
|
+
// Weighted closeness
|
|
349
|
+
const centralities = weightedClosenessCentrality(graph, {
|
|
350
|
+
normalized?: boolean,
|
|
351
|
+
weight?: string // Edge property for weights
|
|
352
|
+
});
|
|
353
|
+
// Returns: CentralityResult (Record<string, number>)
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
#### PageRank
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
import { pageRank, personalizedPageRank, topPageRankNodes } from '@graphty/algorithms';
|
|
360
|
+
|
|
361
|
+
// Standard PageRank
|
|
362
|
+
const result = pageRank(graph, {
|
|
363
|
+
dampingFactor?: number, // Default: 0.85
|
|
364
|
+
maxIterations?: number, // Default: 100
|
|
365
|
+
tolerance?: number, // Default: 1e-6
|
|
366
|
+
initialRanks?: Record<string, number>,
|
|
367
|
+
personalization?: Record<string, number>
|
|
368
|
+
});
|
|
369
|
+
// Returns: { ranks: Record<string, number>, iterations: number, converged: boolean }
|
|
370
|
+
|
|
371
|
+
// Personalized PageRank (with bias)
|
|
372
|
+
const ranks = personalizedPageRank(graph, personalization, options);
|
|
373
|
+
// personalization: Map<NodeId, number> - restart probabilities
|
|
374
|
+
// Returns: CentralityResult (Record<string, number>)
|
|
375
|
+
|
|
376
|
+
// Get top N nodes by PageRank
|
|
377
|
+
const topNodes = topPageRankNodes(graph, n, options);
|
|
378
|
+
// Returns: Array<{ node: NodeId, rank: number }>
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
#### Eigenvector Centrality
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
import { eigenvectorCentrality, nodeEigenvectorCentrality } from '@graphty/algorithms';
|
|
385
|
+
|
|
386
|
+
// Calculate eigenvector centrality for all nodes
|
|
387
|
+
const centralities = eigenvectorCentrality(graph, {
|
|
388
|
+
maxIterations?: number, // Default: 100
|
|
389
|
+
tolerance?: number // Default: 1e-6
|
|
390
|
+
});
|
|
391
|
+
// Returns: CentralityResult (Record<string, number>)
|
|
392
|
+
|
|
393
|
+
// Single node eigenvector centrality
|
|
394
|
+
const centrality = nodeEigenvectorCentrality(graph, nodeId, options);
|
|
395
|
+
// Returns: number
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
#### Katz Centrality
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
import { katzCentrality, nodeKatzCentrality } from '@graphty/algorithms';
|
|
402
|
+
|
|
403
|
+
// Calculate Katz centrality for all nodes
|
|
404
|
+
const centralities = katzCentrality(graph, {
|
|
405
|
+
alpha?: number, // Attenuation factor (default: 0.1)
|
|
406
|
+
beta?: number, // Weight for direct connections (default: 1.0)
|
|
407
|
+
maxIterations?: number, // Default: 100
|
|
408
|
+
tolerance?: number, // Default: 1e-6
|
|
409
|
+
normalized?: boolean // Default: true
|
|
410
|
+
});
|
|
411
|
+
// Returns: CentralityResult (Record<string, number>)
|
|
412
|
+
|
|
413
|
+
// Single node Katz centrality
|
|
414
|
+
const centrality = nodeKatzCentrality(graph, nodeId, options);
|
|
415
|
+
// Returns: number
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
#### HITS Algorithm
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
import { hits, nodeHITS } from '@graphty/algorithms';
|
|
422
|
+
|
|
423
|
+
// Calculate hub and authority scores
|
|
424
|
+
const result = hits(graph, {
|
|
425
|
+
maxIterations?: number, // Default: 100
|
|
426
|
+
tolerance?: number // Default: 1e-6
|
|
427
|
+
});
|
|
428
|
+
// Returns: HITSResult { hubs: CentralityResult, authorities: CentralityResult }
|
|
429
|
+
|
|
430
|
+
// Single node HITS scores
|
|
431
|
+
const scores = nodeHITS(graph, nodeId, options);
|
|
432
|
+
// Returns: { hub: number, authority: number }
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Connected Components
|
|
436
|
+
|
|
437
|
+
#### Basic Component Operations
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
import {
|
|
441
|
+
connectedComponents,
|
|
442
|
+
isConnected,
|
|
443
|
+
numberOfConnectedComponents,
|
|
444
|
+
largestConnectedComponent,
|
|
445
|
+
getConnectedComponent
|
|
446
|
+
} from '@graphty/algorithms';
|
|
447
|
+
|
|
448
|
+
// Find all components
|
|
449
|
+
const components = connectedComponents(graph);
|
|
450
|
+
// Returns: NodeId[][] (array of component arrays)
|
|
451
|
+
|
|
452
|
+
// Check if graph is connected
|
|
453
|
+
const connected = isConnected(graph);
|
|
454
|
+
// Returns: boolean
|
|
455
|
+
|
|
456
|
+
// Count components
|
|
457
|
+
const count = numberOfConnectedComponents(graph);
|
|
458
|
+
// Returns: number
|
|
459
|
+
|
|
460
|
+
// Get largest component
|
|
461
|
+
const largest = largestConnectedComponent(graph);
|
|
462
|
+
// Returns: NodeId[]
|
|
463
|
+
|
|
464
|
+
// Get component containing a specific node
|
|
465
|
+
const component = getConnectedComponent(graph, nodeId);
|
|
466
|
+
// Returns: Set<NodeId>
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
#### Strongly Connected Components
|
|
470
|
+
|
|
471
|
+
```typescript
|
|
472
|
+
import {
|
|
473
|
+
stronglyConnectedComponents,
|
|
474
|
+
findStronglyConnectedComponents,
|
|
475
|
+
isStronglyConnected,
|
|
476
|
+
condensationGraph
|
|
477
|
+
} from '@graphty/algorithms';
|
|
478
|
+
|
|
479
|
+
// Find SCCs using Tarjan's algorithm
|
|
480
|
+
const sccs = stronglyConnectedComponents(graph);
|
|
481
|
+
// Returns: ComponentResult
|
|
482
|
+
|
|
483
|
+
// Alternative: using DFS
|
|
484
|
+
const sccs = findStronglyConnectedComponents(graph);
|
|
485
|
+
// Returns: NodeId[][]
|
|
486
|
+
|
|
487
|
+
// Check if directed graph is strongly connected
|
|
488
|
+
const stronglyConnected = isStronglyConnected(graph);
|
|
489
|
+
// Returns: boolean
|
|
490
|
+
|
|
491
|
+
// Create condensation graph (DAG of SCCs)
|
|
492
|
+
const condensation = condensationGraph(graph);
|
|
493
|
+
// Returns: { graph: Graph, componentMap: Map<NodeId, number> }
|
|
494
|
+
|
|
495
|
+
// Alternative DFS-based connected components
|
|
496
|
+
const components = connectedComponentsDFS(graph);
|
|
497
|
+
// Returns: ComponentResult
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
#### Weakly Connected Components
|
|
501
|
+
|
|
502
|
+
```typescript
|
|
503
|
+
import { weaklyConnectedComponents, isWeaklyConnected } from '@graphty/algorithms';
|
|
504
|
+
|
|
505
|
+
// Find WCCs (ignoring edge direction)
|
|
506
|
+
const wccs = weaklyConnectedComponents(graph);
|
|
507
|
+
// Returns: ComponentResult
|
|
508
|
+
|
|
509
|
+
// Check if directed graph is weakly connected
|
|
510
|
+
const weaklyConnected = isWeaklyConnected(graph);
|
|
511
|
+
// Returns: boolean
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### Data Structures
|
|
515
|
+
|
|
516
|
+
#### Priority Queue
|
|
517
|
+
|
|
518
|
+
Min-heap implementation used internally by algorithms.
|
|
519
|
+
|
|
520
|
+
```typescript
|
|
521
|
+
import { PriorityQueue } from '@graphty/algorithms';
|
|
522
|
+
|
|
523
|
+
const pq = new PriorityQueue<T>((a, b) => a.priority - b.priority);
|
|
524
|
+
|
|
525
|
+
pq.enqueue(item);
|
|
526
|
+
pq.dequeue();
|
|
527
|
+
pq.peek();
|
|
528
|
+
pq.isEmpty();
|
|
529
|
+
pq.size;
|
|
530
|
+
pq.clear();
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
#### Union-Find (Disjoint Set)
|
|
534
|
+
|
|
535
|
+
Efficient data structure for tracking connected components.
|
|
536
|
+
|
|
537
|
+
```typescript
|
|
538
|
+
import { UnionFind } from '@graphty/algorithms';
|
|
539
|
+
|
|
540
|
+
const uf = new UnionFind<T>();
|
|
541
|
+
|
|
542
|
+
uf.makeSet(item);
|
|
543
|
+
uf.find(item);
|
|
544
|
+
uf.union(item1, item2);
|
|
545
|
+
uf.connected(item1, item2);
|
|
546
|
+
uf.getSetSize(item);
|
|
547
|
+
uf.numberOfSets;
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
### Minimum Spanning Tree Algorithms
|
|
551
|
+
|
|
552
|
+
#### Kruskal's Algorithm
|
|
553
|
+
|
|
554
|
+
```typescript
|
|
555
|
+
import { kruskalMST, minimumSpanningTree } from '@graphty/algorithms';
|
|
556
|
+
|
|
557
|
+
// Find MST using Kruskal's algorithm
|
|
558
|
+
const mst = kruskalMST(graph);
|
|
559
|
+
// Returns: { edges: Edge[], weight: number }
|
|
560
|
+
|
|
561
|
+
// Alternative alias
|
|
562
|
+
const mst = minimumSpanningTree(graph);
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
#### Prim's Algorithm
|
|
566
|
+
|
|
567
|
+
```typescript
|
|
568
|
+
import { primMST } from '@graphty/algorithms';
|
|
569
|
+
|
|
570
|
+
// Find MST using Prim's algorithm
|
|
571
|
+
const mst = primMST(graph, startNode?);
|
|
572
|
+
// Returns: { edges: Edge[], weight: number }
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### Community Detection Algorithms
|
|
576
|
+
|
|
577
|
+
#### Louvain Method
|
|
578
|
+
|
|
579
|
+
```typescript
|
|
580
|
+
import { louvain } from '@graphty/algorithms';
|
|
581
|
+
|
|
582
|
+
// Detect communities using Louvain method
|
|
583
|
+
const communities = louvain(graph, {
|
|
584
|
+
resolution?: number, // Default: 1.0
|
|
585
|
+
randomSeed?: number
|
|
586
|
+
});
|
|
587
|
+
// Returns: { communities: Map<NodeId, number>, modularity: number }
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
#### Leiden Algorithm
|
|
591
|
+
|
|
592
|
+
```typescript
|
|
593
|
+
import { leiden } from '@graphty/algorithms';
|
|
594
|
+
|
|
595
|
+
// Improved community detection
|
|
596
|
+
const communities = leiden(graph, {
|
|
597
|
+
resolution?: number, // Default: 1.0
|
|
598
|
+
iterations?: number, // Default: 10
|
|
599
|
+
randomSeed?: number
|
|
600
|
+
});
|
|
601
|
+
// Returns: { communities: Map<NodeId, number>, modularity: number }
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
#### Label Propagation
|
|
605
|
+
|
|
606
|
+
```typescript
|
|
607
|
+
import { labelPropagation, labelPropagationAsync, labelPropagationSemiSupervised } from '@graphty/algorithms';
|
|
608
|
+
|
|
609
|
+
// Basic label propagation
|
|
610
|
+
const labels = labelPropagation(graph, {
|
|
611
|
+
maxIterations?: number // Default: 100
|
|
612
|
+
});
|
|
613
|
+
// Returns: Map<NodeId, number>
|
|
614
|
+
|
|
615
|
+
// Asynchronous version
|
|
616
|
+
const labels = labelPropagationAsync(graph, options);
|
|
617
|
+
|
|
618
|
+
// Semi-supervised with seed communities
|
|
619
|
+
const labels = labelPropagationSemiSupervised(graph, seedLabels, options);
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
#### Girvan-Newman Algorithm
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
import { girvanNewman } from '@graphty/algorithms';
|
|
626
|
+
|
|
627
|
+
// Edge betweenness based community detection
|
|
628
|
+
const dendrogram = girvanNewman(graph, {
|
|
629
|
+
targetCommunities?: number // Stop at this many communities
|
|
630
|
+
});
|
|
631
|
+
// Returns: { levels: Array<{ modularity: number, communities: NodeId[][] }> }
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
### Pathfinding Algorithms
|
|
635
|
+
|
|
636
|
+
#### A* Algorithm
|
|
637
|
+
|
|
638
|
+
```typescript
|
|
639
|
+
import { astar, astarWithDetails, heuristics } from '@graphty/algorithms';
|
|
640
|
+
|
|
641
|
+
// A* pathfinding with heuristic
|
|
642
|
+
const path = astar(graph, start, goal, {
|
|
643
|
+
heuristic: heuristics.euclidean, // or manhattan, chebyshev, zero
|
|
644
|
+
weight?: (edge: Edge) => number
|
|
645
|
+
});
|
|
646
|
+
// Returns: { path: NodeId[], cost: number } | null
|
|
647
|
+
|
|
648
|
+
// A* with search details
|
|
649
|
+
const result = astarWithDetails(graph, start, goal, options);
|
|
650
|
+
// Returns: { path: NodeId[], cost: number, explored: Set<NodeId>, parent: Map<NodeId, NodeId> } | null
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
### Flow Algorithms
|
|
654
|
+
|
|
655
|
+
#### Maximum Flow
|
|
656
|
+
|
|
657
|
+
```typescript
|
|
658
|
+
import { fordFulkerson, edmondsKarp } from '@graphty/algorithms';
|
|
659
|
+
|
|
660
|
+
// Ford-Fulkerson using DFS
|
|
661
|
+
const flow = fordFulkerson(graph, source, sink, {
|
|
662
|
+
capacityKey?: string // Edge property for capacity
|
|
663
|
+
});
|
|
664
|
+
// Returns: { maxFlow: number, flowGraph: Map<NodeId, Map<NodeId, number>> }
|
|
665
|
+
|
|
666
|
+
// Edmonds-Karp using BFS (better complexity)
|
|
667
|
+
const flow = edmondsKarp(graph, source, sink, options);
|
|
668
|
+
|
|
669
|
+
// Create bipartite flow network
|
|
670
|
+
const flowNetwork = createBipartiteFlowNetwork(leftNodes, rightNodes, edges, capacities?);
|
|
671
|
+
// Returns: FlowNetwork
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
#### Minimum Cut
|
|
675
|
+
|
|
676
|
+
```typescript
|
|
677
|
+
import { minSTCut, stoerWagner, kargerMinCut } from '@graphty/algorithms';
|
|
678
|
+
|
|
679
|
+
// Min s-t cut using max flow
|
|
680
|
+
const cut = minSTCut(graph, source, sink);
|
|
681
|
+
// Returns: { cutValue: number, sourcePartition: Set<NodeId>, sinkPartition: Set<NodeId> }
|
|
682
|
+
|
|
683
|
+
// Global minimum cut (Stoer-Wagner)
|
|
684
|
+
const cut = stoerWagner(graph);
|
|
685
|
+
// Returns: { cutValue: number, partition1: Set<NodeId>, partition2: Set<NodeId> }
|
|
686
|
+
|
|
687
|
+
// Randomized min cut (Karger)
|
|
688
|
+
const cut = kargerMinCut(graph, iterations?);
|
|
689
|
+
// Returns: { cutValue: number, partition1: Set<NodeId>, partition2: Set<NodeId> }
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
### Clustering Algorithms
|
|
693
|
+
|
|
694
|
+
#### Hierarchical Clustering
|
|
695
|
+
|
|
696
|
+
```typescript
|
|
697
|
+
import { hierarchicalClustering, cutDendrogram, cutDendrogramKClusters } from '@graphty/algorithms';
|
|
698
|
+
|
|
699
|
+
// Agglomerative clustering
|
|
700
|
+
const result = hierarchicalClustering(graph, linkage);
|
|
701
|
+
// graph: Map<NodeId, Set<NodeId>>
|
|
702
|
+
// linkage: 'single' | 'complete' | 'average' | 'ward' (default: 'single')
|
|
703
|
+
// Returns: HierarchicalClusteringResult { root: ClusterNode, dendrogram: ClusterNode[], clusters: Map<number, Set<NodeId>[]> }
|
|
704
|
+
|
|
705
|
+
// Cut at specific height
|
|
706
|
+
const clusters = cutDendrogram(result.root, height);
|
|
707
|
+
// Returns: Set<NodeId>[]
|
|
708
|
+
|
|
709
|
+
// Get exactly k clusters
|
|
710
|
+
const clusters = cutDendrogramKClusters(result.root, k);
|
|
711
|
+
// Returns: Set<NodeId>[]
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
#### K-Core Decomposition
|
|
715
|
+
|
|
716
|
+
```typescript
|
|
717
|
+
import { kCoreDecomposition, getKCore, kTruss, degeneracyOrdering } from '@graphty/algorithms';
|
|
718
|
+
|
|
719
|
+
// Find all k-cores
|
|
720
|
+
const result = kCoreDecomposition(graph);
|
|
721
|
+
// graph: Map<NodeId, Set<NodeId>>
|
|
722
|
+
// Returns: KCoreResult { cores: Map<number, Set<NodeId>>, coreness: Map<NodeId, number>, maxCore: number }
|
|
723
|
+
|
|
724
|
+
// Extract specific k-core subgraph
|
|
725
|
+
const kCore = getKCore(graph, k);
|
|
726
|
+
// Returns: Set<NodeId>
|
|
727
|
+
|
|
728
|
+
// Find k-truss (triangular cores)
|
|
729
|
+
const truss = kTruss(graph, k);
|
|
730
|
+
// Returns: Set<string> (edge strings)
|
|
731
|
+
|
|
732
|
+
// Degeneracy ordering
|
|
733
|
+
const ordering = degeneracyOrdering(graph);
|
|
734
|
+
// Returns: NodeId[]
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
#### Spectral Clustering
|
|
738
|
+
|
|
739
|
+
```typescript
|
|
740
|
+
import { spectralClustering } from '@graphty/algorithms';
|
|
741
|
+
|
|
742
|
+
// Spectral clustering using graph Laplacian
|
|
743
|
+
const result = spectralClustering(graph, {
|
|
744
|
+
k: number, // Number of clusters
|
|
745
|
+
laplacianType?: 'unnormalized' | 'normalized' | 'randomWalk', // Default: 'normalized'
|
|
746
|
+
maxIterations?: number, // Default: 100
|
|
747
|
+
tolerance?: number // Default: 1e-4
|
|
748
|
+
});
|
|
749
|
+
// Returns: SpectralClusteringResult { communities: NodeId[][], clusterAssignments: Map<NodeId, number> }
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
#### Markov Clustering (MCL)
|
|
753
|
+
|
|
754
|
+
```typescript
|
|
755
|
+
import { markovClustering } from '@graphty/algorithms';
|
|
756
|
+
|
|
757
|
+
// MCL algorithm for network clustering
|
|
758
|
+
const result = markovClustering(graph, {
|
|
759
|
+
expansion?: number, // Expansion parameter (default: 2)
|
|
760
|
+
inflation?: number, // Inflation parameter (default: 2)
|
|
761
|
+
maxIterations?: number, // Default: 100
|
|
762
|
+
tolerance?: number // Default: 1e-6
|
|
763
|
+
});
|
|
764
|
+
// Returns: MCLResult { communities: NodeId[][], attractors: Set<NodeId>, iterations: number, converged: boolean }
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
### Matching Algorithms
|
|
768
|
+
|
|
769
|
+
#### Bipartite Matching
|
|
770
|
+
|
|
771
|
+
```typescript
|
|
772
|
+
import { maximumBipartiteMatching, greedyBipartiteMatching, bipartitePartition } from '@graphty/algorithms';
|
|
773
|
+
|
|
774
|
+
// Maximum bipartite matching (Hungarian algorithm)
|
|
775
|
+
const matching = maximumBipartiteMatching(graph, {
|
|
776
|
+
leftNodes?: Set<NodeId>, // Optional: specify left partition
|
|
777
|
+
rightNodes?: Set<NodeId>, // Optional: specify right partition
|
|
778
|
+
});
|
|
779
|
+
// Returns: BipartiteMatchingResult { matching: Map<NodeId, NodeId>, size: number }
|
|
780
|
+
|
|
781
|
+
// Greedy bipartite matching (faster, approximate)
|
|
782
|
+
const matching = greedyBipartiteMatching(graph, options);
|
|
783
|
+
|
|
784
|
+
// Partition graph into bipartite sets
|
|
785
|
+
const partition = bipartitePartition(graph);
|
|
786
|
+
// Returns: { left: Set<NodeId>, right: Set<NodeId> } | null
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
#### Graph Isomorphism
|
|
790
|
+
|
|
791
|
+
```typescript
|
|
792
|
+
import { isGraphIsomorphic, findAllIsomorphisms } from '@graphty/algorithms';
|
|
793
|
+
|
|
794
|
+
// Check if two graphs are isomorphic
|
|
795
|
+
const result = isGraphIsomorphic(graph1, graph2, {
|
|
796
|
+
nodeMatch?: (node1: NodeId, node2: NodeId, g1: Graph, g2: Graph) => boolean,
|
|
797
|
+
edgeMatch?: (edge1: [NodeId, NodeId], edge2: [NodeId, NodeId], g1: Graph, g2: Graph) => boolean,
|
|
798
|
+
findAllMappings?: boolean // Find all possible isomorphisms
|
|
799
|
+
});
|
|
800
|
+
// Returns: IsomorphismResult { isIsomorphic: boolean, mapping?: Map<NodeId, NodeId> }
|
|
801
|
+
|
|
802
|
+
// Find all isomorphism mappings
|
|
803
|
+
const mappings = findAllIsomorphisms(graph1, graph2, options);
|
|
804
|
+
// Returns: Array<Map<NodeId, NodeId>>
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
### Link Prediction Algorithms
|
|
808
|
+
|
|
809
|
+
#### Common Neighbors
|
|
810
|
+
|
|
811
|
+
```typescript
|
|
812
|
+
import { commonNeighborsScore, commonNeighborsPrediction, commonNeighborsForPairs } from '@graphty/algorithms';
|
|
813
|
+
|
|
814
|
+
// Score for a specific pair
|
|
815
|
+
const score = commonNeighborsScore(graph, node1, node2);
|
|
816
|
+
// Returns: number
|
|
817
|
+
|
|
818
|
+
// Predict links for all non-connected pairs
|
|
819
|
+
const predictions = commonNeighborsPrediction(graph, {
|
|
820
|
+
directed?: boolean, // Consider direction
|
|
821
|
+
includeExisting?: boolean, // Include existing edges
|
|
822
|
+
topK?: number // Return only top K predictions
|
|
823
|
+
});
|
|
824
|
+
// Returns: LinkPredictionScore[]
|
|
825
|
+
|
|
826
|
+
// Score multiple specific pairs
|
|
827
|
+
const scores = commonNeighborsForPairs(graph, pairs, options);
|
|
828
|
+
// Returns: LinkPredictionScore[]
|
|
829
|
+
|
|
830
|
+
// Evaluate prediction performance
|
|
831
|
+
const evaluation = evaluateCommonNeighbors(graph, testEdges);
|
|
832
|
+
// Returns: { precision, recall, f1Score }
|
|
833
|
+
|
|
834
|
+
// Get top candidates for a node
|
|
835
|
+
const candidates = getTopCandidatesForNode(graph, nodeId, { topK?: number });
|
|
836
|
+
// Returns: LinkPredictionScore[]
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
#### Adamic-Adar Index
|
|
840
|
+
|
|
841
|
+
```typescript
|
|
842
|
+
import { adamicAdarScore, adamicAdarPrediction, adamicAdarForPairs } from '@graphty/algorithms';
|
|
843
|
+
|
|
844
|
+
// Adamic-Adar score for a pair (weighted by neighbor degrees)
|
|
845
|
+
const score = adamicAdarScore(graph, node1, node2);
|
|
846
|
+
// Returns: number
|
|
847
|
+
|
|
848
|
+
// Predict links using Adamic-Adar
|
|
849
|
+
const predictions = adamicAdarPrediction(graph, {
|
|
850
|
+
directed?: boolean,
|
|
851
|
+
includeExisting?: boolean,
|
|
852
|
+
topK?: number
|
|
853
|
+
});
|
|
854
|
+
// Returns: LinkPredictionScore[]
|
|
855
|
+
|
|
856
|
+
// Score multiple pairs
|
|
857
|
+
const scores = adamicAdarForPairs(graph, pairs, options);
|
|
858
|
+
// Returns: LinkPredictionScore[]
|
|
859
|
+
|
|
860
|
+
// Compare Adamic-Adar with Common Neighbors
|
|
861
|
+
const comparison = compareAdamicAdarWithCommonNeighbors(graph, pairs);
|
|
862
|
+
// Returns: Array<{ source, target, adamicAdar, commonNeighbors }>
|
|
863
|
+
|
|
864
|
+
// Evaluate prediction performance
|
|
865
|
+
const evaluation = evaluateAdamicAdar(graph, testEdges);
|
|
866
|
+
// Returns: { precision, recall, f1Score }
|
|
867
|
+
|
|
868
|
+
// Get top candidates for a node
|
|
869
|
+
const candidates = getTopAdamicAdarCandidatesForNode(graph, nodeId, { topK?: number });
|
|
870
|
+
// Returns: LinkPredictionScore[]
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
### Research Algorithms (2023-2025)
|
|
874
|
+
|
|
875
|
+
Cutting-edge graph algorithms based on recent research.
|
|
876
|
+
|
|
877
|
+
#### SynC - Synergistic Deep Graph Clustering
|
|
878
|
+
|
|
879
|
+
```typescript
|
|
880
|
+
import { syncClustering } from '@graphty/algorithms';
|
|
881
|
+
|
|
882
|
+
// Deep learning based clustering
|
|
883
|
+
const result = syncClustering(graph, {
|
|
884
|
+
k: number, // Number of clusters
|
|
885
|
+
maxIterations?: number, // Default: 100
|
|
886
|
+
learningRate?: number, // Default: 0.01
|
|
887
|
+
hiddenDim?: number, // Default: 64
|
|
888
|
+
randomSeed?: number
|
|
889
|
+
});
|
|
890
|
+
// Returns: SynCResult {
|
|
891
|
+
// communities: NodeId[][],
|
|
892
|
+
// clusterAssignments: Map<NodeId, number>,
|
|
893
|
+
// embeddings: Map<NodeId, number[]>,
|
|
894
|
+
// iterations: number,
|
|
895
|
+
// converged: boolean
|
|
896
|
+
// }
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
#### TeraHAC - Scalable Hierarchical Agglomerative Clustering
|
|
900
|
+
|
|
901
|
+
```typescript
|
|
902
|
+
import { teraHAC } from '@graphty/algorithms';
|
|
903
|
+
|
|
904
|
+
// Scalable hierarchical clustering
|
|
905
|
+
const result = teraHAC(graph, {
|
|
906
|
+
linkage?: 'single' | 'complete' | 'average', // Default: 'average'
|
|
907
|
+
k?: number, // Target number of clusters
|
|
908
|
+
threshold?: number, // Distance threshold for merging
|
|
909
|
+
sampleSize?: number, // Default: 1000
|
|
910
|
+
randomSeed?: number
|
|
911
|
+
});
|
|
912
|
+
// Returns: TeraHACResult {
|
|
913
|
+
// root: TeraHACClusterNode,
|
|
914
|
+
// dendrogram: TeraHACClusterNode[],
|
|
915
|
+
// clusters: NodeId[][],
|
|
916
|
+
// mergeDistances: number[]
|
|
917
|
+
// }
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
#### GRSBM - Greedy Recursive Spectral Bisection with Modularity
|
|
921
|
+
|
|
922
|
+
```typescript
|
|
923
|
+
import { grsbm } from '@graphty/algorithms';
|
|
924
|
+
|
|
925
|
+
// Explainable community detection
|
|
926
|
+
const result = grsbm(graph, {
|
|
927
|
+
minClusterSize?: number, // Default: 5
|
|
928
|
+
maxDepth?: number, // Default: 10
|
|
929
|
+
modularityThreshold?: number, // Default: 0.1
|
|
930
|
+
explainClusters?: boolean // Default: true
|
|
931
|
+
});
|
|
932
|
+
// Returns: GRSBMResult {
|
|
933
|
+
// clusters: GRSBMCluster[], // Each cluster has id, nodes, modularity, explanation
|
|
934
|
+
// hierarchy: Map<number, number[]>,
|
|
935
|
+
// totalModularity: number
|
|
936
|
+
// }
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
## Algorithm Categories Summary
|
|
940
|
+
|
|
941
|
+
### Available Algorithms by Category:
|
|
942
|
+
|
|
943
|
+
- **Traversal**: BFS, DFS, Topological Sort, Cycle Detection, Bipartite Check
|
|
944
|
+
- **Shortest Path**: Dijkstra, Bellman-Ford, Floyd-Warshall, A*
|
|
945
|
+
- **Centrality**: Degree, Betweenness, Closeness, PageRank, Eigenvector, Katz, HITS
|
|
946
|
+
- **Components**: Connected, Strongly Connected, Weakly Connected, Condensation Graph
|
|
947
|
+
- **Community Detection**: Louvain, Leiden, Label Propagation, Girvan-Newman
|
|
948
|
+
- **Clustering**: Hierarchical, K-Core, Spectral, Markov (MCL)
|
|
949
|
+
- **Minimum Spanning Tree**: Kruskal, Prim
|
|
950
|
+
- **Network Flow**: Ford-Fulkerson, Edmonds-Karp, Min-Cut (Stoer-Wagner, Karger)
|
|
951
|
+
- **Matching**: Bipartite Matching, Graph Isomorphism
|
|
952
|
+
- **Link Prediction**: Common Neighbors, Adamic-Adar
|
|
953
|
+
- **Research Algorithms**: SynC, TeraHAC, GRSBM
|
|
954
|
+
|
|
955
|
+
## Examples
|
|
956
|
+
|
|
957
|
+
The library includes comprehensive examples demonstrating each algorithm. Find them in the [examples directory](https://github.com/graphty-org/algorithms/tree/main/examples):
|
|
958
|
+
|
|
959
|
+
### Basic Algorithms
|
|
960
|
+
- [BFS Traversal](https://github.com/graphty-org/algorithms/blob/main/examples/bfs-example.js) - Breadth-first search and shortest paths
|
|
961
|
+
- [DFS Traversal](https://github.com/graphty-org/algorithms/blob/main/examples/dfs-example.js) - Depth-first search and applications
|
|
962
|
+
- [Dijkstra's Algorithm](https://github.com/graphty-org/algorithms/blob/main/examples/dijkstra-example.js) - Weighted shortest paths
|
|
963
|
+
- [Bellman-Ford](https://github.com/graphty-org/algorithms/blob/main/examples/bellman-ford-example.js) - Shortest paths with negative weights
|
|
964
|
+
- [Floyd-Warshall](https://github.com/graphty-org/algorithms/blob/main/examples/floyd-warshall-example.js) - All pairs shortest paths
|
|
965
|
+
|
|
966
|
+
### Centrality Measures
|
|
967
|
+
- [Degree Centrality](https://github.com/graphty-org/algorithms/blob/main/examples/degree-centrality-example.js) - Node importance by connections
|
|
968
|
+
- [Betweenness Centrality](https://github.com/graphty-org/algorithms/blob/main/examples/betweenness-centrality-example.js) - Bridge nodes
|
|
969
|
+
- [Closeness Centrality](https://github.com/graphty-org/algorithms/blob/main/examples/closeness-centrality-example.js) - Central nodes
|
|
970
|
+
- [PageRank](https://github.com/graphty-org/algorithms/blob/main/examples/pagerank-example.js) - Node ranking algorithm
|
|
971
|
+
- [Eigenvector Centrality](https://github.com/graphty-org/algorithms/blob/main/examples/eigenvector-centrality-example.js) - Influence from important nodes
|
|
972
|
+
- [Katz Centrality](https://github.com/graphty-org/algorithms/blob/main/examples/katz-centrality-example.js) - Weighted path counting
|
|
973
|
+
- [HITS Algorithm](https://github.com/graphty-org/algorithms/blob/main/examples/hits-algorithm-example.js) - Hub and authority scores
|
|
974
|
+
|
|
975
|
+
### Graph Structure
|
|
976
|
+
- [Connected Components](https://github.com/graphty-org/algorithms/blob/main/examples/connected-components-example.js) - Find graph components
|
|
977
|
+
- [Kruskal's MST](https://github.com/graphty-org/algorithms/blob/main/examples/kruskal-example.js) - Minimum spanning tree
|
|
978
|
+
- [Prim's MST](https://github.com/graphty-org/algorithms/blob/main/examples/prim-example.js) - Alternative MST algorithm
|
|
979
|
+
|
|
980
|
+
### Community Detection
|
|
981
|
+
- [Louvain Method](https://github.com/graphty-org/algorithms/blob/main/examples/louvain-example.js) - Modularity-based communities
|
|
982
|
+
- [Leiden Algorithm](https://github.com/graphty-org/algorithms/blob/main/examples/leiden-community.ts) - Improved Louvain
|
|
983
|
+
- [Label Propagation](https://github.com/graphty-org/algorithms/blob/main/examples/label-propagation.ts) - Fast community detection
|
|
984
|
+
- [Girvan-Newman](https://github.com/graphty-org/algorithms/blob/main/examples/girvan-newman-example.js) - Hierarchical communities
|
|
985
|
+
|
|
986
|
+
### Clustering
|
|
987
|
+
- [Hierarchical Clustering](https://github.com/graphty-org/algorithms/blob/main/examples/hierarchical-clustering.ts) - Graph clustering
|
|
988
|
+
- [K-Core Decomposition](https://github.com/graphty-org/algorithms/blob/main/examples/k-core-decomposition.ts) - Core analysis
|
|
989
|
+
- [Spectral Clustering](https://github.com/graphty-org/algorithms/blob/main/examples/spectral-clustering-example.js) - Eigenvalue-based clustering
|
|
990
|
+
- [MCL Clustering](https://github.com/graphty-org/algorithms/blob/main/examples/mcl-clustering-example.js) - Markov clustering
|
|
991
|
+
|
|
992
|
+
### Matching
|
|
993
|
+
- [Bipartite Matching](https://github.com/graphty-org/algorithms/blob/main/examples/bipartite-matching-example.js) - Job assignment, dating apps
|
|
994
|
+
- [Graph Isomorphism](https://github.com/graphty-org/algorithms/blob/main/examples/graph-isomorphism-example.js) - Structural equivalence
|
|
995
|
+
|
|
996
|
+
### Link Prediction
|
|
997
|
+
- [Common Neighbors](https://github.com/graphty-org/algorithms/blob/main/examples/common-neighbors-example.js) - Friend suggestions
|
|
998
|
+
- [Adamic-Adar](https://github.com/graphty-org/algorithms/blob/main/examples/adamic-adar-example.js) - Weighted predictions
|
|
999
|
+
|
|
1000
|
+
### Advanced Algorithms
|
|
1001
|
+
- [A* Pathfinding](https://github.com/graphty-org/algorithms/blob/main/examples/astar-pathfinding.ts) - Heuristic pathfinding
|
|
1002
|
+
- [Flow Algorithms](https://github.com/graphty-org/algorithms/blob/main/examples/flow-algorithms.ts) - Maximum flow and applications
|
|
1003
|
+
- [Ford-Fulkerson Flow](https://github.com/graphty-org/algorithms/blob/main/examples/ford-fulkerson-flow.ts) - Maximum flow implementation
|
|
1004
|
+
- [Minimum Cut](https://github.com/graphty-org/algorithms/blob/main/examples/min-cut.ts) - Graph partitioning
|
|
1005
|
+
|
|
1006
|
+
### Research Algorithms
|
|
1007
|
+
- [SynC Clustering](https://github.com/graphty-org/algorithms/blob/main/examples/sync-example.js) - Deep learning based clustering
|
|
1008
|
+
- [TeraHAC](https://github.com/graphty-org/algorithms/blob/main/examples/terahac-example.js) - Scalable hierarchical clustering
|
|
1009
|
+
- [GRSBM](https://github.com/graphty-org/algorithms/blob/main/examples/grsbm-example.js) - Explainable community detection
|
|
1010
|
+
|
|
1011
|
+
## Advanced Usage Examples
|
|
1012
|
+
|
|
1013
|
+
### Working with Weighted Graphs
|
|
1014
|
+
|
|
1015
|
+
```typescript
|
|
1016
|
+
const graph = new Graph();
|
|
1017
|
+
|
|
1018
|
+
// Add weighted edges
|
|
1019
|
+
graph.addEdge('A', 'B', 5);
|
|
1020
|
+
graph.addEdge('B', 'C', 3);
|
|
1021
|
+
graph.addEdge('A', 'C', 10);
|
|
1022
|
+
|
|
1023
|
+
// Find shortest path considering weights
|
|
1024
|
+
const result = dijkstra(graph, 'A');
|
|
1025
|
+
const pathToC = dijkstraPath(graph, 'A', 'C');
|
|
1026
|
+
console.log(pathToC); // { path: ['A', 'B', 'C'], distance: 8 }
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
### Directed Graphs
|
|
1030
|
+
|
|
1031
|
+
```typescript
|
|
1032
|
+
const directedGraph = new Graph({ directed: true });
|
|
1033
|
+
|
|
1034
|
+
directedGraph.addEdge('A', 'B');
|
|
1035
|
+
directedGraph.addEdge('B', 'C');
|
|
1036
|
+
directedGraph.addEdge('C', 'A');
|
|
1037
|
+
|
|
1038
|
+
// Check for cycles
|
|
1039
|
+
console.log(hasCycleDFS(directedGraph)); // true
|
|
1040
|
+
|
|
1041
|
+
// Find strongly connected components
|
|
1042
|
+
const sccs = stronglyConnectedComponents(directedGraph);
|
|
1043
|
+
console.log(sccs.components); // [['A', 'B', 'C']]
|
|
1044
|
+
```
|
|
1045
|
+
|
|
1046
|
+
### Network Analysis
|
|
1047
|
+
|
|
1048
|
+
```typescript
|
|
1049
|
+
// Identify important nodes
|
|
1050
|
+
const graph = createSocialNetwork(); // Your graph
|
|
1051
|
+
|
|
1052
|
+
// Find influencers (high PageRank)
|
|
1053
|
+
const influencers = topPageRankNodes(graph, 10);
|
|
1054
|
+
|
|
1055
|
+
// Find bridges (high betweenness)
|
|
1056
|
+
const bridgers = Array.from(betweennessCentrality(graph).entries())
|
|
1057
|
+
.sort((a, b) => b[1] - a[1])
|
|
1058
|
+
.slice(0, 10);
|
|
1059
|
+
|
|
1060
|
+
// Find communities (connected components)
|
|
1061
|
+
const communities = connectedComponents(graph);
|
|
1062
|
+
console.log(`Found ${communities.components.length} communities`);
|
|
1063
|
+
```
|
|
1064
|
+
|
|
1065
|
+
### Custom Edge Properties
|
|
1066
|
+
|
|
1067
|
+
```typescript
|
|
1068
|
+
const graph = new Graph();
|
|
1069
|
+
|
|
1070
|
+
// Add edges with custom data
|
|
1071
|
+
graph.addEdge('A', 'B', 1, {
|
|
1072
|
+
type: 'road',
|
|
1073
|
+
distance: 100,
|
|
1074
|
+
traffic: 'heavy'
|
|
1075
|
+
});
|
|
1076
|
+
|
|
1077
|
+
// Use custom weight in algorithms
|
|
1078
|
+
const result = dijkstra(graph, 'A', {
|
|
1079
|
+
weightKey: 'distance' // Use 'distance' property as weight
|
|
1080
|
+
});
|
|
1081
|
+
```
|
|
1082
|
+
|
|
1083
|
+
### Graph Visualization Preparation
|
|
1084
|
+
|
|
1085
|
+
```typescript
|
|
1086
|
+
// Prepare data for visualization
|
|
1087
|
+
const graph = loadGraph();
|
|
1088
|
+
|
|
1089
|
+
// Calculate layout metrics
|
|
1090
|
+
const centralities = degreeCentrality(graph, { normalized: true });
|
|
1091
|
+
const ranks = pageRank(graph);
|
|
1092
|
+
|
|
1093
|
+
// Export for visualization
|
|
1094
|
+
const nodes = Array.from(graph.nodes()).map(node => ({
|
|
1095
|
+
id: node.id,
|
|
1096
|
+
data: node.data,
|
|
1097
|
+
size: centralities.get(node.id) || 0,
|
|
1098
|
+
importance: ranks.get(node.id) || 0
|
|
1099
|
+
}));
|
|
1100
|
+
|
|
1101
|
+
const edges = Array.from(graph.edges()).map(edge => ({
|
|
1102
|
+
source: edge.source,
|
|
1103
|
+
target: edge.target,
|
|
1104
|
+
weight: edge.weight || 1,
|
|
1105
|
+
data: edge.data
|
|
1106
|
+
}));
|
|
1107
|
+
```
|
|
1108
|
+
|
|
1109
|
+
## Type Definitions
|
|
1110
|
+
|
|
1111
|
+
### Core Types
|
|
1112
|
+
|
|
1113
|
+
```typescript
|
|
1114
|
+
type NodeId = string | number;
|
|
1115
|
+
|
|
1116
|
+
interface Node {
|
|
1117
|
+
id: NodeId;
|
|
1118
|
+
data?: Record<string, unknown>;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
interface Edge {
|
|
1122
|
+
source: NodeId;
|
|
1123
|
+
target: NodeId;
|
|
1124
|
+
weight?: number;
|
|
1125
|
+
id?: string;
|
|
1126
|
+
data?: Record<string, unknown>;
|
|
1127
|
+
}
|
|
1128
|
+
```
|
|
1129
|
+
|
|
1130
|
+
### Algorithm Result Types
|
|
1131
|
+
|
|
1132
|
+
```typescript
|
|
1133
|
+
interface TraversalResult {
|
|
1134
|
+
visited: Set<NodeId>;
|
|
1135
|
+
order: NodeId[];
|
|
1136
|
+
tree?: Map<NodeId, NodeId>;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
interface ShortestPathResult {
|
|
1140
|
+
path: NodeId[];
|
|
1141
|
+
distance: number;
|
|
1142
|
+
predecessor: NodeId | null;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
interface BellmanFordResult {
|
|
1146
|
+
distances: Map<NodeId, number>;
|
|
1147
|
+
predecessors: Map<NodeId, NodeId | null>;
|
|
1148
|
+
hasNegativeCycle: boolean;
|
|
1149
|
+
negativeCycleNodes?: Set<NodeId>;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
type CentralityResult = Record<string, number>;
|
|
1153
|
+
|
|
1154
|
+
interface PageRankResult {
|
|
1155
|
+
ranks: Record<string, number>;
|
|
1156
|
+
iterations: number;
|
|
1157
|
+
converged: boolean;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
interface CommunityResult {
|
|
1161
|
+
communities: Map<NodeId, number>;
|
|
1162
|
+
modularity: number;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
interface ComponentResult {
|
|
1166
|
+
components: NodeId[][];
|
|
1167
|
+
componentMap: Map<NodeId, number>;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
interface HITSResult {
|
|
1171
|
+
hubs: CentralityResult;
|
|
1172
|
+
authorities: CentralityResult;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
interface SpectralClusteringResult {
|
|
1176
|
+
communities: NodeId[][];
|
|
1177
|
+
clusterAssignments: Map<NodeId, number>;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
interface MCLResult {
|
|
1181
|
+
communities: NodeId[][];
|
|
1182
|
+
attractors: Set<NodeId>;
|
|
1183
|
+
iterations: number;
|
|
1184
|
+
converged: boolean;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
interface BipartiteMatchingResult {
|
|
1188
|
+
matching: Map<NodeId, NodeId>;
|
|
1189
|
+
size: number;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
interface LinkPredictionScore {
|
|
1193
|
+
source: NodeId;
|
|
1194
|
+
target: NodeId;
|
|
1195
|
+
score: number;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
interface HierarchicalClusteringResult<T> {
|
|
1199
|
+
root: ClusterNode<T>;
|
|
1200
|
+
dendrogram: ClusterNode<T>[];
|
|
1201
|
+
clusters: Map<number, Set<T>[]>;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
interface KCoreResult<T> {
|
|
1205
|
+
cores: Map<number, Set<T>>;
|
|
1206
|
+
coreness: Map<T, number>;
|
|
1207
|
+
maxCore: number;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
interface IsomorphismResult {
|
|
1211
|
+
isIsomorphic: boolean;
|
|
1212
|
+
mapping?: Map<NodeId, NodeId>;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
interface SynCResult {
|
|
1216
|
+
communities: NodeId[][];
|
|
1217
|
+
clusterAssignments: Map<NodeId, number>;
|
|
1218
|
+
embeddings: Map<NodeId, number[]>;
|
|
1219
|
+
iterations: number;
|
|
1220
|
+
converged: boolean;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
interface TeraHACResult {
|
|
1224
|
+
root: TeraHACClusterNode;
|
|
1225
|
+
dendrogram: TeraHACClusterNode[];
|
|
1226
|
+
clusters: NodeId[][];
|
|
1227
|
+
mergeDistances: number[];
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
interface GRSBMResult {
|
|
1231
|
+
clusters: GRSBMCluster[];
|
|
1232
|
+
hierarchy: Map<number, number[]>;
|
|
1233
|
+
totalModularity: number;
|
|
103
1234
|
}
|
|
104
1235
|
```
|
|
105
1236
|
|
|
1237
|
+
## Performance Considerations
|
|
1238
|
+
|
|
1239
|
+
- **Graph Representation**: Uses adjacency lists for O(1) neighbor access
|
|
1240
|
+
- **Algorithm Complexity**:
|
|
1241
|
+
- BFS/DFS: O(V + E)
|
|
1242
|
+
- Dijkstra: O((V + E) log V) with binary heap
|
|
1243
|
+
- Bellman-Ford: O(VE)
|
|
1244
|
+
- Floyd-Warshall: O(V³)
|
|
1245
|
+
- PageRank: O(k(V + E)) where k is iterations
|
|
1246
|
+
- Connected Components: O(V + E)
|
|
1247
|
+
- Kruskal's MST: O(E log E)
|
|
1248
|
+
- Prim's MST: O((V + E) log V)
|
|
1249
|
+
- A*: O((V + E) log V) - depends on heuristic quality
|
|
1250
|
+
- Ford-Fulkerson: O(E * f) where f is max flow
|
|
1251
|
+
- Edmonds-Karp: O(VE²)
|
|
1252
|
+
- Louvain/Leiden: O(n log n) average case
|
|
1253
|
+
- Hierarchical Clustering: O(n² log n)
|
|
1254
|
+
- SynC: O(kni) where k is clusters, n is nodes, i is iterations
|
|
1255
|
+
- TeraHAC: O(n log n) with sampling
|
|
1256
|
+
- GRSBM: O(m log n) where m is edges
|
|
1257
|
+
- **Memory Usage**: O(V + E) for graph storage
|
|
1258
|
+
- **Browser Optimization**: Algorithms use iterative approaches where possible to avoid stack overflow
|
|
1259
|
+
|
|
106
1260
|
## Development
|
|
107
1261
|
|
|
108
1262
|
### Prerequisites
|
|
@@ -145,8 +1299,48 @@ npm run lint:pkg # Check for unused dependencies
|
|
|
145
1299
|
|
|
146
1300
|
# Git
|
|
147
1301
|
npm run commit # Conventional commit helper
|
|
1302
|
+
|
|
1303
|
+
# HTML Examples
|
|
1304
|
+
npm run examples:html # Run interactive HTML examples
|
|
1305
|
+
npm run build:gh-pages # Build for GitHub Pages deployment
|
|
148
1306
|
```
|
|
149
1307
|
|
|
1308
|
+
### Development Server
|
|
1309
|
+
|
|
1310
|
+
The project includes interactive HTML examples demonstrating each algorithm. To run them locally:
|
|
1311
|
+
|
|
1312
|
+
1. **Copy the environment configuration:**
|
|
1313
|
+
```bash
|
|
1314
|
+
cp .env.example .env
|
|
1315
|
+
```
|
|
1316
|
+
|
|
1317
|
+
2. **Configure the server (optional):**
|
|
1318
|
+
Edit `.env` to set your preferred host and port:
|
|
1319
|
+
```bash
|
|
1320
|
+
# Server host (defaults to true for network exposure)
|
|
1321
|
+
HOST=localhost # For local-only access
|
|
1322
|
+
# HOST=0.0.0.0 # For network access
|
|
1323
|
+
# HOST=my.server.com # Custom domain
|
|
1324
|
+
|
|
1325
|
+
# Server port (defaults to 9000)
|
|
1326
|
+
PORT=9000 # Must be between 9000-9099
|
|
1327
|
+
```
|
|
1328
|
+
|
|
1329
|
+
3. **Start the development server:**
|
|
1330
|
+
```bash
|
|
1331
|
+
npm run examples:html
|
|
1332
|
+
```
|
|
1333
|
+
|
|
1334
|
+
4. **Open your browser** to `http://localhost:9000` (or your configured host/port)
|
|
1335
|
+
|
|
1336
|
+
The HTML examples provide:
|
|
1337
|
+
- Interactive visualizations for each algorithm
|
|
1338
|
+
- Step-by-step execution with play/pause controls
|
|
1339
|
+
- Multiple graph types for testing
|
|
1340
|
+
- Real-time parameter adjustment
|
|
1341
|
+
- Educational information about complexity and use cases
|
|
1342
|
+
- Mobile debugging console (Eruda) for testing on mobile devices
|
|
1343
|
+
|
|
150
1344
|
### Project Structure
|
|
151
1345
|
|
|
152
1346
|
```
|
|
@@ -156,12 +1350,16 @@ src/
|
|
|
156
1350
|
│ ├── traversal/ # BFS, DFS
|
|
157
1351
|
│ ├── shortest-path/ # Dijkstra, Bellman-Ford
|
|
158
1352
|
│ ├── centrality/ # Degree, Betweenness, PageRank
|
|
159
|
-
│ ├── community/ # Louvain, Girvan-Newman
|
|
160
1353
|
│ └── components/ # Connected components
|
|
161
1354
|
├── data-structures/ # Supporting data structures
|
|
162
1355
|
├── types/ # TypeScript type definitions
|
|
163
1356
|
└── utils/ # Utility functions
|
|
164
1357
|
|
|
1358
|
+
examples/
|
|
1359
|
+
├── html/ # Interactive HTML examples
|
|
1360
|
+
│ ├── shared/ # Shared utilities and styles
|
|
1361
|
+
│ └── algorithms/ # Algorithm-specific examples
|
|
1362
|
+
|
|
165
1363
|
test/
|
|
166
1364
|
├── unit/ # Unit tests
|
|
167
1365
|
├── browser/ # Browser-specific tests
|
|
@@ -190,4 +1388,4 @@ MIT © Adam Powers
|
|
|
190
1388
|
## Related Projects
|
|
191
1389
|
|
|
192
1390
|
- [@graphty/layout](https://github.com/graphty-org/layout) - Graph layout algorithms
|
|
193
|
-
- [@graphty/graphty-element](https://github.com/graphty-org/graphty-element) - 3D graph visualization web component
|
|
1391
|
+
- [@graphty/graphty-element](https://github.com/graphty-org/graphty-element) - 3D graph visualization web component
|