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,172 +0,0 @@
1
- """Functions for finding chains in a graph."""
2
-
3
- import networkx as nx
4
- from networkx.utils import not_implemented_for
5
-
6
- __all__ = ["chain_decomposition"]
7
-
8
-
9
- @not_implemented_for("directed")
10
- @not_implemented_for("multigraph")
11
- @nx._dispatchable
12
- def chain_decomposition(G, root=None):
13
- """Returns the chain decomposition of a graph.
14
-
15
- The *chain decomposition* of a graph with respect a depth-first
16
- search tree is a set of cycles or paths derived from the set of
17
- fundamental cycles of the tree in the following manner. Consider
18
- each fundamental cycle with respect to the given tree, represented
19
- as a list of edges beginning with the nontree edge oriented away
20
- from the root of the tree. For each fundamental cycle, if it
21
- overlaps with any previous fundamental cycle, just take the initial
22
- non-overlapping segment, which is a path instead of a cycle. Each
23
- cycle or path is called a *chain*. For more information, see [1]_.
24
-
25
- Parameters
26
- ----------
27
- G : undirected graph
28
-
29
- root : node (optional)
30
- A node in the graph `G`. If specified, only the chain
31
- decomposition for the connected component containing this node
32
- will be returned. This node indicates the root of the depth-first
33
- search tree.
34
-
35
- Yields
36
- ------
37
- chain : list
38
- A list of edges representing a chain. There is no guarantee on
39
- the orientation of the edges in each chain (for example, if a
40
- chain includes the edge joining nodes 1 and 2, the chain may
41
- include either (1, 2) or (2, 1)).
42
-
43
- Raises
44
- ------
45
- NodeNotFound
46
- If `root` is not in the graph `G`.
47
-
48
- Examples
49
- --------
50
- >>> G = nx.Graph([(0, 1), (1, 4), (3, 4), (3, 5), (4, 5)])
51
- >>> list(nx.chain_decomposition(G))
52
- [[(4, 5), (5, 3), (3, 4)]]
53
-
54
- Notes
55
- -----
56
- The worst-case running time of this implementation is linear in the
57
- number of nodes and number of edges [1]_.
58
-
59
- References
60
- ----------
61
- .. [1] Jens M. Schmidt (2013). "A simple test on 2-vertex-
62
- and 2-edge-connectivity." *Information Processing Letters*,
63
- 113, 241–244. Elsevier. <https://doi.org/10.1016/j.ipl.2013.01.016>
64
-
65
- """
66
-
67
- def _dfs_cycle_forest(G, root=None):
68
- """Builds a directed graph composed of cycles from the given graph.
69
-
70
- `G` is an undirected simple graph. `root` is a node in the graph
71
- from which the depth-first search is started.
72
-
73
- This function returns both the depth-first search cycle graph
74
- (as a :class:`~networkx.DiGraph`) and the list of nodes in
75
- depth-first preorder. The depth-first search cycle graph is a
76
- directed graph whose edges are the edges of `G` oriented toward
77
- the root if the edge is a tree edge and away from the root if
78
- the edge is a non-tree edge. If `root` is not specified, this
79
- performs a depth-first search on each connected component of `G`
80
- and returns a directed forest instead.
81
-
82
- If `root` is not in the graph, this raises :exc:`KeyError`.
83
-
84
- """
85
- # Create a directed graph from the depth-first search tree with
86
- # root node `root` in which tree edges are directed toward the
87
- # root and nontree edges are directed away from the root. For
88
- # each node with an incident nontree edge, this creates a
89
- # directed cycle starting with the nontree edge and returning to
90
- # that node.
91
- #
92
- # The `parent` node attribute stores the parent of each node in
93
- # the DFS tree. The `nontree` edge attribute indicates whether
94
- # the edge is a tree edge or a nontree edge.
95
- #
96
- # We also store the order of the nodes found in the depth-first
97
- # search in the `nodes` list.
98
- H = nx.DiGraph()
99
- nodes = []
100
- for u, v, d in nx.dfs_labeled_edges(G, source=root):
101
- if d == "forward":
102
- # `dfs_labeled_edges()` yields (root, root, 'forward')
103
- # if it is beginning the search on a new connected
104
- # component.
105
- if u == v:
106
- H.add_node(v, parent=None)
107
- nodes.append(v)
108
- else:
109
- H.add_node(v, parent=u)
110
- H.add_edge(v, u, nontree=False)
111
- nodes.append(v)
112
- # `dfs_labeled_edges` considers nontree edges in both
113
- # orientations, so we need to not add the edge if it its
114
- # other orientation has been added.
115
- elif d == "nontree" and v not in H[u]:
116
- H.add_edge(v, u, nontree=True)
117
- else:
118
- # Do nothing on 'reverse' edges; we only care about
119
- # forward and nontree edges.
120
- pass
121
- return H, nodes
122
-
123
- def _build_chain(G, u, v, visited):
124
- """Generate the chain starting from the given nontree edge.
125
-
126
- `G` is a DFS cycle graph as constructed by
127
- :func:`_dfs_cycle_graph`. The edge (`u`, `v`) is a nontree edge
128
- that begins a chain. `visited` is a set representing the nodes
129
- in `G` that have already been visited.
130
-
131
- This function yields the edges in an initial segment of the
132
- fundamental cycle of `G` starting with the nontree edge (`u`,
133
- `v`) that includes all the edges up until the first node that
134
- appears in `visited`. The tree edges are given by the 'parent'
135
- node attribute. The `visited` set is updated to add each node in
136
- an edge yielded by this function.
137
-
138
- """
139
- while v not in visited:
140
- yield u, v
141
- visited.add(v)
142
- u, v = v, G.nodes[v]["parent"]
143
- yield u, v
144
-
145
- # Check if the root is in the graph G. If not, raise NodeNotFound
146
- if root is not None and root not in G:
147
- raise nx.NodeNotFound(f"Root node {root} is not in graph")
148
-
149
- # Create a directed version of H that has the DFS edges directed
150
- # toward the root and the nontree edges directed away from the root
151
- # (in each connected component).
152
- H, nodes = _dfs_cycle_forest(G, root)
153
-
154
- # Visit the nodes again in DFS order. For each node, and for each
155
- # nontree edge leaving that node, compute the fundamental cycle for
156
- # that nontree edge starting with that edge. If the fundamental
157
- # cycle overlaps with any visited nodes, just take the prefix of the
158
- # cycle up to the point of visited nodes.
159
- #
160
- # We repeat this process for each connected component (implicitly,
161
- # since `nodes` already has a list of the nodes grouped by connected
162
- # component).
163
- visited = set()
164
- for u in nodes:
165
- visited.add(u)
166
- # For each nontree edge going out of node u...
167
- edges = ((u, v) for u, v, d in H.out_edges(u, data="nontree") if d)
168
- for u, v in edges:
169
- # Create the cycle or cycle prefix starting with the
170
- # nontree edge.
171
- chain = list(_build_chain(H, u, v, visited))
172
- yield chain
@@ -1,443 +0,0 @@
1
- """
2
- Algorithms for chordal graphs.
3
-
4
- A graph is chordal if every cycle of length at least 4 has a chord
5
- (an edge joining two nodes not adjacent in the cycle).
6
- https://en.wikipedia.org/wiki/Chordal_graph
7
- """
8
-
9
- import sys
10
-
11
- import networkx as nx
12
- from networkx.algorithms.components import connected_components
13
- from networkx.utils import arbitrary_element, not_implemented_for
14
-
15
- __all__ = [
16
- "is_chordal",
17
- "find_induced_nodes",
18
- "chordal_graph_cliques",
19
- "chordal_graph_treewidth",
20
- "NetworkXTreewidthBoundExceeded",
21
- "complete_to_chordal_graph",
22
- ]
23
-
24
-
25
- class NetworkXTreewidthBoundExceeded(nx.NetworkXException):
26
- """Exception raised when a treewidth bound has been provided and it has
27
- been exceeded"""
28
-
29
-
30
- @not_implemented_for("directed")
31
- @not_implemented_for("multigraph")
32
- @nx._dispatchable
33
- def is_chordal(G):
34
- """Checks whether G is a chordal graph.
35
-
36
- A graph is chordal if every cycle of length at least 4 has a chord
37
- (an edge joining two nodes not adjacent in the cycle).
38
-
39
- Parameters
40
- ----------
41
- G : graph
42
- A NetworkX graph.
43
-
44
- Returns
45
- -------
46
- chordal : bool
47
- True if G is a chordal graph and False otherwise.
48
-
49
- Raises
50
- ------
51
- NetworkXNotImplemented
52
- The algorithm does not support DiGraph, MultiGraph and MultiDiGraph.
53
-
54
- Examples
55
- --------
56
- >>> e = [
57
- ... (1, 2),
58
- ... (1, 3),
59
- ... (2, 3),
60
- ... (2, 4),
61
- ... (3, 4),
62
- ... (3, 5),
63
- ... (3, 6),
64
- ... (4, 5),
65
- ... (4, 6),
66
- ... (5, 6),
67
- ... ]
68
- >>> G = nx.Graph(e)
69
- >>> nx.is_chordal(G)
70
- True
71
-
72
- Notes
73
- -----
74
- The routine tries to go through every node following maximum cardinality
75
- search. It returns False when it finds that the separator for any node
76
- is not a clique. Based on the algorithms in [1]_.
77
-
78
- Self loops are ignored.
79
-
80
- References
81
- ----------
82
- .. [1] R. E. Tarjan and M. Yannakakis, Simple linear-time algorithms
83
- to test chordality of graphs, test acyclicity of hypergraphs, and
84
- selectively reduce acyclic hypergraphs, SIAM J. Comput., 13 (1984),
85
- pp. 566–579.
86
- """
87
- if len(G.nodes) <= 3:
88
- return True
89
- return len(_find_chordality_breaker(G)) == 0
90
-
91
-
92
- @nx._dispatchable
93
- def find_induced_nodes(G, s, t, treewidth_bound=sys.maxsize):
94
- """Returns the set of induced nodes in the path from s to t.
95
-
96
- Parameters
97
- ----------
98
- G : graph
99
- A chordal NetworkX graph
100
- s : node
101
- Source node to look for induced nodes
102
- t : node
103
- Destination node to look for induced nodes
104
- treewidth_bound: float
105
- Maximum treewidth acceptable for the graph H. The search
106
- for induced nodes will end as soon as the treewidth_bound is exceeded.
107
-
108
- Returns
109
- -------
110
- induced_nodes : Set of nodes
111
- The set of induced nodes in the path from s to t in G
112
-
113
- Raises
114
- ------
115
- NetworkXError
116
- The algorithm does not support DiGraph, MultiGraph and MultiDiGraph.
117
- If the input graph is an instance of one of these classes, a
118
- :exc:`NetworkXError` is raised.
119
- The algorithm can only be applied to chordal graphs. If the input
120
- graph is found to be non-chordal, a :exc:`NetworkXError` is raised.
121
-
122
- Examples
123
- --------
124
- >>> G = nx.Graph()
125
- >>> G = nx.generators.classic.path_graph(10)
126
- >>> induced_nodes = nx.find_induced_nodes(G, 1, 9, 2)
127
- >>> sorted(induced_nodes)
128
- [1, 2, 3, 4, 5, 6, 7, 8, 9]
129
-
130
- Notes
131
- -----
132
- G must be a chordal graph and (s,t) an edge that is not in G.
133
-
134
- If a treewidth_bound is provided, the search for induced nodes will end
135
- as soon as the treewidth_bound is exceeded.
136
-
137
- The algorithm is inspired by Algorithm 4 in [1]_.
138
- A formal definition of induced node can also be found on that reference.
139
-
140
- Self Loops are ignored
141
-
142
- References
143
- ----------
144
- .. [1] Learning Bounded Treewidth Bayesian Networks.
145
- Gal Elidan, Stephen Gould; JMLR, 9(Dec):2699--2731, 2008.
146
- http://jmlr.csail.mit.edu/papers/volume9/elidan08a/elidan08a.pdf
147
- """
148
- if not is_chordal(G):
149
- raise nx.NetworkXError("Input graph is not chordal.")
150
-
151
- H = nx.Graph(G)
152
- H.add_edge(s, t)
153
- induced_nodes = set()
154
- triplet = _find_chordality_breaker(H, s, treewidth_bound)
155
- while triplet:
156
- (u, v, w) = triplet
157
- induced_nodes.update(triplet)
158
- for n in triplet:
159
- if n != s:
160
- H.add_edge(s, n)
161
- triplet = _find_chordality_breaker(H, s, treewidth_bound)
162
- if induced_nodes:
163
- # Add t and the second node in the induced path from s to t.
164
- induced_nodes.add(t)
165
- for u in G[s]:
166
- if len(induced_nodes & set(G[u])) == 2:
167
- induced_nodes.add(u)
168
- break
169
- return induced_nodes
170
-
171
-
172
- @nx._dispatchable
173
- def chordal_graph_cliques(G):
174
- """Returns all maximal cliques of a chordal graph.
175
-
176
- The algorithm breaks the graph in connected components and performs a
177
- maximum cardinality search in each component to get the cliques.
178
-
179
- Parameters
180
- ----------
181
- G : graph
182
- A NetworkX graph
183
-
184
- Yields
185
- ------
186
- frozenset of nodes
187
- Maximal cliques, each of which is a frozenset of
188
- nodes in `G`. The order of cliques is arbitrary.
189
-
190
- Raises
191
- ------
192
- NetworkXError
193
- The algorithm does not support DiGraph, MultiGraph and MultiDiGraph.
194
- The algorithm can only be applied to chordal graphs. If the input
195
- graph is found to be non-chordal, a :exc:`NetworkXError` is raised.
196
-
197
- Examples
198
- --------
199
- >>> e = [
200
- ... (1, 2),
201
- ... (1, 3),
202
- ... (2, 3),
203
- ... (2, 4),
204
- ... (3, 4),
205
- ... (3, 5),
206
- ... (3, 6),
207
- ... (4, 5),
208
- ... (4, 6),
209
- ... (5, 6),
210
- ... (7, 8),
211
- ... ]
212
- >>> G = nx.Graph(e)
213
- >>> G.add_node(9)
214
- >>> cliques = [c for c in chordal_graph_cliques(G)]
215
- >>> cliques[0]
216
- frozenset({1, 2, 3})
217
- """
218
- for C in (G.subgraph(c).copy() for c in connected_components(G)):
219
- if C.number_of_nodes() == 1:
220
- if nx.number_of_selfloops(C) > 0:
221
- raise nx.NetworkXError("Input graph is not chordal.")
222
- yield frozenset(C.nodes())
223
- else:
224
- unnumbered = set(C.nodes())
225
- v = arbitrary_element(C)
226
- unnumbered.remove(v)
227
- numbered = {v}
228
- clique_wanna_be = {v}
229
- while unnumbered:
230
- v = _max_cardinality_node(C, unnumbered, numbered)
231
- unnumbered.remove(v)
232
- numbered.add(v)
233
- new_clique_wanna_be = set(C.neighbors(v)) & numbered
234
- sg = C.subgraph(clique_wanna_be)
235
- if _is_complete_graph(sg):
236
- new_clique_wanna_be.add(v)
237
- if not new_clique_wanna_be >= clique_wanna_be:
238
- yield frozenset(clique_wanna_be)
239
- clique_wanna_be = new_clique_wanna_be
240
- else:
241
- raise nx.NetworkXError("Input graph is not chordal.")
242
- yield frozenset(clique_wanna_be)
243
-
244
-
245
- @nx._dispatchable
246
- def chordal_graph_treewidth(G):
247
- """Returns the treewidth of the chordal graph G.
248
-
249
- Parameters
250
- ----------
251
- G : graph
252
- A NetworkX graph
253
-
254
- Returns
255
- -------
256
- treewidth : int
257
- The size of the largest clique in the graph minus one.
258
-
259
- Raises
260
- ------
261
- NetworkXError
262
- The algorithm does not support DiGraph, MultiGraph and MultiDiGraph.
263
- The algorithm can only be applied to chordal graphs. If the input
264
- graph is found to be non-chordal, a :exc:`NetworkXError` is raised.
265
-
266
- Examples
267
- --------
268
- >>> e = [
269
- ... (1, 2),
270
- ... (1, 3),
271
- ... (2, 3),
272
- ... (2, 4),
273
- ... (3, 4),
274
- ... (3, 5),
275
- ... (3, 6),
276
- ... (4, 5),
277
- ... (4, 6),
278
- ... (5, 6),
279
- ... (7, 8),
280
- ... ]
281
- >>> G = nx.Graph(e)
282
- >>> G.add_node(9)
283
- >>> nx.chordal_graph_treewidth(G)
284
- 3
285
-
286
- References
287
- ----------
288
- .. [1] https://en.wikipedia.org/wiki/Tree_decomposition#Treewidth
289
- """
290
- if not is_chordal(G):
291
- raise nx.NetworkXError("Input graph is not chordal.")
292
-
293
- max_clique = -1
294
- for clique in nx.chordal_graph_cliques(G):
295
- max_clique = max(max_clique, len(clique))
296
- return max_clique - 1
297
-
298
-
299
- def _is_complete_graph(G):
300
- """Returns True if G is a complete graph."""
301
- if nx.number_of_selfloops(G) > 0:
302
- raise nx.NetworkXError("Self loop found in _is_complete_graph()")
303
- n = G.number_of_nodes()
304
- if n < 2:
305
- return True
306
- e = G.number_of_edges()
307
- max_edges = (n * (n - 1)) / 2
308
- return e == max_edges
309
-
310
-
311
- def _find_missing_edge(G):
312
- """Given a non-complete graph G, returns a missing edge."""
313
- nodes = set(G)
314
- for u in G:
315
- missing = nodes - set(list(G[u].keys()) + [u])
316
- if missing:
317
- return (u, missing.pop())
318
-
319
-
320
- def _max_cardinality_node(G, choices, wanna_connect):
321
- """Returns a the node in choices that has more connections in G
322
- to nodes in wanna_connect.
323
- """
324
- max_number = -1
325
- for x in choices:
326
- number = len([y for y in G[x] if y in wanna_connect])
327
- if number > max_number:
328
- max_number = number
329
- max_cardinality_node = x
330
- return max_cardinality_node
331
-
332
-
333
- def _find_chordality_breaker(G, s=None, treewidth_bound=sys.maxsize):
334
- """Given a graph G, starts a max cardinality search
335
- (starting from s if s is given and from an arbitrary node otherwise)
336
- trying to find a non-chordal cycle.
337
-
338
- If it does find one, it returns (u,v,w) where u,v,w are the three
339
- nodes that together with s are involved in the cycle.
340
-
341
- It ignores any self loops.
342
- """
343
- if len(G) == 0:
344
- raise nx.NetworkXPointlessConcept("Graph has no nodes.")
345
- unnumbered = set(G)
346
- if s is None:
347
- s = arbitrary_element(G)
348
- unnumbered.remove(s)
349
- numbered = {s}
350
- current_treewidth = -1
351
- while unnumbered: # and current_treewidth <= treewidth_bound:
352
- v = _max_cardinality_node(G, unnumbered, numbered)
353
- unnumbered.remove(v)
354
- numbered.add(v)
355
- clique_wanna_be = set(G[v]) & numbered
356
- sg = G.subgraph(clique_wanna_be)
357
- if _is_complete_graph(sg):
358
- # The graph seems to be chordal by now. We update the treewidth
359
- current_treewidth = max(current_treewidth, len(clique_wanna_be))
360
- if current_treewidth > treewidth_bound:
361
- raise nx.NetworkXTreewidthBoundExceeded(
362
- f"treewidth_bound exceeded: {current_treewidth}"
363
- )
364
- else:
365
- # sg is not a clique,
366
- # look for an edge that is not included in sg
367
- (u, w) = _find_missing_edge(sg)
368
- return (u, v, w)
369
- return ()
370
-
371
-
372
- @not_implemented_for("directed")
373
- @nx._dispatchable(returns_graph=True)
374
- def complete_to_chordal_graph(G):
375
- """Return a copy of G completed to a chordal graph
376
-
377
- Adds edges to a copy of G to create a chordal graph. A graph G=(V,E) is
378
- called chordal if for each cycle with length bigger than 3, there exist
379
- two non-adjacent nodes connected by an edge (called a chord).
380
-
381
- Parameters
382
- ----------
383
- G : NetworkX graph
384
- Undirected graph
385
-
386
- Returns
387
- -------
388
- H : NetworkX graph
389
- The chordal enhancement of G
390
- alpha : Dictionary
391
- The elimination ordering of nodes of G
392
-
393
- Notes
394
- -----
395
- There are different approaches to calculate the chordal
396
- enhancement of a graph. The algorithm used here is called
397
- MCS-M and gives at least minimal (local) triangulation of graph. Note
398
- that this triangulation is not necessarily a global minimum.
399
-
400
- https://en.wikipedia.org/wiki/Chordal_graph
401
-
402
- References
403
- ----------
404
- .. [1] Berry, Anne & Blair, Jean & Heggernes, Pinar & Peyton, Barry. (2004)
405
- Maximum Cardinality Search for Computing Minimal Triangulations of
406
- Graphs. Algorithmica. 39. 287-298. 10.1007/s00453-004-1084-3.
407
-
408
- Examples
409
- --------
410
- >>> from networkx.algorithms.chordal import complete_to_chordal_graph
411
- >>> G = nx.wheel_graph(10)
412
- >>> H, alpha = complete_to_chordal_graph(G)
413
- """
414
- H = G.copy()
415
- alpha = {node: 0 for node in H}
416
- if nx.is_chordal(H):
417
- return H, alpha
418
- chords = set()
419
- weight = {node: 0 for node in H.nodes()}
420
- unnumbered_nodes = list(H.nodes())
421
- for i in range(len(H.nodes()), 0, -1):
422
- # get the node in unnumbered_nodes with the maximum weight
423
- z = max(unnumbered_nodes, key=lambda node: weight[node])
424
- unnumbered_nodes.remove(z)
425
- alpha[z] = i
426
- update_nodes = []
427
- for y in unnumbered_nodes:
428
- if G.has_edge(y, z):
429
- update_nodes.append(y)
430
- else:
431
- # y_weight will be bigger than node weights between y and z
432
- y_weight = weight[y]
433
- lower_nodes = [
434
- node for node in unnumbered_nodes if weight[node] < y_weight
435
- ]
436
- if nx.has_path(H.subgraph(lower_nodes + [z, y]), y, z):
437
- update_nodes.append(y)
438
- chords.add((z, y))
439
- # during calculation of paths the weights should not be updated
440
- for node in update_nodes:
441
- weight[node] += 1
442
- H.add_edges_from(chords)
443
- return H, alpha