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