@graphty/algorithms 1.3.1 → 1.4.2

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 (313) hide show
  1. package/README.md +358 -413
  2. package/dist/algorithms.js +564 -261
  3. package/dist/algorithms.js.map +1 -1
  4. package/dist/src/algorithms/centrality/betweenness.d.ts +10 -0
  5. package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
  6. package/dist/src/algorithms/centrality/betweenness.js +27 -6
  7. package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
  8. package/dist/src/algorithms/centrality/closeness.d.ts +11 -2
  9. package/dist/src/algorithms/centrality/closeness.d.ts.map +1 -1
  10. package/dist/src/algorithms/centrality/closeness.js +17 -3
  11. package/dist/src/algorithms/centrality/closeness.js.map +1 -1
  12. package/dist/src/algorithms/centrality/degree.d.ts +7 -0
  13. package/dist/src/algorithms/centrality/degree.d.ts.map +1 -1
  14. package/dist/src/algorithms/centrality/degree.js +9 -6
  15. package/dist/src/algorithms/centrality/degree.js.map +1 -1
  16. package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts +21 -3
  17. package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts.map +1 -1
  18. package/dist/src/algorithms/centrality/delta-pagerank-simple.js +25 -7
  19. package/dist/src/algorithms/centrality/delta-pagerank-simple.js.map +1 -1
  20. package/dist/src/algorithms/centrality/delta-pagerank.d.ts +28 -2
  21. package/dist/src/algorithms/centrality/delta-pagerank.d.ts.map +1 -1
  22. package/dist/src/algorithms/centrality/delta-pagerank.js +30 -4
  23. package/dist/src/algorithms/centrality/delta-pagerank.js.map +1 -1
  24. package/dist/src/algorithms/centrality/eigenvector.d.ts +10 -3
  25. package/dist/src/algorithms/centrality/eigenvector.d.ts.map +1 -1
  26. package/dist/src/algorithms/centrality/eigenvector.js +11 -4
  27. package/dist/src/algorithms/centrality/eigenvector.js.map +1 -1
  28. package/dist/src/algorithms/centrality/hits.d.ts +10 -3
  29. package/dist/src/algorithms/centrality/hits.d.ts.map +1 -1
  30. package/dist/src/algorithms/centrality/hits.js +11 -4
  31. package/dist/src/algorithms/centrality/hits.js.map +1 -1
  32. package/dist/src/algorithms/centrality/index.d.ts +1 -1
  33. package/dist/src/algorithms/centrality/index.d.ts.map +1 -1
  34. package/dist/src/algorithms/centrality/index.js +1 -1
  35. package/dist/src/algorithms/centrality/index.js.map +1 -1
  36. package/dist/src/algorithms/centrality/katz.d.ts +10 -3
  37. package/dist/src/algorithms/centrality/katz.d.ts.map +1 -1
  38. package/dist/src/algorithms/centrality/katz.js +13 -8
  39. package/dist/src/algorithms/centrality/katz.js.map +1 -1
  40. package/dist/src/algorithms/centrality/pagerank.d.ts +14 -0
  41. package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -1
  42. package/dist/src/algorithms/centrality/pagerank.js +16 -1
  43. package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
  44. package/dist/src/algorithms/community/girvan-newman.d.ts +2 -3
  45. package/dist/src/algorithms/community/girvan-newman.d.ts.map +1 -1
  46. package/dist/src/algorithms/community/girvan-newman.js +21 -4
  47. package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
  48. package/dist/src/algorithms/community/index.d.ts.map +1 -1
  49. package/dist/src/algorithms/community/index.js.map +1 -1
  50. package/dist/src/algorithms/community/label-propagation.d.ts +0 -3
  51. package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -1
  52. package/dist/src/algorithms/community/label-propagation.js +13 -6
  53. package/dist/src/algorithms/community/label-propagation.js.map +1 -1
  54. package/dist/src/algorithms/community/leiden.d.ts +0 -1
  55. package/dist/src/algorithms/community/leiden.d.ts.map +1 -1
  56. package/dist/src/algorithms/community/leiden.js +37 -6
  57. package/dist/src/algorithms/community/leiden.js.map +1 -1
  58. package/dist/src/algorithms/community/louvain-optimized.d.ts +37 -0
  59. package/dist/src/algorithms/community/louvain-optimized.d.ts.map +1 -1
  60. package/dist/src/algorithms/community/louvain-optimized.js +42 -7
  61. package/dist/src/algorithms/community/louvain-optimized.js.map +1 -1
  62. package/dist/src/algorithms/community/louvain.d.ts +2 -3
  63. package/dist/src/algorithms/community/louvain.d.ts.map +1 -1
  64. package/dist/src/algorithms/community/louvain.js +19 -6
  65. package/dist/src/algorithms/community/louvain.js.map +1 -1
  66. package/dist/src/algorithms/community/modularity-utils.d.ts +0 -4
  67. package/dist/src/algorithms/community/modularity-utils.d.ts.map +1 -1
  68. package/dist/src/algorithms/community/modularity-utils.js +1 -5
  69. package/dist/src/algorithms/community/modularity-utils.js.map +1 -1
  70. package/dist/src/algorithms/components/connected.d.ts +23 -0
  71. package/dist/src/algorithms/components/connected.d.ts.map +1 -1
  72. package/dist/src/algorithms/components/connected.js +29 -3
  73. package/dist/src/algorithms/components/connected.js.map +1 -1
  74. package/dist/src/algorithms/matching/bipartite.d.ts +10 -0
  75. package/dist/src/algorithms/matching/bipartite.d.ts.map +1 -1
  76. package/dist/src/algorithms/matching/bipartite.js +10 -0
  77. package/dist/src/algorithms/matching/bipartite.js.map +1 -1
  78. package/dist/src/algorithms/matching/index.d.ts.map +1 -1
  79. package/dist/src/algorithms/matching/index.js.map +1 -1
  80. package/dist/src/algorithms/matching/isomorphism.d.ts +8 -0
  81. package/dist/src/algorithms/matching/isomorphism.d.ts.map +1 -1
  82. package/dist/src/algorithms/matching/isomorphism.js +36 -2
  83. package/dist/src/algorithms/matching/isomorphism.js.map +1 -1
  84. package/dist/src/algorithms/mst/index.d.ts.map +1 -1
  85. package/dist/src/algorithms/mst/index.js.map +1 -1
  86. package/dist/src/algorithms/mst/kruskal.d.ts +14 -0
  87. package/dist/src/algorithms/mst/kruskal.d.ts.map +1 -1
  88. package/dist/src/algorithms/mst/kruskal.js +17 -3
  89. package/dist/src/algorithms/mst/kruskal.js.map +1 -1
  90. package/dist/src/algorithms/mst/prim.d.ts +9 -0
  91. package/dist/src/algorithms/mst/prim.d.ts.map +1 -1
  92. package/dist/src/algorithms/mst/prim.js +9 -0
  93. package/dist/src/algorithms/mst/prim.js.map +1 -1
  94. package/dist/src/algorithms/shortest-path/bellman-ford.d.ts +10 -0
  95. package/dist/src/algorithms/shortest-path/bellman-ford.d.ts.map +1 -1
  96. package/dist/src/algorithms/shortest-path/bellman-ford.js +10 -0
  97. package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
  98. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts +11 -4
  99. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts.map +1 -1
  100. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +18 -16
  101. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js.map +1 -1
  102. package/dist/src/algorithms/shortest-path/dijkstra.d.ts +15 -0
  103. package/dist/src/algorithms/shortest-path/dijkstra.d.ts.map +1 -1
  104. package/dist/src/algorithms/shortest-path/dijkstra.js +15 -0
  105. package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
  106. package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts +17 -0
  107. package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts.map +1 -1
  108. package/dist/src/algorithms/shortest-path/floyd-warshall.js +17 -0
  109. package/dist/src/algorithms/shortest-path/floyd-warshall.js.map +1 -1
  110. package/dist/src/algorithms/shortest-path/index.d.ts.map +1 -1
  111. package/dist/src/algorithms/shortest-path/index.js.map +1 -1
  112. package/dist/src/algorithms/traversal/bfs-unified.d.ts +13 -0
  113. package/dist/src/algorithms/traversal/bfs-unified.d.ts.map +1 -1
  114. package/dist/src/algorithms/traversal/bfs-unified.js +37 -0
  115. package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -1
  116. package/dist/src/algorithms/traversal/bfs-variants.d.ts +23 -0
  117. package/dist/src/algorithms/traversal/bfs-variants.d.ts.map +1 -1
  118. package/dist/src/algorithms/traversal/bfs-variants.js +34 -0
  119. package/dist/src/algorithms/traversal/bfs-variants.js.map +1 -1
  120. package/dist/src/algorithms/traversal/bfs.d.ts +1 -1
  121. package/dist/src/algorithms/traversal/bfs.d.ts.map +1 -1
  122. package/dist/src/algorithms/traversal/bfs.js +1 -1
  123. package/dist/src/algorithms/traversal/bfs.js.map +1 -1
  124. package/dist/src/algorithms/traversal/dfs.d.ts +10 -0
  125. package/dist/src/algorithms/traversal/dfs.d.ts.map +1 -1
  126. package/dist/src/algorithms/traversal/dfs.js +48 -0
  127. package/dist/src/algorithms/traversal/dfs.js.map +1 -1
  128. package/dist/src/algorithms/traversal/index.d.ts.map +1 -1
  129. package/dist/src/algorithms/traversal/index.js.map +1 -1
  130. package/dist/src/benchmark-all-algorithms.d.ts +2 -0
  131. package/dist/src/benchmark-all-algorithms.d.ts.map +1 -1
  132. package/dist/src/benchmark-all-algorithms.js +32 -3
  133. package/dist/src/benchmark-all-algorithms.js.map +1 -1
  134. package/dist/src/clustering/hierarchical.d.ts +8 -1
  135. package/dist/src/clustering/hierarchical.d.ts.map +1 -1
  136. package/dist/src/clustering/hierarchical.js +22 -6
  137. package/dist/src/clustering/hierarchical.js.map +1 -1
  138. package/dist/src/clustering/index.d.ts.map +1 -1
  139. package/dist/src/clustering/index.js.map +1 -1
  140. package/dist/src/clustering/k-core.d.ts +2 -5
  141. package/dist/src/clustering/k-core.d.ts.map +1 -1
  142. package/dist/src/clustering/k-core.js +14 -12
  143. package/dist/src/clustering/k-core.js.map +1 -1
  144. package/dist/src/clustering/mcl.d.ts +6 -0
  145. package/dist/src/clustering/mcl.d.ts.map +1 -1
  146. package/dist/src/clustering/mcl.js +34 -3
  147. package/dist/src/clustering/mcl.js.map +1 -1
  148. package/dist/src/clustering/spectral.d.ts +4 -1
  149. package/dist/src/clustering/spectral.d.ts.map +1 -1
  150. package/dist/src/clustering/spectral.js +61 -28
  151. package/dist/src/clustering/spectral.js.map +1 -1
  152. package/dist/src/core/graph.d.ts +45 -0
  153. package/dist/src/core/graph.d.ts.map +1 -1
  154. package/dist/src/core/graph.js +45 -1
  155. package/dist/src/core/graph.js.map +1 -1
  156. package/dist/src/data-structures/index.d.ts.map +1 -1
  157. package/dist/src/data-structures/index.js.map +1 -1
  158. package/dist/src/data-structures/priority-queue.d.ts +18 -1
  159. package/dist/src/data-structures/priority-queue.d.ts.map +1 -1
  160. package/dist/src/data-structures/priority-queue.js +26 -5
  161. package/dist/src/data-structures/priority-queue.js.map +1 -1
  162. package/dist/src/data-structures/union-find.d.ts +21 -0
  163. package/dist/src/data-structures/union-find.d.ts.map +1 -1
  164. package/dist/src/data-structures/union-find.js +21 -0
  165. package/dist/src/data-structures/union-find.js.map +1 -1
  166. package/dist/src/flow/ford-fulkerson.d.ts +4 -2
  167. package/dist/src/flow/ford-fulkerson.d.ts.map +1 -1
  168. package/dist/src/flow/ford-fulkerson.js +31 -2
  169. package/dist/src/flow/ford-fulkerson.js.map +1 -1
  170. package/dist/src/flow/min-cut.d.ts +0 -3
  171. package/dist/src/flow/min-cut.d.ts.map +1 -1
  172. package/dist/src/flow/min-cut.js +17 -4
  173. package/dist/src/flow/min-cut.js.map +1 -1
  174. package/dist/src/index.d.ts +2 -1
  175. package/dist/src/index.d.ts.map +1 -1
  176. package/dist/src/index.js +2 -1
  177. package/dist/src/index.js.map +1 -1
  178. package/dist/src/link-prediction/adamic-adar.d.ts +26 -0
  179. package/dist/src/link-prediction/adamic-adar.d.ts.map +1 -1
  180. package/dist/src/link-prediction/adamic-adar.js +36 -10
  181. package/dist/src/link-prediction/adamic-adar.js.map +1 -1
  182. package/dist/src/link-prediction/common-neighbors.d.ts +21 -0
  183. package/dist/src/link-prediction/common-neighbors.d.ts.map +1 -1
  184. package/dist/src/link-prediction/common-neighbors.js +27 -6
  185. package/dist/src/link-prediction/common-neighbors.js.map +1 -1
  186. package/dist/src/link-prediction/index.d.ts.map +1 -1
  187. package/dist/src/optimized/bit-packed.d.ts +103 -53
  188. package/dist/src/optimized/bit-packed.d.ts.map +1 -1
  189. package/dist/src/optimized/bit-packed.js +104 -54
  190. package/dist/src/optimized/bit-packed.js.map +1 -1
  191. package/dist/src/optimized/csr-graph.d.ts +87 -24
  192. package/dist/src/optimized/csr-graph.d.ts.map +1 -1
  193. package/dist/src/optimized/csr-graph.js +87 -24
  194. package/dist/src/optimized/csr-graph.js.map +1 -1
  195. package/dist/src/optimized/direction-optimized-bfs.d.ts +37 -16
  196. package/dist/src/optimized/direction-optimized-bfs.d.ts.map +1 -1
  197. package/dist/src/optimized/direction-optimized-bfs.js +39 -20
  198. package/dist/src/optimized/direction-optimized-bfs.js.map +1 -1
  199. package/dist/src/optimized/graph-adapter.d.ts +58 -9
  200. package/dist/src/optimized/graph-adapter.d.ts.map +1 -1
  201. package/dist/src/optimized/graph-adapter.js +58 -10
  202. package/dist/src/optimized/graph-adapter.js.map +1 -1
  203. package/dist/src/optimized/index.d.ts +1 -1
  204. package/dist/src/optimized/index.d.ts.map +1 -1
  205. package/dist/src/optimized/index.js +3 -1
  206. package/dist/src/optimized/index.js.map +1 -1
  207. package/dist/src/pathfinding/astar.d.ts +25 -9
  208. package/dist/src/pathfinding/astar.d.ts.map +1 -1
  209. package/dist/src/pathfinding/astar.js +25 -10
  210. package/dist/src/pathfinding/astar.js.map +1 -1
  211. package/dist/src/pathfinding/utils.d.ts +15 -6
  212. package/dist/src/pathfinding/utils.d.ts.map +1 -1
  213. package/dist/src/pathfinding/utils.js +19 -7
  214. package/dist/src/pathfinding/utils.js.map +1 -1
  215. package/dist/src/research/grsbm.d.ts +0 -1
  216. package/dist/src/research/grsbm.d.ts.map +1 -1
  217. package/dist/src/research/grsbm.js +22 -9
  218. package/dist/src/research/grsbm.js.map +1 -1
  219. package/dist/src/research/index.d.ts.map +1 -1
  220. package/dist/src/research/index.js.map +1 -1
  221. package/dist/src/research/sync.d.ts +0 -1
  222. package/dist/src/research/sync.d.ts.map +1 -1
  223. package/dist/src/research/sync.js +28 -7
  224. package/dist/src/research/sync.js.map +1 -1
  225. package/dist/src/research/terahac.d.ts +0 -1
  226. package/dist/src/research/terahac.d.ts.map +1 -1
  227. package/dist/src/research/terahac.js +32 -4
  228. package/dist/src/research/terahac.js.map +1 -1
  229. package/dist/src/utils/graph-converters.d.ts +31 -0
  230. package/dist/src/utils/graph-converters.d.ts.map +1 -1
  231. package/dist/src/utils/graph-converters.js +31 -0
  232. package/dist/src/utils/graph-converters.js.map +1 -1
  233. package/dist/src/utils/graph-utilities.d.ts.map +1 -1
  234. package/dist/src/utils/graph-utilities.js.map +1 -1
  235. package/dist/src/utils/math-utilities.d.ts +11 -0
  236. package/dist/src/utils/math-utilities.d.ts.map +1 -1
  237. package/dist/src/utils/math-utilities.js +14 -5
  238. package/dist/src/utils/math-utilities.js.map +1 -1
  239. package/dist/src/utils/optimization-helpers.d.ts +9 -0
  240. package/dist/src/utils/optimization-helpers.d.ts.map +1 -1
  241. package/dist/src/utils/optimization-helpers.js +12 -0
  242. package/dist/src/utils/optimization-helpers.js.map +1 -1
  243. package/dist/src/utils/priorityQueue.d.ts +24 -0
  244. package/dist/src/utils/priorityQueue.d.ts.map +1 -1
  245. package/dist/src/utils/priorityQueue.js +34 -4
  246. package/dist/src/utils/priorityQueue.js.map +1 -1
  247. package/package.json +49 -45
  248. package/src/algorithms/centrality/betweenness.ts +34 -17
  249. package/src/algorithms/centrality/closeness.ts +34 -17
  250. package/src/algorithms/centrality/degree.ts +15 -19
  251. package/src/algorithms/centrality/delta-pagerank-simple.ts +36 -28
  252. package/src/algorithms/centrality/delta-pagerank.ts +34 -11
  253. package/src/algorithms/centrality/eigenvector.ts +14 -15
  254. package/src/algorithms/centrality/hits.ts +17 -17
  255. package/src/algorithms/centrality/index.ts +20 -15
  256. package/src/algorithms/centrality/katz.ts +17 -25
  257. package/src/algorithms/centrality/pagerank.ts +26 -17
  258. package/src/algorithms/community/girvan-newman.ts +39 -28
  259. package/src/algorithms/community/index.ts +6 -7
  260. package/src/algorithms/community/label-propagation.ts +20 -28
  261. package/src/algorithms/community/leiden.ts +61 -37
  262. package/src/algorithms/community/louvain-optimized.ts +49 -20
  263. package/src/algorithms/community/louvain.ts +35 -25
  264. package/src/algorithms/community/modularity-utils.ts +5 -17
  265. package/src/algorithms/components/connected.ts +40 -17
  266. package/src/algorithms/matching/bipartite.ts +17 -10
  267. package/src/algorithms/matching/index.ts +4 -4
  268. package/src/algorithms/matching/isomorphism.ts +53 -23
  269. package/src/algorithms/mst/index.ts +3 -4
  270. package/src/algorithms/mst/kruskal.ts +21 -6
  271. package/src/algorithms/mst/prim.ts +13 -4
  272. package/src/algorithms/shortest-path/bellman-ford.ts +16 -15
  273. package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +28 -28
  274. package/src/algorithms/shortest-path/dijkstra.ts +23 -17
  275. package/src/algorithms/shortest-path/floyd-warshall.ts +21 -4
  276. package/src/algorithms/shortest-path/index.ts +5 -5
  277. package/src/algorithms/traversal/bfs-unified.ts +64 -60
  278. package/src/algorithms/traversal/bfs-variants.ts +61 -37
  279. package/src/algorithms/traversal/bfs.ts +1 -7
  280. package/src/algorithms/traversal/dfs.ts +61 -42
  281. package/src/algorithms/traversal/index.ts +3 -3
  282. package/src/benchmark-all-algorithms.ts +57 -25
  283. package/src/clustering/hierarchical.ts +40 -34
  284. package/src/clustering/index.ts +8 -8
  285. package/src/clustering/k-core.ts +26 -42
  286. package/src/clustering/mcl.ts +53 -23
  287. package/src/clustering/spectral.ts +91 -57
  288. package/src/core/graph.ts +54 -14
  289. package/src/data-structures/index.ts +2 -2
  290. package/src/data-structures/priority-queue.ts +36 -11
  291. package/src/data-structures/union-find.ts +22 -1
  292. package/src/flow/ford-fulkerson.ts +62 -35
  293. package/src/flow/min-cut.ts +43 -45
  294. package/src/index.ts +3 -2
  295. package/src/link-prediction/adamic-adar.ts +65 -51
  296. package/src/link-prediction/common-neighbors.ts +45 -36
  297. package/src/link-prediction/index.ts +1 -1
  298. package/src/optimized/bit-packed.ts +106 -56
  299. package/src/optimized/csr-graph.ts +93 -30
  300. package/src/optimized/direction-optimized-bfs.ts +44 -25
  301. package/src/optimized/graph-adapter.ts +64 -16
  302. package/src/optimized/index.ts +7 -9
  303. package/src/pathfinding/astar.ts +40 -25
  304. package/src/pathfinding/utils.ts +20 -13
  305. package/src/research/grsbm.ts +30 -24
  306. package/src/research/index.ts +4 -4
  307. package/src/research/sync.ts +39 -23
  308. package/src/research/terahac.ts +54 -20
  309. package/src/utils/graph-converters.ts +42 -14
  310. package/src/utils/graph-utilities.ts +11 -37
  311. package/src/utils/math-utilities.ts +17 -8
  312. package/src/utils/optimization-helpers.ts +27 -21
  313. package/src/utils/priorityQueue.ts +40 -6
