okstra 0.130.4 → 0.131.0

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 (365) hide show
  1. package/README.md +0 -1
  2. package/docs/architecture.md +2 -2
  3. package/docs/cli.md +1 -1
  4. package/docs/for-ai/README.md +0 -2
  5. package/docs/for-ai/skills/okstra-run.md +13 -2
  6. package/docs/for-ai/skills/okstra-setup.md +4 -1
  7. package/docs/project-structure-overview.md +5 -4
  8. package/docs/task-process/implementation-planning.md +13 -0
  9. package/docs/task-process/implementation.md +17 -2
  10. package/package.json +1 -1
  11. package/runtime/BUILD.json +2 -2
  12. package/runtime/agents/workers/report-writer-worker.md +7 -0
  13. package/runtime/bin/lib/okstra/usage.sh +4 -4
  14. package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
  15. package/runtime/prompts/lead/plan-body-verification.md +26 -5
  16. package/runtime/prompts/lead/report-writer.md +6 -2
  17. package/runtime/prompts/profiles/_common-contract.md +2 -1
  18. package/runtime/prompts/profiles/_implementation-deliverable.md +6 -1
  19. package/runtime/prompts/profiles/_implementation-executor.md +2 -2
  20. package/runtime/prompts/profiles/_implementation-verifier.md +33 -10
  21. package/runtime/prompts/profiles/final-verification.md +21 -6
  22. package/runtime/prompts/profiles/implementation-planning.md +16 -4
  23. package/runtime/python/okstra_ctl/codex_dispatch.py +31 -0
  24. package/runtime/python/okstra_ctl/conformance.py +49 -11
  25. package/runtime/python/okstra_ctl/report_finalize.py +52 -1
  26. package/runtime/python/okstra_ctl/run.py +15 -3
  27. package/runtime/python/okstra_ctl/worker_prompt_contract.py +14 -6
  28. package/runtime/python/okstra_ctl/worker_prompt_policy.py +19 -1
  29. package/runtime/python/okstra_vendor/__init__.py +0 -44
  30. package/runtime/schemas/final-report-v1.0.schema.json +99 -5
  31. package/runtime/skills/okstra-run/SKILL.md +11 -4
  32. package/runtime/skills/okstra-setup/SKILL.md +3 -2
  33. package/runtime/skills/okstra-setup/references/project-config.md +16 -7
  34. package/runtime/templates/reports/final-report.template.md +15 -9
  35. package/runtime/templates/reports/i18n/en.json +1 -0
  36. package/runtime/templates/reports/i18n/ko.json +1 -0
  37. package/runtime/validators/lib/fixtures.sh +6 -0
  38. package/runtime/validators/validate-run.py +1722 -98
  39. package/src/cli-registry.mjs +0 -7
  40. package/src/commands/lifecycle/doctor.mjs +0 -9
  41. package/src/lib/skill-catalog.mjs +0 -1
  42. package/docs/for-ai/skills/okstra-graphify.md +0 -64
  43. package/runtime/python/okstra_ctl/graphify_cmd.py +0 -225
  44. package/runtime/python/okstra_vendor/graphify/.vendored-version +0 -1
  45. package/runtime/python/okstra_vendor/graphify/__init__.py +0 -28
  46. package/runtime/python/okstra_vendor/graphify/__main__.py +0 -1371
  47. package/runtime/python/okstra_vendor/graphify/analyze.py +0 -540
  48. package/runtime/python/okstra_vendor/graphify/benchmark.py +0 -129
  49. package/runtime/python/okstra_vendor/graphify/build.py +0 -107
  50. package/runtime/python/okstra_vendor/graphify/cache.py +0 -169
  51. package/runtime/python/okstra_vendor/graphify/cluster.py +0 -137
  52. package/runtime/python/okstra_vendor/graphify/detect.py +0 -510
  53. package/runtime/python/okstra_vendor/graphify/export.py +0 -1014
  54. package/runtime/python/okstra_vendor/graphify/extract.py +0 -3277
  55. package/runtime/python/okstra_vendor/graphify/hooks.py +0 -220
  56. package/runtime/python/okstra_vendor/graphify/ingest.py +0 -297
  57. package/runtime/python/okstra_vendor/graphify/manifest.py +0 -4
  58. package/runtime/python/okstra_vendor/graphify/report.py +0 -175
  59. package/runtime/python/okstra_vendor/graphify/security.py +0 -203
  60. package/runtime/python/okstra_vendor/graphify/serve.py +0 -373
  61. package/runtime/python/okstra_vendor/graphify/skill-aider.md +0 -1184
  62. package/runtime/python/okstra_vendor/graphify/skill-claw.md +0 -1184
  63. package/runtime/python/okstra_vendor/graphify/skill-codex.md +0 -1242
  64. package/runtime/python/okstra_vendor/graphify/skill-copilot.md +0 -1268
  65. package/runtime/python/okstra_vendor/graphify/skill-droid.md +0 -1239
  66. package/runtime/python/okstra_vendor/graphify/skill-kiro.md +0 -1183
  67. package/runtime/python/okstra_vendor/graphify/skill-opencode.md +0 -1238
  68. package/runtime/python/okstra_vendor/graphify/skill-trae.md +0 -1208
  69. package/runtime/python/okstra_vendor/graphify/skill-vscode.md +0 -253
  70. package/runtime/python/okstra_vendor/graphify/skill-windows.md +0 -1245
  71. package/runtime/python/okstra_vendor/graphify/skill.md +0 -1319
  72. package/runtime/python/okstra_vendor/graphify/transcribe.py +0 -182
  73. package/runtime/python/okstra_vendor/graphify/validate.py +0 -72
  74. package/runtime/python/okstra_vendor/graphify/watch.py +0 -188
  75. package/runtime/python/okstra_vendor/graphify/wiki.py +0 -214
  76. package/runtime/python/okstra_vendor/networkx/__init__.py +0 -62
  77. package/runtime/python/okstra_vendor/networkx/algorithms/__init__.py +0 -134
  78. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/__init__.py +0 -26
  79. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clique.py +0 -259
  80. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clustering_coefficient.py +0 -71
  81. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/connectivity.py +0 -412
  82. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/density.py +0 -396
  83. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/distance_measures.py +0 -150
  84. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/dominating_set.py +0 -149
  85. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/kcomponents.py +0 -369
  86. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/matching.py +0 -44
  87. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/maxcut.py +0 -143
  88. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/ramsey.py +0 -53
  89. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/steinertree.py +0 -265
  90. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/traveling_salesman.py +0 -1508
  91. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/treewidth.py +0 -255
  92. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/vertex_cover.py +0 -83
  93. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/__init__.py +0 -5
  94. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/connectivity.py +0 -122
  95. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/correlation.py +0 -302
  96. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/mixing.py +0 -255
  97. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/neighbor_degree.py +0 -160
  98. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/pairs.py +0 -127
  99. package/runtime/python/okstra_vendor/networkx/algorithms/asteroidal.py +0 -164
  100. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/__init__.py +0 -88
  101. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/basic.py +0 -322
  102. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/centrality.py +0 -290
  103. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/cluster.py +0 -289
  104. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/covering.py +0 -57
  105. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/edgelist.py +0 -360
  106. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/extendability.py +0 -105
  107. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/generators.py +0 -603
  108. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/link_analysis.py +0 -316
  109. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matching.py +0 -590
  110. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matrix.py +0 -232
  111. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/projection.py +0 -526
  112. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/redundancy.py +0 -112
  113. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/spectral.py +0 -69
  114. package/runtime/python/okstra_vendor/networkx/algorithms/boundary.py +0 -168
  115. package/runtime/python/okstra_vendor/networkx/algorithms/bridges.py +0 -205
  116. package/runtime/python/okstra_vendor/networkx/algorithms/broadcasting.py +0 -164
  117. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/__init__.py +0 -20
  118. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness.py +0 -591
  119. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness_subset.py +0 -236
  120. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/closeness.py +0 -282
  121. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness.py +0 -364
  122. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness_subset.py +0 -227
  123. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_closeness.py +0 -96
  124. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/degree_alg.py +0 -150
  125. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/dispersion.py +0 -107
  126. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/eigenvector.py +0 -357
  127. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/flow_matrix.py +0 -130
  128. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/group.py +0 -787
  129. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/harmonic.py +0 -88
  130. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/katz.py +0 -331
  131. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/laplacian.py +0 -150
  132. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/load.py +0 -200
  133. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/percolation.py +0 -128
  134. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/reaching.py +0 -209
  135. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/second_order.py +0 -141
  136. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/subgraph_alg.py +0 -361
  137. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/trophic.py +0 -181
  138. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/voterank_alg.py +0 -95
  139. package/runtime/python/okstra_vendor/networkx/algorithms/chains.py +0 -172
  140. package/runtime/python/okstra_vendor/networkx/algorithms/chordal.py +0 -443
  141. package/runtime/python/okstra_vendor/networkx/algorithms/clique.py +0 -818
  142. package/runtime/python/okstra_vendor/networkx/algorithms/cluster.py +0 -732
  143. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/__init__.py +0 -4
  144. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/equitable_coloring.py +0 -505
  145. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/greedy_coloring.py +0 -565
  146. package/runtime/python/okstra_vendor/networkx/algorithms/communicability_alg.py +0 -163
  147. package/runtime/python/okstra_vendor/networkx/algorithms/community/__init__.py +0 -28
  148. package/runtime/python/okstra_vendor/networkx/algorithms/community/asyn_fluid.py +0 -153
  149. package/runtime/python/okstra_vendor/networkx/algorithms/community/bipartitions.py +0 -354
  150. package/runtime/python/okstra_vendor/networkx/algorithms/community/centrality.py +0 -171
  151. package/runtime/python/okstra_vendor/networkx/algorithms/community/community_utils.py +0 -30
  152. package/runtime/python/okstra_vendor/networkx/algorithms/community/divisive.py +0 -216
  153. package/runtime/python/okstra_vendor/networkx/algorithms/community/kclique.py +0 -79
  154. package/runtime/python/okstra_vendor/networkx/algorithms/community/label_propagation.py +0 -338
  155. package/runtime/python/okstra_vendor/networkx/algorithms/community/leiden.py +0 -162
  156. package/runtime/python/okstra_vendor/networkx/algorithms/community/local.py +0 -220
  157. package/runtime/python/okstra_vendor/networkx/algorithms/community/louvain.py +0 -384
  158. package/runtime/python/okstra_vendor/networkx/algorithms/community/lukes.py +0 -227
  159. package/runtime/python/okstra_vendor/networkx/algorithms/community/modularity_max.py +0 -452
  160. package/runtime/python/okstra_vendor/networkx/algorithms/community/quality.py +0 -347
  161. package/runtime/python/okstra_vendor/networkx/algorithms/components/__init__.py +0 -6
  162. package/runtime/python/okstra_vendor/networkx/algorithms/components/attracting.py +0 -115
  163. package/runtime/python/okstra_vendor/networkx/algorithms/components/biconnected.py +0 -394
  164. package/runtime/python/okstra_vendor/networkx/algorithms/components/connected.py +0 -282
  165. package/runtime/python/okstra_vendor/networkx/algorithms/components/semiconnected.py +0 -71
  166. package/runtime/python/okstra_vendor/networkx/algorithms/components/strongly_connected.py +0 -359
  167. package/runtime/python/okstra_vendor/networkx/algorithms/components/weakly_connected.py +0 -196
  168. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/__init__.py +0 -11
  169. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/connectivity.py +0 -811
  170. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/cuts.py +0 -616
  171. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/disjoint_paths.py +0 -408
  172. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_augmentation.py +0 -1270
  173. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_kcomponents.py +0 -592
  174. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcomponents.py +0 -220
  175. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcutsets.py +0 -235
  176. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/stoerwagner.py +0 -152
  177. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/utils.py +0 -88
  178. package/runtime/python/okstra_vendor/networkx/algorithms/core.py +0 -588
  179. package/runtime/python/okstra_vendor/networkx/algorithms/covering.py +0 -142
  180. package/runtime/python/okstra_vendor/networkx/algorithms/cuts.py +0 -416
  181. package/runtime/python/okstra_vendor/networkx/algorithms/cycles.py +0 -1234
  182. package/runtime/python/okstra_vendor/networkx/algorithms/d_separation.py +0 -677
  183. package/runtime/python/okstra_vendor/networkx/algorithms/dag.py +0 -1392
  184. package/runtime/python/okstra_vendor/networkx/algorithms/distance_measures.py +0 -1095
  185. package/runtime/python/okstra_vendor/networkx/algorithms/distance_regular.py +0 -272
  186. package/runtime/python/okstra_vendor/networkx/algorithms/dominance.py +0 -142
  187. package/runtime/python/okstra_vendor/networkx/algorithms/dominating.py +0 -268
  188. package/runtime/python/okstra_vendor/networkx/algorithms/efficiency_measures.py +0 -167
  189. package/runtime/python/okstra_vendor/networkx/algorithms/euler.py +0 -470
  190. package/runtime/python/okstra_vendor/networkx/algorithms/flow/__init__.py +0 -11
  191. package/runtime/python/okstra_vendor/networkx/algorithms/flow/boykovkolmogorov.py +0 -370
  192. package/runtime/python/okstra_vendor/networkx/algorithms/flow/capacityscaling.py +0 -407
  193. package/runtime/python/okstra_vendor/networkx/algorithms/flow/dinitz_alg.py +0 -238
  194. package/runtime/python/okstra_vendor/networkx/algorithms/flow/edmondskarp.py +0 -241
  195. package/runtime/python/okstra_vendor/networkx/algorithms/flow/gomory_hu.py +0 -178
  196. package/runtime/python/okstra_vendor/networkx/algorithms/flow/maxflow.py +0 -611
  197. package/runtime/python/okstra_vendor/networkx/algorithms/flow/mincost.py +0 -356
  198. package/runtime/python/okstra_vendor/networkx/algorithms/flow/networksimplex.py +0 -662
  199. package/runtime/python/okstra_vendor/networkx/algorithms/flow/preflowpush.py +0 -425
  200. package/runtime/python/okstra_vendor/networkx/algorithms/flow/shortestaugmentingpath.py +0 -300
  201. package/runtime/python/okstra_vendor/networkx/algorithms/flow/utils.py +0 -194
  202. package/runtime/python/okstra_vendor/networkx/algorithms/graph_hashing.py +0 -435
  203. package/runtime/python/okstra_vendor/networkx/algorithms/graphical.py +0 -483
  204. package/runtime/python/okstra_vendor/networkx/algorithms/hierarchy.py +0 -57
  205. package/runtime/python/okstra_vendor/networkx/algorithms/hybrid.py +0 -196
  206. package/runtime/python/okstra_vendor/networkx/algorithms/isolate.py +0 -107
  207. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/__init__.py +0 -7
  208. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/ismags.py +0 -1306
  209. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorph.py +0 -336
  210. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorphvf2.py +0 -1262
  211. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/matchhelpers.py +0 -352
  212. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/temporalisomorphvf2.py +0 -308
  213. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tree_isomorphism.py +0 -264
  214. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2pp.py +0 -1102
  215. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2userfunc.py +0 -192
  216. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/__init__.py +0 -2
  217. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/hits_alg.py +0 -337
  218. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/pagerank_alg.py +0 -498
  219. package/runtime/python/okstra_vendor/networkx/algorithms/link_prediction.py +0 -687
  220. package/runtime/python/okstra_vendor/networkx/algorithms/lowest_common_ancestors.py +0 -280
  221. package/runtime/python/okstra_vendor/networkx/algorithms/matching.py +0 -1148
  222. package/runtime/python/okstra_vendor/networkx/algorithms/minors/__init__.py +0 -27
  223. package/runtime/python/okstra_vendor/networkx/algorithms/minors/contraction.py +0 -738
  224. package/runtime/python/okstra_vendor/networkx/algorithms/mis.py +0 -78
  225. package/runtime/python/okstra_vendor/networkx/algorithms/moral.py +0 -59
  226. package/runtime/python/okstra_vendor/networkx/algorithms/node_classification.py +0 -219
  227. package/runtime/python/okstra_vendor/networkx/algorithms/non_randomness.py +0 -155
  228. package/runtime/python/okstra_vendor/networkx/algorithms/operators/__init__.py +0 -4
  229. package/runtime/python/okstra_vendor/networkx/algorithms/operators/all.py +0 -324
  230. package/runtime/python/okstra_vendor/networkx/algorithms/operators/binary.py +0 -468
  231. package/runtime/python/okstra_vendor/networkx/algorithms/operators/product.py +0 -633
  232. package/runtime/python/okstra_vendor/networkx/algorithms/operators/unary.py +0 -77
  233. package/runtime/python/okstra_vendor/networkx/algorithms/perfect_graph.py +0 -73
  234. package/runtime/python/okstra_vendor/networkx/algorithms/planar_drawing.py +0 -464
  235. package/runtime/python/okstra_vendor/networkx/algorithms/planarity.py +0 -1463
  236. package/runtime/python/okstra_vendor/networkx/algorithms/polynomials.py +0 -306
  237. package/runtime/python/okstra_vendor/networkx/algorithms/reciprocity.py +0 -98
  238. package/runtime/python/okstra_vendor/networkx/algorithms/regular.py +0 -167
  239. package/runtime/python/okstra_vendor/networkx/algorithms/richclub.py +0 -138
  240. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/__init__.py +0 -5
  241. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/astar.py +0 -239
  242. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/dense.py +0 -264
  243. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/generic.py +0 -716
  244. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/unweighted.py +0 -625
  245. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/weighted.py +0 -2542
  246. package/runtime/python/okstra_vendor/networkx/algorithms/similarity.py +0 -2107
  247. package/runtime/python/okstra_vendor/networkx/algorithms/simple_paths.py +0 -966
  248. package/runtime/python/okstra_vendor/networkx/algorithms/smallworld.py +0 -404
  249. package/runtime/python/okstra_vendor/networkx/algorithms/smetric.py +0 -30
  250. package/runtime/python/okstra_vendor/networkx/algorithms/sparsifiers.py +0 -296
  251. package/runtime/python/okstra_vendor/networkx/algorithms/structuralholes.py +0 -374
  252. package/runtime/python/okstra_vendor/networkx/algorithms/summarization.py +0 -564
  253. package/runtime/python/okstra_vendor/networkx/algorithms/swap.py +0 -406
  254. package/runtime/python/okstra_vendor/networkx/algorithms/threshold.py +0 -981
  255. package/runtime/python/okstra_vendor/networkx/algorithms/time_dependent.py +0 -142
  256. package/runtime/python/okstra_vendor/networkx/algorithms/tournament.py +0 -406
  257. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/__init__.py +0 -5
  258. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/beamsearch.py +0 -90
  259. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/breadth_first_search.py +0 -576
  260. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/depth_first_search.py +0 -529
  261. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgebfs.py +0 -185
  262. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgedfs.py +0 -182
  263. package/runtime/python/okstra_vendor/networkx/algorithms/tree/__init__.py +0 -7
  264. package/runtime/python/okstra_vendor/networkx/algorithms/tree/branchings.py +0 -1042
  265. package/runtime/python/okstra_vendor/networkx/algorithms/tree/coding.py +0 -413
  266. package/runtime/python/okstra_vendor/networkx/algorithms/tree/decomposition.py +0 -88
  267. package/runtime/python/okstra_vendor/networkx/algorithms/tree/distance_measures.py +0 -219
  268. package/runtime/python/okstra_vendor/networkx/algorithms/tree/mst.py +0 -1281
  269. package/runtime/python/okstra_vendor/networkx/algorithms/tree/operations.py +0 -106
  270. package/runtime/python/okstra_vendor/networkx/algorithms/tree/recognition.py +0 -273
  271. package/runtime/python/okstra_vendor/networkx/algorithms/triads.py +0 -500
  272. package/runtime/python/okstra_vendor/networkx/algorithms/vitality.py +0 -76
  273. package/runtime/python/okstra_vendor/networkx/algorithms/voronoi.py +0 -86
  274. package/runtime/python/okstra_vendor/networkx/algorithms/walks.py +0 -77
  275. package/runtime/python/okstra_vendor/networkx/algorithms/wiener.py +0 -278
  276. package/runtime/python/okstra_vendor/networkx/classes/__init__.py +0 -13
  277. package/runtime/python/okstra_vendor/networkx/classes/coreviews.py +0 -435
  278. package/runtime/python/okstra_vendor/networkx/classes/digraph.py +0 -1363
  279. package/runtime/python/okstra_vendor/networkx/classes/filters.py +0 -95
  280. package/runtime/python/okstra_vendor/networkx/classes/function.py +0 -1549
  281. package/runtime/python/okstra_vendor/networkx/classes/graph.py +0 -2082
  282. package/runtime/python/okstra_vendor/networkx/classes/graphviews.py +0 -269
  283. package/runtime/python/okstra_vendor/networkx/classes/multidigraph.py +0 -977
  284. package/runtime/python/okstra_vendor/networkx/classes/multigraph.py +0 -1294
  285. package/runtime/python/okstra_vendor/networkx/classes/reportviews.py +0 -1447
  286. package/runtime/python/okstra_vendor/networkx/convert.py +0 -502
  287. package/runtime/python/okstra_vendor/networkx/convert_matrix.py +0 -1314
  288. package/runtime/python/okstra_vendor/networkx/drawing/__init__.py +0 -7
  289. package/runtime/python/okstra_vendor/networkx/drawing/layout.py +0 -2036
  290. package/runtime/python/okstra_vendor/networkx/drawing/nx_agraph.py +0 -470
  291. package/runtime/python/okstra_vendor/networkx/drawing/nx_latex.py +0 -570
  292. package/runtime/python/okstra_vendor/networkx/drawing/nx_pydot.py +0 -361
  293. package/runtime/python/okstra_vendor/networkx/drawing/nx_pylab.py +0 -2978
  294. package/runtime/python/okstra_vendor/networkx/exception.py +0 -131
  295. package/runtime/python/okstra_vendor/networkx/generators/__init__.py +0 -34
  296. package/runtime/python/okstra_vendor/networkx/generators/atlas.dat.gz +0 -0
  297. package/runtime/python/okstra_vendor/networkx/generators/atlas.py +0 -227
  298. package/runtime/python/okstra_vendor/networkx/generators/classic.py +0 -1091
  299. package/runtime/python/okstra_vendor/networkx/generators/cographs.py +0 -68
  300. package/runtime/python/okstra_vendor/networkx/generators/community.py +0 -1070
  301. package/runtime/python/okstra_vendor/networkx/generators/degree_seq.py +0 -886
  302. package/runtime/python/okstra_vendor/networkx/generators/directed.py +0 -572
  303. package/runtime/python/okstra_vendor/networkx/generators/duplication.py +0 -174
  304. package/runtime/python/okstra_vendor/networkx/generators/ego.py +0 -66
  305. package/runtime/python/okstra_vendor/networkx/generators/expanders.py +0 -499
  306. package/runtime/python/okstra_vendor/networkx/generators/geometric.py +0 -1037
  307. package/runtime/python/okstra_vendor/networkx/generators/harary_graph.py +0 -163
  308. package/runtime/python/okstra_vendor/networkx/generators/internet_as_graphs.py +0 -443
  309. package/runtime/python/okstra_vendor/networkx/generators/intersection.py +0 -125
  310. package/runtime/python/okstra_vendor/networkx/generators/interval_graph.py +0 -70
  311. package/runtime/python/okstra_vendor/networkx/generators/joint_degree_seq.py +0 -664
  312. package/runtime/python/okstra_vendor/networkx/generators/lattice.py +0 -405
  313. package/runtime/python/okstra_vendor/networkx/generators/line.py +0 -501
  314. package/runtime/python/okstra_vendor/networkx/generators/mycielski.py +0 -110
  315. package/runtime/python/okstra_vendor/networkx/generators/nonisomorphic_trees.py +0 -259
  316. package/runtime/python/okstra_vendor/networkx/generators/random_clustered.py +0 -117
  317. package/runtime/python/okstra_vendor/networkx/generators/random_graphs.py +0 -1416
  318. package/runtime/python/okstra_vendor/networkx/generators/small.py +0 -1070
  319. package/runtime/python/okstra_vendor/networkx/generators/social.py +0 -554
  320. package/runtime/python/okstra_vendor/networkx/generators/spectral_graph_forge.py +0 -120
  321. package/runtime/python/okstra_vendor/networkx/generators/stochastic.py +0 -54
  322. package/runtime/python/okstra_vendor/networkx/generators/sudoku.py +0 -131
  323. package/runtime/python/okstra_vendor/networkx/generators/time_series.py +0 -74
  324. package/runtime/python/okstra_vendor/networkx/generators/trees.py +0 -1070
  325. package/runtime/python/okstra_vendor/networkx/generators/triads.py +0 -94
  326. package/runtime/python/okstra_vendor/networkx/lazy_imports.py +0 -188
  327. package/runtime/python/okstra_vendor/networkx/linalg/__init__.py +0 -13
  328. package/runtime/python/okstra_vendor/networkx/linalg/algebraicconnectivity.py +0 -650
  329. package/runtime/python/okstra_vendor/networkx/linalg/attrmatrix.py +0 -466
  330. package/runtime/python/okstra_vendor/networkx/linalg/bethehessianmatrix.py +0 -77
  331. package/runtime/python/okstra_vendor/networkx/linalg/graphmatrix.py +0 -168
  332. package/runtime/python/okstra_vendor/networkx/linalg/laplacianmatrix.py +0 -512
  333. package/runtime/python/okstra_vendor/networkx/linalg/modularitymatrix.py +0 -166
  334. package/runtime/python/okstra_vendor/networkx/linalg/spectrum.py +0 -186
  335. package/runtime/python/okstra_vendor/networkx/readwrite/__init__.py +0 -17
  336. package/runtime/python/okstra_vendor/networkx/readwrite/adjlist.py +0 -330
  337. package/runtime/python/okstra_vendor/networkx/readwrite/edgelist.py +0 -489
  338. package/runtime/python/okstra_vendor/networkx/readwrite/gexf.py +0 -1084
  339. package/runtime/python/okstra_vendor/networkx/readwrite/gml.py +0 -879
  340. package/runtime/python/okstra_vendor/networkx/readwrite/graph6.py +0 -427
  341. package/runtime/python/okstra_vendor/networkx/readwrite/graphml.py +0 -1053
  342. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/__init__.py +0 -19
  343. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/adjacency.py +0 -156
  344. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/cytoscape.py +0 -190
  345. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/node_link.py +0 -261
  346. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tree.py +0 -137
  347. package/runtime/python/okstra_vendor/networkx/readwrite/leda.py +0 -108
  348. package/runtime/python/okstra_vendor/networkx/readwrite/multiline_adjlist.py +0 -393
  349. package/runtime/python/okstra_vendor/networkx/readwrite/p2g.py +0 -113
  350. package/runtime/python/okstra_vendor/networkx/readwrite/pajek.py +0 -286
  351. package/runtime/python/okstra_vendor/networkx/readwrite/sparse6.py +0 -379
  352. package/runtime/python/okstra_vendor/networkx/readwrite/text.py +0 -851
  353. package/runtime/python/okstra_vendor/networkx/relabel.py +0 -285
  354. package/runtime/python/okstra_vendor/networkx/utils/__init__.py +0 -8
  355. package/runtime/python/okstra_vendor/networkx/utils/backends.py +0 -2171
  356. package/runtime/python/okstra_vendor/networkx/utils/configs.py +0 -396
  357. package/runtime/python/okstra_vendor/networkx/utils/decorators.py +0 -1233
  358. package/runtime/python/okstra_vendor/networkx/utils/heaps.py +0 -338
  359. package/runtime/python/okstra_vendor/networkx/utils/mapped_queue.py +0 -297
  360. package/runtime/python/okstra_vendor/networkx/utils/misc.py +0 -703
  361. package/runtime/python/okstra_vendor/networkx/utils/random_sequence.py +0 -198
  362. package/runtime/python/okstra_vendor/networkx/utils/rcm.py +0 -159
  363. package/runtime/python/okstra_vendor/networkx/utils/union_find.py +0 -106
  364. package/runtime/skills/okstra-graphify/SKILL.md +0 -169
  365. package/src/commands/graphify.mjs +0 -32
