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,73 +0,0 @@
1
- import itertools
2
-
3
- import networkx as nx
4
- from networkx.utils.decorators import not_implemented_for
5
-
6
- __all__ = ["is_perfect_graph"]
7
-
8
-
9
- @nx._dispatchable
10
- @not_implemented_for("directed")
11
- @not_implemented_for("multigraph")
12
- def is_perfect_graph(G):
13
- r"""Return True if G is a perfect graph, else False.
14
-
15
- A graph G is perfect if, for every induced subgraph H of G, the chromatic
16
- number of H equals the size of the largest clique in H.
17
-
18
- According to the **Strong Perfect Graph Theorem (SPGT)**:
19
- A graph is perfect if and only if neither the graph G nor its complement
20
- :math:`\overline{G}` contains an **induced odd hole** — an induced cycle of
21
- odd length at least five without chords.
22
-
23
- Parameters
24
- ----------
25
- G : NetworkX Graph
26
- The graph to check. Must be a finite, simple, undirected graph.
27
-
28
- Returns
29
- -------
30
- bool
31
- True if G is a perfect graph, else False.
32
-
33
- Notes
34
- -----
35
- This function uses a direct approach: cycle enumeration to detect
36
- chordless odd cycles in G and :math:`\overline{G}`. This implementation
37
- runs in exponential time in the worst case, since the number of chordless
38
- cycles can grow exponentially.
39
-
40
- The perfect-graph recognition problem is theoretically solvable in
41
- polynomial time. Chudnovsky *et al.* (2006) proved it can be solved in
42
- :math:`O(n^9)` time via a complex structural decomposition [1]_, [2]_.
43
- This implementation opts for a direct, transparent check rather than
44
- implementing that high-degree polynomial-time decomposition algorithm.
45
-
46
- See Also
47
- --------
48
- is_chordal, is_bipartite :
49
- Related checks for specific categories of perfect graphs, such as chordal
50
- graphs, and bipartite graphs.
51
- chordless_cycles :
52
- Used to detect "holes" in the graph
53
-
54
- References
55
- ----------
56
- .. [1] M. Chudnovsky, N. Robertson, P. Seymour, and R. Thomas,
57
- *The Strong Perfect Graph Theorem*,
58
- Annals of Mathematics, vol. 164, no. 1, pp. 51–229, 2006.
59
- https://doi.org/10.4007/annals.2006.164.51
60
- .. [2] M. Chudnovsky, G. Cornuéjols, X. Liu, P. Seymour, and K. Vušković,
61
- *Recognizing Berge Graphs*,
62
- Combinatorica 25(2): 143–186, 2005.
63
- DOI: 10.1007/s00493-005-0003-8
64
- Preprint available at:
65
- https://web.math.princeton.edu/~pds/papers/algexp/Bergealg.pdf
66
- """
67
-
68
- return not any(
69
- (len(c) >= 5) and (len(c) % 2 == 1)
70
- for c in itertools.chain(
71
- nx.chordless_cycles(G), nx.chordless_cycles(nx.complement(G))
72
- )
73
- )
@@ -1,464 +0,0 @@
1
- from collections import defaultdict
2
-
3
- import networkx as nx
4
-
5
- __all__ = ["combinatorial_embedding_to_pos"]
6
-
7
-
8
- def combinatorial_embedding_to_pos(embedding, fully_triangulate=False):
9
- """Assigns every node a (x, y) position based on the given embedding
10
-
11
- The algorithm iteratively inserts nodes of the input graph in a certain
12
- order and rearranges previously inserted nodes so that the planar drawing
13
- stays valid. This is done efficiently by only maintaining relative
14
- positions during the node placements and calculating the absolute positions
15
- at the end. For more information see [1]_.
16
-
17
- Parameters
18
- ----------
19
- embedding : nx.PlanarEmbedding
20
- This defines the order of the edges
21
-
22
- fully_triangulate : bool
23
- If set to True the algorithm adds edges to a copy of the input
24
- embedding and makes it chordal.
25
-
26
- Returns
27
- -------
28
- pos : dict
29
- Maps each node to a tuple that defines the (x, y) position
30
-
31
- References
32
- ----------
33
- .. [1] M. Chrobak and T.H. Payne:
34
- A Linear-time Algorithm for Drawing a Planar Graph on a Grid 1989
35
- http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.51.6677
36
-
37
- """
38
- if len(embedding.nodes()) < 4:
39
- # Position the node in any triangle
40
- default_positions = [(0, 0), (2, 0), (1, 1)]
41
- pos = {}
42
- for i, v in enumerate(embedding.nodes()):
43
- pos[v] = default_positions[i]
44
- return pos
45
-
46
- embedding, outer_face = triangulate_embedding(embedding, fully_triangulate)
47
-
48
- # The following dicts map a node to another node
49
- # If a node is not in the key set it means that the node is not yet in G_k
50
- # If a node maps to None then the corresponding subtree does not exist
51
- left_t_child = {}
52
- right_t_child = {}
53
-
54
- # The following dicts map a node to an integer
55
- delta_x = {}
56
- y_coordinate = {}
57
-
58
- node_list = get_canonical_ordering(embedding, outer_face)
59
-
60
- # 1. Phase: Compute relative positions
61
-
62
- # Initialization
63
- v1, v2, v3 = node_list[0][0], node_list[1][0], node_list[2][0]
64
-
65
- delta_x[v1] = 0
66
- y_coordinate[v1] = 0
67
- right_t_child[v1] = v3
68
- left_t_child[v1] = None
69
-
70
- delta_x[v2] = 1
71
- y_coordinate[v2] = 0
72
- right_t_child[v2] = None
73
- left_t_child[v2] = None
74
-
75
- delta_x[v3] = 1
76
- y_coordinate[v3] = 1
77
- right_t_child[v3] = v2
78
- left_t_child[v3] = None
79
-
80
- for k in range(3, len(node_list)):
81
- vk, contour_nbrs = node_list[k]
82
- wp = contour_nbrs[0]
83
- wp1 = contour_nbrs[1]
84
- wq = contour_nbrs[-1]
85
- wq1 = contour_nbrs[-2]
86
- adds_mult_tri = len(contour_nbrs) > 2
87
-
88
- # Stretch gaps:
89
- delta_x[wp1] += 1
90
- delta_x[wq] += 1
91
-
92
- delta_x_wp_wq = sum(delta_x[x] for x in contour_nbrs[1:])
93
-
94
- # Adjust offsets
95
- delta_x[vk] = (-y_coordinate[wp] + delta_x_wp_wq + y_coordinate[wq]) // 2
96
- y_coordinate[vk] = (y_coordinate[wp] + delta_x_wp_wq + y_coordinate[wq]) // 2
97
- delta_x[wq] = delta_x_wp_wq - delta_x[vk]
98
- if adds_mult_tri:
99
- delta_x[wp1] -= delta_x[vk]
100
-
101
- # Install v_k:
102
- right_t_child[wp] = vk
103
- right_t_child[vk] = wq
104
- if adds_mult_tri:
105
- left_t_child[vk] = wp1
106
- right_t_child[wq1] = None
107
- else:
108
- left_t_child[vk] = None
109
-
110
- # 2. Phase: Set absolute positions
111
- pos = {}
112
- pos[v1] = (0, y_coordinate[v1])
113
- remaining_nodes = [v1]
114
- while remaining_nodes:
115
- parent_node = remaining_nodes.pop()
116
-
117
- # Calculate position for left child
118
- set_position(
119
- parent_node, left_t_child, remaining_nodes, delta_x, y_coordinate, pos
120
- )
121
- # Calculate position for right child
122
- set_position(
123
- parent_node, right_t_child, remaining_nodes, delta_x, y_coordinate, pos
124
- )
125
- return pos
126
-
127
-
128
- def set_position(parent, tree, remaining_nodes, delta_x, y_coordinate, pos):
129
- """Helper method to calculate the absolute position of nodes."""
130
- child = tree[parent]
131
- parent_node_x = pos[parent][0]
132
- if child is not None:
133
- # Calculate pos of child
134
- child_x = parent_node_x + delta_x[child]
135
- pos[child] = (child_x, y_coordinate[child])
136
- # Remember to calculate pos of its children
137
- remaining_nodes.append(child)
138
-
139
-
140
- def get_canonical_ordering(embedding, outer_face):
141
- """Returns a canonical ordering of the nodes
142
-
143
- The canonical ordering of nodes (v1, ..., vn) must fulfill the following
144
- conditions:
145
- (See Lemma 1 in [2]_)
146
-
147
- - For the subgraph G_k of the input graph induced by v1, ..., vk it holds:
148
- - 2-connected
149
- - internally triangulated
150
- - the edge (v1, v2) is part of the outer face
151
- - For a node v(k+1) the following holds:
152
- - The node v(k+1) is part of the outer face of G_k
153
- - It has at least two neighbors in G_k
154
- - All neighbors of v(k+1) in G_k lie consecutively on the outer face of
155
- G_k (excluding the edge (v1, v2)).
156
-
157
- The algorithm used here starts with G_n (containing all nodes). It first
158
- selects the nodes v1 and v2. And then tries to find the order of the other
159
- nodes by checking which node can be removed in order to fulfill the
160
- conditions mentioned above. This is done by calculating the number of
161
- chords of nodes on the outer face. For more information see [1]_.
162
-
163
- Parameters
164
- ----------
165
- embedding : nx.PlanarEmbedding
166
- The embedding must be triangulated
167
- outer_face : list
168
- The nodes on the outer face of the graph
169
-
170
- Returns
171
- -------
172
- ordering : list
173
- A list of tuples `(vk, wp_wq)`. Here `vk` is the node at this position
174
- in the canonical ordering. The element `wp_wq` is a list of nodes that
175
- make up the outer face of G_k.
176
-
177
- References
178
- ----------
179
- .. [1] Steven Chaplick.
180
- Canonical Orders of Planar Graphs and (some of) Their Applications 2015
181
- https://wuecampus2.uni-wuerzburg.de/moodle/pluginfile.php/545727/mod_resource/content/0/vg-ss15-vl03-canonical-orders-druckversion.pdf
182
- .. [2] M. Chrobak and T.H. Payne:
183
- A Linear-time Algorithm for Drawing a Planar Graph on a Grid 1989
184
- http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.51.6677
185
-
186
- """
187
- v1 = outer_face[0]
188
- v2 = outer_face[1]
189
- chords = defaultdict(int) # Maps nodes to the number of their chords
190
- marked_nodes = set()
191
- ready_to_pick = set(outer_face)
192
-
193
- # Initialize outer_face_ccw_nbr (do not include v1 -> v2)
194
- outer_face_ccw_nbr = {}
195
- prev_nbr = v2
196
- for idx in range(2, len(outer_face)):
197
- outer_face_ccw_nbr[prev_nbr] = outer_face[idx]
198
- prev_nbr = outer_face[idx]
199
- outer_face_ccw_nbr[prev_nbr] = v1
200
-
201
- # Initialize outer_face_cw_nbr (do not include v2 -> v1)
202
- outer_face_cw_nbr = {}
203
- prev_nbr = v1
204
- for idx in range(len(outer_face) - 1, 0, -1):
205
- outer_face_cw_nbr[prev_nbr] = outer_face[idx]
206
- prev_nbr = outer_face[idx]
207
-
208
- def is_outer_face_nbr(x, y):
209
- if x not in outer_face_ccw_nbr:
210
- return outer_face_cw_nbr[x] == y
211
- if x not in outer_face_cw_nbr:
212
- return outer_face_ccw_nbr[x] == y
213
- return outer_face_ccw_nbr[x] == y or outer_face_cw_nbr[x] == y
214
-
215
- def is_on_outer_face(x):
216
- return x not in marked_nodes and (x in outer_face_ccw_nbr or x == v1)
217
-
218
- # Initialize number of chords
219
- for v in outer_face:
220
- for nbr in embedding.neighbors_cw_order(v):
221
- if is_on_outer_face(nbr) and not is_outer_face_nbr(v, nbr):
222
- chords[v] += 1
223
- ready_to_pick.discard(v)
224
-
225
- # Initialize canonical_ordering
226
- canonical_ordering = [None] * len(embedding.nodes())
227
- canonical_ordering[0] = (v1, [])
228
- canonical_ordering[1] = (v2, [])
229
- ready_to_pick.discard(v1)
230
- ready_to_pick.discard(v2)
231
-
232
- for k in range(len(embedding.nodes()) - 1, 1, -1):
233
- # 1. Pick v from ready_to_pick
234
- v = ready_to_pick.pop()
235
- marked_nodes.add(v)
236
-
237
- # v has exactly two neighbors on the outer face (wp and wq)
238
- wp = None
239
- wq = None
240
- # Iterate over neighbors of v to find wp and wq
241
- nbr_iterator = iter(embedding.neighbors_cw_order(v))
242
- while True:
243
- nbr = next(nbr_iterator)
244
- if nbr in marked_nodes:
245
- # Only consider nodes that are not yet removed
246
- continue
247
- if is_on_outer_face(nbr):
248
- # nbr is either wp or wq
249
- if nbr == v1:
250
- wp = v1
251
- elif nbr == v2:
252
- wq = v2
253
- else:
254
- if outer_face_cw_nbr[nbr] == v:
255
- # nbr is wp
256
- wp = nbr
257
- else:
258
- # nbr is wq
259
- wq = nbr
260
- if wp is not None and wq is not None:
261
- # We don't need to iterate any further
262
- break
263
-
264
- # Obtain new nodes on outer face (neighbors of v from wp to wq)
265
- wp_wq = [wp]
266
- nbr = wp
267
- while nbr != wq:
268
- # Get next neighbor (clockwise on the outer face)
269
- next_nbr = embedding[v][nbr]["ccw"]
270
- wp_wq.append(next_nbr)
271
- # Update outer face
272
- outer_face_cw_nbr[nbr] = next_nbr
273
- outer_face_ccw_nbr[next_nbr] = nbr
274
- # Move to next neighbor of v
275
- nbr = next_nbr
276
-
277
- if len(wp_wq) == 2:
278
- # There was a chord between wp and wq, decrease number of chords
279
- chords[wp] -= 1
280
- if chords[wp] == 0:
281
- ready_to_pick.add(wp)
282
- chords[wq] -= 1
283
- if chords[wq] == 0:
284
- ready_to_pick.add(wq)
285
- else:
286
- # Update all chords involving w_(p+1) to w_(q-1)
287
- new_face_nodes = set(wp_wq[1:-1])
288
- for w in new_face_nodes:
289
- # If we do not find a chord for w later we can pick it next
290
- ready_to_pick.add(w)
291
- for nbr in embedding.neighbors_cw_order(w):
292
- if is_on_outer_face(nbr) and not is_outer_face_nbr(w, nbr):
293
- # There is a chord involving w
294
- chords[w] += 1
295
- ready_to_pick.discard(w)
296
- if nbr not in new_face_nodes:
297
- # Also increase chord for the neighbor
298
- # We only iterator over new_face_nodes
299
- chords[nbr] += 1
300
- ready_to_pick.discard(nbr)
301
- # Set the canonical ordering node and the list of contour neighbors
302
- canonical_ordering[k] = (v, wp_wq)
303
-
304
- return canonical_ordering
305
-
306
-
307
- def triangulate_face(embedding, v1, v2):
308
- """Triangulates the face given by half edge (v, w)
309
-
310
- Parameters
311
- ----------
312
- embedding : nx.PlanarEmbedding
313
- v1 : node
314
- The half-edge (v1, v2) belongs to the face that gets triangulated
315
- v2 : node
316
- """
317
- _, v3 = embedding.next_face_half_edge(v1, v2)
318
- _, v4 = embedding.next_face_half_edge(v2, v3)
319
- if v1 in (v2, v3):
320
- # The component has less than 3 nodes
321
- return
322
- while v1 != v4:
323
- # Add edge if not already present on other side
324
- if embedding.has_edge(v1, v3):
325
- # Cannot triangulate at this position
326
- v1, v2, v3 = v2, v3, v4
327
- else:
328
- # Add edge for triangulation
329
- embedding.add_half_edge(v1, v3, ccw=v2)
330
- embedding.add_half_edge(v3, v1, cw=v2)
331
- v1, v2, v3 = v1, v3, v4
332
- # Get next node
333
- _, v4 = embedding.next_face_half_edge(v2, v3)
334
-
335
-
336
- def triangulate_embedding(embedding, fully_triangulate=True):
337
- """Triangulates the embedding.
338
-
339
- Traverses faces of the embedding and adds edges to a copy of the
340
- embedding to triangulate it.
341
- The method also ensures that the resulting graph is 2-connected by adding
342
- edges if the same vertex is contained twice on a path around a face.
343
-
344
- Parameters
345
- ----------
346
- embedding : nx.PlanarEmbedding
347
- The input graph must contain at least 3 nodes.
348
-
349
- fully_triangulate : bool
350
- If set to False the face with the most nodes is chooses as outer face.
351
- This outer face does not get triangulated.
352
-
353
- Returns
354
- -------
355
- (embedding, outer_face) : (nx.PlanarEmbedding, list) tuple
356
- The element `embedding` is a new embedding containing all edges from
357
- the input embedding and the additional edges to triangulate the graph.
358
- The element `outer_face` is a list of nodes that lie on the outer face.
359
- If the graph is fully triangulated these are three arbitrary connected
360
- nodes.
361
-
362
- """
363
- if len(embedding.nodes) <= 1:
364
- return embedding, list(embedding.nodes)
365
- embedding = nx.PlanarEmbedding(embedding)
366
-
367
- # Get a list with a node for each connected component
368
- component_nodes = [next(iter(x)) for x in nx.connected_components(embedding)]
369
-
370
- # 1. Make graph a single component (add edge between components)
371
- for i in range(len(component_nodes) - 1):
372
- v1 = component_nodes[i]
373
- v2 = component_nodes[i + 1]
374
- embedding.connect_components(v1, v2)
375
-
376
- # 2. Calculate faces, ensure 2-connectedness and determine outer face
377
- outer_face = [] # A face with the most number of nodes
378
- face_list = []
379
- edges_visited = set() # Used to keep track of already visited faces
380
- for v in embedding.nodes():
381
- for w in embedding.neighbors_cw_order(v):
382
- new_face = make_bi_connected(embedding, v, w, edges_visited)
383
- if new_face:
384
- # Found a new face
385
- face_list.append(new_face)
386
- if len(new_face) > len(outer_face):
387
- # The face is a candidate to be the outer face
388
- outer_face = new_face
389
-
390
- # 3. Triangulate (internal) faces
391
- for face in face_list:
392
- if face is not outer_face or fully_triangulate:
393
- # Triangulate this face
394
- triangulate_face(embedding, face[0], face[1])
395
-
396
- if fully_triangulate:
397
- v1 = outer_face[0]
398
- v2 = outer_face[1]
399
- v3 = embedding[v2][v1]["ccw"]
400
- outer_face = [v1, v2, v3]
401
-
402
- return embedding, outer_face
403
-
404
-
405
- def make_bi_connected(embedding, starting_node, outgoing_node, edges_counted):
406
- """Triangulate a face and make it 2-connected
407
-
408
- This method also adds all edges on the face to `edges_counted`.
409
-
410
- Parameters
411
- ----------
412
- embedding: nx.PlanarEmbedding
413
- The embedding that defines the faces
414
- starting_node : node
415
- A node on the face
416
- outgoing_node : node
417
- A node such that the half edge (starting_node, outgoing_node) belongs
418
- to the face
419
- edges_counted: set
420
- Set of all half-edges that belong to a face that have been visited
421
-
422
- Returns
423
- -------
424
- face_nodes: list
425
- A list of all nodes at the border of this face
426
- """
427
-
428
- # Check if the face has already been calculated
429
- if (starting_node, outgoing_node) in edges_counted:
430
- # This face was already counted
431
- return []
432
- edges_counted.add((starting_node, outgoing_node))
433
-
434
- # Add all edges to edges_counted which have this face to their left
435
- v1 = starting_node
436
- v2 = outgoing_node
437
- face_list = [starting_node] # List of nodes around the face
438
- face_set = set(face_list) # Set for faster queries
439
- _, v3 = embedding.next_face_half_edge(v1, v2)
440
-
441
- # Move the nodes v1, v2, v3 around the face:
442
- while v2 != starting_node or v3 != outgoing_node:
443
- if v1 == v2:
444
- raise nx.NetworkXException("Invalid half-edge")
445
- # cycle is not completed yet
446
- if v2 in face_set:
447
- # v2 encountered twice: Add edge to ensure 2-connectedness
448
- embedding.add_half_edge(v1, v3, ccw=v2)
449
- embedding.add_half_edge(v3, v1, cw=v2)
450
- edges_counted.add((v2, v3))
451
- edges_counted.add((v3, v1))
452
- v2 = v1
453
- else:
454
- face_set.add(v2)
455
- face_list.append(v2)
456
-
457
- # set next edge
458
- v1 = v2
459
- v2, v3 = embedding.next_face_half_edge(v2, v3)
460
-
461
- # remember that this edge has been counted
462
- edges_counted.add((v1, v2))
463
-
464
- return face_list