okstra 0.130.3 → 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 (367) 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 +21 -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/report_views.py +32 -5
  27. package/runtime/python/okstra_ctl/run.py +15 -3
  28. package/runtime/python/okstra_ctl/worker_prompt_contract.py +14 -6
  29. package/runtime/python/okstra_ctl/worker_prompt_policy.py +19 -1
  30. package/runtime/python/okstra_vendor/__init__.py +0 -44
  31. package/runtime/schemas/final-report-v1.0.schema.json +101 -6
  32. package/runtime/skills/okstra-run/SKILL.md +11 -4
  33. package/runtime/skills/okstra-setup/SKILL.md +3 -2
  34. package/runtime/skills/okstra-setup/references/project-config.md +16 -7
  35. package/runtime/templates/reports/final-report.template.md +18 -12
  36. package/runtime/templates/reports/i18n/en.json +1 -0
  37. package/runtime/templates/reports/i18n/ko.json +1 -0
  38. package/runtime/templates/reports/report.css +18 -0
  39. package/runtime/validators/lib/fixtures.sh +6 -0
  40. package/runtime/validators/validate-run.py +1722 -98
  41. package/src/cli-registry.mjs +0 -7
  42. package/src/commands/lifecycle/doctor.mjs +0 -9
  43. package/src/lib/skill-catalog.mjs +0 -1
  44. package/docs/for-ai/skills/okstra-graphify.md +0 -64
  45. package/runtime/python/okstra_ctl/graphify_cmd.py +0 -225
  46. package/runtime/python/okstra_vendor/graphify/.vendored-version +0 -1
  47. package/runtime/python/okstra_vendor/graphify/__init__.py +0 -28
  48. package/runtime/python/okstra_vendor/graphify/__main__.py +0 -1371
  49. package/runtime/python/okstra_vendor/graphify/analyze.py +0 -540
  50. package/runtime/python/okstra_vendor/graphify/benchmark.py +0 -129
  51. package/runtime/python/okstra_vendor/graphify/build.py +0 -107
  52. package/runtime/python/okstra_vendor/graphify/cache.py +0 -169
  53. package/runtime/python/okstra_vendor/graphify/cluster.py +0 -137
  54. package/runtime/python/okstra_vendor/graphify/detect.py +0 -510
  55. package/runtime/python/okstra_vendor/graphify/export.py +0 -1014
  56. package/runtime/python/okstra_vendor/graphify/extract.py +0 -3277
  57. package/runtime/python/okstra_vendor/graphify/hooks.py +0 -220
  58. package/runtime/python/okstra_vendor/graphify/ingest.py +0 -297
  59. package/runtime/python/okstra_vendor/graphify/manifest.py +0 -4
  60. package/runtime/python/okstra_vendor/graphify/report.py +0 -175
  61. package/runtime/python/okstra_vendor/graphify/security.py +0 -203
  62. package/runtime/python/okstra_vendor/graphify/serve.py +0 -373
  63. package/runtime/python/okstra_vendor/graphify/skill-aider.md +0 -1184
  64. package/runtime/python/okstra_vendor/graphify/skill-claw.md +0 -1184
  65. package/runtime/python/okstra_vendor/graphify/skill-codex.md +0 -1242
  66. package/runtime/python/okstra_vendor/graphify/skill-copilot.md +0 -1268
  67. package/runtime/python/okstra_vendor/graphify/skill-droid.md +0 -1239
  68. package/runtime/python/okstra_vendor/graphify/skill-kiro.md +0 -1183
  69. package/runtime/python/okstra_vendor/graphify/skill-opencode.md +0 -1238
  70. package/runtime/python/okstra_vendor/graphify/skill-trae.md +0 -1208
  71. package/runtime/python/okstra_vendor/graphify/skill-vscode.md +0 -253
  72. package/runtime/python/okstra_vendor/graphify/skill-windows.md +0 -1245
  73. package/runtime/python/okstra_vendor/graphify/skill.md +0 -1319
  74. package/runtime/python/okstra_vendor/graphify/transcribe.py +0 -182
  75. package/runtime/python/okstra_vendor/graphify/validate.py +0 -72
  76. package/runtime/python/okstra_vendor/graphify/watch.py +0 -188
  77. package/runtime/python/okstra_vendor/graphify/wiki.py +0 -214
  78. package/runtime/python/okstra_vendor/networkx/__init__.py +0 -62
  79. package/runtime/python/okstra_vendor/networkx/algorithms/__init__.py +0 -134
  80. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/__init__.py +0 -26
  81. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clique.py +0 -259
  82. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clustering_coefficient.py +0 -71
  83. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/connectivity.py +0 -412
  84. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/density.py +0 -396
  85. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/distance_measures.py +0 -150
  86. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/dominating_set.py +0 -149
  87. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/kcomponents.py +0 -369
  88. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/matching.py +0 -44
  89. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/maxcut.py +0 -143
  90. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/ramsey.py +0 -53
  91. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/steinertree.py +0 -265
  92. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/traveling_salesman.py +0 -1508
  93. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/treewidth.py +0 -255
  94. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/vertex_cover.py +0 -83
  95. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/__init__.py +0 -5
  96. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/connectivity.py +0 -122
  97. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/correlation.py +0 -302
  98. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/mixing.py +0 -255
  99. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/neighbor_degree.py +0 -160
  100. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/pairs.py +0 -127
  101. package/runtime/python/okstra_vendor/networkx/algorithms/asteroidal.py +0 -164
  102. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/__init__.py +0 -88
  103. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/basic.py +0 -322
  104. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/centrality.py +0 -290
  105. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/cluster.py +0 -289
  106. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/covering.py +0 -57
  107. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/edgelist.py +0 -360
  108. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/extendability.py +0 -105
  109. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/generators.py +0 -603
  110. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/link_analysis.py +0 -316
  111. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matching.py +0 -590
  112. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matrix.py +0 -232
  113. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/projection.py +0 -526
  114. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/redundancy.py +0 -112
  115. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/spectral.py +0 -69
  116. package/runtime/python/okstra_vendor/networkx/algorithms/boundary.py +0 -168
  117. package/runtime/python/okstra_vendor/networkx/algorithms/bridges.py +0 -205
  118. package/runtime/python/okstra_vendor/networkx/algorithms/broadcasting.py +0 -164
  119. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/__init__.py +0 -20
  120. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness.py +0 -591
  121. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness_subset.py +0 -236
  122. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/closeness.py +0 -282
  123. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness.py +0 -364
  124. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness_subset.py +0 -227
  125. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_closeness.py +0 -96
  126. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/degree_alg.py +0 -150
  127. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/dispersion.py +0 -107
  128. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/eigenvector.py +0 -357
  129. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/flow_matrix.py +0 -130
  130. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/group.py +0 -787
  131. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/harmonic.py +0 -88
  132. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/katz.py +0 -331
  133. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/laplacian.py +0 -150
  134. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/load.py +0 -200
  135. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/percolation.py +0 -128
  136. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/reaching.py +0 -209
  137. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/second_order.py +0 -141
  138. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/subgraph_alg.py +0 -361
  139. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/trophic.py +0 -181
  140. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/voterank_alg.py +0 -95
  141. package/runtime/python/okstra_vendor/networkx/algorithms/chains.py +0 -172
  142. package/runtime/python/okstra_vendor/networkx/algorithms/chordal.py +0 -443
  143. package/runtime/python/okstra_vendor/networkx/algorithms/clique.py +0 -818
  144. package/runtime/python/okstra_vendor/networkx/algorithms/cluster.py +0 -732
  145. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/__init__.py +0 -4
  146. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/equitable_coloring.py +0 -505
  147. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/greedy_coloring.py +0 -565
  148. package/runtime/python/okstra_vendor/networkx/algorithms/communicability_alg.py +0 -163
  149. package/runtime/python/okstra_vendor/networkx/algorithms/community/__init__.py +0 -28
  150. package/runtime/python/okstra_vendor/networkx/algorithms/community/asyn_fluid.py +0 -153
  151. package/runtime/python/okstra_vendor/networkx/algorithms/community/bipartitions.py +0 -354
  152. package/runtime/python/okstra_vendor/networkx/algorithms/community/centrality.py +0 -171
  153. package/runtime/python/okstra_vendor/networkx/algorithms/community/community_utils.py +0 -30
  154. package/runtime/python/okstra_vendor/networkx/algorithms/community/divisive.py +0 -216
  155. package/runtime/python/okstra_vendor/networkx/algorithms/community/kclique.py +0 -79
  156. package/runtime/python/okstra_vendor/networkx/algorithms/community/label_propagation.py +0 -338
  157. package/runtime/python/okstra_vendor/networkx/algorithms/community/leiden.py +0 -162
  158. package/runtime/python/okstra_vendor/networkx/algorithms/community/local.py +0 -220
  159. package/runtime/python/okstra_vendor/networkx/algorithms/community/louvain.py +0 -384
  160. package/runtime/python/okstra_vendor/networkx/algorithms/community/lukes.py +0 -227
  161. package/runtime/python/okstra_vendor/networkx/algorithms/community/modularity_max.py +0 -452
  162. package/runtime/python/okstra_vendor/networkx/algorithms/community/quality.py +0 -347
  163. package/runtime/python/okstra_vendor/networkx/algorithms/components/__init__.py +0 -6
  164. package/runtime/python/okstra_vendor/networkx/algorithms/components/attracting.py +0 -115
  165. package/runtime/python/okstra_vendor/networkx/algorithms/components/biconnected.py +0 -394
  166. package/runtime/python/okstra_vendor/networkx/algorithms/components/connected.py +0 -282
  167. package/runtime/python/okstra_vendor/networkx/algorithms/components/semiconnected.py +0 -71
  168. package/runtime/python/okstra_vendor/networkx/algorithms/components/strongly_connected.py +0 -359
  169. package/runtime/python/okstra_vendor/networkx/algorithms/components/weakly_connected.py +0 -196
  170. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/__init__.py +0 -11
  171. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/connectivity.py +0 -811
  172. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/cuts.py +0 -616
  173. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/disjoint_paths.py +0 -408
  174. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_augmentation.py +0 -1270
  175. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_kcomponents.py +0 -592
  176. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcomponents.py +0 -220
  177. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcutsets.py +0 -235
  178. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/stoerwagner.py +0 -152
  179. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/utils.py +0 -88
  180. package/runtime/python/okstra_vendor/networkx/algorithms/core.py +0 -588
  181. package/runtime/python/okstra_vendor/networkx/algorithms/covering.py +0 -142
  182. package/runtime/python/okstra_vendor/networkx/algorithms/cuts.py +0 -416
  183. package/runtime/python/okstra_vendor/networkx/algorithms/cycles.py +0 -1234
  184. package/runtime/python/okstra_vendor/networkx/algorithms/d_separation.py +0 -677
  185. package/runtime/python/okstra_vendor/networkx/algorithms/dag.py +0 -1392
  186. package/runtime/python/okstra_vendor/networkx/algorithms/distance_measures.py +0 -1095
  187. package/runtime/python/okstra_vendor/networkx/algorithms/distance_regular.py +0 -272
  188. package/runtime/python/okstra_vendor/networkx/algorithms/dominance.py +0 -142
  189. package/runtime/python/okstra_vendor/networkx/algorithms/dominating.py +0 -268
  190. package/runtime/python/okstra_vendor/networkx/algorithms/efficiency_measures.py +0 -167
  191. package/runtime/python/okstra_vendor/networkx/algorithms/euler.py +0 -470
  192. package/runtime/python/okstra_vendor/networkx/algorithms/flow/__init__.py +0 -11
  193. package/runtime/python/okstra_vendor/networkx/algorithms/flow/boykovkolmogorov.py +0 -370
  194. package/runtime/python/okstra_vendor/networkx/algorithms/flow/capacityscaling.py +0 -407
  195. package/runtime/python/okstra_vendor/networkx/algorithms/flow/dinitz_alg.py +0 -238
  196. package/runtime/python/okstra_vendor/networkx/algorithms/flow/edmondskarp.py +0 -241
  197. package/runtime/python/okstra_vendor/networkx/algorithms/flow/gomory_hu.py +0 -178
  198. package/runtime/python/okstra_vendor/networkx/algorithms/flow/maxflow.py +0 -611
  199. package/runtime/python/okstra_vendor/networkx/algorithms/flow/mincost.py +0 -356
  200. package/runtime/python/okstra_vendor/networkx/algorithms/flow/networksimplex.py +0 -662
  201. package/runtime/python/okstra_vendor/networkx/algorithms/flow/preflowpush.py +0 -425
  202. package/runtime/python/okstra_vendor/networkx/algorithms/flow/shortestaugmentingpath.py +0 -300
  203. package/runtime/python/okstra_vendor/networkx/algorithms/flow/utils.py +0 -194
  204. package/runtime/python/okstra_vendor/networkx/algorithms/graph_hashing.py +0 -435
  205. package/runtime/python/okstra_vendor/networkx/algorithms/graphical.py +0 -483
  206. package/runtime/python/okstra_vendor/networkx/algorithms/hierarchy.py +0 -57
  207. package/runtime/python/okstra_vendor/networkx/algorithms/hybrid.py +0 -196
  208. package/runtime/python/okstra_vendor/networkx/algorithms/isolate.py +0 -107
  209. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/__init__.py +0 -7
  210. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/ismags.py +0 -1306
  211. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorph.py +0 -336
  212. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorphvf2.py +0 -1262
  213. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/matchhelpers.py +0 -352
  214. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/temporalisomorphvf2.py +0 -308
  215. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tree_isomorphism.py +0 -264
  216. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2pp.py +0 -1102
  217. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2userfunc.py +0 -192
  218. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/__init__.py +0 -2
  219. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/hits_alg.py +0 -337
  220. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/pagerank_alg.py +0 -498
  221. package/runtime/python/okstra_vendor/networkx/algorithms/link_prediction.py +0 -687
  222. package/runtime/python/okstra_vendor/networkx/algorithms/lowest_common_ancestors.py +0 -280
  223. package/runtime/python/okstra_vendor/networkx/algorithms/matching.py +0 -1148
  224. package/runtime/python/okstra_vendor/networkx/algorithms/minors/__init__.py +0 -27
  225. package/runtime/python/okstra_vendor/networkx/algorithms/minors/contraction.py +0 -738
  226. package/runtime/python/okstra_vendor/networkx/algorithms/mis.py +0 -78
  227. package/runtime/python/okstra_vendor/networkx/algorithms/moral.py +0 -59
  228. package/runtime/python/okstra_vendor/networkx/algorithms/node_classification.py +0 -219
  229. package/runtime/python/okstra_vendor/networkx/algorithms/non_randomness.py +0 -155
  230. package/runtime/python/okstra_vendor/networkx/algorithms/operators/__init__.py +0 -4
  231. package/runtime/python/okstra_vendor/networkx/algorithms/operators/all.py +0 -324
  232. package/runtime/python/okstra_vendor/networkx/algorithms/operators/binary.py +0 -468
  233. package/runtime/python/okstra_vendor/networkx/algorithms/operators/product.py +0 -633
  234. package/runtime/python/okstra_vendor/networkx/algorithms/operators/unary.py +0 -77
  235. package/runtime/python/okstra_vendor/networkx/algorithms/perfect_graph.py +0 -73
  236. package/runtime/python/okstra_vendor/networkx/algorithms/planar_drawing.py +0 -464
  237. package/runtime/python/okstra_vendor/networkx/algorithms/planarity.py +0 -1463
  238. package/runtime/python/okstra_vendor/networkx/algorithms/polynomials.py +0 -306
  239. package/runtime/python/okstra_vendor/networkx/algorithms/reciprocity.py +0 -98
  240. package/runtime/python/okstra_vendor/networkx/algorithms/regular.py +0 -167
  241. package/runtime/python/okstra_vendor/networkx/algorithms/richclub.py +0 -138
  242. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/__init__.py +0 -5
  243. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/astar.py +0 -239
  244. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/dense.py +0 -264
  245. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/generic.py +0 -716
  246. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/unweighted.py +0 -625
  247. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/weighted.py +0 -2542
  248. package/runtime/python/okstra_vendor/networkx/algorithms/similarity.py +0 -2107
  249. package/runtime/python/okstra_vendor/networkx/algorithms/simple_paths.py +0 -966
  250. package/runtime/python/okstra_vendor/networkx/algorithms/smallworld.py +0 -404
  251. package/runtime/python/okstra_vendor/networkx/algorithms/smetric.py +0 -30
  252. package/runtime/python/okstra_vendor/networkx/algorithms/sparsifiers.py +0 -296
  253. package/runtime/python/okstra_vendor/networkx/algorithms/structuralholes.py +0 -374
  254. package/runtime/python/okstra_vendor/networkx/algorithms/summarization.py +0 -564
  255. package/runtime/python/okstra_vendor/networkx/algorithms/swap.py +0 -406
  256. package/runtime/python/okstra_vendor/networkx/algorithms/threshold.py +0 -981
  257. package/runtime/python/okstra_vendor/networkx/algorithms/time_dependent.py +0 -142
  258. package/runtime/python/okstra_vendor/networkx/algorithms/tournament.py +0 -406
  259. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/__init__.py +0 -5
  260. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/beamsearch.py +0 -90
  261. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/breadth_first_search.py +0 -576
  262. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/depth_first_search.py +0 -529
  263. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgebfs.py +0 -185
  264. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgedfs.py +0 -182
  265. package/runtime/python/okstra_vendor/networkx/algorithms/tree/__init__.py +0 -7
  266. package/runtime/python/okstra_vendor/networkx/algorithms/tree/branchings.py +0 -1042
  267. package/runtime/python/okstra_vendor/networkx/algorithms/tree/coding.py +0 -413
  268. package/runtime/python/okstra_vendor/networkx/algorithms/tree/decomposition.py +0 -88
  269. package/runtime/python/okstra_vendor/networkx/algorithms/tree/distance_measures.py +0 -219
  270. package/runtime/python/okstra_vendor/networkx/algorithms/tree/mst.py +0 -1281
  271. package/runtime/python/okstra_vendor/networkx/algorithms/tree/operations.py +0 -106
  272. package/runtime/python/okstra_vendor/networkx/algorithms/tree/recognition.py +0 -273
  273. package/runtime/python/okstra_vendor/networkx/algorithms/triads.py +0 -500
  274. package/runtime/python/okstra_vendor/networkx/algorithms/vitality.py +0 -76
  275. package/runtime/python/okstra_vendor/networkx/algorithms/voronoi.py +0 -86
  276. package/runtime/python/okstra_vendor/networkx/algorithms/walks.py +0 -77
  277. package/runtime/python/okstra_vendor/networkx/algorithms/wiener.py +0 -278
  278. package/runtime/python/okstra_vendor/networkx/classes/__init__.py +0 -13
  279. package/runtime/python/okstra_vendor/networkx/classes/coreviews.py +0 -435
  280. package/runtime/python/okstra_vendor/networkx/classes/digraph.py +0 -1363
  281. package/runtime/python/okstra_vendor/networkx/classes/filters.py +0 -95
  282. package/runtime/python/okstra_vendor/networkx/classes/function.py +0 -1549
  283. package/runtime/python/okstra_vendor/networkx/classes/graph.py +0 -2082
  284. package/runtime/python/okstra_vendor/networkx/classes/graphviews.py +0 -269
  285. package/runtime/python/okstra_vendor/networkx/classes/multidigraph.py +0 -977
  286. package/runtime/python/okstra_vendor/networkx/classes/multigraph.py +0 -1294
  287. package/runtime/python/okstra_vendor/networkx/classes/reportviews.py +0 -1447
  288. package/runtime/python/okstra_vendor/networkx/convert.py +0 -502
  289. package/runtime/python/okstra_vendor/networkx/convert_matrix.py +0 -1314
  290. package/runtime/python/okstra_vendor/networkx/drawing/__init__.py +0 -7
  291. package/runtime/python/okstra_vendor/networkx/drawing/layout.py +0 -2036
  292. package/runtime/python/okstra_vendor/networkx/drawing/nx_agraph.py +0 -470
  293. package/runtime/python/okstra_vendor/networkx/drawing/nx_latex.py +0 -570
  294. package/runtime/python/okstra_vendor/networkx/drawing/nx_pydot.py +0 -361
  295. package/runtime/python/okstra_vendor/networkx/drawing/nx_pylab.py +0 -2978
  296. package/runtime/python/okstra_vendor/networkx/exception.py +0 -131
  297. package/runtime/python/okstra_vendor/networkx/generators/__init__.py +0 -34
  298. package/runtime/python/okstra_vendor/networkx/generators/atlas.dat.gz +0 -0
  299. package/runtime/python/okstra_vendor/networkx/generators/atlas.py +0 -227
  300. package/runtime/python/okstra_vendor/networkx/generators/classic.py +0 -1091
  301. package/runtime/python/okstra_vendor/networkx/generators/cographs.py +0 -68
  302. package/runtime/python/okstra_vendor/networkx/generators/community.py +0 -1070
  303. package/runtime/python/okstra_vendor/networkx/generators/degree_seq.py +0 -886
  304. package/runtime/python/okstra_vendor/networkx/generators/directed.py +0 -572
  305. package/runtime/python/okstra_vendor/networkx/generators/duplication.py +0 -174
  306. package/runtime/python/okstra_vendor/networkx/generators/ego.py +0 -66
  307. package/runtime/python/okstra_vendor/networkx/generators/expanders.py +0 -499
  308. package/runtime/python/okstra_vendor/networkx/generators/geometric.py +0 -1037
  309. package/runtime/python/okstra_vendor/networkx/generators/harary_graph.py +0 -163
  310. package/runtime/python/okstra_vendor/networkx/generators/internet_as_graphs.py +0 -443
  311. package/runtime/python/okstra_vendor/networkx/generators/intersection.py +0 -125
  312. package/runtime/python/okstra_vendor/networkx/generators/interval_graph.py +0 -70
  313. package/runtime/python/okstra_vendor/networkx/generators/joint_degree_seq.py +0 -664
  314. package/runtime/python/okstra_vendor/networkx/generators/lattice.py +0 -405
  315. package/runtime/python/okstra_vendor/networkx/generators/line.py +0 -501
  316. package/runtime/python/okstra_vendor/networkx/generators/mycielski.py +0 -110
  317. package/runtime/python/okstra_vendor/networkx/generators/nonisomorphic_trees.py +0 -259
  318. package/runtime/python/okstra_vendor/networkx/generators/random_clustered.py +0 -117
  319. package/runtime/python/okstra_vendor/networkx/generators/random_graphs.py +0 -1416
  320. package/runtime/python/okstra_vendor/networkx/generators/small.py +0 -1070
  321. package/runtime/python/okstra_vendor/networkx/generators/social.py +0 -554
  322. package/runtime/python/okstra_vendor/networkx/generators/spectral_graph_forge.py +0 -120
  323. package/runtime/python/okstra_vendor/networkx/generators/stochastic.py +0 -54
  324. package/runtime/python/okstra_vendor/networkx/generators/sudoku.py +0 -131
  325. package/runtime/python/okstra_vendor/networkx/generators/time_series.py +0 -74
  326. package/runtime/python/okstra_vendor/networkx/generators/trees.py +0 -1070
  327. package/runtime/python/okstra_vendor/networkx/generators/triads.py +0 -94
  328. package/runtime/python/okstra_vendor/networkx/lazy_imports.py +0 -188
  329. package/runtime/python/okstra_vendor/networkx/linalg/__init__.py +0 -13
  330. package/runtime/python/okstra_vendor/networkx/linalg/algebraicconnectivity.py +0 -650
  331. package/runtime/python/okstra_vendor/networkx/linalg/attrmatrix.py +0 -466
  332. package/runtime/python/okstra_vendor/networkx/linalg/bethehessianmatrix.py +0 -77
  333. package/runtime/python/okstra_vendor/networkx/linalg/graphmatrix.py +0 -168
  334. package/runtime/python/okstra_vendor/networkx/linalg/laplacianmatrix.py +0 -512
  335. package/runtime/python/okstra_vendor/networkx/linalg/modularitymatrix.py +0 -166
  336. package/runtime/python/okstra_vendor/networkx/linalg/spectrum.py +0 -186
  337. package/runtime/python/okstra_vendor/networkx/readwrite/__init__.py +0 -17
  338. package/runtime/python/okstra_vendor/networkx/readwrite/adjlist.py +0 -330
  339. package/runtime/python/okstra_vendor/networkx/readwrite/edgelist.py +0 -489
  340. package/runtime/python/okstra_vendor/networkx/readwrite/gexf.py +0 -1084
  341. package/runtime/python/okstra_vendor/networkx/readwrite/gml.py +0 -879
  342. package/runtime/python/okstra_vendor/networkx/readwrite/graph6.py +0 -427
  343. package/runtime/python/okstra_vendor/networkx/readwrite/graphml.py +0 -1053
  344. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/__init__.py +0 -19
  345. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/adjacency.py +0 -156
  346. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/cytoscape.py +0 -190
  347. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/node_link.py +0 -261
  348. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tree.py +0 -137
  349. package/runtime/python/okstra_vendor/networkx/readwrite/leda.py +0 -108
  350. package/runtime/python/okstra_vendor/networkx/readwrite/multiline_adjlist.py +0 -393
  351. package/runtime/python/okstra_vendor/networkx/readwrite/p2g.py +0 -113
  352. package/runtime/python/okstra_vendor/networkx/readwrite/pajek.py +0 -286
  353. package/runtime/python/okstra_vendor/networkx/readwrite/sparse6.py +0 -379
  354. package/runtime/python/okstra_vendor/networkx/readwrite/text.py +0 -851
  355. package/runtime/python/okstra_vendor/networkx/relabel.py +0 -285
  356. package/runtime/python/okstra_vendor/networkx/utils/__init__.py +0 -8
  357. package/runtime/python/okstra_vendor/networkx/utils/backends.py +0 -2171
  358. package/runtime/python/okstra_vendor/networkx/utils/configs.py +0 -396
  359. package/runtime/python/okstra_vendor/networkx/utils/decorators.py +0 -1233
  360. package/runtime/python/okstra_vendor/networkx/utils/heaps.py +0 -338
  361. package/runtime/python/okstra_vendor/networkx/utils/mapped_queue.py +0 -297
  362. package/runtime/python/okstra_vendor/networkx/utils/misc.py +0 -703
  363. package/runtime/python/okstra_vendor/networkx/utils/random_sequence.py +0 -198
  364. package/runtime/python/okstra_vendor/networkx/utils/rcm.py +0 -159
  365. package/runtime/python/okstra_vendor/networkx/utils/union_find.py +0 -106
  366. package/runtime/skills/okstra-graphify/SKILL.md +0 -169
  367. 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