@@ -1,6 +1,6 @@
1
- import type {Graph} from "../core/graph.js";
2
- import type {NodeId} from "../types/index.js";
3
- import {euclideanDistance} from "../utils/math-utilities.js";
1
+ import type { Graph } from "../core/graph.js";
2
+ import type { NodeId } from "../types/index.js";
3
+ import { euclideanDistance } from "../utils/math-utilities.js";
4
4
 
5
5
  /**
6
6
  * Spectral Clustering implementation
@@ -29,24 +29,19 @@ export interface SpectralClusteringResult {
29
29
  /**
30
30
  * Perform spectral clustering on a graph
31
31
  *
32
- * @warning This implementation uses simplified power iteration for eigenvector
32
+ * Note: This implementation uses simplified power iteration for eigenvector
33
33
  * computation with approximate eigenvalues. For production use cases requiring
34
34
  * precise clustering, consider using a proper linear algebra library like ml-matrix.
35
35
  *
36
36
  * The approximate eigenvalues (0.1, 0.2 for second and third eigenvectors) work
37
37
  * well for most graph structures but may produce suboptimal results for graphs
38
38
  * with unusual spectral properties.
39
+ * @param graph - The input graph to cluster
40
+ * @param options - Spectral clustering options (k, laplacianType, etc.)
41
+ * @returns Spectral clustering result with communities and cluster assignments
39
42
  */
