@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.
Files changed (230) hide show
  1. package/README.md +490 -336
  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 +40 -21
  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 +1 -0
  113. package/dist/src/index.d.ts.map +1 -1
  114. package/dist/src/index.js +4 -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.map +1 -1
  143. package/dist/src/research/grsbm.js +6 -14
  144. package/dist/src/research/grsbm.js.map +1 -1
  145. package/dist/src/research/sync.d.ts.map +1 -1
  146. package/dist/src/research/sync.js +3 -29
  147. package/dist/src/research/sync.js.map +1 -1
  148. package/dist/src/research/terahac.d.ts +2 -0
  149. package/dist/src/research/terahac.d.ts.map +1 -1
  150. package/dist/src/research/terahac.js +7 -3
  151. package/dist/src/research/terahac.js.map +1 -1
  152. package/dist/src/types/index.d.ts +8 -0
  153. package/dist/src/types/index.d.ts.map +1 -1
  154. package/dist/src/utils/algorithm-utilities.d.ts +2 -0
  155. package/dist/src/utils/algorithm-utilities.d.ts.map +1 -0
  156. package/dist/src/utils/algorithm-utilities.js +2 -0
  157. package/dist/src/utils/algorithm-utilities.js.map +1 -0
  158. package/dist/src/utils/graph-converters.d.ts +79 -0
  159. package/dist/src/utils/graph-converters.d.ts.map +1 -0
  160. package/dist/src/utils/graph-converters.js +196 -0
  161. package/dist/src/utils/graph-converters.js.map +1 -0
  162. package/dist/src/utils/graph-utilities.d.ts +62 -0
  163. package/dist/src/utils/graph-utilities.d.ts.map +1 -0
  164. package/dist/src/utils/graph-utilities.js +148 -0
  165. package/dist/src/utils/graph-utilities.js.map +1 -0
  166. package/dist/src/utils/index.d.ts +5 -0
  167. package/dist/src/utils/index.d.ts.map +1 -0
  168. package/dist/src/utils/index.js +5 -0
  169. package/dist/src/utils/index.js.map +1 -0
  170. package/dist/src/utils/math-utilities.d.ts +52 -0
  171. package/dist/src/utils/math-utilities.d.ts.map +1 -0
  172. package/dist/src/utils/math-utilities.js +123 -0
  173. package/dist/src/utils/math-utilities.js.map +1 -0
  174. package/dist/src/utils/matrix-utilities.d.ts +2 -0
  175. package/dist/src/utils/matrix-utilities.d.ts.map +1 -0
  176. package/dist/src/utils/matrix-utilities.js +2 -0
  177. package/dist/src/utils/matrix-utilities.js.map +1 -0
  178. package/dist/src/utils/optimization-helpers.d.ts +33 -0
  179. package/dist/src/utils/optimization-helpers.d.ts.map +1 -0
  180. package/dist/src/utils/optimization-helpers.js +47 -0
  181. package/dist/src/utils/optimization-helpers.js.map +1 -0
  182. package/package.json +18 -3
  183. package/src/algorithms/centrality/betweenness.ts +167 -199
  184. package/src/algorithms/centrality/closeness.ts +73 -191
  185. package/src/algorithms/centrality/degree.ts +3 -3
  186. package/src/algorithms/centrality/delta-pagerank-simple.ts +366 -0
  187. package/src/algorithms/centrality/delta-pagerank.ts +435 -0
  188. package/src/algorithms/centrality/index.ts +2 -0
  189. package/src/algorithms/centrality/pagerank.ts +66 -0
  190. package/src/algorithms/community/girvan-newman.ts +52 -59
  191. package/src/algorithms/community/index.ts +2 -0
  192. package/src/algorithms/community/label-propagation.ts +64 -35
  193. package/src/algorithms/community/leiden.ts +40 -41
  194. package/src/algorithms/community/louvain-optimized.ts +445 -0
  195. package/src/algorithms/community/louvain.ts +24 -104
  196. package/src/algorithms/community/modularity-utils.ts +146 -0
  197. package/src/algorithms/matching/bipartite.ts +8 -44
  198. package/src/algorithms/shortest-path/bellman-ford.ts +1 -14
  199. package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +248 -0
  200. package/src/algorithms/shortest-path/dijkstra.ts +17 -15
  201. package/src/algorithms/traversal/bfs-unified.ts +433 -0
  202. package/src/algorithms/traversal/bfs-variants.ts +496 -0
  203. package/src/algorithms/traversal/bfs.ts +10 -228
  204. package/src/benchmark-all-algorithms.ts +548 -0
  205. package/src/clustering/hierarchical.ts +241 -251
  206. package/src/clustering/index.ts +4 -2
  207. package/src/clustering/k-core.ts +87 -39
  208. package/src/clustering/spectral.ts +44 -20
  209. package/src/core/graph.ts +4 -4
  210. package/src/flow/ford-fulkerson.ts +186 -254
  211. package/src/flow/min-cut.ts +21 -11
  212. package/src/index.ts +6 -0
  213. package/src/link-prediction/adamic-adar.ts +17 -30
  214. package/src/link-prediction/common-neighbors.ts +7 -16
  215. package/src/optimized/bit-packed.ts +340 -0
  216. package/src/optimized/csr-graph.ts +455 -0
  217. package/src/optimized/direction-optimized-bfs.ts +291 -0
  218. package/src/optimized/graph-adapter.ts +200 -0
  219. package/src/optimized/index.ts +36 -0
  220. package/src/research/grsbm.ts +7 -16
  221. package/src/research/sync.ts +3 -32
  222. package/src/research/terahac.ts +10 -2
  223. package/src/types/index.ts +8 -0
  224. package/src/utils/algorithm-utilities.ts +2 -0
  225. package/src/utils/graph-converters.ts +241 -0
  226. package/src/utils/graph-utilities.ts +199 -0
  227. package/src/utils/index.ts +4 -0
  228. package/src/utils/math-utilities.ts +140 -0
  229. package/src/utils/matrix-utilities.ts +2 -0
  230. package/src/utils/optimization-helpers.ts +81 -0
