@optave/codegraph 3.7.0 → 3.8.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 (401) hide show
  1. package/README.md +28 -16
  2. package/dist/ast-analysis/engine.d.ts.map +1 -1
  3. package/dist/ast-analysis/engine.js +195 -30
  4. package/dist/ast-analysis/engine.js.map +1 -1
  5. package/dist/ast-analysis/metrics.d.ts +0 -3
  6. package/dist/ast-analysis/metrics.d.ts.map +1 -1
  7. package/dist/ast-analysis/metrics.js +30 -13
  8. package/dist/ast-analysis/metrics.js.map +1 -1
  9. package/dist/ast-analysis/rules/javascript.d.ts.map +1 -1
  10. package/dist/ast-analysis/rules/javascript.js +0 -1
  11. package/dist/ast-analysis/rules/javascript.js.map +1 -1
  12. package/dist/ast-analysis/shared.d.ts.map +1 -1
  13. package/dist/ast-analysis/shared.js +24 -19
  14. package/dist/ast-analysis/shared.js.map +1 -1
  15. package/dist/ast-analysis/visitor-utils.d.ts.map +1 -1
  16. package/dist/ast-analysis/visitor-utils.js +55 -39
  17. package/dist/ast-analysis/visitor-utils.js.map +1 -1
  18. package/dist/ast-analysis/visitor.d.ts.map +1 -1
  19. package/dist/ast-analysis/visitor.js +91 -70
  20. package/dist/ast-analysis/visitor.js.map +1 -1
  21. package/dist/ast-analysis/visitors/ast-store-visitor.d.ts.map +1 -1
  22. package/dist/ast-analysis/visitors/ast-store-visitor.js +52 -129
  23. package/dist/ast-analysis/visitors/ast-store-visitor.js.map +1 -1
  24. package/dist/ast-analysis/visitors/complexity-visitor.d.ts.map +1 -1
  25. package/dist/ast-analysis/visitors/complexity-visitor.js +32 -39
  26. package/dist/ast-analysis/visitors/complexity-visitor.js.map +1 -1
  27. package/dist/ast-analysis/visitors/dataflow-visitor.d.ts.map +1 -1
  28. package/dist/ast-analysis/visitors/dataflow-visitor.js +57 -38
  29. package/dist/ast-analysis/visitors/dataflow-visitor.js.map +1 -1
  30. package/dist/cli/commands/ast.js +2 -2
  31. package/dist/cli/commands/ast.js.map +1 -1
  32. package/dist/cli/commands/watch.d.ts.map +1 -1
  33. package/dist/cli/commands/watch.js +16 -2
  34. package/dist/cli/commands/watch.js.map +1 -1
  35. package/dist/db/connection.d.ts.map +1 -1
  36. package/dist/db/connection.js +29 -26
  37. package/dist/db/connection.js.map +1 -1
  38. package/dist/db/query-builder.d.ts.map +1 -1
  39. package/dist/db/query-builder.js +16 -5
  40. package/dist/db/query-builder.js.map +1 -1
  41. package/dist/db/repository/base.d.ts +10 -0
  42. package/dist/db/repository/base.d.ts.map +1 -1
  43. package/dist/db/repository/base.js +17 -0
  44. package/dist/db/repository/base.js.map +1 -1
  45. package/dist/db/repository/native-repository.d.ts +6 -1
  46. package/dist/db/repository/native-repository.d.ts.map +1 -1
  47. package/dist/db/repository/native-repository.js +77 -1
  48. package/dist/db/repository/native-repository.js.map +1 -1
  49. package/dist/db/repository/nodes.d.ts.map +1 -1
  50. package/dist/db/repository/nodes.js +8 -4
  51. package/dist/db/repository/nodes.js.map +1 -1
  52. package/dist/db/repository/sqlite-repository.d.ts +3 -0
  53. package/dist/db/repository/sqlite-repository.d.ts.map +1 -1
  54. package/dist/db/repository/sqlite-repository.js +26 -0
  55. package/dist/db/repository/sqlite-repository.js.map +1 -1
  56. package/dist/domain/analysis/brief.d.ts.map +1 -1
  57. package/dist/domain/analysis/brief.js +13 -17
  58. package/dist/domain/analysis/brief.js.map +1 -1
  59. package/dist/domain/analysis/context.d.ts.map +1 -1
  60. package/dist/domain/analysis/context.js +14 -11
  61. package/dist/domain/analysis/context.js.map +1 -1
  62. package/dist/domain/analysis/dependencies.d.ts.map +1 -1
  63. package/dist/domain/analysis/dependencies.js +53 -52
  64. package/dist/domain/analysis/dependencies.js.map +1 -1
  65. package/dist/domain/analysis/fn-impact.d.ts +2 -7
  66. package/dist/domain/analysis/fn-impact.d.ts.map +1 -1
  67. package/dist/domain/analysis/fn-impact.js +33 -31
  68. package/dist/domain/analysis/fn-impact.js.map +1 -1
  69. package/dist/domain/analysis/implementations.d.ts.map +1 -1
  70. package/dist/domain/analysis/implementations.js +11 -19
  71. package/dist/domain/analysis/implementations.js.map +1 -1
  72. package/dist/domain/analysis/module-map.d.ts.map +1 -1
  73. package/dist/domain/analysis/module-map.js +55 -76
  74. package/dist/domain/analysis/module-map.js.map +1 -1
  75. package/dist/domain/analysis/query-helpers.d.ts +7 -0
  76. package/dist/domain/analysis/query-helpers.d.ts.map +1 -1
  77. package/dist/domain/analysis/query-helpers.js +15 -1
  78. package/dist/domain/analysis/query-helpers.js.map +1 -1
  79. package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
  80. package/dist/domain/graph/builder/pipeline.js +315 -43
  81. package/dist/domain/graph/builder/pipeline.js.map +1 -1
  82. package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
  83. package/dist/domain/graph/builder/stages/build-edges.js +106 -1
  84. package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
  85. package/dist/domain/graph/builder/stages/collect-files.d.ts.map +1 -1
  86. package/dist/domain/graph/builder/stages/collect-files.js +17 -5
  87. package/dist/domain/graph/builder/stages/collect-files.js.map +1 -1
  88. package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
  89. package/dist/domain/graph/builder/stages/detect-changes.js +99 -51
  90. package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
  91. package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
  92. package/dist/domain/graph/builder/stages/finalize.js +34 -7
  93. package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
  94. package/dist/domain/graph/builder/stages/insert-nodes.d.ts.map +1 -1
  95. package/dist/domain/graph/builder/stages/insert-nodes.js +50 -26
  96. package/dist/domain/graph/builder/stages/insert-nodes.js.map +1 -1
  97. package/dist/domain/graph/builder/stages/resolve-imports.d.ts.map +1 -1
  98. package/dist/domain/graph/builder/stages/resolve-imports.js +95 -84
  99. package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
  100. package/dist/domain/graph/cycles.d.ts +6 -0
  101. package/dist/domain/graph/cycles.d.ts.map +1 -1
  102. package/dist/domain/graph/cycles.js +114 -22
  103. package/dist/domain/graph/cycles.js.map +1 -1
  104. package/dist/domain/graph/resolve.js +1 -1
  105. package/dist/domain/graph/resolve.js.map +1 -1
  106. package/dist/domain/graph/watcher.d.ts +2 -0
  107. package/dist/domain/graph/watcher.d.ts.map +1 -1
  108. package/dist/domain/graph/watcher.js +170 -75
  109. package/dist/domain/graph/watcher.js.map +1 -1
  110. package/dist/domain/parser.d.ts +1 -6
  111. package/dist/domain/parser.d.ts.map +1 -1
  112. package/dist/domain/parser.js +101 -32
  113. package/dist/domain/parser.js.map +1 -1
  114. package/dist/domain/search/generator.js +1 -1
  115. package/dist/domain/search/generator.js.map +1 -1
  116. package/dist/domain/search/models.d.ts +4 -3
  117. package/dist/domain/search/models.d.ts.map +1 -1
  118. package/dist/domain/search/models.js +18 -5
  119. package/dist/domain/search/models.js.map +1 -1
  120. package/dist/domain/search/search/hybrid.d.ts.map +1 -1
  121. package/dist/domain/search/search/hybrid.js +29 -18
  122. package/dist/domain/search/search/hybrid.js.map +1 -1
  123. package/dist/extractors/clojure.d.ts +12 -0
  124. package/dist/extractors/clojure.d.ts.map +1 -0
  125. package/dist/extractors/clojure.js +245 -0
  126. package/dist/extractors/clojure.js.map +1 -0
  127. package/dist/extractors/cuda.d.ts +11 -0
  128. package/dist/extractors/cuda.d.ts.map +1 -0
  129. package/dist/extractors/cuda.js +302 -0
  130. package/dist/extractors/cuda.js.map +1 -0
  131. package/dist/extractors/erlang.d.ts +14 -0
  132. package/dist/extractors/erlang.d.ts.map +1 -0
  133. package/dist/extractors/erlang.js +239 -0
  134. package/dist/extractors/erlang.js.map +1 -0
  135. package/dist/extractors/fsharp.d.ts +13 -0
  136. package/dist/extractors/fsharp.d.ts.map +1 -0
  137. package/dist/extractors/fsharp.js +218 -0
  138. package/dist/extractors/fsharp.js.map +1 -0
  139. package/dist/extractors/gleam.d.ts +14 -0
  140. package/dist/extractors/gleam.d.ts.map +1 -0
  141. package/dist/extractors/gleam.js +229 -0
  142. package/dist/extractors/gleam.js.map +1 -0
  143. package/dist/extractors/go.js +36 -33
  144. package/dist/extractors/go.js.map +1 -1
  145. package/dist/extractors/groovy.d.ts +10 -0
  146. package/dist/extractors/groovy.d.ts.map +1 -0
  147. package/dist/extractors/groovy.js +304 -0
  148. package/dist/extractors/groovy.js.map +1 -0
  149. package/dist/extractors/helpers.d.ts.map +1 -1
  150. package/dist/extractors/helpers.js +40 -29
  151. package/dist/extractors/helpers.js.map +1 -1
  152. package/dist/extractors/index.d.ts +11 -0
  153. package/dist/extractors/index.d.ts.map +1 -1
  154. package/dist/extractors/index.js +11 -0
  155. package/dist/extractors/index.js.map +1 -1
  156. package/dist/extractors/java.js +58 -46
  157. package/dist/extractors/java.js.map +1 -1
  158. package/dist/extractors/javascript.js +46 -45
  159. package/dist/extractors/javascript.js.map +1 -1
  160. package/dist/extractors/julia.d.ts +16 -0
  161. package/dist/extractors/julia.d.ts.map +1 -0
  162. package/dist/extractors/julia.js +287 -0
  163. package/dist/extractors/julia.js.map +1 -0
  164. package/dist/extractors/kotlin.js +84 -78
  165. package/dist/extractors/kotlin.js.map +1 -1
  166. package/dist/extractors/objc.d.ts +9 -0
  167. package/dist/extractors/objc.d.ts.map +1 -0
  168. package/dist/extractors/objc.js +406 -0
  169. package/dist/extractors/objc.js.map +1 -0
  170. package/dist/extractors/ocaml.js +74 -0
  171. package/dist/extractors/ocaml.js.map +1 -1
  172. package/dist/extractors/python.js +29 -24
  173. package/dist/extractors/python.js.map +1 -1
  174. package/dist/extractors/r.d.ts +13 -0
  175. package/dist/extractors/r.d.ts.map +1 -0
  176. package/dist/extractors/r.js +251 -0
  177. package/dist/extractors/r.js.map +1 -0
  178. package/dist/extractors/rust.js +41 -32
  179. package/dist/extractors/rust.js.map +1 -1
  180. package/dist/extractors/solidity.d.ts +9 -0
  181. package/dist/extractors/solidity.d.ts.map +1 -0
  182. package/dist/extractors/solidity.js +365 -0
  183. package/dist/extractors/solidity.js.map +1 -0
  184. package/dist/extractors/swift.js +83 -81
  185. package/dist/extractors/swift.js.map +1 -1
  186. package/dist/extractors/verilog.d.ts +9 -0
  187. package/dist/extractors/verilog.d.ts.map +1 -0
  188. package/dist/extractors/verilog.js +286 -0
  189. package/dist/extractors/verilog.js.map +1 -0
  190. package/dist/extractors/zig.js +58 -60
  191. package/dist/extractors/zig.js.map +1 -1
  192. package/dist/features/ast.d.ts +16 -14
  193. package/dist/features/ast.d.ts.map +1 -1
  194. package/dist/features/ast.js +84 -83
  195. package/dist/features/ast.js.map +1 -1
  196. package/dist/features/audit.d.ts.map +1 -1
  197. package/dist/features/audit.js +8 -6
  198. package/dist/features/audit.js.map +1 -1
  199. package/dist/features/branch-compare.d.ts.map +1 -1
  200. package/dist/features/branch-compare.js +69 -72
  201. package/dist/features/branch-compare.js.map +1 -1
  202. package/dist/features/communities.d.ts.map +1 -1
  203. package/dist/features/communities.js +19 -7
  204. package/dist/features/communities.js.map +1 -1
  205. package/dist/features/complexity.d.ts.map +1 -1
  206. package/dist/features/complexity.js +120 -125
  207. package/dist/features/complexity.js.map +1 -1
  208. package/dist/features/dataflow.d.ts.map +1 -1
  209. package/dist/features/dataflow.js +136 -137
  210. package/dist/features/dataflow.js.map +1 -1
  211. package/dist/features/flow.d.ts.map +1 -1
  212. package/dist/features/flow.js +84 -79
  213. package/dist/features/flow.js.map +1 -1
  214. package/dist/features/structure-query.d.ts.map +1 -1
  215. package/dist/features/structure-query.js +69 -65
  216. package/dist/features/structure-query.js.map +1 -1
  217. package/dist/graph/algorithms/bfs.d.ts +2 -0
  218. package/dist/graph/algorithms/bfs.d.ts.map +1 -1
  219. package/dist/graph/algorithms/bfs.js +27 -0
  220. package/dist/graph/algorithms/bfs.js.map +1 -1
  221. package/dist/graph/algorithms/centrality.d.ts +2 -0
  222. package/dist/graph/algorithms/centrality.d.ts.map +1 -1
  223. package/dist/graph/algorithms/centrality.js +28 -0
  224. package/dist/graph/algorithms/centrality.js.map +1 -1
  225. package/dist/graph/algorithms/leiden/optimiser.d.ts.map +1 -1
  226. package/dist/graph/algorithms/leiden/optimiser.js +70 -55
  227. package/dist/graph/algorithms/leiden/optimiser.js.map +1 -1
  228. package/dist/graph/algorithms/leiden/partition.d.ts.map +1 -1
  229. package/dist/graph/algorithms/leiden/partition.js +288 -266
  230. package/dist/graph/algorithms/leiden/partition.js.map +1 -1
  231. package/dist/graph/algorithms/louvain.d.ts +3 -4
  232. package/dist/graph/algorithms/louvain.d.ts.map +1 -1
  233. package/dist/graph/algorithms/louvain.js +29 -0
  234. package/dist/graph/algorithms/louvain.js.map +1 -1
  235. package/dist/graph/algorithms/shortest-path.d.ts +2 -0
  236. package/dist/graph/algorithms/shortest-path.d.ts.map +1 -1
  237. package/dist/graph/algorithms/shortest-path.js +18 -1
  238. package/dist/graph/algorithms/shortest-path.js.map +1 -1
  239. package/dist/graph/model.d.ts.map +1 -1
  240. package/dist/graph/model.js +5 -1
  241. package/dist/graph/model.js.map +1 -1
  242. package/dist/infrastructure/config.d.ts.map +1 -1
  243. package/dist/infrastructure/config.js +6 -4
  244. package/dist/infrastructure/config.js.map +1 -1
  245. package/dist/infrastructure/suppress.d.ts +25 -0
  246. package/dist/infrastructure/suppress.d.ts.map +1 -0
  247. package/dist/infrastructure/suppress.js +43 -0
  248. package/dist/infrastructure/suppress.js.map +1 -0
  249. package/dist/mcp/server.d.ts.map +1 -1
  250. package/dist/mcp/server.js +29 -24
  251. package/dist/mcp/server.js.map +1 -1
  252. package/dist/presentation/dataflow.d.ts.map +1 -1
  253. package/dist/presentation/dataflow.js +47 -38
  254. package/dist/presentation/dataflow.js.map +1 -1
  255. package/dist/presentation/diff-impact-mermaid.d.ts.map +1 -1
  256. package/dist/presentation/diff-impact-mermaid.js +60 -51
  257. package/dist/presentation/diff-impact-mermaid.js.map +1 -1
  258. package/dist/presentation/queries-cli/exports.d.ts.map +1 -1
  259. package/dist/presentation/queries-cli/exports.js +20 -14
  260. package/dist/presentation/queries-cli/exports.js.map +1 -1
  261. package/dist/presentation/queries-cli/impact.d.ts.map +1 -1
  262. package/dist/presentation/queries-cli/impact.js +15 -13
  263. package/dist/presentation/queries-cli/impact.js.map +1 -1
  264. package/dist/presentation/queries-cli/inspect.d.ts.map +1 -1
  265. package/dist/presentation/queries-cli/inspect.js +101 -79
  266. package/dist/presentation/queries-cli/inspect.js.map +1 -1
  267. package/dist/presentation/queries-cli/overview.d.ts.map +1 -1
  268. package/dist/presentation/queries-cli/overview.js +25 -16
  269. package/dist/presentation/queries-cli/overview.js.map +1 -1
  270. package/dist/presentation/queries-cli/path.js +26 -20
  271. package/dist/presentation/queries-cli/path.js.map +1 -1
  272. package/dist/presentation/result-formatter.d.ts +10 -0
  273. package/dist/presentation/result-formatter.d.ts.map +1 -1
  274. package/dist/presentation/result-formatter.js +16 -1
  275. package/dist/presentation/result-formatter.js.map +1 -1
  276. package/dist/presentation/viewer.d.ts.map +1 -1
  277. package/dist/presentation/viewer.js +18 -12
  278. package/dist/presentation/viewer.js.map +1 -1
  279. package/dist/shared/errors.d.ts +5 -0
  280. package/dist/shared/errors.d.ts.map +1 -1
  281. package/dist/shared/errors.js +5 -0
  282. package/dist/shared/errors.js.map +1 -1
  283. package/dist/shared/hierarchy.d.ts +8 -2
  284. package/dist/shared/hierarchy.d.ts.map +1 -1
  285. package/dist/shared/hierarchy.js +42 -1
  286. package/dist/shared/hierarchy.js.map +1 -1
  287. package/dist/shared/normalize.d.ts +6 -1
  288. package/dist/shared/normalize.d.ts.map +1 -1
  289. package/dist/shared/normalize.js +20 -12
  290. package/dist/shared/normalize.js.map +1 -1
  291. package/dist/shared/paginate.d.ts +0 -9
  292. package/dist/shared/paginate.d.ts.map +1 -1
  293. package/dist/shared/paginate.js +0 -15
  294. package/dist/shared/paginate.js.map +1 -1
  295. package/dist/types.d.ts +129 -3
  296. package/dist/types.d.ts.map +1 -1
  297. package/grammars/tree-sitter-clojure.wasm +0 -0
  298. package/grammars/tree-sitter-cuda.wasm +0 -0
  299. package/grammars/tree-sitter-erlang.wasm +0 -0
  300. package/grammars/tree-sitter-fsharp.wasm +0 -0
  301. package/grammars/tree-sitter-gleam.wasm +0 -0
  302. package/grammars/tree-sitter-groovy.wasm +0 -0
  303. package/grammars/tree-sitter-julia.wasm +0 -0
  304. package/grammars/tree-sitter-objc.wasm +0 -0
  305. package/grammars/tree-sitter-ocaml_interface.wasm +0 -0
  306. package/grammars/tree-sitter-r.wasm +0 -0
  307. package/grammars/tree-sitter-solidity.wasm +0 -0
  308. package/grammars/tree-sitter-verilog.wasm +0 -0
  309. package/package.json +18 -7
  310. package/src/ast-analysis/engine.ts +245 -42
  311. package/src/ast-analysis/metrics.ts +33 -11
  312. package/src/ast-analysis/rules/javascript.ts +0 -1
  313. package/src/ast-analysis/shared.ts +33 -24
  314. package/src/ast-analysis/visitor-utils.ts +52 -32
  315. package/src/ast-analysis/visitor.ts +132 -71
  316. package/src/ast-analysis/visitors/ast-store-visitor.ts +49 -119
  317. package/src/ast-analysis/visitors/complexity-visitor.ts +35 -40
  318. package/src/ast-analysis/visitors/dataflow-visitor.ts +87 -43
  319. package/src/cli/commands/ast.ts +2 -2
  320. package/src/cli/commands/watch.ts +16 -2
  321. package/src/db/connection.ts +29 -28
  322. package/src/db/query-builder.ts +15 -3
  323. package/src/db/repository/base.ts +20 -0
  324. package/src/db/repository/native-repository.ts +79 -1
  325. package/src/db/repository/nodes.ts +13 -8
  326. package/src/db/repository/sqlite-repository.ts +29 -0
  327. package/src/domain/analysis/brief.ts +15 -25
  328. package/src/domain/analysis/context.ts +17 -10
  329. package/src/domain/analysis/dependencies.ts +67 -76
  330. package/src/domain/analysis/fn-impact.ts +36 -43
  331. package/src/domain/analysis/implementations.ts +11 -17
  332. package/src/domain/analysis/module-map.ts +58 -92
  333. package/src/domain/analysis/query-helpers.ts +18 -1
  334. package/src/domain/graph/builder/pipeline.ts +366 -41
  335. package/src/domain/graph/builder/stages/build-edges.ts +162 -1
  336. package/src/domain/graph/builder/stages/collect-files.ts +18 -7
  337. package/src/domain/graph/builder/stages/detect-changes.ts +110 -56
  338. package/src/domain/graph/builder/stages/finalize.ts +41 -11
  339. package/src/domain/graph/builder/stages/insert-nodes.ts +75 -39
  340. package/src/domain/graph/builder/stages/resolve-imports.ts +122 -100
  341. package/src/domain/graph/cycles.ts +110 -23
  342. package/src/domain/graph/resolve.ts +1 -1
  343. package/src/domain/graph/watcher.ts +202 -96
  344. package/src/domain/parser.ts +122 -28
  345. package/src/domain/search/generator.ts +1 -1
  346. package/src/domain/search/models.ts +17 -4
  347. package/src/domain/search/search/hybrid.ts +69 -51
  348. package/src/extractors/clojure.ts +273 -0
  349. package/src/extractors/cuda.ts +316 -0
  350. package/src/extractors/erlang.ts +252 -0
  351. package/src/extractors/fsharp.ts +253 -0
  352. package/src/extractors/gleam.ts +246 -0
  353. package/src/extractors/go.ts +43 -33
  354. package/src/extractors/groovy.ts +332 -0
  355. package/src/extractors/helpers.ts +37 -23
  356. package/src/extractors/index.ts +11 -0
  357. package/src/extractors/java.ts +66 -47
  358. package/src/extractors/javascript.ts +45 -46
  359. package/src/extractors/julia.ts +318 -0
  360. package/src/extractors/kotlin.ts +84 -77
  361. package/src/extractors/objc.ts +431 -0
  362. package/src/extractors/ocaml.ts +78 -0
  363. package/src/extractors/python.ts +31 -25
  364. package/src/extractors/r.ts +253 -0
  365. package/src/extractors/rust.ts +37 -29
  366. package/src/extractors/solidity.ts +394 -0
  367. package/src/extractors/swift.ts +81 -80
  368. package/src/extractors/verilog.ts +315 -0
  369. package/src/extractors/zig.ts +58 -61
  370. package/src/features/ast.ts +131 -112
  371. package/src/features/audit.ts +8 -6
  372. package/src/features/branch-compare.ts +105 -79
  373. package/src/features/communities.ts +25 -10
  374. package/src/features/complexity.ts +171 -134
  375. package/src/features/dataflow.ts +165 -175
  376. package/src/features/flow.ts +129 -92
  377. package/src/features/structure-query.ts +79 -64
  378. package/src/graph/algorithms/bfs.ts +34 -0
  379. package/src/graph/algorithms/centrality.ts +30 -0
  380. package/src/graph/algorithms/leiden/optimiser.ts +99 -55
  381. package/src/graph/algorithms/leiden/partition.ts +359 -294
  382. package/src/graph/algorithms/louvain.ts +31 -4
  383. package/src/graph/algorithms/shortest-path.ts +20 -1
  384. package/src/graph/model.ts +6 -1
  385. package/src/infrastructure/config.ts +6 -4
  386. package/src/infrastructure/suppress.ts +47 -0
  387. package/src/mcp/server.ts +53 -37
  388. package/src/presentation/dataflow.ts +50 -44
  389. package/src/presentation/diff-impact-mermaid.ts +104 -62
  390. package/src/presentation/queries-cli/exports.ts +21 -13
  391. package/src/presentation/queries-cli/impact.ts +15 -13
  392. package/src/presentation/queries-cli/inspect.ts +100 -81
  393. package/src/presentation/queries-cli/overview.ts +26 -16
  394. package/src/presentation/queries-cli/path.ts +33 -25
  395. package/src/presentation/result-formatter.ts +19 -1
  396. package/src/presentation/viewer.ts +42 -14
  397. package/src/shared/errors.ts +6 -0
  398. package/src/shared/hierarchy.ts +50 -2
  399. package/src/shared/normalize.ts +31 -12
  400. package/src/shared/paginate.ts +0 -17
  401. package/src/types.ts +138 -3