40
- export function spectralClustering(
41
- graph: Graph,
42
- options: SpectralClusteringOptions,
43
- ): SpectralClusteringResult {
44
- const {
45
- k,
46
- laplacianType = "normalized",
47
- maxIterations = 100,
48
- tolerance = 1e-4,
49
- } = options;
43
+ export function spectralClustering(graph: Graph, options: SpectralClusteringOptions): SpectralClusteringResult {
44
+ const { k, laplacianType = "normalized", maxIterations = 100, tolerance = 1e-4 } = options;
50
45
 
51
46
  // Input validation
52
47
  if (k < 1 || !Number.isInteger(k)) {
@@ -62,7 +57,7 @@ export function spectralClustering(
62
57
  const communities: NodeId[][] = nodeIds.map((id) => [id]);
63
58
  const clusterAssignments = new Map<NodeId, number>();
64
59
  nodeIds.forEach((id, index) => clusterAssignments.set(id, index));
65
- return {communities, clusterAssignments};
60
+ return { communities, clusterAssignments };
66
61
  }
67
62
 
68
63
  // Build adjacency matrix
@@ -97,7 +92,7 @@ export function spectralClustering(
97
92
  const kmeans = kMeansClustering(dataPoints, k, maxIterations, tolerance);
98
93
 
99
94
  // Build communities
100
- const communities: NodeId[][] = Array.from({length: k}, () => []);
95
+ const communities: NodeId[][] = Array.from({ length: k }, () => []);
101
96
  const clusterAssignments = new Map<NodeId, number>();
102
97
 
103
98
  for (let i = 0; i < nodeIds.length; i++) {
@@ -139,10 +134,13 @@ export function spectralClustering(
139
134
 
140
135
  /**
141
136
  * Build adjacency matrix from graph
137
+ * @param graph - The input graph
138
+ * @param nodeIds - Array of node IDs defining matrix index order
139
+ * @returns Square adjacency matrix with edge weights
142
140
  */
143
141
  function buildAdjacencyMatrix(graph: Graph, nodeIds: NodeId[]): number[][] {
144
142
  const n = nodeIds.length;
145
- const matrix: number[][] = Array.from({length: n}, () => Array(n).fill(0) as number[]);
143
+ const matrix: number[][] = Array.from({ length: n }, () => Array(n).fill(0) as number[]);
146
144
  const nodeToIndex = new Map<NodeId, number>();
147
145
 
148
146
  nodeIds.forEach((id, index) => nodeToIndex.set(id, index));
@@ -180,10 +178,13 @@ function buildAdjacencyMatrix(graph: Graph, nodeIds: NodeId[]): number[][] {
180
178
 
181
179
  /**
182
180
  * Build Laplacian matrix from adjacency matrix
181
+ * @param adjacency - Square adjacency matrix
182
+ * @param type - Type of Laplacian (unnormalized, normalized, or randomWalk)
183
+ * @returns The computed Laplacian matrix
183
184
  */
184
185
  function buildLaplacianMatrix(adjacency: number[][], type: string): number[][] {
185
186
  const n = adjacency.length;
186
- const laplacian: number[][] = Array.from({length: n}, () => Array(n).fill(0) as number[]);
187
+ const laplacian: number[][] = Array.from({ length: n }, () => Array(n).fill(0) as number[]);
187
188
 
188
189
  // Calculate degree matrix
189
190
  const degrees = Array(n).fill(0) as number[];
@@ -239,7 +240,14 @@ function buildLaplacianMatrix(adjacency: number[][], type: string): number[][] {
239
240
  const adjacencyVal = adjacencyRow[j];
240
241
  const di = degrees[i];
241
242
  const dj = degrees[j];
242
- if (adjacencyVal !== undefined && adjacencyVal > 0 && di !== undefined && dj !== undefined && di > 0 && dj > 0) {
243
+ if (
244
+ adjacencyVal !== undefined &&
245
+ adjacencyVal > 0 &&
246
+ di !== undefined &&
247
+ dj !== undefined &&
248
+ di > 0 &&
249
+ dj > 0
250
+ ) {
243
251
  const laplacianRow = laplacian[i];
244
252
  if (laplacianRow) {
245
253
  laplacianRow[j] = -adjacencyVal / Math.sqrt(di * dj);
@@ -283,15 +291,21 @@ function buildLaplacianMatrix(adjacency: number[][], type: string): number[][] {
283
291
  /**
284
292
  * Find k smallest eigenvectors using simplified eigendecomposition
285
293
  * This is a simplified implementation - in practice, you'd use LAPACK or similar
294
+ * @param matrix - The Laplacian matrix for eigendecomposition
295
+ * @param k - Number of smallest eigenvectors to find
296
+ * @returns Object containing eigenvalues and corresponding eigenvectors
286
297
  */
287
- function findSmallestEigenvectors(matrix: number[][], k: number): {
298
+ function findSmallestEigenvectors(
299
+ matrix: number[][],
300
+ k: number,
301
+ ): {
288
302
  eigenvalues: number[];
289
303
  eigenvectors: number[][];
290
304
  } {
291
305
  const n = matrix.length;
292
306
 
293
307
  if (n === 0 || k === 0) {
294
- return {eigenvalues: [], eigenvectors: []};
308
+ return { eigenvalues: [], eigenvectors: [] };
295
309
  }
296
310
 
297
311
  // For very small matrices, use the full power iteration approach
@@ -314,10 +328,12 @@ function findSmallestEigenvectors(matrix: number[][], k: number): {
314
328
 
315
329
  for (let eigIdx = 0; eigIdx < k; eigIdx++) {
316
330
  // Initialize random vector
317
- let vector = Array(n).fill(0).map(() => Math.random() - 0.5);
331
+ let vector = Array(n)
332
+ .fill(0)
333
+ .map(() => Math.random() - 0.5);
318
334
 
319
335
  // Normalize initial vector
320
- const initNorm = Math.sqrt(vector.reduce((sum, val) => sum + (val * val), 0));
336
+ const initNorm = Math.sqrt(vector.reduce((sum, val) => sum + val * val, 0));
321
337
  if (initNorm > 0) {
322
338
  vector = vector.map((val) => val / initNorm);
323
339
  }
@@ -329,8 +345,8 @@ function findSmallestEigenvectors(matrix: number[][], k: number): {
329
345
  continue;
330
346
  }
331
347
 
332
- const dot = vector.reduce((sum, val, idx) => sum + (val * (ejVector[idx] ?? 0)), 0);
333
- vector = vector.map((val, idx) => val - (dot * (ejVector[idx] ?? 0)));
348
+ const dot = vector.reduce((sum, val, idx) => sum + val * (ejVector[idx] ?? 0), 0);
349
+ vector = vector.map((val, idx) => val - dot * (ejVector[idx] ?? 0));
334
350
  }
335
351
 
336
352
  // Power iteration
@@ -345,7 +361,7 @@ function findSmallestEigenvectors(matrix: number[][], k: number): {
345
361
  if (matrixVal !== undefined && vecVal !== undefined) {
346
362
  const nvVal = newVector[i];
347
363
  if (nvVal !== undefined) {
348
- newVector[i] = nvVal + (matrixVal * vecVal);
364
+ newVector[i] = nvVal + matrixVal * vecVal;
349
365
  }
350
366
  }
351
367
  }
@@ -358,20 +374,20 @@ function findSmallestEigenvectors(matrix: number[][], k: number): {
358
374
  continue;
359
375
  }
360
376
 
361
- const dot = newVector.reduce((sum, val, idx) => sum + (val * (ejVector[idx] ?? 0)), 0);
377
+ const dot = newVector.reduce((sum, val, idx) => sum + val * (ejVector[idx] ?? 0), 0);
362
378
  for (let i = 0; i < n; i++) {
363
379
  const ejVal = ejVector[i];
364
380
  if (ejVal !== undefined) {
365
381
  const nvVal = newVector[i];
366
382
  if (nvVal !== undefined) {
367
- newVector[i] = nvVal - (dot * ejVal);
383
+ newVector[i] = nvVal - dot * ejVal;
368
384
  }
369
385
  }
370
386
  }
371
387
  }
372
388
 
373
389
  // Normalize
374
- const norm = Math.sqrt(newVector.reduce((sum, val) => sum + ((val * val)), 0));
390
+ const norm = Math.sqrt(newVector.reduce((sum, val) => sum + val * val, 0));
375
391
  if (norm > 1e-10) {
376
392
  vector = newVector.map((val) => val / norm);
377
393
  } else {
@@ -390,29 +406,30 @@ function findSmallestEigenvectors(matrix: number[][], k: number): {
390
406
  if (matrixVal !== undefined && vecVal !== undefined) {
391
407
  const avVal = Av[i];
392
408
  if (avVal !== undefined) {
393
- Av[i] = avVal + (matrixVal * vecVal);
409
+ Av[i] = avVal + matrixVal * vecVal;
394
410
  }
395
411
  }
396
412
  }
397
413
  }
398
414
  eigenvalue = vector.reduce((sum, val, idx) => {
399
415
  const avVal = Av[idx];
400
- return sum + (val * (avVal ?? 0));
416
+ return sum + val * (avVal ?? 0);
401
417
  }, 0);
402
418
 
403
419
  eigenvectors.push(vector);
404
420
  eigenvalues.push(eigenvalue);
405
421
  }
406
422
 
407
- return {eigenvalues, eigenvectors};
423
+ return { eigenvalues, eigenvectors };
408
424
  }
409
425
 
410
426
  /**
411
427
  * Normalize matrix rows to unit length
428
+ * @param matrix - Matrix to normalize in place
412
429
  */
413
430
  function normalizeRows(matrix: number[][]): void {
414
431
  for (const row of matrix) {
415
- const norm = Math.sqrt(row.reduce((sum, val) => sum + (val * val), 0));
432
+ const norm = Math.sqrt(row.reduce((sum, val) => sum + val * val, 0));
416
433
  if (norm > 0) {
417
434
  for (let j = 0; j < row.length; j++) {
418
435
  const val = row[j];
@@ -426,25 +443,30 @@ function normalizeRows(matrix: number[][]): void {
426
443
 
427
444
  /**
428
445
  * K-means clustering algorithm
446
+ * @param data - Array of data points, each point is an array of coordinates
447
+ * @param k - Number of clusters to form
448
+ * @param maxIterations - Maximum number of iterations
449
+ * @param tolerance - Convergence tolerance for centroid movement
450
+ * @returns Object containing cluster assignments and final centroids
429
451
  */
430
452
  function kMeansClustering(
431
453
  data: number[][],
432
454
  k: number,
433
455
  maxIterations: number,
434
456
  tolerance = 1e-4,
435
- ): {assignments: number[], centroids: number[][]} {
457
+ ): { assignments: number[]; centroids: number[][] } {
436
458
  const n = data.length;
437
459
  const d = data[0]?.length ?? 0;
438
460
 
439
461
  // Handle edge cases
440
462
  if (n === 0 || k === 0) {
441
- return {assignments: [], centroids: []};
463
+ return { assignments: [], centroids: [] };
442
464
  }
443
465
 
444
466
  if (k >= n) {
445
467
  // Each point is its own cluster
446
468
  return {
447
- assignments: Array.from({length: n}, (_, i) => i),
469
+ assignments: Array.from({ length: n }, (_, i) => i),
448
470
  centroids: data.slice(0, n),
449
471
  };
450
472
  }
@@ -457,7 +479,7 @@ function kMeansClustering(
457
479
  const idx = Math.floor(Math.random() * n);
458
480
  if (!selectedIndices.has(idx) && data[idx]) {
459
481
  selectedIndices.add(idx);
460
- centroids.push([... data[idx]]);
482
+ centroids.push([...data[idx]]);
461
483
  }
462
484
  }
463
485
 
@@ -509,14 +531,14 @@ function kMeansClustering(
509
531
  break;
510
532
  }
511
533
 
512
- oldAssignments = [... assignments];
534
+ oldAssignments = [...assignments];
513
535
 
514
536
  // Store old centroids for tolerance-based convergence check
515
- const oldCentroids = centroids.map((c) => [... c]);
537
+ const oldCentroids = centroids.map((c) => [...c]);
516
538
 
517
539
  // Update centroids
518
540
  const counts = Array(k).fill(0) as number[];
519
- const sums: number[][] = Array.from({length: k}, () => Array(d).fill(0) as number[]);
541
+ const sums: number[][] = Array.from({ length: k }, () => Array(d).fill(0) as number[]);
520
542
 
521
543
  for (let i = 0; i < n; i++) {
522
544
  const cluster = assignments[i] ?? 0;
@@ -581,13 +603,21 @@ function kMeansClustering(
581
603
  }
582
604
  }
583
605
 
584
- return {assignments, centroids};
606
+ return { assignments, centroids };
585
607
  }
586
608
 
587
609
  /**
588
610
  * Compute smallest eigenvectors for small k (optimized for k=2, k=3)
611
+ * @param matrix - The Laplacian matrix
612
+ * @param k - Number of eigenvectors to compute (1-3)
613
+ * @param n - Size of the matrix
614
+ * @returns Object containing eigenvalues and eigenvectors
589
615
  */
590
- function computeSmallestEigenvectorsSimple(matrix: number[][], k: number, n: number): {
616
+ function computeSmallestEigenvectorsSimple(
617
+ matrix: number[][],
618
+ k: number,
619
+ n: number,
620
+ ): {
591
621
  eigenvalues: number[];
592
622
  eigenvectors: number[][];
593
623
  } {
@@ -603,11 +633,13 @@ function computeSmallestEigenvectorsSimple(matrix: number[][], k: number, n: num
603
633
  if (k >= 2) {
604
634
  // Use power iteration on I - L/lambda_max to find second smallest
605
635
  const maxEig = 2; // For normalized Laplacian, max eigenvalue <= 2
606
- let vector = Array(n).fill(0).map(() => Math.random() - 0.5);
636
+ let vector = Array(n)
637
+ .fill(0)
638
+ .map(() => Math.random() - 0.5);
607
639
 
608
640
  // Make orthogonal to first eigenvector
609
- const dot1 = vector.reduce((sum, val) => sum + (val / Math.sqrt(n)), 0);
610
- vector = vector.map((val) => val - (dot1 / Math.sqrt(n)));
641
+ const dot1 = vector.reduce((sum, val) => sum + val / Math.sqrt(n), 0);
642
+ vector = vector.map((val) => val - dot1 / Math.sqrt(n));
611
643
 
612
644
  // Power iteration on shifted matrix
613
645
  for (let iter = 0; iter < 100; iter++) {
@@ -624,18 +656,18 @@ function computeSmallestEigenvectorsSimple(matrix: number[][], k: number, n: num
624
656
  for (let j = 0; j < n; j++) {
625
657
  const matrixVal = matrix[i]?.[j] ?? 0;
626
658
  const vecVal = vector[j] ?? 0;
627
- newVector[i] = (newVector[i] ?? 0) - ((matrixVal * vecVal) / maxEig);
659
+ newVector[i] = (newVector[i] ?? 0) - (matrixVal * vecVal) / maxEig;
628
660
  }
629
661
  }
630
662
 
631
663
  // Orthogonalize against first eigenvector
632
- const dot = newVector.reduce((sum, val) => sum + (val / Math.sqrt(n)), 0);
664
+ const dot = newVector.reduce((sum, val) => sum + val / Math.sqrt(n), 0);
633
665
  for (let i = 0; i < n; i++) {
634
- newVector[i] = (newVector[i] ?? 0) - (dot / Math.sqrt(n));
666
+ newVector[i] = (newVector[i] ?? 0) - dot / Math.sqrt(n);
635
667
  }
636
668
 
637
669
  // Normalize
638
- const norm = Math.sqrt(newVector.reduce((sum, val) => sum + (val * val), 0));
670
+ const norm = Math.sqrt(newVector.reduce((sum, val) => sum + val * val, 0));
639
671
  if (norm > 1e-10) {
640
672
  vector = newVector.map((val) => val / norm);
641
673
  }
@@ -647,12 +679,14 @@ function computeSmallestEigenvectorsSimple(matrix: number[][], k: number, n: num
647
679
 
648
680
  // For k = 3, add another eigenvector
649
681
  if (k >= 3) {
650
- let vector = Array(n).fill(0).map(() => Math.random() - 0.5);
682
+ let vector = Array(n)
683
+ .fill(0)
684
+ .map(() => Math.random() - 0.5);
651
685
 
652
686
  // Orthogonalize against previous eigenvectors
653
687
  for (const prev of eigenvectors) {
654
- const dot = vector.reduce((sum, val, idx) => sum + (val * (prev[idx] ?? 0)), 0);
655
- vector = vector.map((val, idx) => val - (dot * (prev[idx] ?? 0)));
688
+ const dot = vector.reduce((sum, val, idx) => sum + val * (prev[idx] ?? 0), 0);
689
+ vector = vector.map((val, idx) => val - dot * (prev[idx] ?? 0));
656
690
  }
657
691
 
658
692
  // Similar power iteration
@@ -669,20 +703,20 @@ function computeSmallestEigenvectorsSimple(matrix: number[][], k: number, n: num
669
703
  for (let j = 0; j < n; j++) {
670
704
  const matrixVal = matrix[i]?.[j] ?? 0;
671
705
  const vecVal = vector[j] ?? 0;
672
- newVector[i] = (newVector[i] ?? 0) - ((matrixVal * vecVal) / 2);
706
+ newVector[i] = (newVector[i] ?? 0) - (matrixVal * vecVal) / 2;
673
707
  }
674
708
  }
675
709
 
676
710
  // Orthogonalize
677
711
  for (const prev of eigenvectors) {
678
- const dot = newVector.reduce((sum, val, idx) => sum + (val * (prev[idx] ?? 0)), 0);
712
+ const dot = newVector.reduce((sum, val, idx) => sum + val * (prev[idx] ?? 0), 0);
679
713
  for (let i = 0; i < n; i++) {
680
- newVector[i] = (newVector[i] ?? 0) - (dot * (prev[i] ?? 0));
714
+ newVector[i] = (newVector[i] ?? 0) - dot * (prev[i] ?? 0);
681
715
  }
682
716
  }
683
717
 
684
718
  // Normalize
685
- const norm = Math.sqrt(newVector.reduce((sum, val) => sum + (val * val), 0));
719
+ const norm = Math.sqrt(newVector.reduce((sum, val) => sum + val * val, 0));
686
720
  if (norm > 1e-10) {
687
721
  vector = newVector.map((val) => val / norm);
688
722
  }
@@ -692,5 +726,5 @@ function computeSmallestEigenvectorsSimple(matrix: number[][], k: number, n: num
692
726
  eigenvalues.push(0.2); // Approximate
693
727
  }
694
728
 
695
- return {eigenvalues: eigenvalues.slice(0, k), eigenvectors: eigenvectors.slice(0, k)};
729
+ return { eigenvalues: eigenvalues.slice(0, k), eigenvectors: eigenvectors.slice(0, k) };
696
730
  }
package/src/core/graph.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type {Edge, GraphConfig, Node, NodeId} from "../types/index.js";
1
+ import type { Edge, GraphConfig, Node, NodeId } from "../types/index.js";
2
2
 
3
3
  /**
4
4
  * Core Graph data structure for the Graphty Algorithms library
@@ -13,12 +13,16 @@ export class Graph {
13
13
  private config: GraphConfig;
14
14
  private edgeCount: number;
15
15
 
16
+ /**
17
+ * Creates a new Graph instance.
18
+ * @param config - Configuration options for the graph
19
+ */
16
20
  constructor(config: Partial<GraphConfig> = {}) {
17
21
  this.config = {
18
22
  directed: false,
19
23
  allowSelfLoops: true,
20
24
  allowParallelEdges: false,
21
- ... config,
25
+ ...config,
22
26
  };
23
27
  this.nodeMap = new Map();
24
28
  this.adjacencyList = new Map();
@@ -28,10 +32,12 @@ export class Graph {
28
32
 
29
33
  /**
30
34
  * Add a node to the graph
35
+ * @param id - The unique identifier for the node
36
+ * @param data - Optional key-value data to attach to the node
31
37
  */
32
38
  addNode(id: NodeId, data?: Record<string, unknown>): void {
33
39
  if (!this.nodeMap.has(id)) {
34
- this.nodeMap.set(id, {id, data});
40
+ this.nodeMap.set(id, { id, data });
35
41
  this.adjacencyList.set(id, new Map());
36
42
 
37
43
  if (this.config.directed) {
@@ -42,6 +48,8 @@ export class Graph {
42
48
 
43
49
  /**
44
50
  * Remove a node from the graph
51
+ * @param id - The unique identifier of the node to remove
52
+ * @returns True if the node was removed, false if it did not exist
45
53
  */
46
54
  removeNode(id: NodeId): boolean {
47
55
  if (!this.nodeMap.has(id)) {
@@ -85,6 +93,10 @@ export class Graph {
85
93
 
86
94
  /**
87
95
  * Add an edge to the graph
96
+ * @param source - The source node identifier
97
+ * @param target - The target node identifier
98
+ * @param weight - The weight of the edge (defaults to 1)
99
+ * @param data - Optional key-value data to attach to the edge
88
100
  */
89
101
  addEdge(source: NodeId, target: NodeId, weight = 1, data?: Record<string, unknown>): void {
90
102
  // Ensure both nodes exist
@@ -101,7 +113,7 @@ export class Graph {
101
113
  throw new Error("Parallel edges are not allowed in this graph");
102
114
  }
103
115
 
104
- const edge: Edge = {source, target, weight, data};
116
+ const edge: Edge = { source, target, weight, data };
105
117
 
106
118
  // Add to adjacency list
107
119
  const sourceAdjacency = this.adjacencyList.get(source);
@@ -120,7 +132,7 @@ export class Graph {
120
132
  } else {
121
133
  // For undirected graphs, add the reverse edge
122
134
  if (source !== target) {
123
- const reverseEdge: Edge = {source: target, target: source, weight, data};
135
+ const reverseEdge: Edge = { source: target, target: source, weight, data };
124
136
  const targetAdjacency = this.adjacencyList.get(target);
125
137
 
126
138
  if (targetAdjacency) {
@@ -134,6 +146,9 @@ export class Graph {
134
146
 
135
147
  /**
136
148
  * Remove an edge from the graph
149
+ * @param source - The source node identifier
150
+ * @param target - The target node identifier
151
+ * @returns True if the edge was removed, false if it did not exist
137
152
  */
138
153
  removeEdge(source: NodeId, target: NodeId): boolean {
139
154
  const sourceEdges = this.adjacencyList.get(source);
@@ -162,6 +177,8 @@ export class Graph {
162
177
 
163
178
  /**
164
179
  * Check if a node exists in the graph
180
+ * @param id - The unique identifier of the node to check
181
+ * @returns True if the node exists, false otherwise
165
182
  */
166
183
  hasNode(id: NodeId): boolean {
167
184
  return this.nodeMap.has(id);
@@ -169,6 +186,9 @@ export class Graph {
169
186
 
170
187
  /**
171
188
  * Check if an edge exists in the graph
189
+ * @param source - The source node identifier
190
+ * @param target - The target node identifier
191
+ * @returns True if the edge exists, false otherwise
172
192
  */
173
193
  hasEdge(source: NodeId, target: NodeId): boolean {
174
194
  const sourceEdges = this.adjacencyList.get(source);
@@ -177,6 +197,8 @@ export class Graph {
177
197
 
178
198
  /**
179
199
  * Get a node by ID
200
+ * @param id - The unique identifier of the node to retrieve
201
+ * @returns The node if found, undefined otherwise
180
202
  */
181
203
  getNode(id: NodeId): Node | undefined {
182
204
  return this.nodeMap.get(id);
@@ -184,6 +206,9 @@ export class Graph {
184
206
 
185
207
  /**
186
208
  * Get an edge by source and target
209
+ * @param source - The source node identifier
210
+ * @param target - The target node identifier
211
+ * @returns The edge if found, undefined otherwise
187
212
  */
188
213
  getEdge(source: NodeId, target: NodeId): Edge | undefined {
189
214
  const sourceEdges = this.adjacencyList.get(source);
@@ -192,6 +217,7 @@ export class Graph {
192
217
 
193
218
  /**
194
219
  * Get the number of nodes in the graph
220
+ * @returns The total count of nodes
195
221
  */
196
222
  get nodeCount(): number {
197
223
  return this.nodeMap.size;
@@ -199,6 +225,7 @@ export class Graph {
199
225
 
200
226
  /**
201
227
  * Get the number of edges in the graph
228
+ * @returns The total count of edges
202
229
  */
203
230
  get totalEdgeCount(): number {
204
231
  return this.edgeCount;
@@ -206,6 +233,7 @@ export class Graph {
206
233
 
207
234
  /**
208
235
  * Check if the graph is directed
236
+ * @returns True if the graph is directed, false otherwise
209
237
  */
210
238
  get isDirected(): boolean {
211
239
  return this.config.directed;
@@ -213,6 +241,7 @@ export class Graph {
213
241
 
214
242
  /**
215
243
  * Get all nodes in the graph
244
+ * @returns An iterator over all nodes
216
245
  */
217
246
  nodes(): IterableIterator<Node> {
218
247
  return this.nodeMap.values();
@@ -220,6 +249,7 @@ export class Graph {
220
249
 
221
250
  /**
222
251
  * Get all edges in the graph
252
+ * @yields Each unique edge in the graph
223
253
  */
224
254
  *edges(): IterableIterator<Edge> {
225
255
  for (const [source, edges] of this.adjacencyList) {
@@ -236,6 +266,8 @@ export class Graph {
236
266
 
237
267
  /**
238
268
  * Get neighbors of a node (outgoing edges)
269
+ * @param nodeId - The node identifier to get neighbors for
270
+ * @returns An iterator over the neighbor node identifiers
239
271
  */
240
272
  neighbors(nodeId: NodeId): IterableIterator<NodeId> {
241
273
  const edges = this.adjacencyList.get(nodeId);
@@ -244,6 +276,8 @@ export class Graph {
244
276
 
245
277
  /**
246
278
  * Get incoming neighbors of a node (directed graphs only)
279
+ * @param nodeId - The node identifier to get incoming neighbors for
280
+ * @returns An iterator over the incoming neighbor node identifiers
247
281
  */
248
282
  inNeighbors(nodeId: NodeId): IterableIterator<NodeId> {
249
283
  if (!this.config.directed) {
@@ -256,6 +290,8 @@ export class Graph {
256
290
 
257
291
  /**
258
292
  * Get outgoing neighbors of a node
293
+ * @param nodeId - The node identifier to get outgoing neighbors for
294
+ * @returns An iterator over the outgoing neighbor node identifiers
259
295
  */
260
296
  outNeighbors(nodeId: NodeId): IterableIterator<NodeId> {
261
297
  return this.neighbors(nodeId);
@@ -263,6 +299,8 @@ export class Graph {
263
299
 
264
300
  /**
265
301
  * Get the degree of a node
302
+ * @param nodeId - The node identifier to get the degree for
303
+ * @returns The total degree of the node
266
304
  */
267
305
  degree(nodeId: NodeId): number {
268
306
  if (this.config.directed) {
@@ -275,6 +313,8 @@ export class Graph {
275
313
 
276
314
  /**
277
315
  * Get the in-degree of a node
316
+ * @param nodeId - The node identifier to get the in-degree for
317
+ * @returns The number of incoming edges to the node
278
318
  */
279
319
  inDegree(nodeId: NodeId): number {
280
320
  if (!this.config.directed) {
@@ -287,6 +327,8 @@ export class Graph {
287
327
 
288
328
  /**
289
329
  * Get the out-degree of a node
330
+ * @param nodeId - The node identifier to get the out-degree for
331
+ * @returns The number of outgoing edges from the node
290
332
  */
291
333
  outDegree(nodeId: NodeId): number {
292
334
  const edges = this.adjacencyList.get(nodeId);
@@ -295,23 +337,19 @@ export class Graph {
295
337
 
296
338
  /**
297
339
  * Create a copy of the graph
340
+ * @returns A new Graph instance with the same nodes and edges
298
341
  */
299
342
  clone(): Graph {
300
343
  const cloned = new Graph(this.config);
301
344
 
302
345
  // Copy nodes
303
346
  for (const node of this.nodeMap.values()) {
304
- cloned.addNode(node.id, node.data ? {... node.data} : undefined);
347
+ cloned.addNode(node.id, node.data ? { ...node.data } : undefined);
305
348
  }
306
349
 
307
350
  // Copy edges
308
351
  for (const edge of this.edges()) {
309
- cloned.addEdge(
310
- edge.source,
311
- edge.target,
312
- edge.weight,
313
- edge.data ? {... edge.data} : undefined,
314
- );
352
+ cloned.addEdge(edge.source, edge.target, edge.weight, edge.data ? { ...edge.data } : undefined);
315
353
  }
316
354
 
317
355
  return cloned;
@@ -319,9 +357,10 @@ export class Graph {
319
357
 
320
358
  /**
321
359
  * Get graph configuration
360
+ * @returns A copy of the graph configuration object
322
361
  */
323
362
  getConfig(): GraphConfig {
324
- return {... this.config};
363
+ return { ...this.config };
325
364
  }
326
365
 
327
366
  /**
@@ -337,6 +376,7 @@ export class Graph {
337
376
  /**
338
377
  * Get the number of unique edges in the graph
339
378
  * For undirected graphs, each edge is counted once
379
+ * @returns The count of unique edges
340
380
  */
341
381
  get uniqueEdgeCount(): number {
342
382
  if (this.config.directed) {
@@ -345,7 +385,7 @@ export class Graph {
345
385
 
346
386
  // For undirected graphs, we need to count each edge only once
347
387
  let count = 0;
348
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
388
+
349
389
  for (const _edge of this.edges()) {
350
390
  count++;
351
391
  }
@@ -2,5 +2,5 @@
2
2
  * Data structures supporting graph algorithms
3
3
  */
4
4
 
5
- export {PriorityQueue} from "./priority-queue.js";
6
- export {UnionFind} from "./union-find.js";
5
+ export { PriorityQueue } from "./priority-queue.js";
6
+ export { UnionFind } from "./union-find.js";