package/README.md CHANGED
@@ -4,18 +4,57 @@
4
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
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/)
7
8
 
8
- A comprehensive TypeScript graph algorithms library with 100+ 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.
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**: 100+ graph algorithms including traversal, shortest paths, centrality, clustering, flow, matching, link prediction, 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
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); // source, target, weight
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); // 3
42
- console.log(graph.totalEdgeCount); // 2
43
- 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
44
83
 
45
84
  // Run algorithms
46
- const traversal = breadthFirstSearch(graph, 'A');
47
- console.log(traversal.order); // ['A', 'B', 'C']
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); // 3
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; // Default: false
72
- allowSelfLoops: boolean; // Default: false
73
- allowParallelEdges: boolean; // Default: false
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
- maxDepth?: number, // Optional: limit traversal depth
182
- visitCallback?: (node: NodeId, depth: number) => void
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: NodeId[] | null
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, 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
- previsitCallback?: (node: NodeId) => void,
207
- 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)
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 { dijkstra, dijkstraPath, singleSourceShortestPath, allPairsShortestPath } from '@graphty/algorithms';
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 // Optional: stop when target is reached
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 { bellmanFord, bellmanFordPath, hasNegativeCycle } from '@graphty/algorithms';
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 { floydWarshall, floydWarshallPath, transitiveClosure } from '@graphty/algorithms';
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?: boolean, // Default: false
302
- weight?: string // Optional: edge property for weighted degree
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?: boolean });
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 { betweennessCentrality, nodeBetweennessCentrality, edgeBetweennessCentrality } from '@graphty/algorithms';
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?: boolean, // Default: false
319
- weight?: string, // Optional: use weighted shortest paths
320
- endpoints?: boolean // Default: false, include endpoints in paths
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 { closenessCentrality, nodeClosenessCentrality, weightedClosenessCentrality } from '@graphty/algorithms';
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?: boolean // Default: false
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, { normalized?: boolean });
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?: boolean,
351
- weight?: string // Edge property for weights
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 { pageRank, personalizedPageRank, topPageRankNodes } from '@graphty/algorithms';
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?: number, // Default: 0.85
364
- maxIterations?: number, // Default: 100
365
- tolerance?: number, // Default: 1e-6
366
- initialRanks?: Record<string, number>,
367
- personalization?: Record<string, number>
368
- });
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 { eigenvectorCentrality, nodeEigenvectorCentrality } from '@graphty/algorithms';
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?: number, // Default: 100
389
- tolerance?: number // Default: 1e-6
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?: number, // Attenuation factor (default: 0.1)
406
- beta?: number, // Weight for direct connections (default: 1.0)
407
- maxIterations?: number, // Default: 100
408
- tolerance?: number, // Default: 1e-6
409
- normalized?: boolean // Default: true
410
- });
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?: number, // Default: 100
426
- tolerance?: number // Default: 1e-6
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 { weaklyConnectedComponents, isWeaklyConnected } from '@graphty/algorithms';
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?: number, // Default: 1.0
585
- randomSeed?: number
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?: number, // Default: 1.0
598
- iterations?: number, // Default: 10
599
- randomSeed?: number
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 { labelPropagation, labelPropagationAsync, labelPropagationSemiSupervised } from '@graphty/algorithms';
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?: number // Default: 100
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?: number // Stop at this many communities
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* Algorithm
734
+ #### A\* Algorithm
637
735
 