@@ -1,396 +0,0 @@
1
- """Fast algorithms for the densest subgraph problem"""
2
-
3
- import math
4
-
5
- import networkx as nx
6
-
7
- __all__ = ["densest_subgraph"]
8
-
9
-
10
- def _greedy_plus_plus(G, iterations):
11
- if G.number_of_edges() == 0:
12
- return 0.0, set()
13
- if iterations < 1:
14
- raise ValueError(
15
- f"The number of iterations must be an integer >= 1. Provided: {iterations}"
16
- )
17
-
18
- loads = {node: 0 for node in G.nodes} # Load vector for Greedy++.
19
- best_density = 0.0 # Highest density encountered.
20
- best_subgraph = set() # Nodes of the best subgraph found.
21
-
22
- for _ in range(iterations):
23
- # Initialize heap for fast access to minimum weighted degree.
24
- heap = nx.utils.BinaryHeap()
25
-
26
- # Compute initial weighted degrees and add nodes to the heap.
27
- for node, degree in G.degree:
28
- heap.insert(node, loads[node] + degree)
29
- # Set up tracking for current graph state.
30
- remaining_nodes = set(G.nodes)
31
- num_edges = G.number_of_edges()
32
- current_degrees = dict(G.degree)
33
-
34
- while remaining_nodes:
35
- num_nodes = len(remaining_nodes)
36
-
37
- # Current density of the (implicit) graph
38
- current_density = num_edges / num_nodes
39
-
40
- # Update the best density.
41
- if current_density > best_density:
42
- best_density = current_density
43
- best_subgraph = set(remaining_nodes)
44
-
45
- # Pop the node with the smallest weighted degree.
46
- node, _ = heap.pop()
47
- if node not in remaining_nodes:
48
- continue # Skip nodes already removed.
49
-
50
- # Update the load of the popped node.
51
- loads[node] += current_degrees[node]
52
-
53
- # Update neighbors' degrees and the heap.
54
- for neighbor in G.neighbors(node):
55
- if neighbor in remaining_nodes:
56
- current_degrees[neighbor] -= 1
57
- num_edges -= 1
58
- heap.insert(neighbor, loads[neighbor] + current_degrees[neighbor])
59
-
60
- # Remove the node from the remaining nodes.
61
- remaining_nodes.remove(node)
62
-
63
- return best_density, best_subgraph
64
-
65
-
66
- def _fractional_peeling(G, b, x, node_to_idx, edge_to_idx):
67
- """
68
- Optimized fractional peeling using NumPy arrays.
69
-
70
- Parameters
71
- ----------
72
- G : networkx.Graph
73
- The input graph.
74
- b : numpy.ndarray
75
- Induced load vector.
76
- x : numpy.ndarray
77
- Fractional edge values.
78
- node_to_idx : dict
79
- Mapping from node to index.
80
- edge_to_idx : dict
81
- Mapping from edge to index.
82
-
83
- Returns
84
- -------
85
- best_density : float
86
- The best density found.
87
- best_subgraph : set
88
- The subset of nodes defining the densest subgraph.
89
- """
90
- heap = nx.utils.BinaryHeap()
91
-
92
- remaining_nodes = set(G.nodes)
93
-
94
- # Initialize heap with b values
95
- for idx, node in enumerate(G):
96
- heap.insert(node, b[idx])
97
-
98
- num_edges = G.number_of_edges()
99
-
100
- best_density = 0.0
101
- best_subgraph = set()
102
-
103
- while remaining_nodes:
104
- num_nodes = len(remaining_nodes)
105
- current_density = num_edges / num_nodes
106
-
107
- if current_density > best_density:
108
- best_density = current_density
109
- best_subgraph = set(remaining_nodes)
110
-
111
- # Pop the node with the smallest b
112
- node, _ = heap.pop()
113
- while node not in remaining_nodes:
114
- node, _ = heap.pop() # Clean the heap from stale values
115
-
116
- # Update neighbors b values by subtracting fractional x value
117
- for neighbor in G.neighbors(node):
118
- if neighbor in remaining_nodes:
119
- neighbor_idx = node_to_idx[neighbor]
120
- # Take off fractional value
121
- b[neighbor_idx] -= x[edge_to_idx[(neighbor, node)]]
122
- num_edges -= 1
123
- heap.insert(neighbor, b[neighbor_idx])
124
-
125
- remaining_nodes.remove(node) # peel off node
126
-
127
- return best_density, best_subgraph
128
-
129
-
130
- def _fista(G, iterations):
131
- if G.number_of_edges() == 0:
132
- return 0.0, set()
133
- if iterations < 1:
134
- raise ValueError(
135
- f"The number of iterations must be an integer >= 1. Provided: {iterations}"
136
- )
137
- import numpy as np
138
-
139
- # 1. Node Mapping: Assign a unique index to each node and edge
140
- node_to_idx = {node: idx for idx, node in enumerate(G)}
141
- num_nodes = G.number_of_nodes()
142
- num_undirected_edges = G.number_of_edges()
143
-
144
- # 2. Edge Mapping: Assign a unique index to each bidirectional edge
145
- bidirectional_edges = [(u, v) for u, v in G.edges] + [(v, u) for u, v in G.edges]
146
- edge_to_idx = {edge: idx for idx, edge in enumerate(bidirectional_edges)}
147
-
148
- num_edges = len(bidirectional_edges)
149
-
150
- # 3. Reverse Edge Mapping: Map each (bidirectional) edge to its reverse edge index
151
- reverse_edge_idx = np.empty(num_edges, dtype=np.int32)
152
- for idx in range(num_undirected_edges):
153
- reverse_edge_idx[idx] = num_undirected_edges + idx
154
- for idx in range(num_undirected_edges, 2 * num_undirected_edges):
155
- reverse_edge_idx[idx] = idx - num_undirected_edges
156
-
157
- # 4. Initialize Variables as NumPy Arrays
158
- x = np.full(num_edges, 0.5, dtype=np.float32)
159
- y = x.copy()
160
- z = np.zeros(num_edges, dtype=np.float32)
161
- b = np.zeros(num_nodes, dtype=np.float32) # Induced load vector
162
- tk = 1.0 # Momentum term
163
-
164
- # 5. Precompute Edge Source Indices
165
- edge_src_indices = np.array(
166
- [node_to_idx[u] for u, _ in bidirectional_edges], dtype=np.int32
167
- )
168
-
169
- # 6. Compute Learning Rate
170
- max_degree = max(deg for _, deg in G.degree)
171
- # 0.9 for floating point errs when max_degree is very large
172
- learning_rate = 0.9 / max_degree
173
-
174
- # 7. Iterative Updates
175
- for _ in range(iterations):
176
- # 7a. Update b: sum y over outgoing edges for each node
177
- b[:] = 0.0 # Reset b to zero
178
- np.add.at(b, edge_src_indices, y) # b_u = \sum_{v : (u,v) \in E(G)} y_{uv}
179
-
180
- # 7b. Compute z, z_{uv} = y_{uv} - 2 * learning_rate * b_u
181
- z = y - 2.0 * learning_rate * b[edge_src_indices]
182
-
183
- # 7c. Update Momentum Term
184
- tknew = (1.0 + math.sqrt(1 + 4.0 * tk**2)) / 2.0
185
-
186
- # 7d. Update x in a vectorized manner, x_{uv} = (z_{uv} - z_{vu} + 1.0) / 2.0
187
- new_xuv = (z - z[reverse_edge_idx] + 1.0) / 2.0
188
- clamped_x = np.clip(new_xuv, 0.0, 1.0) # Clamp x_{uv} between 0 and 1
189
-
190
- # Update y using the FISTA update formula (similar to gradient descent)
191
- y = (
192
- clamped_x
193
- + ((tk - 1.0) / tknew) * (clamped_x - x)
194
- + (tk / tknew) * (clamped_x - y)
195
- )
196
-
197
- # Update x
198
- x = clamped_x
199
-
200
- # Update tk, the momemntum term
201
- tk = tknew
202
-
203
- # Rebalance the b values! Otherwise performance is a bit suboptimal.
204
- b[:] = 0.0
205
- np.add.at(b, edge_src_indices, x) # b_u = \sum_{v : (u,v) \in E(G)} x_{uv}
206
-
207
- # Extract the actual (approximate) dense subgraph.
208
- return _fractional_peeling(G, b, x, node_to_idx, edge_to_idx)
209
-
210
-
211
- ALGORITHMS = {"greedy++": _greedy_plus_plus, "fista": _fista}
212
-
213
-
214
- @nx.utils.not_implemented_for("directed")
215
- @nx.utils.not_implemented_for("multigraph")
216
- @nx._dispatchable
217
- def densest_subgraph(G, iterations=1, *, method="fista"):
218
- r"""Returns an approximate densest subgraph for a graph `G`.
219
-
220
- This function runs an iterative algorithm to find the densest subgraph,
221
- and returns both the density and the subgraph. For a discussion on the
222
- notion of density used and the different algorithms available on
223
- networkx, please see the Notes section below.
224
-
225
- Parameters
226
- ----------
227
- G : NetworkX graph
228
- Undirected graph.
229
-
230
- iterations : int, optional (default=1)
231
- Number of iterations to use for the iterative algorithm. Can be
232
- specified positionally or as a keyword argument.
233
-
234
- method : string, optional (default='fista')
235
- The algorithm to use to approximate the densest subgraph. Supported
236
- options: 'greedy++' by Boob et al. [2]_ and 'fista' by Harb et al. [3]_.
237
- Must be specified as a keyword argument. Other inputs produce a
238
- ValueError.
239
-
240
- Returns
241
- -------
242
- d : float
243
- The density of the approximate subgraph found.
244
-
245
- S : set
246
- The subset of nodes defining the approximate densest subgraph.
247
-
248
- Examples
249
- --------
250
- >>> G = nx.star_graph(4)
251
- >>> nx.approximation.densest_subgraph(G, iterations=1)
252
- (0.8, {0, 1, 2, 3, 4})
253
-
254
- Notes
255
- -----
256
- **Problem Definition:**
257
- The densest subgraph problem (DSG) asks to find the subgraph
258
- $S \subseteq V(G)$ with maximum density. For a subset of the nodes of
259
- $G$, $S \subseteq V(G)$, define $E(S) = \{ (u,v) : (u,v)\in E(G),
260
- u\in S, v\in S \}$ as the set of edges with both endpoints in $S$.
261
- The density of $S$ is defined as $|E(S)|/|S|$, the ratio between the
262
- edges in the subgraph $G[S]$ and the number of nodes in that subgraph.
263
- Note that this is different from the standard graph theoretic definition
264
- of density, defined as $\frac{2|E(S)|}{|S|(|S|-1)}$, for historical
265
- reasons.
266
-
267
- **Exact Algorithms:**
268
- The densest subgraph problem is polynomial time solvable using maximum
269
- flow, commonly referred to as Goldberg's algorithm. However, the
270
- algorithm is quite involved. It first binary searches on the optimal
271
- density, $d^\ast$. For a guess of the density $d$, it sets up a flow
272
- network $G'$ with size $O(m)$. The maximum flow solution either
273
- informs the algorithm that no subgraph with density $d$ exists, or it
274
- provides a subgraph with density at least $d$. However, this is
275
- inherently bottlenecked by the maximum flow algorithm. For example, [2]_
276
- notes that Goldberg’s algorithm was not feasible on many large graphs
277
- even though they used a highly optimized maximum flow library.
278
-
279
- **Charikar's Greedy Peeling:**
280
- While exact solution algorithms are quite involved, there are several
281
- known approximation algorithms for the densest subgraph problem.
282
-
283
- Charikar [1]_ described a very simple 1/2-approximation algorithm for DSG
284
- known as the greedy "peeling" algorithm. The algorithm creates an
285
- ordering of the nodes as follows. The first node $v_1$ is the one with
286
- the smallest degree in $G$ (ties broken arbitrarily). It selects
287
- $v_2$ to be the smallest degree node in $G \setminus v_1$. Letting
288
- $G_i$ be the graph after removing $v_1, ..., v_i$ (with $G_0=G$),
289
- the algorithm returns the graph among $G_0, ..., G_n$ with the highest
290
- density.
291
-
292
- **Greedy++:**
293
- Boob et al. [2]_ generalized this algorithm into Greedy++, an iterative
294
- algorithm that runs several rounds of "peeling". In fact, Greedy++ with 1
295
- iteration is precisely Charikar's algorithm. The algorithm converges to a
296
- $(1-\epsilon)$ approximate densest subgraph in $O(\Delta(G)\log
297
- n/\epsilon^2)$ iterations, where $\Delta(G)$ is the maximum degree,
298
- and $n$ is the number of nodes in $G$. The algorithm also has other
299
- desirable properties as shown by [4]_ and [5]_.
300
-
301
- **FISTA Algorithm:**
302
- Harb et al. [3]_ gave a faster and more scalable algorithm using ideas
303
- from quadratic programming for the densest subgraph, which is based on a
304
- fast iterative shrinkage-thresholding algorithm (FISTA) algorithm. It is
305
- known that computing the densest subgraph can be formulated as the
306
- following convex optimization problem:
307
-
308
- Minimize $\sum_{u \in V(G)} b_u^2$
309
-
310
- Subject to:
311
-
312
- $b_u = \sum_{v: \{u,v\} \in E(G)} x_{uv}$ for all $u \in V(G)$
313
-
314
- $x_{uv} + x_{vu} = 1.0$ for all $\{u,v\} \in E(G)$
315
-
316
- $x_{uv} \geq 0, x_{vu} \geq 0$ for all $\{u,v\} \in E(G)$
317
-
318
- Here, $x_{uv}$ represents the fraction of edge $\{u,v\}$ assigned to
319
- $u$, and $x_{vu}$ to $v$.
320
-
321
- The FISTA algorithm efficiently solves this convex program using gradient
322
- descent with projections. For a learning rate $\alpha$, the algorithm
323
- does:
324
-
325
- 1. **Initialization**: Set $x^{(0)}_{uv} = x^{(0)}_{vu} = 0.5$ for all
326
- edges as a feasible solution.
327
-
328
- 2. **Gradient Update**: For iteration $k\geq 1$, set
329
- $x^{(k+1)}_{uv} = x^{(k)}_{uv} - 2 \alpha \sum_{v: \{u,v\} \in E(G)}
330
- x^{(k)}_{uv}$. However, now $x^{(k+1)}_{uv}$ might be infeasible!
331
- To ensure feasibility, we project $x^{(k+1)}_{uv}$.
332
-
333
- 3. **Projection to the Feasible Set**: Compute
334
- $b^{(k+1)}_u = \sum_{v: \{u,v\} \in E(G)} x^{(k)}_{uv}$ for all
335
- nodes $u$. Define $z^{(k+1)}_{uv} = x^{(k+1)}_{uv} - 2 \alpha
336
- b^{(k+1)}_u$. Update $x^{(k+1)}_{uv} =
337
- CLAMP((z^{(k+1)}_{uv} - z^{(k+1)}_{vu} + 1.0) / 2.0)$, where
338
- $CLAMP(x) = \max(0, \min(1, x))$.
339
-
340
- With a learning rate of $\alpha=1/\Delta(G)$, where $\Delta(G)$ is
341
- the maximum degree, the algorithm converges to the optimum solution of
342
- the convex program.
343
-
344
- **Fractional Peeling:**
345
- To obtain a **discrete** subgraph, we use fractional peeling, an
346
- adaptation of the standard peeling algorithm which peels the minimum
347
- degree vertex in each iteration, and returns the densest subgraph found
348
- along the way. Here, we instead peel the vertex with the smallest
349
- induced load $b_u$:
350
-
351
- 1. Compute $b_u$ and $x_{uv}$.
352
-
353
- 2. Iteratively remove the vertex with the smallest $b_u$, updating its
354
- neighbors' load by $x_{vu}$.
355
-
356
- Fractional peeling transforms the approximately optimal fractional
357
- values $b_u, x_{uv}$ into a discrete subgraph. Unlike traditional
358
- peeling, which removes the lowest-degree node, this method accounts for
359
- fractional edge contributions from the convex program.
360
-
361
- This approach is both scalable and theoretically sound, ensuring a quick
362
- approximation of the densest subgraph while leveraging fractional load
363
- balancing.
364
-
365
- References
366
- ----------
367
- .. [1] Charikar, Moses. "Greedy approximation algorithms for finding dense
368
- components in a graph." In International workshop on approximation
369
- algorithms for combinatorial optimization, pp. 84-95. Berlin, Heidelberg:
370
- Springer Berlin Heidelberg, 2000.
371
-
372
- .. [2] Boob, Digvijay, Yu Gao, Richard Peng, Saurabh Sawlani, Charalampos
373
- Tsourakakis, Di Wang, and Junxing Wang. "Flowless: Extracting densest
374
- subgraphs without flow computations." In Proceedings of The Web Conference
375
- 2020, pp. 573-583. 2020.
376
-
377
- .. [3] Harb, Elfarouk, Kent Quanrud, and Chandra Chekuri. "Faster and scalable
378
- algorithms for densest subgraph and decomposition." Advances in Neural
379
- Information Processing Systems 35 (2022): 26966-26979.
380
-
381
- .. [4] Harb, Elfarouk, Kent Quanrud, and Chandra Chekuri. "Convergence to
382
- lexicographically optimal base in a (contra) polymatroid and applications
383
- to densest subgraph and tree packing." arXiv preprint arXiv:2305.02987
384
- (2023).
385
-
386
- .. [5] Chekuri, Chandra, Kent Quanrud, and Manuel R. Torres. "Densest
387
- subgraph: Supermodularity, iterative peeling, and flow." In Proceedings of
388
- the 2022 Annual ACM-SIAM Symposium on Discrete Algorithms (SODA), pp.
389
- 1531-1555. Society for Industrial and Applied Mathematics, 2022.
390
- """
391
- try:
392
- algo = ALGORITHMS[method]
393
- except KeyError as e:
394
- raise ValueError(f"{method} is not a valid choice for an algorithm.") from e
395
-
396
- return algo(G, iterations)
@@ -1,150 +0,0 @@
1
- """Distance measures approximated metrics."""
2
-
3
- import networkx as nx
4
- from networkx.utils.decorators import py_random_state
5
-
6
- __all__ = ["diameter"]
7
-
8
-
9
- @py_random_state(1)
10
- @nx._dispatchable(name="approximate_diameter")
11
- def diameter(G, seed=None):
12
- """Returns a lower bound on the diameter of the graph G.
13
-
14
- The function computes a lower bound on the diameter (i.e., the maximum eccentricity)
15
- of a directed or undirected graph G. The procedure used varies depending on the graph
16
- being directed or not.
17
-
18
- If G is an `undirected` graph, then the function uses the `2-sweep` algorithm [1]_.
19
- The main idea is to pick the farthest node from a random node and return its eccentricity.
20
-
21
- Otherwise, if G is a `directed` graph, the function uses the `2-dSweep` algorithm [2]_,
22
- The procedure starts by selecting a random source node $s$ from which it performs a
23
- forward and a backward BFS. Let $a_1$ and $a_2$ be the farthest nodes in the forward and
24
- backward cases, respectively. Then, it computes the backward eccentricity of $a_1$ using
25
- a backward BFS and the forward eccentricity of $a_2$ using a forward BFS.
26
- Finally, it returns the best lower bound between the two.
27
-
28
- In both cases, the time complexity is linear with respect to the size of G.
29
-
30
- Parameters
31
- ----------
32
- G : NetworkX graph
33
-
34
- seed : integer, random_state, or None (default)
35
- Indicator of random number generation state.
36
- See :ref:`Randomness<randomness>`.
37
-
38
- Returns
39
- -------
40
- d : integer
41
- Lower Bound on the Diameter of G
42
-
43
- Examples
44
- --------
45
- >>> G = nx.path_graph(10) # undirected graph
46
- >>> nx.diameter(G)
47
- 9
48
- >>> G = nx.cycle_graph(3, create_using=nx.DiGraph) # directed graph
49
- >>> nx.diameter(G)
50
- 2
51
-
52
- Raises
53
- ------
54
- NetworkXError
55
- If the graph is empty or
56
- If the graph is undirected and not connected or
57
- If the graph is directed and not strongly connected.
58
-
59
- See Also
60
- --------
61
- networkx.algorithms.distance_measures.diameter
62
-
63
- References
64
- ----------
65
- .. [1] Magnien, Clémence, Matthieu Latapy, and Michel Habib.
66
- *Fast computation of empirically tight bounds for the diameter of massive graphs.*
67
- Journal of Experimental Algorithmics (JEA), 2009.
68
- https://arxiv.org/pdf/0904.2728.pdf
69
- .. [2] Crescenzi, Pierluigi, Roberto Grossi, Leonardo Lanzi, and Andrea Marino.
70
- *On computing the diameter of real-world directed (weighted) graphs.*
71
- International Symposium on Experimental Algorithms. Springer, Berlin, Heidelberg, 2012.
72
- https://courses.cs.ut.ee/MTAT.03.238/2014_fall/uploads/Main/diameter.pdf
73
- """
74
- # if G is empty
75
- if not G:
76
- raise nx.NetworkXError("Expected non-empty NetworkX graph!")
77
- # if there's only a node
78
- if G.number_of_nodes() == 1:
79
- return 0
80
- # if G is directed
81
- if G.is_directed():
82
- return _two_sweep_directed(G, seed)
83
- # else if G is undirected
84
- return _two_sweep_undirected(G, seed)
85
-
86
-
87
- def _two_sweep_undirected(G, seed):
88
- """Helper function for finding a lower bound on the diameter
89
- for undirected Graphs.
90
-
91
- The idea is to pick the farthest node from a random node
92
- and return its eccentricity.
93
-
94
- ``G`` is a NetworkX undirected graph.
95
-
96
- .. note::
97
-
98
- ``seed`` is a random.Random or numpy.random.RandomState instance
99
- """
100
- # select a random source node
101
- source = seed.choice(list(G))
102
- # get the distances to the other nodes
103
- distances = nx.shortest_path_length(G, source)
104
- # if some nodes have not been visited, then the graph is not connected
105
- if len(distances) != len(G):
106
- raise nx.NetworkXError("Graph not connected.")
107
- # take a node that is (one of) the farthest nodes from the source
108
- *_, node = distances
109
- # return the eccentricity of the node
110
- return nx.eccentricity(G, node)
111
-
112
-
113
- def _two_sweep_directed(G, seed):
114
- """Helper function for finding a lower bound on the diameter
115
- for directed Graphs.
116
-
117
- It implements 2-dSweep, the directed version of the 2-sweep algorithm.
118
- The algorithm follows the following steps.
119
- 1. Select a source node $s$ at random.
120
- 2. Perform a forward BFS from $s$ to select a node $a_1$ at the maximum
121
- distance from the source, and compute $LB_1$, the backward eccentricity of $a_1$.
122
- 3. Perform a backward BFS from $s$ to select a node $a_2$ at the maximum
123
- distance from the source, and compute $LB_2$, the forward eccentricity of $a_2$.
124
- 4. Return the maximum between $LB_1$ and $LB_2$.
125
-
126
- ``G`` is a NetworkX directed graph.
127
-
128
- .. note::
129
-
130
- ``seed`` is a random.Random or numpy.random.RandomState instance
131
- """
132
- # get a new digraph G' with the edges reversed in the opposite direction
133
- G_reversed = G.reverse()
134
- # select a random source node
135
- source = seed.choice(list(G))
136
- # compute forward distances from source
137
- forward_distances = nx.shortest_path_length(G, source)
138
- # compute backward distances from source
139
- backward_distances = nx.shortest_path_length(G_reversed, source)
140
- # if either the source can't reach every node or not every node
141
- # can reach the source, then the graph is not strongly connected
142
- n = len(G)
143
- if len(forward_distances) != n or len(backward_distances) != n:
144
- raise nx.NetworkXError("DiGraph not strongly connected.")
145
- # take a node a_1 at the maximum distance from the source in G
146
- *_, a_1 = forward_distances
147
- # take a node a_2 at the maximum distance from the source in G_reversed
148
- *_, a_2 = backward_distances
149
- # return the max between the backward eccentricity of a_1 and the forward eccentricity of a_2
150
- return max(nx.eccentricity(G_reversed, a_1), nx.eccentricity(G, a_2))
@@ -1,149 +0,0 @@
1
- """Functions for finding node and edge dominating sets.
2
-
3
- A `dominating set`_ for an undirected graph *G* with vertex set *V*
4
- and edge set *E* is a subset *D* of *V* such that every vertex not in
5
- *D* is adjacent to at least one member of *D*. An `edge dominating set`_
6
- is a subset *F* of *E* such that every edge not in *F* is
7
- incident to an endpoint of at least one edge in *F*.
8
-
9
- .. _dominating set: https://en.wikipedia.org/wiki/Dominating_set
10
- .. _edge dominating set: https://en.wikipedia.org/wiki/Edge_dominating_set
11
-
12
- """
13
-
14
- import networkx as nx
15
-
16
- from ...utils import not_implemented_for
17
- from ..matching import maximal_matching
18
-
19
- __all__ = ["min_weighted_dominating_set", "min_edge_dominating_set"]
20
-
21
-
22
- # TODO Why doesn't this algorithm work for directed graphs?
23
- @not_implemented_for("directed")
24
- @nx._dispatchable(node_attrs="weight")
25
- def min_weighted_dominating_set(G, weight=None):
26
- r"""Returns a dominating set that approximates the minimum weight node
27
- dominating set.
28
-
29
- Parameters
30
- ----------
31
- G : NetworkX graph
32
- Undirected graph.
33
-
34
- weight : string
35
- The node attribute storing the weight of an node. If provided,
36
- the node attribute with this key must be a number for each
37
- node. If not provided, each node is assumed to have weight one.
38
-
39
- Returns
40
- -------
41
- min_weight_dominating_set : set
42
- A set of nodes, the sum of whose weights is no more than `(\log
43
- w(V)) w(V^*)`, where `w(V)` denotes the sum of the weights of
44
- each node in the graph and `w(V^*)` denotes the sum of the
45
- weights of each node in the minimum weight dominating set.
46
-
47
- Examples
48
- --------
49
- >>> G = nx.Graph([(0, 1), (0, 4), (1, 4), (1, 2), (2, 3), (3, 4), (2, 5)])
50
- >>> nx.approximation.min_weighted_dominating_set(G)
51
- {1, 2, 4}
52
-
53
- Raises
54
- ------
55
- NetworkXNotImplemented
56
- If G is directed.
57
-
58
- Notes
59
- -----
60
- This algorithm computes an approximate minimum weighted dominating
61
- set for the graph `G`. The returned solution has weight `(\log
62
- w(V)) w(V^*)`, where `w(V)` denotes the sum of the weights of each
63
- node in the graph and `w(V^*)` denotes the sum of the weights of
64
- each node in the minimum weight dominating set for the graph.
65
-
66
- This implementation of the algorithm runs in $O(m)$ time, where $m$
67
- is the number of edges in the graph.
68
-
69
- References
70
- ----------
71
- .. [1] Vazirani, Vijay V.
72
- *Approximation Algorithms*.
73
- Springer Science & Business Media, 2001.
74
-
75
- """
76
- # The unique dominating set for the null graph is the empty set.
77
- if len(G) == 0:
78
- return set()
79
-
80
- # This is the dominating set that will eventually be returned.
81
- dom_set = set()
82
-
83
- def _cost(node_and_neighborhood):
84
- """Returns the cost-effectiveness of greedily choosing the given
85
- node.
86
-
87
- `node_and_neighborhood` is a two-tuple comprising a node and its
88
- closed neighborhood.
89
-
90
- """
91
- v, neighborhood = node_and_neighborhood
92
- return G.nodes[v].get(weight, 1) / len(neighborhood - dom_set)
93
-
94
- # This is a set of all vertices not already covered by the
95
- # dominating set.
96
- vertices = set(G)
97
- # This is a dictionary mapping each node to the closed neighborhood
98
- # of that node.
99
- neighborhoods = {v: {v} | set(G[v]) for v in G}
100
-
101
- # Continue until all vertices are adjacent to some node in the
102
- # dominating set.
103
- while vertices:
104
- # Find the most cost-effective node to add, along with its
105
- # closed neighborhood.
106
- dom_node, min_set = min(neighborhoods.items(), key=_cost)
107
- # Add the node to the dominating set and reduce the remaining
108
- # set of nodes to cover.
109
- dom_set.add(dom_node)
110
- del neighborhoods[dom_node]
111
- vertices -= min_set
112
-
113
- return dom_set
114
-
115
-
116
- @nx._dispatchable
117
- def min_edge_dominating_set(G):
118
- r"""Returns minimum cardinality edge dominating set.
119
-
120
- Parameters
121
- ----------
122
- G : NetworkX graph
123
- Undirected graph
124
-
125
- Returns
126
- -------
127
- min_edge_dominating_set : set
128
- Returns a set of dominating edges whose size is no more than 2 * OPT.
129
-
130
- Examples
131
- --------
132
- >>> G = nx.petersen_graph()
133
- >>> nx.approximation.min_edge_dominating_set(G)
134
- {(0, 1), (4, 9), (6, 8), (5, 7), (2, 3)}
135
-
136
- Raises
137
- ------
138
- ValueError
139
- If the input graph `G` is empty.
140
-
141
- Notes
142
- -----
143
- The algorithm computes an approximate solution to the edge dominating set
144
- problem. The result is no more than 2 * OPT in terms of size of the set.
145
- Runtime of the algorithm is $O(|E|)$.
146
- """
147
- if not G:
148
- raise ValueError("Expected non-empty NetworkX graph!")
149
- return maximal_matching(G)