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