okstra 0.114.0 → 0.116.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 (337) hide show
  1. package/docs/kr/architecture.md +2 -2
  2. package/docs/kr/follow-ups/2026-07-10-final-report-option-3.md +51 -0
  3. package/package.json +1 -1
  4. package/runtime/BUILD.json +2 -2
  5. package/runtime/agents/workers/report-writer-worker.md +1 -0
  6. package/runtime/prompts/launch.template.md +34 -0
  7. package/runtime/prompts/lead/convergence.md +2 -0
  8. package/runtime/prompts/lead/okstra-lead-contract.md +1 -1
  9. package/runtime/prompts/lead/report-writer.md +1 -1
  10. package/runtime/prompts/profiles/implementation-planning.md +1 -0
  11. package/runtime/python/okstra_ctl/implementation_stage.py +46 -39
  12. package/runtime/python/okstra_ctl/incremental_carry.py +70 -0
  13. package/runtime/python/okstra_ctl/incremental_scope.py +89 -0
  14. package/runtime/python/okstra_ctl/report_views.py +151 -12
  15. package/runtime/python/okstra_ctl/run.py +24 -24
  16. package/runtime/python/okstra_ctl/stage_targets.py +26 -0
  17. package/runtime/python/okstra_ctl/worktree.py +1 -1
  18. package/runtime/python/okstra_token_usage/claude.py +58 -19
  19. package/runtime/python/okstra_token_usage/collect.py +3 -1
  20. package/runtime/python/okstra_vendor/__init__.py +3 -0
  21. package/runtime/schemas/final-report-v1.0.schema.json +39 -0
  22. package/runtime/templates/reports/final-report.template.md +27 -0
  23. package/runtime/templates/reports/i18n/en.json +23 -12
  24. package/runtime/templates/reports/i18n/ko.json +23 -12
  25. package/runtime/templates/reports/report.css +55 -0
  26. package/runtime/templates/reports/report.js +53 -1
  27. package/runtime/validators/validate-run.py +50 -0
  28. package/src/cli-registry.mjs +14 -0
  29. package/src/commands/execute/incremental-carry.mjs +20 -0
  30. package/src/commands/execute/incremental-scope.mjs +20 -0
  31. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/__init__.py +0 -0
  32. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_approx_clust_coeff.py +0 -41
  33. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_clique.py +0 -112
  34. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_connectivity.py +0 -199
  35. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_density.py +0 -146
  36. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_distance_measures.py +0 -59
  37. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_dominating_set.py +0 -78
  38. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_kcomponents.py +0 -303
  39. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_matching.py +0 -8
  40. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_maxcut.py +0 -94
  41. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_ramsey.py +0 -31
  42. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_steinertree.py +0 -306
  43. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_traveling_salesman.py +0 -1014
  44. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_treewidth.py +0 -274
  45. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_vertex_cover.py +0 -68
  46. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/__init__.py +0 -0
  47. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/base_test.py +0 -81
  48. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_connectivity.py +0 -143
  49. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_correlation.py +0 -122
  50. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_mixing.py +0 -174
  51. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_neighbor_degree.py +0 -107
  52. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_pairs.py +0 -87
  53. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/__init__.py +0 -0
  54. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_basic.py +0 -125
  55. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_centrality.py +0 -192
  56. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_cluster.py +0 -84
  57. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_covering.py +0 -33
  58. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_edgelist.py +0 -240
  59. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_extendability.py +0 -334
  60. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_generators.py +0 -407
  61. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_link_analysis.py +0 -218
  62. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_matching.py +0 -327
  63. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_matrix.py +0 -138
  64. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_project.py +0 -409
  65. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_redundancy.py +0 -35
  66. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_spectral_bipartivity.py +0 -80
  67. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/__init__.py +0 -0
  68. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_betweenness_centrality.py +0 -923
  69. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_betweenness_centrality_subset.py +0 -354
  70. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_closeness_centrality.py +0 -274
  71. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_betweenness_centrality.py +0 -259
  72. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_betweenness_centrality_subset.py +0 -147
  73. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_closeness.py +0 -43
  74. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_degree_centrality.py +0 -144
  75. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_dispersion.py +0 -73
  76. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_eigenvector_centrality.py +0 -186
  77. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_group.py +0 -277
  78. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_harmonic_centrality.py +0 -122
  79. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_katz_centrality.py +0 -345
  80. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_laplacian_centrality.py +0 -220
  81. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_load_centrality.py +0 -344
  82. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_percolation_centrality.py +0 -87
  83. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_reaching.py +0 -140
  84. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_second_order_centrality.py +0 -82
  85. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_subgraph.py +0 -110
  86. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_trophic.py +0 -302
  87. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_voterank.py +0 -64
  88. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/tests/__init__.py +0 -0
  89. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/tests/test_coloring.py +0 -863
  90. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/__init__.py +0 -0
  91. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_asyn_fluid.py +0 -147
  92. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_bipartitions.py +0 -157
  93. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_centrality.py +0 -85
  94. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_divisive.py +0 -106
  95. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_kclique.py +0 -91
  96. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_label_propagation.py +0 -241
  97. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_leiden.py +0 -138
  98. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_local.py +0 -76
  99. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_louvain.py +0 -264
  100. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_lukes.py +0 -152
  101. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_modularity_max.py +0 -340
  102. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_quality.py +0 -139
  103. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_utils.py +0 -26
  104. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/__init__.py +0 -0
  105. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_attracting.py +0 -70
  106. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_biconnected.py +0 -248
  107. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_connected.py +0 -138
  108. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_semiconnected.py +0 -55
  109. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_strongly_connected.py +0 -193
  110. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_weakly_connected.py +0 -96
  111. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/__init__.py +0 -0
  112. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_connectivity.py +0 -421
  113. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_cuts.py +0 -309
  114. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_disjoint_paths.py +0 -249
  115. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_edge_augmentation.py +0 -502
  116. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_edge_kcomponents.py +0 -488
  117. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_kcomponents.py +0 -323
  118. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_kcutsets.py +0 -280
  119. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_stoer_wagner.py +0 -102
  120. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/__init__.py +0 -0
  121. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/gl1.gpickle.bz2 +0 -0
  122. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/gw1.gpickle.bz2 +0 -0
  123. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/netgen-2.gpickle.bz2 +0 -0
  124. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_gomory_hu.py +0 -128
  125. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_maxflow.py +0 -573
  126. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_maxflow_large_graph.py +0 -155
  127. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_mincost.py +0 -475
  128. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_networksimplex.py +0 -481
  129. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/wlm3.gpickle.bz2 +0 -0
  130. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/__init__.py +0 -0
  131. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/iso_r01_s80.A99 +0 -0
  132. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/iso_r01_s80.B99 +0 -0
  133. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/si2_b06_m200.A99 +0 -0
  134. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/si2_b06_m200.B99 +0 -0
  135. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_ismags.py +0 -719
  136. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_isomorphism.py +0 -103
  137. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_isomorphvf2.py +0 -490
  138. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_match_helpers.py +0 -64
  139. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_temporalisomorphvf2.py +0 -212
  140. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_tree_isomorphism.py +0 -202
  141. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2pp.py +0 -1655
  142. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2pp_helpers.py +0 -3118
  143. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2userfunc.py +0 -196
  144. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/__init__.py +0 -0
  145. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/test_hits.py +0 -77
  146. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/test_pagerank.py +0 -213
  147. package/runtime/python/okstra_vendor/networkx/algorithms/minors/tests/test_contraction.py +0 -544
  148. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/__init__.py +0 -0
  149. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_all.py +0 -328
  150. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_binary.py +0 -451
  151. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_product.py +0 -491
  152. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_unary.py +0 -55
  153. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/__init__.py +0 -0
  154. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_astar.py +0 -254
  155. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_dense.py +0 -212
  156. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_dense_numpy.py +0 -88
  157. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_generic.py +0 -511
  158. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_unweighted.py +0 -149
  159. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_weighted.py +0 -983
  160. package/runtime/python/okstra_vendor/networkx/algorithms/tests/__init__.py +0 -0
  161. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_asteroidal.py +0 -23
  162. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_boundary.py +0 -154
  163. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_bridges.py +0 -144
  164. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_broadcasting.py +0 -109
  165. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_chains.py +0 -136
  166. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_chordal.py +0 -129
  167. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_clique.py +0 -300
  168. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cluster.py +0 -678
  169. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_communicability.py +0 -80
  170. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_core.py +0 -266
  171. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_covering.py +0 -85
  172. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cuts.py +0 -171
  173. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cycles.py +0 -984
  174. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_d_separation.py +0 -340
  175. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dag.py +0 -835
  176. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_distance_measures.py +0 -831
  177. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_distance_regular.py +0 -85
  178. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dominance.py +0 -299
  179. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dominating.py +0 -115
  180. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_efficiency.py +0 -58
  181. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_euler.py +0 -314
  182. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_graph_hashing.py +0 -872
  183. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_graphical.py +0 -163
  184. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_hierarchy.py +0 -46
  185. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_hybrid.py +0 -24
  186. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_isolate.py +0 -26
  187. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_link_prediction.py +0 -615
  188. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_lowest_common_ancestors.py +0 -459
  189. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_matching.py +0 -556
  190. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_max_weight_clique.py +0 -179
  191. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_mis.py +0 -62
  192. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_moral.py +0 -15
  193. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_node_classification.py +0 -140
  194. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_non_randomness.py +0 -60
  195. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_perfect_graph.py +0 -27
  196. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_planar_drawing.py +0 -274
  197. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_planarity.py +0 -556
  198. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_polynomials.py +0 -57
  199. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_reciprocity.py +0 -37
  200. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_regular.py +0 -88
  201. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_richclub.py +0 -149
  202. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_similarity.py +0 -1158
  203. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_simple_paths.py +0 -803
  204. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_smallworld.py +0 -76
  205. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_smetric.py +0 -8
  206. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_sparsifiers.py +0 -138
  207. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_structuralholes.py +0 -191
  208. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_summarization.py +0 -642
  209. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_swap.py +0 -179
  210. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_threshold.py +0 -270
  211. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_time_dependent.py +0 -431
  212. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_tournament.py +0 -161
  213. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_triads.py +0 -248
  214. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_vitality.py +0 -41
  215. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_voronoi.py +0 -103
  216. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_walks.py +0 -54
  217. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_wiener.py +0 -157
  218. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/__init__.py +0 -0
  219. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_beamsearch.py +0 -25
  220. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_bfs.py +0 -203
  221. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_dfs.py +0 -307
  222. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_edgebfs.py +0 -147
  223. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_edgedfs.py +0 -131
  224. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/__init__.py +0 -0
  225. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_branchings.py +0 -624
  226. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_coding.py +0 -114
  227. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_decomposition.py +0 -79
  228. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_distance_measures.py +0 -99
  229. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_mst.py +0 -934
  230. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_operations.py +0 -53
  231. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_recognition.py +0 -174
  232. package/runtime/python/okstra_vendor/networkx/classes/tests/__init__.py +0 -0
  233. package/runtime/python/okstra_vendor/networkx/classes/tests/dispatch_interface.py +0 -192
  234. package/runtime/python/okstra_vendor/networkx/classes/tests/historical_tests.py +0 -476
  235. package/runtime/python/okstra_vendor/networkx/classes/tests/test_coreviews.py +0 -362
  236. package/runtime/python/okstra_vendor/networkx/classes/tests/test_digraph.py +0 -331
  237. package/runtime/python/okstra_vendor/networkx/classes/tests/test_digraph_historical.py +0 -110
  238. package/runtime/python/okstra_vendor/networkx/classes/tests/test_filters.py +0 -177
  239. package/runtime/python/okstra_vendor/networkx/classes/tests/test_function.py +0 -1045
  240. package/runtime/python/okstra_vendor/networkx/classes/tests/test_graph.py +0 -950
  241. package/runtime/python/okstra_vendor/networkx/classes/tests/test_graph_historical.py +0 -12
  242. package/runtime/python/okstra_vendor/networkx/classes/tests/test_graphviews.py +0 -349
  243. package/runtime/python/okstra_vendor/networkx/classes/tests/test_multidigraph.py +0 -459
  244. package/runtime/python/okstra_vendor/networkx/classes/tests/test_multigraph.py +0 -528
  245. package/runtime/python/okstra_vendor/networkx/classes/tests/test_reportviews.py +0 -1421
  246. package/runtime/python/okstra_vendor/networkx/classes/tests/test_special.py +0 -131
  247. package/runtime/python/okstra_vendor/networkx/classes/tests/test_subgraphviews.py +0 -371
  248. package/runtime/python/okstra_vendor/networkx/conftest.py +0 -261
  249. package/runtime/python/okstra_vendor/networkx/drawing/tests/__init__.py +0 -0
  250. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_complex.png +0 -0
  251. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_empty_graph.png +0 -0
  252. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_house_with_colors.png +0 -0
  253. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_labels_and_colors.png +0 -0
  254. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_shortest_path.png +0 -0
  255. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_house_with_colors.png +0 -0
  256. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_agraph.py +0 -237
  257. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_image_comparison_pylab_mpl.py +0 -229
  258. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_latex.py +0 -285
  259. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_layout.py +0 -631
  260. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_pydot.py +0 -146
  261. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_pylab.py +0 -1582
  262. package/runtime/python/okstra_vendor/networkx/generators/tests/__init__.py +0 -0
  263. package/runtime/python/okstra_vendor/networkx/generators/tests/test_atlas.py +0 -75
  264. package/runtime/python/okstra_vendor/networkx/generators/tests/test_classic.py +0 -642
  265. package/runtime/python/okstra_vendor/networkx/generators/tests/test_cographs.py +0 -20
  266. package/runtime/python/okstra_vendor/networkx/generators/tests/test_community.py +0 -362
  267. package/runtime/python/okstra_vendor/networkx/generators/tests/test_degree_seq.py +0 -224
  268. package/runtime/python/okstra_vendor/networkx/generators/tests/test_directed.py +0 -189
  269. package/runtime/python/okstra_vendor/networkx/generators/tests/test_duplication.py +0 -103
  270. package/runtime/python/okstra_vendor/networkx/generators/tests/test_ego.py +0 -39
  271. package/runtime/python/okstra_vendor/networkx/generators/tests/test_expanders.py +0 -182
  272. package/runtime/python/okstra_vendor/networkx/generators/tests/test_geometric.py +0 -488
  273. package/runtime/python/okstra_vendor/networkx/generators/tests/test_harary_graph.py +0 -133
  274. package/runtime/python/okstra_vendor/networkx/generators/tests/test_internet_as_graphs.py +0 -221
  275. package/runtime/python/okstra_vendor/networkx/generators/tests/test_intersection.py +0 -28
  276. package/runtime/python/okstra_vendor/networkx/generators/tests/test_interval_graph.py +0 -144
  277. package/runtime/python/okstra_vendor/networkx/generators/tests/test_joint_degree_seq.py +0 -125
  278. package/runtime/python/okstra_vendor/networkx/generators/tests/test_lattice.py +0 -264
  279. package/runtime/python/okstra_vendor/networkx/generators/tests/test_line.py +0 -316
  280. package/runtime/python/okstra_vendor/networkx/generators/tests/test_mycielski.py +0 -30
  281. package/runtime/python/okstra_vendor/networkx/generators/tests/test_nonisomorphic_trees.py +0 -82
  282. package/runtime/python/okstra_vendor/networkx/generators/tests/test_random_clustered.py +0 -33
  283. package/runtime/python/okstra_vendor/networkx/generators/tests/test_random_graphs.py +0 -495
  284. package/runtime/python/okstra_vendor/networkx/generators/tests/test_small.py +0 -220
  285. package/runtime/python/okstra_vendor/networkx/generators/tests/test_spectral_graph_forge.py +0 -49
  286. package/runtime/python/okstra_vendor/networkx/generators/tests/test_stochastic.py +0 -72
  287. package/runtime/python/okstra_vendor/networkx/generators/tests/test_sudoku.py +0 -92
  288. package/runtime/python/okstra_vendor/networkx/generators/tests/test_time_series.py +0 -64
  289. package/runtime/python/okstra_vendor/networkx/generators/tests/test_trees.py +0 -195
  290. package/runtime/python/okstra_vendor/networkx/generators/tests/test_triads.py +0 -15
  291. package/runtime/python/okstra_vendor/networkx/linalg/tests/__init__.py +0 -0
  292. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_algebraic_connectivity.py +0 -400
  293. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_attrmatrix.py +0 -108
  294. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_bethehessian.py +0 -40
  295. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_graphmatrix.py +0 -275
  296. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_laplacian.py +0 -334
  297. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_modularity.py +0 -86
  298. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_spectrum.py +0 -70
  299. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/__init__.py +0 -0
  300. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_adjacency.py +0 -78
  301. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_cytoscape.py +0 -78
  302. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_node_link.py +0 -109
  303. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_tree.py +0 -48
  304. package/runtime/python/okstra_vendor/networkx/readwrite/tests/__init__.py +0 -0
  305. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_adjlist.py +0 -354
  306. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_edgelist.py +0 -318
  307. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_gexf.py +0 -612
  308. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_gml.py +0 -744
  309. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_graph6.py +0 -181
  310. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_graphml.py +0 -1531
  311. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_leda.py +0 -30
  312. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_p2g.py +0 -63
  313. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_pajek.py +0 -128
  314. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_sparse6.py +0 -166
  315. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_text.py +0 -1742
  316. package/runtime/python/okstra_vendor/networkx/tests/__init__.py +0 -0
  317. package/runtime/python/okstra_vendor/networkx/tests/test_all_random_functions.py +0 -248
  318. package/runtime/python/okstra_vendor/networkx/tests/test_convert.py +0 -321
  319. package/runtime/python/okstra_vendor/networkx/tests/test_convert_numpy.py +0 -531
  320. package/runtime/python/okstra_vendor/networkx/tests/test_convert_pandas.py +0 -349
  321. package/runtime/python/okstra_vendor/networkx/tests/test_convert_scipy.py +0 -281
  322. package/runtime/python/okstra_vendor/networkx/tests/test_exceptions.py +0 -40
  323. package/runtime/python/okstra_vendor/networkx/tests/test_import.py +0 -11
  324. package/runtime/python/okstra_vendor/networkx/tests/test_lazy_imports.py +0 -96
  325. package/runtime/python/okstra_vendor/networkx/tests/test_relabel.py +0 -349
  326. package/runtime/python/okstra_vendor/networkx/tests/test_removed_functions_exception_messages.py +0 -8
  327. package/runtime/python/okstra_vendor/networkx/utils/tests/__init__.py +0 -0
  328. package/runtime/python/okstra_vendor/networkx/utils/tests/test__init.py +0 -11
  329. package/runtime/python/okstra_vendor/networkx/utils/tests/test_backends.py +0 -225
  330. package/runtime/python/okstra_vendor/networkx/utils/tests/test_config.py +0 -263
  331. package/runtime/python/okstra_vendor/networkx/utils/tests/test_decorators.py +0 -510
  332. package/runtime/python/okstra_vendor/networkx/utils/tests/test_heaps.py +0 -131
  333. package/runtime/python/okstra_vendor/networkx/utils/tests/test_mapped_queue.py +0 -268
  334. package/runtime/python/okstra_vendor/networkx/utils/tests/test_misc.py +0 -393
  335. package/runtime/python/okstra_vendor/networkx/utils/tests/test_random_sequence.py +0 -53
  336. package/runtime/python/okstra_vendor/networkx/utils/tests/test_rcm.py +0 -63
  337. package/runtime/python/okstra_vendor/networkx/utils/tests/test_unionfind.py +0 -55