638
736
  ```typescript
639
- import { astar, astarWithDetails, heuristics } from '@graphty/algorithms';
737
+ import { astar } from '@graphty/algorithms'
640
738
 
641
739
  // A* pathfinding with heuristic
642
- const path = astar(graph, start, goal, {
643
- heuristic: heuristics.euclidean, // or manhattan, chebyshev, zero
644
- weight?: (edge: Edge) => number
645
- });
646
- // Returns: { path: NodeId[], cost: number } | null
647
-
648
- // A* with search details
649
- const result = astarWithDetails(graph, start, goal, options);
650
- // Returns: { path: NodeId[], cost: number, explored: Set<NodeId>, parent: Map<NodeId, NodeId> } | null
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 { hierarchicalClustering, cutDendrogram, cutDendrogramKClusters } from '@graphty/algorithms';
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 { kCoreDecomposition, getKCore, kTruss, degeneracyOrdering } from '@graphty/algorithms';
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, // Number of clusters
745
- laplacianType?: 'unnormalized' | 'normalized' | 'randomWalk', // Default: 'normalized'
746
- maxIterations?: number, // Default: 100
747
- tolerance?: number // Default: 1e-4
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?: number, // Expansion parameter (default: 2)
760
- inflation?: number, // Inflation parameter (default: 2)
761
- maxIterations?: number, // Default: 100
762
- tolerance?: number // Default: 1e-6
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 { maximumBipartiteMatching, greedyBipartiteMatching, bipartitePartition } from '@graphty/algorithms';
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?: Set<NodeId>, // Optional: specify left partition
777
- rightNodes?: Set<NodeId>, // Optional: specify right partition
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?: (node1: NodeId, node2: NodeId, g1: Graph, g2: Graph) => boolean,
797
- edgeMatch?: (edge1: [NodeId, NodeId], edge2: [NodeId, NodeId], g1: Graph, g2: Graph) => boolean,
798
- findAllMappings?: boolean // Find all possible isomorphisms
799
- });
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 { commonNeighborsScore, commonNeighborsPrediction, commonNeighborsForPairs } from '@graphty/algorithms';
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?: boolean, // Consider direction
821
- includeExisting?: boolean, // Include existing edges
822
- topK?: number // Return only top K predictions
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?: number });
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 { adamicAdarScore, adamicAdarPrediction, adamicAdarForPairs } from '@graphty/algorithms';
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?: boolean,
851
- includeExisting?: boolean,
852
- topK?: number
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, { topK?: number });
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, // Number of clusters
885
- maxIterations?: number, // Default: 100
886
- learningRate?: number, // Default: 0.01
887
- hiddenDim?: number, // Default: 64
888
- randomSeed?: number
889
- });
890
- // Returns: SynCResult {
891
- // communities: NodeId[][],
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?: 'single' | 'complete' | 'average', // Default: 'average'
907
- k?: number, // Target number of clusters
908
- threshold?: number, // Distance threshold for merging
909
- sampleSize?: number, // Default: 1000
910
- randomSeed?: number
911
- });
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?: number, // Default: 5
928
- maxDepth?: number, // Default: 10
929
- modularityThreshold?: number, // Default: 0.1
930
- explainClusters?: boolean // Default: true
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
- The library includes comprehensive examples demonstrating each algorithm. Find them in the [examples directory](https://github.com/graphty-org/algorithms/tree/main/examples):
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
- - [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
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); // { 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 }
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)); // true
1182
+ console.log(hasCycleDFS(directedGraph)) // true
1040
1183
 
1041
1184
  // Find strongly connected components
1042
- const sccs = stronglyConnectedComponents(directedGraph);
1043
- console.log(sccs.components); // [['A', 'B', 'C']]
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(); // Your graph
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
- path: NodeId[];
1141
- distance: number;
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
- predecessors: Map<NodeId, NodeId | null>;
1148
- hasNegativeCycle: boolean;
1149
- negativeCycleNodes?: Set<NodeId>;
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*: O((V + E) log V) - depends on heuristic quality
1250
- - 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
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
- # Git
1301
- npm run commit # Conventional commit helper
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