@@ -17,6 +17,9 @@ function iget(a, i) {
17
17
  function u8get(a, i) {
18
18
  return a[i];
19
19
  }
20
+ /* ------------------------------------------------------------------ */
21
+ /* Aggregate helpers (shared by initializeAggregates & compact) */
22
+ /* ------------------------------------------------------------------ */
20
23
  /**
21
24
  * Accumulate per-community node-level totals (size, count, strength) into the
22
25
  * provided aggregate arrays. Both `initializeAggregates` and `compactCommunityIds`
@@ -101,303 +104,322 @@ function buildSortedCommunityIds(ids, opts, communityTotalSize, communityNodeCou
101
104
  a - b);
102
105
  }
103
106
  }
104
- export function makePartition(graph) {
105
- const n = graph.n;
106
- const nodeCommunity = new Int32Array(n);
107
- for (let i = 0; i < n; i++)
108
- nodeCommunity[i] = i;
109
- let communityCount = n;
110
- let communityTotalSize = new Float64Array(communityCount);
111
- let communityNodeCount = new Int32Array(communityCount);
112
- let communityInternalEdgeWeight = new Float64Array(communityCount);
113
- let communityTotalStrength = new Float64Array(communityCount);
114
- let communityTotalOutStrength = new Float64Array(communityCount);
115
- let communityTotalInStrength = new Float64Array(communityCount);
116
- const candidateCommunities = new Int32Array(n);
117
- let candidateCommunityCount = 0;
118
- const neighborEdgeWeightToCommunity = new Float64Array(n);
119
- const outEdgeWeightToCommunity = new Float64Array(n);
120
- const inEdgeWeightFromCommunity = new Float64Array(n);
121
- const isCandidateCommunity = new Uint8Array(n);
122
- function ensureCommCapacity(newCount) {
123
- if (newCount <= communityTotalSize.length)
124
- return;
125
- const growTo = Math.max(newCount, Math.ceil(communityTotalSize.length * 1.5));
126
- communityTotalSize = growFloat(communityTotalSize, growTo);
127
- communityNodeCount = growInt(communityNodeCount, growTo);
128
- communityInternalEdgeWeight = growFloat(communityInternalEdgeWeight, growTo);
129
- communityTotalStrength = growFloat(communityTotalStrength, growTo);
130
- communityTotalOutStrength = growFloat(communityTotalOutStrength, growTo);
131
- communityTotalInStrength = growFloat(communityTotalInStrength, growTo);
132
- }
133
- function initializeAggregates() {
134
- communityTotalSize.fill(0);
135
- communityNodeCount.fill(0);
136
- communityInternalEdgeWeight.fill(0);
137
- communityTotalStrength.fill(0);
138
- communityTotalOutStrength.fill(0);
139
- communityTotalInStrength.fill(0);
140
- accumulateNodeAggregates(graph, nodeCommunity, n, communityTotalSize, communityNodeCount, communityInternalEdgeWeight, communityTotalStrength, communityTotalOutStrength, communityTotalInStrength);
141
- accumulateInternalEdgeWeights(graph, nodeCommunity, n, communityInternalEdgeWeight);
142
- }
143
- function resetScratch() {
144
- for (let i = 0; i < candidateCommunityCount; i++) {
145
- const c = iget(candidateCommunities, i);
146
- isCandidateCommunity[c] = 0;
147
- neighborEdgeWeightToCommunity[c] = 0;
148
- outEdgeWeightToCommunity[c] = 0;
149
- inEdgeWeightFromCommunity[c] = 0;
150
- }
151
- candidateCommunityCount = 0;
152
- }
153
- function touch(c) {
154
- if (u8get(isCandidateCommunity, c))
155
- return;
156
- isCandidateCommunity[c] = 1;
157
- candidateCommunities[candidateCommunityCount++] = c;
107
+ /* ------------------------------------------------------------------ */
108
+ /* Extracted: capacity management */
109
+ /* ------------------------------------------------------------------ */
110
+ function ensureCommCapacity(s, newCount) {
111
+ if (newCount <= s.communityTotalSize.length)
112
+ return;
113
+ const growTo = Math.max(newCount, Math.ceil(s.communityTotalSize.length * 1.5));
114
+ s.communityTotalSize = growFloat(s.communityTotalSize, growTo);
115
+ s.communityNodeCount = growInt(s.communityNodeCount, growTo);
116
+ s.communityInternalEdgeWeight = growFloat(s.communityInternalEdgeWeight, growTo);
117
+ s.communityTotalStrength = growFloat(s.communityTotalStrength, growTo);
118
+ s.communityTotalOutStrength = growFloat(s.communityTotalOutStrength, growTo);
119
+ s.communityTotalInStrength = growFloat(s.communityTotalInStrength, growTo);
120
+ }
121
+ /* ------------------------------------------------------------------ */
122
+ /* Extracted: aggregate initialization */
123
+ /* ------------------------------------------------------------------ */
124
+ function initAggregates(s) {
125
+ s.communityTotalSize.fill(0);
126
+ s.communityNodeCount.fill(0);
127
+ s.communityInternalEdgeWeight.fill(0);
128
+ s.communityTotalStrength.fill(0);
129
+ s.communityTotalOutStrength.fill(0);
130
+ s.communityTotalInStrength.fill(0);
131
+ accumulateNodeAggregates(s.graph, s.nodeCommunity, s.n, s.communityTotalSize, s.communityNodeCount, s.communityInternalEdgeWeight, s.communityTotalStrength, s.communityTotalOutStrength, s.communityTotalInStrength);
132
+ accumulateInternalEdgeWeights(s.graph, s.nodeCommunity, s.n, s.communityInternalEdgeWeight);
133
+ }
134
+ /* ------------------------------------------------------------------ */
135
+ /* Extracted: neighbor accumulation */
136
+ /* ------------------------------------------------------------------ */
137
+ function resetScratch(s) {
138
+ for (let i = 0; i < s.candidateCommunityCount; i++) {
139
+ const c = iget(s.candidateCommunities, i);
140
+ s.isCandidateCommunity[c] = 0;
141
+ s.neighborEdgeWeightToCommunity[c] = 0;
142
+ s.outEdgeWeightToCommunity[c] = 0;
143
+ s.inEdgeWeightFromCommunity[c] = 0;
158
144
  }
159
- function accumulateNeighborCommunityEdgeWeights(v) {
160
- resetScratch();
161
- const ci = iget(nodeCommunity, v);
162
- touch(ci);
163
- if (graph.directed) {
164
- const outL = graph.outEdges[v];
165
- for (let k = 0; k < outL.length; k++) {
166
- const j = outL[k].to;
167
- const w = outL[k].w;
168
- const cj = iget(nodeCommunity, j);
169
- touch(cj);
170
- outEdgeWeightToCommunity[cj] = fget(outEdgeWeightToCommunity, cj) + w;
171
- }
172
- const inL = graph.inEdges[v];
173
- for (let k = 0; k < inL.length; k++) {
174
- const i2 = inL[k].from;
175
- const w = inL[k].w;
176
- const ci2 = iget(nodeCommunity, i2);
177
- touch(ci2);
178
- inEdgeWeightFromCommunity[ci2] = fget(inEdgeWeightFromCommunity, ci2) + w;
179
- }
145
+ s.candidateCommunityCount = 0;
146
+ }
147
+ function touchCandidate(s, c) {
148
+ if (u8get(s.isCandidateCommunity, c))
149
+ return;
150
+ s.isCandidateCommunity[c] = 1;
151
+ s.candidateCommunities[s.candidateCommunityCount++] = c;
152
+ }
153
+ function accumulateNeighborWeights(s, v) {
154
+ resetScratch(s);
155
+ const ci = iget(s.nodeCommunity, v);
156
+ touchCandidate(s, ci);
157
+ if (s.graph.directed) {
158
+ const outL = s.graph.outEdges[v];
159
+ for (let k = 0; k < outL.length; k++) {
160
+ const j = outL[k].to;
161
+ const w = outL[k].w;
162
+ const cj = iget(s.nodeCommunity, j);
163
+ touchCandidate(s, cj);
164
+ s.outEdgeWeightToCommunity[cj] = fget(s.outEdgeWeightToCommunity, cj) + w;
180
165
  }
181
- else {
182
- const list = graph.outEdges[v];
183
- for (let k = 0; k < list.length; k++) {
184
- const j = list[k].to;
185
- const w = list[k].w;
186
- const cj = iget(nodeCommunity, j);
187
- touch(cj);
188
- neighborEdgeWeightToCommunity[cj] = fget(neighborEdgeWeightToCommunity, cj) + w;
189
- }
166
+ const inL = s.graph.inEdges[v];
167
+ for (let k = 0; k < inL.length; k++) {
168
+ const i2 = inL[k].from;
169
+ const w = inL[k].w;
170
+ const ci2 = iget(s.nodeCommunity, i2);
171
+ touchCandidate(s, ci2);
172
+ s.inEdgeWeightFromCommunity[ci2] = fget(s.inEdgeWeightFromCommunity, ci2) + w;
190
173
  }
191
- return candidateCommunityCount;
192
174
  }
193
- const twoMUndirected = graph.totalWeight;
194
- function deltaModularityUndirected(v, newC, gamma = 1.0) {
195
- const oldC = iget(nodeCommunity, v);
196
- if (newC === oldC)
197
- return 0;
198
- const strengthV = fget(graph.strengthOut, v);
199
- const weightToNew = newC < neighborEdgeWeightToCommunity.length
200
- ? fget(neighborEdgeWeightToCommunity, newC) || 0
201
- : 0;
202
- const weightToOld = fget(neighborEdgeWeightToCommunity, oldC) || 0;
203
- const totalStrengthNew = newC < communityTotalStrength.length ? fget(communityTotalStrength, newC) : 0;
204
- const totalStrengthOld = fget(communityTotalStrength, oldC);
205
- const gain_remove = -(weightToOld / twoMUndirected -
206
- (gamma * (strengthV * totalStrengthOld)) / (twoMUndirected * twoMUndirected));
207
- const gain_add = weightToNew / twoMUndirected -
208
- (gamma * (strengthV * totalStrengthNew)) / (twoMUndirected * twoMUndirected);
209
- return gain_remove + gain_add;
175
+ else {
176
+ const list = s.graph.outEdges[v];
177
+ for (let k = 0; k < list.length; k++) {
178
+ const j = list[k].to;
179
+ const w = list[k].w;
180
+ const cj = iget(s.nodeCommunity, j);
181
+ touchCandidate(s, cj);
182
+ s.neighborEdgeWeightToCommunity[cj] = fget(s.neighborEdgeWeightToCommunity, cj) + w;
183
+ }
210
184
  }
211
- function deltaModularityDirected(v, newC, gamma = 1.0) {
212
- const oldC = iget(nodeCommunity, v);
213
- if (newC === oldC)
214
- return 0;
215
- const totalEdgeWeight = graph.totalWeight;
216
- const strengthOutV = fget(graph.strengthOut, v);
217
- const strengthInV = fget(graph.strengthIn, v);
218
- const inFromNew = newC < inEdgeWeightFromCommunity.length ? fget(inEdgeWeightFromCommunity, newC) || 0 : 0;
219
- const outToNew = newC < outEdgeWeightToCommunity.length ? fget(outEdgeWeightToCommunity, newC) || 0 : 0;
220
- const inFromOld = fget(inEdgeWeightFromCommunity, oldC) || 0;
221
- const outToOld = fget(outEdgeWeightToCommunity, oldC) || 0;
222
- const totalInStrengthNew = newC < communityTotalInStrength.length ? fget(communityTotalInStrength, newC) : 0;
223
- const totalOutStrengthNew = newC < communityTotalOutStrength.length ? fget(communityTotalOutStrength, newC) : 0;
224
- const totalInStrengthOld = fget(communityTotalInStrength, oldC);
225
- const totalOutStrengthOld = fget(communityTotalOutStrength, oldC);
226
- // Self-loop correction + constant term (see modularity.ts diffModularityDirected)
227
- const selfW = fget(graph.selfLoop, v) || 0;
228
- const deltaInternal = (inFromNew + outToNew - inFromOld - outToOld + 2 * selfW) / totalEdgeWeight;
229
- const deltaExpected = (gamma *
230
- (strengthOutV * (totalInStrengthNew - totalInStrengthOld) +
231
- strengthInV * (totalOutStrengthNew - totalOutStrengthOld) +
232
- 2 * strengthOutV * strengthInV)) /
233
- (totalEdgeWeight * totalEdgeWeight);
234
- return deltaInternal - deltaExpected;
185
+ return s.candidateCommunityCount;
186
+ }
187
+ /* ------------------------------------------------------------------ */
188
+ /* Extracted: modularity delta computations */
189
+ /* ------------------------------------------------------------------ */
190
+ function computeDeltaModularityUndirected(s, v, newC, gamma = 1.0) {
191
+ const oldC = iget(s.nodeCommunity, v);
192
+ if (newC === oldC)
193
+ return 0;
194
+ const twoM = s.graph.totalWeight;
195
+ const strengthV = fget(s.graph.strengthOut, v);
196
+ const weightToNew = newC < s.neighborEdgeWeightToCommunity.length
197
+ ? fget(s.neighborEdgeWeightToCommunity, newC) || 0
198
+ : 0;
199
+ const weightToOld = fget(s.neighborEdgeWeightToCommunity, oldC) || 0;
200
+ const totalStrengthNew = newC < s.communityTotalStrength.length ? fget(s.communityTotalStrength, newC) : 0;
201
+ const totalStrengthOld = fget(s.communityTotalStrength, oldC);
202
+ const gain_remove = -(weightToOld / twoM -
203
+ (gamma * (strengthV * totalStrengthOld)) / (twoM * twoM));
204
+ const gain_add = weightToNew / twoM - (gamma * (strengthV * totalStrengthNew)) / (twoM * twoM);
205
+ return gain_remove + gain_add;
206
+ }
207
+ function computeDeltaModularityDirected(s, v, newC, gamma = 1.0) {
208
+ const oldC = iget(s.nodeCommunity, v);
209
+ if (newC === oldC)
210
+ return 0;
211
+ const totalEdgeWeight = s.graph.totalWeight;
212
+ const strengthOutV = fget(s.graph.strengthOut, v);
213
+ const strengthInV = fget(s.graph.strengthIn, v);
214
+ const inFromNew = newC < s.inEdgeWeightFromCommunity.length ? fget(s.inEdgeWeightFromCommunity, newC) || 0 : 0;
215
+ const outToNew = newC < s.outEdgeWeightToCommunity.length ? fget(s.outEdgeWeightToCommunity, newC) || 0 : 0;
216
+ const inFromOld = fget(s.inEdgeWeightFromCommunity, oldC) || 0;
217
+ const outToOld = fget(s.outEdgeWeightToCommunity, oldC) || 0;
218
+ const totalInStrengthNew = newC < s.communityTotalInStrength.length ? fget(s.communityTotalInStrength, newC) : 0;
219
+ const totalOutStrengthNew = newC < s.communityTotalOutStrength.length ? fget(s.communityTotalOutStrength, newC) : 0;
220
+ const totalInStrengthOld = fget(s.communityTotalInStrength, oldC);
221
+ const totalOutStrengthOld = fget(s.communityTotalOutStrength, oldC);
222
+ // Self-loop correction + constant term (see modularity.ts diffModularityDirected)
223
+ const selfW = fget(s.graph.selfLoop, v) || 0;
224
+ const deltaInternal = (inFromNew + outToNew - inFromOld - outToOld + 2 * selfW) / totalEdgeWeight;
225
+ const deltaExpected = (gamma *
226
+ (strengthOutV * (totalInStrengthNew - totalInStrengthOld) +
227
+ strengthInV * (totalOutStrengthNew - totalOutStrengthOld) +
228
+ 2 * strengthOutV * strengthInV)) /
229
+ (totalEdgeWeight * totalEdgeWeight);
230
+ return deltaInternal - deltaExpected;
231
+ }
232
+ function computeDeltaCPM(s, v, newC, gamma = 1.0) {
233
+ const oldC = iget(s.nodeCommunity, v);
234
+ if (newC === oldC)
235
+ return 0;
236
+ let w_old;
237
+ let w_new;
238
+ let selfCorrection = 0;
239
+ if (s.graph.directed) {
240
+ w_old =
241
+ (fget(s.outEdgeWeightToCommunity, oldC) || 0) +
242
+ (fget(s.inEdgeWeightFromCommunity, oldC) || 0);
243
+ w_new =
244
+ newC < s.outEdgeWeightToCommunity.length
245
+ ? (fget(s.outEdgeWeightToCommunity, newC) || 0) +
246
+ (fget(s.inEdgeWeightFromCommunity, newC) || 0)
247
+ : 0;
248
+ // Self-loop correction (see cpm.ts diffCPM)
249
+ selfCorrection = 2 * (fget(s.graph.selfLoop, v) || 0);
235
250
  }
236
- function deltaCPM(v, newC, gamma = 1.0) {
237
- const oldC = iget(nodeCommunity, v);
238
- if (newC === oldC)
239
- return 0;
240
- let w_old;
241
- let w_new;
242
- let selfCorrection = 0;
243
- if (graph.directed) {
244
- w_old =
245
- (fget(outEdgeWeightToCommunity, oldC) || 0) + (fget(inEdgeWeightFromCommunity, oldC) || 0);
246
- w_new =
247
- newC < outEdgeWeightToCommunity.length
248
- ? (fget(outEdgeWeightToCommunity, newC) || 0) +
249
- (fget(inEdgeWeightFromCommunity, newC) || 0)
250
- : 0;
251
- // Self-loop correction (see cpm.ts diffCPM)
252
- selfCorrection = 2 * (fget(graph.selfLoop, v) || 0);
253
- }
254
- else {
255
- w_old = fget(neighborEdgeWeightToCommunity, oldC) || 0;
256
- w_new =
257
- newC < neighborEdgeWeightToCommunity.length
258
- ? fget(neighborEdgeWeightToCommunity, newC) || 0
259
- : 0;
260
- }
261
- const nodeSz = fget(graph.size, v) || 1;
262
- const sizeOld = fget(communityTotalSize, oldC) || 0;
263
- const sizeNew = newC < communityTotalSize.length ? fget(communityTotalSize, newC) : 0;
264
- return w_new - w_old + selfCorrection - gamma * nodeSz * (sizeNew - sizeOld + nodeSz);
251
+ else {
252
+ w_old = fget(s.neighborEdgeWeightToCommunity, oldC) || 0;
253
+ w_new =
254
+ newC < s.neighborEdgeWeightToCommunity.length
255
+ ? fget(s.neighborEdgeWeightToCommunity, newC) || 0
256
+ : 0;
265
257
  }
266
- function moveNodeToCommunity(v, newC) {
267
- const oldC = iget(nodeCommunity, v);
268
- if (oldC === newC)
269
- return false;
270
- if (newC >= communityCount) {
271
- ensureCommCapacity(newC + 1);
272
- communityCount = newC + 1;
273
- }
274
- const strengthOutV = fget(graph.strengthOut, v);
275
- const strengthInV = fget(graph.strengthIn, v);
276
- const selfLoopWeight = fget(graph.selfLoop, v);
277
- const nodeSz = fget(graph.size, v);
278
- communityNodeCount[oldC] = iget(communityNodeCount, oldC) - 1;
279
- communityNodeCount[newC] = iget(communityNodeCount, newC) + 1;
280
- communityTotalSize[oldC] = fget(communityTotalSize, oldC) - nodeSz;
281
- communityTotalSize[newC] = fget(communityTotalSize, newC) + nodeSz;
282
- if (graph.directed) {
283
- communityTotalOutStrength[oldC] = fget(communityTotalOutStrength, oldC) - strengthOutV;
284
- communityTotalOutStrength[newC] = fget(communityTotalOutStrength, newC) + strengthOutV;
285
- communityTotalInStrength[oldC] = fget(communityTotalInStrength, oldC) - strengthInV;
286
- communityTotalInStrength[newC] = fget(communityTotalInStrength, newC) + strengthInV;
287
- }
288
- else {
289
- communityTotalStrength[oldC] = fget(communityTotalStrength, oldC) - strengthOutV;
290
- communityTotalStrength[newC] = fget(communityTotalStrength, newC) + strengthOutV;
291
- }
292
- if (graph.directed) {
293
- const outToOld = fget(outEdgeWeightToCommunity, oldC) || 0;
294
- const inFromOld = fget(inEdgeWeightFromCommunity, oldC) || 0;
295
- const outToNew = newC < outEdgeWeightToCommunity.length ? fget(outEdgeWeightToCommunity, newC) || 0 : 0;
296
- const inFromNew = newC < inEdgeWeightFromCommunity.length ? fget(inEdgeWeightFromCommunity, newC) || 0 : 0;
297
- // outToOld/inFromOld already include the self-loop weight (self-loops are
298
- // in outEdges/inEdges), so subtract it once to avoid triple-counting.
299
- communityInternalEdgeWeight[oldC] =
300
- fget(communityInternalEdgeWeight, oldC) - (outToOld + inFromOld - selfLoopWeight);
301
- communityInternalEdgeWeight[newC] =
302
- fget(communityInternalEdgeWeight, newC) + (outToNew + inFromNew + selfLoopWeight);
303
- }
304
- else {
305
- const weightToOld = fget(neighborEdgeWeightToCommunity, oldC) || 0;
306
- const weightToNew = fget(neighborEdgeWeightToCommunity, newC) || 0;
307
- communityInternalEdgeWeight[oldC] =
308
- fget(communityInternalEdgeWeight, oldC) - (2 * weightToOld + selfLoopWeight);
309
- communityInternalEdgeWeight[newC] =
310
- fget(communityInternalEdgeWeight, newC) + (2 * weightToNew + selfLoopWeight);
311
- }
312
- nodeCommunity[v] = newC;
313
- return true;
258
+ const nodeSz = fget(s.graph.size, v) || 1;
259
+ const sizeOld = fget(s.communityTotalSize, oldC) || 0;
260
+ const sizeNew = newC < s.communityTotalSize.length ? fget(s.communityTotalSize, newC) : 0;
261
+ return w_new - w_old + selfCorrection - gamma * nodeSz * (sizeNew - sizeOld + nodeSz);
262
+ }
263
+ /* ------------------------------------------------------------------ */
264
+ /* Extracted: node move */
265
+ /* ------------------------------------------------------------------ */
266
+ function moveNode(s, v, newC) {
267
+ const oldC = iget(s.nodeCommunity, v);
268
+ if (oldC === newC)
269
+ return false;
270
+ if (newC >= s.communityCount) {
271
+ ensureCommCapacity(s, newC + 1);
272
+ s.communityCount = newC + 1;
314
273
  }
315
- function compactCommunityIds(opts = {}) {
316
- const ids = [];
317
- for (let c = 0; c < communityCount; c++)
318
- if (iget(communityNodeCount, c) > 0)
319
- ids.push(c);
320
- buildSortedCommunityIds(ids, opts, communityTotalSize, communityNodeCount);
321
- const newId = new Int32Array(communityCount).fill(-1);
322
- ids.forEach((c, i) => {
323
- newId[c] = i;
324
- });
325
- for (let i = 0; i < nodeCommunity.length; i++)
326
- nodeCommunity[i] = iget(newId, iget(nodeCommunity, i));
327
- const remappedCount = ids.length;
328
- const newTotalSize = new Float64Array(remappedCount);
329
- const newNodeCount = new Int32Array(remappedCount);
330
- const newInternalEdgeWeight = new Float64Array(remappedCount);
331
- const newTotalStrength = new Float64Array(remappedCount);
332
- const newTotalOutStrength = new Float64Array(remappedCount);
333
- const newTotalInStrength = new Float64Array(remappedCount);
334
- accumulateNodeAggregates(graph, nodeCommunity, n, newTotalSize, newNodeCount, newInternalEdgeWeight, newTotalStrength, newTotalOutStrength, newTotalInStrength);
335
- accumulateInternalEdgeWeights(graph, nodeCommunity, n, newInternalEdgeWeight);
336
- communityCount = remappedCount;
337
- communityTotalSize = newTotalSize;
338
- communityNodeCount = newNodeCount;
339
- communityInternalEdgeWeight = newInternalEdgeWeight;
340
- communityTotalStrength = newTotalStrength;
341
- communityTotalOutStrength = newTotalOutStrength;
342
- communityTotalInStrength = newTotalInStrength;
274
+ const strengthOutV = fget(s.graph.strengthOut, v);
275
+ const strengthInV = fget(s.graph.strengthIn, v);
276
+ const selfLoopWeight = fget(s.graph.selfLoop, v);
277
+ const nodeSz = fget(s.graph.size, v);
278
+ s.communityNodeCount[oldC] = iget(s.communityNodeCount, oldC) - 1;
279
+ s.communityNodeCount[newC] = iget(s.communityNodeCount, newC) + 1;
280
+ s.communityTotalSize[oldC] = fget(s.communityTotalSize, oldC) - nodeSz;
281
+ s.communityTotalSize[newC] = fget(s.communityTotalSize, newC) + nodeSz;
282
+ if (s.graph.directed) {
283
+ s.communityTotalOutStrength[oldC] = fget(s.communityTotalOutStrength, oldC) - strengthOutV;
284
+ s.communityTotalOutStrength[newC] = fget(s.communityTotalOutStrength, newC) + strengthOutV;
285
+ s.communityTotalInStrength[oldC] = fget(s.communityTotalInStrength, oldC) - strengthInV;
286
+ s.communityTotalInStrength[newC] = fget(s.communityTotalInStrength, newC) + strengthInV;
343
287
  }
344
- function getCommunityMembers() {
345
- const comms = new Array(communityCount);
346
- for (let i = 0; i < communityCount; i++)
347
- comms[i] = [];
348
- for (let i = 0; i < n; i++)
349
- comms[iget(nodeCommunity, i)].push(i);
350
- return comms;
288
+ else {
289
+ s.communityTotalStrength[oldC] = fget(s.communityTotalStrength, oldC) - strengthOutV;
290
+ s.communityTotalStrength[newC] = fget(s.communityTotalStrength, newC) + strengthOutV;
351
291
  }
352
- function getCommunityTotalSizeFn(c) {
353
- return c < communityTotalSize.length ? fget(communityTotalSize, c) : 0;
292
+ if (s.graph.directed) {
293
+ const outToOld = fget(s.outEdgeWeightToCommunity, oldC) || 0;
294
+ const inFromOld = fget(s.inEdgeWeightFromCommunity, oldC) || 0;
295
+ const outToNew = newC < s.outEdgeWeightToCommunity.length ? fget(s.outEdgeWeightToCommunity, newC) || 0 : 0;
296
+ const inFromNew = newC < s.inEdgeWeightFromCommunity.length ? fget(s.inEdgeWeightFromCommunity, newC) || 0 : 0;
297
+ // outToOld/inFromOld already include the self-loop weight (self-loops are
298
+ // in outEdges/inEdges), so subtract it once to avoid triple-counting.
299
+ s.communityInternalEdgeWeight[oldC] =
300
+ fget(s.communityInternalEdgeWeight, oldC) - (outToOld + inFromOld - selfLoopWeight);
301
+ s.communityInternalEdgeWeight[newC] =
302
+ fget(s.communityInternalEdgeWeight, newC) + (outToNew + inFromNew + selfLoopWeight);
354
303
  }
355
- function getCommunityNodeCountFn(c) {
356
- return c < communityNodeCount.length ? iget(communityNodeCount, c) : 0;
304
+ else {
305
+ const weightToOld = fget(s.neighborEdgeWeightToCommunity, oldC) || 0;
306
+ const weightToNew = fget(s.neighborEdgeWeightToCommunity, newC) || 0;
307
+ s.communityInternalEdgeWeight[oldC] =
308
+ fget(s.communityInternalEdgeWeight, oldC) - (2 * weightToOld + selfLoopWeight);
309
+ s.communityInternalEdgeWeight[newC] =
310
+ fget(s.communityInternalEdgeWeight, newC) + (2 * weightToNew + selfLoopWeight);
357
311
  }
312
+ s.nodeCommunity[v] = newC;
313
+ return true;
314
+ }
315
+ /* ------------------------------------------------------------------ */
316
+ /* Extracted: community compaction */
317
+ /* ------------------------------------------------------------------ */
318
+ function compactIds(s, opts = {}) {
319
+ const ids = [];
320
+ for (let c = 0; c < s.communityCount; c++)
321
+ if (iget(s.communityNodeCount, c) > 0)
322
+ ids.push(c);
323
+ buildSortedCommunityIds(ids, opts, s.communityTotalSize, s.communityNodeCount);
324
+ const newId = new Int32Array(s.communityCount).fill(-1);
325
+ ids.forEach((c, i) => {
326
+ newId[c] = i;
327
+ });
328
+ for (let i = 0; i < s.nodeCommunity.length; i++)
329
+ s.nodeCommunity[i] = iget(newId, iget(s.nodeCommunity, i));
330
+ const remappedCount = ids.length;
331
+ const newTotalSize = new Float64Array(remappedCount);
332
+ const newNodeCount = new Int32Array(remappedCount);
333
+ const newInternalEdgeWeight = new Float64Array(remappedCount);
334
+ const newTotalStrength = new Float64Array(remappedCount);
335
+ const newTotalOutStrength = new Float64Array(remappedCount);
336
+ const newTotalInStrength = new Float64Array(remappedCount);
337
+ accumulateNodeAggregates(s.graph, s.nodeCommunity, s.n, newTotalSize, newNodeCount, newInternalEdgeWeight, newTotalStrength, newTotalOutStrength, newTotalInStrength);
338
+ accumulateInternalEdgeWeights(s.graph, s.nodeCommunity, s.n, newInternalEdgeWeight);
339
+ s.communityCount = remappedCount;
340
+ s.communityTotalSize = newTotalSize;
341
+ s.communityNodeCount = newNodeCount;
342
+ s.communityInternalEdgeWeight = newInternalEdgeWeight;
343
+ s.communityTotalStrength = newTotalStrength;
344
+ s.communityTotalOutStrength = newTotalOutStrength;
345
+ s.communityTotalInStrength = newTotalInStrength;
346
+ }
347
+ /* ------------------------------------------------------------------ */
348
+ /* Factory: thin wrapper that wires state to extracted functions */
349
+ /* ------------------------------------------------------------------ */
350
+ export function makePartition(graph) {
351
+ const n = graph.n;
352
+ const nodeCommunity = new Int32Array(n);
353
+ for (let i = 0; i < n; i++)
354
+ nodeCommunity[i] = i;
355
+ const s = {
356
+ graph,
357
+ n,
358
+ nodeCommunity,
359
+ communityCount: n,
360
+ communityTotalSize: new Float64Array(n),
361
+ communityNodeCount: new Int32Array(n),
362
+ communityInternalEdgeWeight: new Float64Array(n),
363
+ communityTotalStrength: new Float64Array(n),
364
+ communityTotalOutStrength: new Float64Array(n),
365
+ communityTotalInStrength: new Float64Array(n),
366
+ candidateCommunities: new Int32Array(n),
367
+ candidateCommunityCount: 0,
368
+ neighborEdgeWeightToCommunity: new Float64Array(n),
369
+ outEdgeWeightToCommunity: new Float64Array(n),
370
+ inEdgeWeightFromCommunity: new Float64Array(n),
371
+ isCandidateCommunity: new Uint8Array(n),
372
+ };
358
373
  return {
359
374
  n,
360
375
  get communityCount() {
361
- return communityCount;
376
+ return s.communityCount;
362
377
  },
363
378
  nodeCommunity,
364
379
  get communityTotalSize() {
365
- return communityTotalSize;
380
+ return s.communityTotalSize;
366
381
  },
367
382
  get communityNodeCount() {
368
- return communityNodeCount;
383
+ return s.communityNodeCount;
369
384
  },
370
385
  get communityInternalEdgeWeight() {
371
- return communityInternalEdgeWeight;
386
+ return s.communityInternalEdgeWeight;
372
387
  },
373
388
  get communityTotalStrength() {
374
- return communityTotalStrength;
389
+ return s.communityTotalStrength;
375
390
  },
376
391
  get communityTotalOutStrength() {
377
- return communityTotalOutStrength;
392
+ return s.communityTotalOutStrength;
378
393
  },
379
394
  get communityTotalInStrength() {
380
- return communityTotalInStrength;
395
+ return s.communityTotalInStrength;
381
396
  },
382
397
  resizeCommunities(newCount) {
383
- ensureCommCapacity(newCount);
384
- communityCount = newCount;
398
+ ensureCommCapacity(s, newCount);
399
+ s.communityCount = newCount;
400
+ },
401
+ initializeAggregates: () => initAggregates(s),
402
+ accumulateNeighborCommunityEdgeWeights: (v) => accumulateNeighborWeights(s, v),
403
+ getCandidateCommunityCount: () => s.candidateCommunityCount,
404
+ getCandidateCommunityAt: (i) => iget(s.candidateCommunities, i),
405
+ getNeighborEdgeWeightToCommunity: (c) => fget(s.neighborEdgeWeightToCommunity, c) || 0,
406
+ getOutEdgeWeightToCommunity: (c) => fget(s.outEdgeWeightToCommunity, c) || 0,
407
+ getInEdgeWeightFromCommunity: (c) => fget(s.inEdgeWeightFromCommunity, c) || 0,
408
+ deltaModularityUndirected: (v, newC, gamma) => computeDeltaModularityUndirected(s, v, newC, gamma),
409
+ deltaModularityDirected: (v, newC, gamma) => computeDeltaModularityDirected(s, v, newC, gamma),
410
+ deltaCPM: (v, newC, gamma) => computeDeltaCPM(s, v, newC, gamma),
411
+ moveNodeToCommunity: (v, newC) => moveNode(s, v, newC),
412
+ compactCommunityIds: (opts) => compactIds(s, opts),
413
+ getCommunityMembers() {
414
+ const comms = new Array(s.communityCount);
415
+ for (let i = 0; i < s.communityCount; i++)
416
+ comms[i] = [];
417
+ for (let i = 0; i < n; i++)
418
+ comms[iget(nodeCommunity, i)].push(i);
419
+ return comms;
385
420
  },
386
- initializeAggregates,
387
- accumulateNeighborCommunityEdgeWeights,
388
- getCandidateCommunityCount: () => candidateCommunityCount,
389
- getCandidateCommunityAt: (i) => iget(candidateCommunities, i),
390
- getNeighborEdgeWeightToCommunity: (c) => fget(neighborEdgeWeightToCommunity, c) || 0,
391
- getOutEdgeWeightToCommunity: (c) => fget(outEdgeWeightToCommunity, c) || 0,
392
- getInEdgeWeightFromCommunity: (c) => fget(inEdgeWeightFromCommunity, c) || 0,
393
- deltaModularityUndirected,
394
- deltaModularityDirected,
395
- deltaCPM,
396
- moveNodeToCommunity,
397
- compactCommunityIds,
398
- getCommunityMembers,
399
- getCommunityTotalSize: getCommunityTotalSizeFn,
400
- getCommunityNodeCount: getCommunityNodeCountFn,
421
+ getCommunityTotalSize: (c) => c < s.communityTotalSize.length ? fget(s.communityTotalSize, c) : 0,
422
+ getCommunityNodeCount: (c) => c < s.communityNodeCount.length ? iget(s.communityNodeCount, c) : 0,
401
423
  graph: undefined,
402
424
  };
403
425
  }