@@ -1,631 +0,0 @@
1
- """Unit tests for layout functions."""
2
-
3
- import pytest
4
-
5
- import networkx as nx
6
-
7
- np = pytest.importorskip("numpy")
8
- pytest.importorskip("scipy")
9
-
10
-
11
- class TestLayout:
12
- @classmethod
13
- def setup_class(cls):
14
- cls.Gi = nx.grid_2d_graph(5, 5)
15
- cls.Gs = nx.Graph()
16
- nx.add_path(cls.Gs, "abcdef")
17
- cls.bigG = nx.grid_2d_graph(25, 25) # > 500 nodes for sparse
18
-
19
- def test_spring_fixed_without_pos(self):
20
- G = nx.path_graph(4)
21
- # No pos dict at all
22
- with pytest.raises(ValueError, match="nodes are fixed without positions"):
23
- nx.spring_layout(G, fixed=[0])
24
-
25
- pos = {0: (1, 1), 2: (0, 0)}
26
- # Node 1 not in pos dict
27
- with pytest.raises(ValueError, match="nodes are fixed without positions"):
28
- nx.spring_layout(G, fixed=[0, 1], pos=pos)
29
-
30
- # All fixed nodes in pos dict
31
- out = nx.spring_layout(G, fixed=[0, 2], pos=pos) # No ValueError
32
- assert all(np.array_equal(out[n], pos[n]) for n in (0, 2))
33
-
34
- def test_spring_init_pos(self):
35
- # Tests GH #2448
36
- import math
37
-
38
- G = nx.Graph()
39
- G.add_edges_from([(0, 1), (1, 2), (2, 0), (2, 3)])
40
-
41
- init_pos = {0: (0.0, 0.0)}
42
- fixed_pos = [0]
43
- pos = nx.fruchterman_reingold_layout(G, pos=init_pos, fixed=fixed_pos)
44
- has_nan = any(math.isnan(c) for coords in pos.values() for c in coords)
45
- assert not has_nan, "values should not be nan"
46
-
47
- def test_smoke_empty_graph(self):
48
- G = []
49
- nx.random_layout(G)
50
- nx.circular_layout(G)
51
- nx.planar_layout(G)
52
- nx.spring_layout(G)
53
- nx.fruchterman_reingold_layout(G)
54
- nx.spectral_layout(G)
55
- nx.shell_layout(G)
56
- nx.bipartite_layout(G, G)
57
- nx.spiral_layout(G)
58
- nx.multipartite_layout(G)
59
- nx.kamada_kawai_layout(G)
60
-
61
- def test_smoke_int(self):
62
- G = self.Gi
63
- nx.random_layout(G)
64
- nx.circular_layout(G)
65
- nx.planar_layout(G)
66
- nx.spring_layout(G)
67
- nx.forceatlas2_layout(G)
68
- nx.fruchterman_reingold_layout(G)
69
- nx.fruchterman_reingold_layout(self.bigG)
70
- nx.spectral_layout(G)
71
- nx.spectral_layout(G.to_directed())
72
- nx.spectral_layout(self.bigG)
73
- nx.spectral_layout(self.bigG.to_directed())
74
- nx.shell_layout(G)
75
- nx.spiral_layout(G)
76
- nx.kamada_kawai_layout(G)
77
- nx.kamada_kawai_layout(G, dim=1)
78
- nx.kamada_kawai_layout(G, dim=3)
79
- nx.arf_layout(G)
80
-
81
- def test_smoke_string(self):
82
- G = self.Gs
83
- nx.random_layout(G)
84
- nx.circular_layout(G)
85
- nx.planar_layout(G)
86
- nx.spring_layout(G)
87
- nx.forceatlas2_layout(G)
88
- nx.fruchterman_reingold_layout(G)
89
- nx.spectral_layout(G)
90
- nx.shell_layout(G)
91
- nx.spiral_layout(G)
92
- nx.kamada_kawai_layout(G)
93
- nx.kamada_kawai_layout(G, dim=1)
94
- nx.kamada_kawai_layout(G, dim=3)
95
- nx.arf_layout(G)
96
-
97
- def check_scale_and_center(self, pos, scale, center):
98
- center = np.array(center)
99
- low = center - scale
100
- hi = center + scale
101
- vpos = np.array(list(pos.values()))
102
- length = vpos.max(0) - vpos.min(0)
103
- assert (length <= 2 * scale).all()
104
- assert (vpos >= low).all()
105
- assert (vpos <= hi).all()
106
-
107
- def test_scale_and_center_arg(self):
108
- sc = self.check_scale_and_center
109
- c = (4, 5)
110
- G = nx.complete_graph(9)
111
- G.add_node(9)
112
- sc(nx.random_layout(G, center=c), scale=0.5, center=(4.5, 5.5))
113
- # rest can have 2*scale length: [-scale, scale]
114
- sc(nx.spring_layout(G, scale=2, center=c), scale=2, center=c)
115
- sc(nx.spectral_layout(G, scale=2, center=c), scale=2, center=c)
116
- sc(nx.circular_layout(G, scale=2, center=c), scale=2, center=c)
117
- sc(nx.shell_layout(G, scale=2, center=c), scale=2, center=c)
118
- sc(nx.spiral_layout(G, scale=2, center=c), scale=2, center=c)
119
- sc(nx.kamada_kawai_layout(G, scale=2, center=c), scale=2, center=c)
120
-
121
- c = (2, 3, 5)
122
- sc(nx.kamada_kawai_layout(G, dim=3, scale=2, center=c), scale=2, center=c)
123
-
124
- def test_planar_layout_non_planar_input(self):
125
- G = nx.complete_graph(9)
126
- pytest.raises(nx.NetworkXException, nx.planar_layout, G)
127
-
128
- def test_smoke_planar_layout_embedding_input(self):
129
- embedding = nx.PlanarEmbedding()
130
- embedding.set_data({0: [1, 2], 1: [0, 2], 2: [0, 1]})
131
- nx.planar_layout(embedding)
132
-
133
- def test_default_scale_and_center(self):
134
- sc = self.check_scale_and_center
135
- c = (0, 0)
136
- G = nx.complete_graph(9)
137
- G.add_node(9)
138
- sc(nx.random_layout(G), scale=0.5, center=(0.5, 0.5))
139
- sc(nx.spring_layout(G), scale=1, center=c)
140
- sc(nx.spectral_layout(G), scale=1, center=c)
141
- sc(nx.circular_layout(G), scale=1, center=c)
142
- sc(nx.shell_layout(G), scale=1, center=c)
143
- sc(nx.spiral_layout(G), scale=1, center=c)
144
- sc(nx.kamada_kawai_layout(G), scale=1, center=c)
145
-
146
- c = (0, 0, 0)
147
- sc(nx.kamada_kawai_layout(G, dim=3), scale=1, center=c)
148
-
149
- def test_circular_planar_and_shell_dim_error(self):
150
- G = nx.path_graph(4)
151
- pytest.raises(ValueError, nx.circular_layout, G, dim=1)
152
- pytest.raises(ValueError, nx.shell_layout, G, dim=1)
153
- pytest.raises(ValueError, nx.shell_layout, G, dim=3)
154
- pytest.raises(ValueError, nx.planar_layout, G, dim=1)
155
- pytest.raises(ValueError, nx.planar_layout, G, dim=3)
156
-
157
- def test_adjacency_interface_numpy(self):
158
- A = nx.to_numpy_array(self.Gs)
159
- pos = nx.drawing.layout._fruchterman_reingold(A)
160
- assert pos.shape == (6, 2)
161
- pos = nx.drawing.layout._fruchterman_reingold(A, dim=3)
162
- assert pos.shape == (6, 3)
163
- pos = nx.drawing.layout._sparse_fruchterman_reingold(A)
164
- assert pos.shape == (6, 2)
165
-
166
- def test_adjacency_interface_scipy(self):
167
- A = nx.to_scipy_sparse_array(self.Gs, dtype="d")
168
- pos = nx.drawing.layout._sparse_fruchterman_reingold(A)
169
- assert pos.shape == (6, 2)
170
- pos = nx.drawing.layout._sparse_spectral(A)
171
- assert pos.shape == (6, 2)
172
- pos = nx.drawing.layout._sparse_fruchterman_reingold(A, dim=3)
173
- assert pos.shape == (6, 3)
174
-
175
- def test_single_nodes(self):
176
- G = nx.path_graph(1)
177
- vpos = nx.shell_layout(G)
178
- assert not vpos[0].any()
179
- G = nx.path_graph(4)
180
- vpos = nx.shell_layout(G, [[0], [1, 2], [3]])
181
- assert not vpos[0].any()
182
- assert vpos[3].any() # ensure node 3 not at origin (#3188)
183
- assert np.linalg.norm(vpos[3]) <= 1 # ensure node 3 fits (#3753)
184
- vpos = nx.shell_layout(G, [[0], [1, 2], [3]], rotate=0)
185
- assert np.linalg.norm(vpos[3]) <= 1 # ensure node 3 fits (#3753)
186
-
187
- def test_smoke_initial_pos_forceatlas2(self):
188
- pos = nx.circular_layout(self.Gi)
189
- npos = nx.forceatlas2_layout(self.Gi, pos=pos)
190
-
191
- def test_smoke_initial_pos_fruchterman_reingold(self):
192
- pos = nx.circular_layout(self.Gi)
193
- npos = nx.fruchterman_reingold_layout(self.Gi, pos=pos)
194
-
195
- def test_smoke_initial_pos_arf(self):
196
- pos = nx.circular_layout(self.Gi)
197
- npos = nx.arf_layout(self.Gi, pos=pos)
198
-
199
- def test_fixed_node_fruchterman_reingold(self):
200
- # Dense version (numpy based)
201
- pos = nx.circular_layout(self.Gi)
202
- npos = nx.spring_layout(self.Gi, pos=pos, fixed=[(0, 0)])
203
- assert tuple(pos[(0, 0)]) == tuple(npos[(0, 0)])
204
- # Sparse version (scipy based)
205
- pos = nx.circular_layout(self.bigG)
206
- npos = nx.spring_layout(self.bigG, pos=pos, fixed=[(0, 0)])
207
- for axis in range(2):
208
- assert pos[(0, 0)][axis] == pytest.approx(npos[(0, 0)][axis], abs=1e-7)
209
-
210
- def test_center_parameter(self):
211
- G = nx.path_graph(1)
212
- nx.random_layout(G, center=(1, 1))
213
- vpos = nx.circular_layout(G, center=(1, 1))
214
- assert tuple(vpos[0]) == (1, 1)
215
- vpos = nx.planar_layout(G, center=(1, 1))
216
- assert tuple(vpos[0]) == (1, 1)
217
- vpos = nx.spring_layout(G, center=(1, 1))
218
- assert tuple(vpos[0]) == (1, 1)
219
- vpos = nx.fruchterman_reingold_layout(G, center=(1, 1))
220
- assert tuple(vpos[0]) == (1, 1)
221
- vpos = nx.spectral_layout(G, center=(1, 1))
222
- assert tuple(vpos[0]) == (1, 1)
223
- vpos = nx.shell_layout(G, center=(1, 1))
224
- assert tuple(vpos[0]) == (1, 1)
225
- vpos = nx.spiral_layout(G, center=(1, 1))
226
- assert tuple(vpos[0]) == (1, 1)
227
-
228
- def test_center_wrong_dimensions(self):
229
- G = nx.path_graph(1)
230
- assert id(nx.spring_layout) == id(nx.fruchterman_reingold_layout)
231
- pytest.raises(ValueError, nx.random_layout, G, center=(1, 1, 1))
232
- pytest.raises(ValueError, nx.circular_layout, G, center=(1, 1, 1))
233
- pytest.raises(ValueError, nx.planar_layout, G, center=(1, 1, 1))
234
- pytest.raises(ValueError, nx.spring_layout, G, center=(1, 1, 1))
235
- pytest.raises(ValueError, nx.spring_layout, G, dim=3, center=(1, 1))
236
- pytest.raises(ValueError, nx.spectral_layout, G, center=(1, 1, 1))
237
- pytest.raises(ValueError, nx.spectral_layout, G, dim=3, center=(1, 1))
238
- pytest.raises(ValueError, nx.shell_layout, G, center=(1, 1, 1))
239
- pytest.raises(ValueError, nx.spiral_layout, G, center=(1, 1, 1))
240
- pytest.raises(ValueError, nx.kamada_kawai_layout, G, center=(1, 1, 1))
241
-
242
- def test_empty_graph(self):
243
- G = nx.empty_graph()
244
- vpos = nx.random_layout(G, center=(1, 1))
245
- assert vpos == {}
246
- vpos = nx.circular_layout(G, center=(1, 1))
247
- assert vpos == {}
248
- vpos = nx.planar_layout(G, center=(1, 1))
249
- assert vpos == {}
250
- vpos = nx.bipartite_layout(G, G)
251
- assert vpos == {}
252
- vpos = nx.spring_layout(G, center=(1, 1))
253
- assert vpos == {}
254
- vpos = nx.fruchterman_reingold_layout(G, center=(1, 1))
255
- assert vpos == {}
256
- vpos = nx.spectral_layout(G, center=(1, 1))
257
- assert vpos == {}
258
- vpos = nx.shell_layout(G, center=(1, 1))
259
- assert vpos == {}
260
- vpos = nx.spiral_layout(G, center=(1, 1))
261
- assert vpos == {}
262
- vpos = nx.multipartite_layout(G, center=(1, 1))
263
- assert vpos == {}
264
- vpos = nx.kamada_kawai_layout(G, center=(1, 1))
265
- assert vpos == {}
266
- vpos = nx.forceatlas2_layout(G)
267
- assert vpos == {}
268
- vpos = nx.arf_layout(G)
269
- assert vpos == {}
270
-
271
- def test_bipartite_layout(self):
272
- G = nx.complete_bipartite_graph(3, 5)
273
- top, bottom = nx.bipartite.sets(G)
274
-
275
- vpos = nx.bipartite_layout(G, top)
276
- assert len(vpos) == len(G)
277
-
278
- top_x = vpos[list(top)[0]][0]
279
- bottom_x = vpos[list(bottom)[0]][0]
280
- for node in top:
281
- assert vpos[node][0] == top_x
282
- for node in bottom:
283
- assert vpos[node][0] == bottom_x
284
-
285
- vpos = nx.bipartite_layout(
286
- G, top, align="horizontal", center=(2, 2), scale=2, aspect_ratio=1
287
- )
288
- assert len(vpos) == len(G)
289
-
290
- top_y = vpos[list(top)[0]][1]
291
- bottom_y = vpos[list(bottom)[0]][1]
292
- for node in top:
293
- assert vpos[node][1] == top_y
294
- for node in bottom:
295
- assert vpos[node][1] == bottom_y
296
-
297
- pytest.raises(ValueError, nx.bipartite_layout, G, top, align="foo")
298
-
299
- def test_multipartite_layout(self):
300
- sizes = (0, 5, 7, 2, 8)
301
- G = nx.complete_multipartite_graph(*sizes)
302
-
303
- vpos = nx.multipartite_layout(G)
304
- assert len(vpos) == len(G)
305
-
306
- start = 0
307
- for n in sizes:
308
- end = start + n
309
- assert all(vpos[start][0] == vpos[i][0] for i in range(start + 1, end))
310
- start += n
311
-
312
- vpos = nx.multipartite_layout(G, align="horizontal", scale=2, center=(2, 2))
313
- assert len(vpos) == len(G)
314
-
315
- start = 0
316
- for n in sizes:
317
- end = start + n
318
- assert all(vpos[start][1] == vpos[i][1] for i in range(start + 1, end))
319
- start += n
320
-
321
- pytest.raises(ValueError, nx.multipartite_layout, G, align="foo")
322
-
323
- def test_kamada_kawai_costfn_1d(self):
324
- costfn = nx.drawing.layout._kamada_kawai_costfn
325
-
326
- pos = np.array([4.0, 7.0])
327
- invdist = 1 / np.array([[0.1, 2.0], [2.0, 0.3]])
328
-
329
- cost, grad = costfn(pos, np, invdist, meanweight=0, dim=1)
330
-
331
- assert cost == pytest.approx(((3 / 2.0 - 1) ** 2), abs=1e-7)
332
- assert grad[0] == pytest.approx((-0.5), abs=1e-7)
333
- assert grad[1] == pytest.approx(0.5, abs=1e-7)
334
-
335
- def check_kamada_kawai_costfn(self, pos, invdist, meanwt, dim):
336
- costfn = nx.drawing.layout._kamada_kawai_costfn
337
-
338
- cost, grad = costfn(pos.ravel(), np, invdist, meanweight=meanwt, dim=dim)
339
-
340
- expected_cost = 0.5 * meanwt * np.sum(np.sum(pos, axis=0) ** 2)
341
- for i in range(pos.shape[0]):
342
- for j in range(i + 1, pos.shape[0]):
343
- diff = np.linalg.norm(pos[i] - pos[j])
344
- expected_cost += (diff * invdist[i][j] - 1.0) ** 2
345
-
346
- assert cost == pytest.approx(expected_cost, abs=1e-7)
347
-
348
- dx = 1e-4
349
- for nd in range(pos.shape[0]):
350
- for dm in range(pos.shape[1]):
351
- idx = nd * pos.shape[1] + dm
352
- ps = pos.flatten()
353
-
354
- ps[idx] += dx
355
- cplus = costfn(ps, np, invdist, meanweight=meanwt, dim=pos.shape[1])[0]
356
-
357
- ps[idx] -= 2 * dx
358
- cminus = costfn(ps, np, invdist, meanweight=meanwt, dim=pos.shape[1])[0]
359
-
360
- assert grad[idx] == pytest.approx((cplus - cminus) / (2 * dx), abs=1e-5)
361
-
362
- def test_kamada_kawai_costfn(self):
363
- invdist = 1 / np.array([[0.1, 2.1, 1.7], [2.1, 0.2, 0.6], [1.7, 0.6, 0.3]])
364
- meanwt = 0.3
365
-
366
- # 2d
367
- pos = np.array([[1.3, -3.2], [2.7, -0.3], [5.1, 2.5]])
368
-
369
- self.check_kamada_kawai_costfn(pos, invdist, meanwt, 2)
370
-
371
- # 3d
372
- pos = np.array([[0.9, 8.6, -8.7], [-10, -0.5, -7.1], [9.1, -8.1, 1.6]])
373
-
374
- self.check_kamada_kawai_costfn(pos, invdist, meanwt, 3)
375
-
376
- def test_spiral_layout(self):
377
- G = self.Gs
378
-
379
- # a lower value of resolution should result in a more compact layout
380
- # intuitively, the total distance from the start and end nodes
381
- # via each node in between (transiting through each) will be less,
382
- # assuming rescaling does not occur on the computed node positions
383
- pos_standard = np.array(list(nx.spiral_layout(G, resolution=0.35).values()))
384
- pos_tighter = np.array(list(nx.spiral_layout(G, resolution=0.34).values()))
385
- distances = np.linalg.norm(pos_standard[:-1] - pos_standard[1:], axis=1)
386
- distances_tighter = np.linalg.norm(pos_tighter[:-1] - pos_tighter[1:], axis=1)
387
- assert sum(distances) > sum(distances_tighter)
388
-
389
- # return near-equidistant points after the first value if set to true
390
- pos_equidistant = np.array(list(nx.spiral_layout(G, equidistant=True).values()))
391
- distances_equidistant = np.linalg.norm(
392
- pos_equidistant[:-1] - pos_equidistant[1:], axis=1
393
- )
394
- assert np.allclose(
395
- distances_equidistant[1:], distances_equidistant[-1], atol=0.01
396
- )
397
-
398
- def test_spiral_layout_equidistant(self):
399
- G = nx.path_graph(10)
400
- nx.spiral_layout(G, equidistant=True, store_pos_as="pos")
401
- pos = nx.get_node_attributes(G, "pos")
402
- # Extract individual node positions as an array
403
- p = np.array(list(pos.values()))
404
- # Elementwise-distance between node positions
405
- dist = np.linalg.norm(p[1:] - p[:-1], axis=1)
406
- assert np.allclose(np.diff(dist), 0, atol=1e-3)
407
-
408
- def test_forceatlas2_layout_partial_input_test(self):
409
- # check whether partial pos input still returns a full proper position
410
- G = self.Gs
411
- node = nx.utils.arbitrary_element(G)
412
- pos = nx.circular_layout(G)
413
- del pos[node]
414
- pos = nx.forceatlas2_layout(G, pos=pos)
415
- assert len(pos) == len(G)
416
-
417
- def test_rescale_layout_dict(self):
418
- G = nx.empty_graph()
419
- vpos = nx.random_layout(G, center=(1, 1))
420
- assert nx.rescale_layout_dict(vpos) == {}
421
-
422
- G = nx.empty_graph(2)
423
- vpos = {0: (0.0, 0.0), 1: (1.0, 1.0)}
424
- s_vpos = nx.rescale_layout_dict(vpos)
425
- assert np.linalg.norm([sum(x) for x in zip(*s_vpos.values())]) < 1e-6
426
-
427
- G = nx.empty_graph(3)
428
- vpos = {0: (0, 0), 1: (1, 1), 2: (0.5, 0.5)}
429
- s_vpos = nx.rescale_layout_dict(vpos)
430
-
431
- expectation = {
432
- 0: np.array((-1, -1)),
433
- 1: np.array((1, 1)),
434
- 2: np.array((0, 0)),
435
- }
436
- for k, v in expectation.items():
437
- assert (s_vpos[k] == v).all()
438
- s_vpos = nx.rescale_layout_dict(vpos, scale=2)
439
- expectation = {
440
- 0: np.array((-2, -2)),
441
- 1: np.array((2, 2)),
442
- 2: np.array((0, 0)),
443
- }
444
- for k, v in expectation.items():
445
- assert (s_vpos[k] == v).all()
446
-
447
- def test_arf_layout_partial_input_test(self):
448
- # Checks whether partial pos input still returns a proper position.
449
- G = self.Gs
450
- node = nx.utils.arbitrary_element(G)
451
- pos = nx.circular_layout(G)
452
- del pos[node]
453
- pos = nx.arf_layout(G, pos=pos)
454
- assert len(pos) == len(G)
455
-
456
- def test_arf_layout_negative_a_check(self):
457
- """
458
- Checks input parameters correctly raises errors. For example, `a` should be larger than 1
459
- """
460
- G = self.Gs
461
- pytest.raises(ValueError, nx.arf_layout, G=G, a=-1)
462
-
463
- def test_smoke_seed_input(self):
464
- G = self.Gs
465
- nx.random_layout(G, seed=42)
466
- nx.spring_layout(G, seed=42)
467
- nx.arf_layout(G, seed=42)
468
- nx.forceatlas2_layout(G, seed=42)
469
-
470
- def test_node_at_center(self):
471
- # see gh-7791 avoid divide by zero
472
- G = nx.path_graph(3)
473
- orig_pos = {i: [i - 1, 0.0] for i in range(3)}
474
- new_pos = nx.forceatlas2_layout(G, pos=orig_pos)
475
-
476
- def test_initial_only_some_pos(self):
477
- G = nx.path_graph(3)
478
- orig_pos = {i: [i - 1, 0.0] for i in range(2)}
479
- new_pos = nx.forceatlas2_layout(G, pos=orig_pos, seed=42)
480
-
481
-
482
- def test_multipartite_layout_nonnumeric_partition_labels():
483
- """See gh-5123."""
484
- G = nx.Graph()
485
- G.add_node(0, subset="s0")
486
- G.add_node(1, subset="s0")
487
- G.add_node(2, subset="s1")
488
- G.add_node(3, subset="s1")
489
- G.add_edges_from([(0, 2), (0, 3), (1, 2)])
490
- pos = nx.multipartite_layout(G)
491
- assert len(pos) == len(G)
492
-
493
-
494
- def test_multipartite_layout_layer_order():
495
- """Return the layers in sorted order if the layers of the multipartite
496
- graph are sortable. See gh-5691"""
497
- G = nx.Graph()
498
- node_group = dict(zip(("a", "b", "c", "d", "e"), (2, 3, 1, 2, 4)))
499
- for node, layer in node_group.items():
500
- G.add_node(node, subset=layer)
501
-
502
- # Horizontal alignment, therefore y-coord determines layers
503
- pos = nx.multipartite_layout(G, align="horizontal")
504
-
505
- layers = nx.utils.groups(node_group)
506
- pos_from_layers = nx.multipartite_layout(G, align="horizontal", subset_key=layers)
507
- for (n1, p1), (n2, p2) in zip(pos.items(), pos_from_layers.items()):
508
- assert n1 == n2 and (p1 == p2).all()
509
-
510
- # Nodes "a" and "d" are in the same layer
511
- assert pos["a"][-1] == pos["d"][-1]
512
- # positions should be sorted according to layer
513
- assert pos["c"][-1] < pos["a"][-1] < pos["b"][-1] < pos["e"][-1]
514
-
515
- # Make sure that multipartite_layout still works when layers are not sortable
516
- G.nodes["a"]["subset"] = "layer_0" # Can't sort mixed strs/ints
517
- pos_nosort = nx.multipartite_layout(G) # smoke test: this should not raise
518
- assert pos_nosort.keys() == pos.keys()
519
-
520
-
521
- def _num_nodes_per_bfs_layer(pos):
522
- """Helper function to extract the number of nodes in each layer of bfs_layout"""
523
- x = np.array(list(pos.values()))[:, 0] # node positions in layered dimension
524
- _, layer_count = np.unique(x, return_counts=True)
525
- return layer_count
526
-
527
-
528
- @pytest.mark.parametrize("n", range(2, 7))
529
- def test_bfs_layout_complete_graph(n):
530
- """The complete graph should result in two layers: the starting node and
531
- a second layer containing all neighbors."""
532
- G = nx.complete_graph(n)
533
- nx.bfs_layout(G, start=0, store_pos_as="pos")
534
- pos = nx.get_node_attributes(G, "pos")
535
- assert np.array_equal(_num_nodes_per_bfs_layer(pos), [1, n - 1])
536
-
537
-
538
- def test_bfs_layout_barbell():
539
- G = nx.barbell_graph(5, 3)
540
- # Start in one of the "bells"
541
- pos = nx.bfs_layout(G, start=0)
542
- # start, bell-1, [1] * len(bar)+1, bell-1
543
- expected_nodes_per_layer = [1, 4, 1, 1, 1, 1, 4]
544
- assert np.array_equal(_num_nodes_per_bfs_layer(pos), expected_nodes_per_layer)
545
- # Start in the other "bell" - expect same layer pattern
546
- pos = nx.bfs_layout(G, start=12)
547
- assert np.array_equal(_num_nodes_per_bfs_layer(pos), expected_nodes_per_layer)
548
- # Starting in the center of the bar, expect layers to be symmetric
549
- pos = nx.bfs_layout(G, start=6)
550
- # Expected layers: {6 (start)}, {5, 7}, {4, 8}, {8 nodes from remainder of bells}
551
- expected_nodes_per_layer = [1, 2, 2, 8]
552
- assert np.array_equal(_num_nodes_per_bfs_layer(pos), expected_nodes_per_layer)
553
-
554
-
555
- def test_bfs_layout_disconnected():
556
- G = nx.complete_graph(5)
557
- G.add_edges_from([(10, 11), (11, 12)])
558
- with pytest.raises(nx.NetworkXError, match="bfs_layout didn't include all nodes"):
559
- nx.bfs_layout(G, start=0)
560
-
561
-
562
- def test_bipartite_layout_default_nodes_raises_non_bipartite_input():
563
- G = nx.complete_graph(5)
564
- with pytest.raises(nx.NetworkXError, match="Graph is not bipartite"):
565
- nx.bipartite_layout(G)
566
- # No exception if nodes are explicitly specified
567
- pos = nx.bipartite_layout(G, nodes=[2, 3])
568
-
569
-
570
- def test_bipartite_layout_default_nodes():
571
- G = nx.complete_bipartite_graph(3, 3)
572
- pos = nx.bipartite_layout(G) # no nodes specified
573
- # X coords of nodes should be the same within the bipartite sets
574
- for nodeset in nx.bipartite.sets(G):
575
- xs = [pos[k][0] for k in nodeset]
576
- assert all(x == pytest.approx(xs[0]) for x in xs)
577
-
578
-
579
- @pytest.mark.parametrize(
580
- "layout",
581
- [
582
- nx.random_layout,
583
- nx.circular_layout,
584
- nx.shell_layout,
585
- nx.spring_layout,
586
- nx.kamada_kawai_layout,
587
- nx.spectral_layout,
588
- nx.planar_layout,
589
- nx.spiral_layout,
590
- nx.forceatlas2_layout,
591
- ],
592
- )
593
- def test_layouts_negative_dim(layout):
594
- """Test all layouts that support dim kwarg handle invalid inputs."""
595
- G = nx.path_graph(4)
596
- valid_err_msgs = "|".join(
597
- [
598
- "negative dimensions.*not allowed",
599
- "can only handle 2",
600
- "cannot handle.*2",
601
- ]
602
- )
603
- with pytest.raises(ValueError, match=valid_err_msgs):
604
- layout(G, dim=-1)
605
-
606
-
607
- @pytest.mark.parametrize(
608
- ("num_nodes", "expected_method"), [(100, "force"), (501, "energy")]
609
- )
610
- @pytest.mark.parametrize(
611
- "extra_layout_kwargs",
612
- [
613
- {}, # No extra kwargs
614
- {"pos": {0: (0, 0)}, "fixed": [0]}, # Fixed node position
615
- {"dim": 3}, # 3D layout
616
- ],
617
- )
618
- def test_spring_layout_graph_size_heuristic(
619
- num_nodes, expected_method, extra_layout_kwargs
620
- ):
621
- """Expect 'force' layout for n < 500 and 'energy' for n >= 500"""
622
- G = nx.cycle_graph(num_nodes)
623
- # Seeded layout to compare explicit method to one determined by "auto"
624
- seed = 163674319
625
-
626
- # Compare explicit method to auto method
627
- expected = nx.spring_layout(
628
- G, method=expected_method, seed=seed, **extra_layout_kwargs
629
- )
630
- actual = nx.spring_layout(G, method="auto", seed=seed, **extra_layout_kwargs)
631
- assert np.allclose(list(expected.values()), list(actual.values()), atol=1e-5)