okstra 0.114.0 → 0.115.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 (326) 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/lead/okstra-lead-contract.md +1 -1
  7. package/runtime/python/okstra_ctl/implementation_stage.py +46 -39
  8. package/runtime/python/okstra_ctl/report_views.py +151 -12
  9. package/runtime/python/okstra_ctl/run.py +24 -24
  10. package/runtime/python/okstra_ctl/worktree.py +1 -1
  11. package/runtime/python/okstra_token_usage/claude.py +58 -19
  12. package/runtime/python/okstra_token_usage/collect.py +3 -1
  13. package/runtime/python/okstra_vendor/__init__.py +3 -0
  14. package/runtime/schemas/final-report-v1.0.schema.json +20 -0
  15. package/runtime/templates/reports/final-report.template.md +14 -0
  16. package/runtime/templates/reports/i18n/en.json +23 -12
  17. package/runtime/templates/reports/i18n/ko.json +23 -12
  18. package/runtime/templates/reports/report.css +55 -0
  19. package/runtime/templates/reports/report.js +53 -1
  20. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/__init__.py +0 -0
  21. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_approx_clust_coeff.py +0 -41
  22. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_clique.py +0 -112
  23. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_connectivity.py +0 -199
  24. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_density.py +0 -146
  25. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_distance_measures.py +0 -59
  26. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_dominating_set.py +0 -78
  27. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_kcomponents.py +0 -303
  28. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_matching.py +0 -8
  29. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_maxcut.py +0 -94
  30. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_ramsey.py +0 -31
  31. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_steinertree.py +0 -306
  32. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_traveling_salesman.py +0 -1014
  33. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_treewidth.py +0 -274
  34. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_vertex_cover.py +0 -68
  35. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/__init__.py +0 -0
  36. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/base_test.py +0 -81
  37. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_connectivity.py +0 -143
  38. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_correlation.py +0 -122
  39. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_mixing.py +0 -174
  40. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_neighbor_degree.py +0 -107
  41. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_pairs.py +0 -87
  42. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/__init__.py +0 -0
  43. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_basic.py +0 -125
  44. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_centrality.py +0 -192
  45. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_cluster.py +0 -84
  46. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_covering.py +0 -33
  47. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_edgelist.py +0 -240
  48. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_extendability.py +0 -334
  49. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_generators.py +0 -407
  50. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_link_analysis.py +0 -218
  51. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_matching.py +0 -327
  52. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_matrix.py +0 -138
  53. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_project.py +0 -409
  54. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_redundancy.py +0 -35
  55. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_spectral_bipartivity.py +0 -80
  56. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/__init__.py +0 -0
  57. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_betweenness_centrality.py +0 -923
  58. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_betweenness_centrality_subset.py +0 -354
  59. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_closeness_centrality.py +0 -274
  60. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_betweenness_centrality.py +0 -259
  61. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_betweenness_centrality_subset.py +0 -147
  62. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_closeness.py +0 -43
  63. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_degree_centrality.py +0 -144
  64. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_dispersion.py +0 -73
  65. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_eigenvector_centrality.py +0 -186
  66. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_group.py +0 -277
  67. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_harmonic_centrality.py +0 -122
  68. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_katz_centrality.py +0 -345
  69. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_laplacian_centrality.py +0 -220
  70. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_load_centrality.py +0 -344
  71. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_percolation_centrality.py +0 -87
  72. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_reaching.py +0 -140
  73. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_second_order_centrality.py +0 -82
  74. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_subgraph.py +0 -110
  75. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_trophic.py +0 -302
  76. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_voterank.py +0 -64
  77. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/tests/__init__.py +0 -0
  78. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/tests/test_coloring.py +0 -863
  79. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/__init__.py +0 -0
  80. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_asyn_fluid.py +0 -147
  81. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_bipartitions.py +0 -157
  82. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_centrality.py +0 -85
  83. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_divisive.py +0 -106
  84. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_kclique.py +0 -91
  85. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_label_propagation.py +0 -241
  86. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_leiden.py +0 -138
  87. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_local.py +0 -76
  88. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_louvain.py +0 -264
  89. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_lukes.py +0 -152
  90. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_modularity_max.py +0 -340
  91. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_quality.py +0 -139
  92. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_utils.py +0 -26
  93. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/__init__.py +0 -0
  94. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_attracting.py +0 -70
  95. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_biconnected.py +0 -248
  96. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_connected.py +0 -138
  97. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_semiconnected.py +0 -55
  98. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_strongly_connected.py +0 -193
  99. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_weakly_connected.py +0 -96
  100. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/__init__.py +0 -0
  101. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_connectivity.py +0 -421
  102. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_cuts.py +0 -309
  103. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_disjoint_paths.py +0 -249
  104. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_edge_augmentation.py +0 -502
  105. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_edge_kcomponents.py +0 -488
  106. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_kcomponents.py +0 -323
  107. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_kcutsets.py +0 -280
  108. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_stoer_wagner.py +0 -102
  109. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/__init__.py +0 -0
  110. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/gl1.gpickle.bz2 +0 -0
  111. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/gw1.gpickle.bz2 +0 -0
  112. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/netgen-2.gpickle.bz2 +0 -0
  113. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_gomory_hu.py +0 -128
  114. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_maxflow.py +0 -573
  115. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_maxflow_large_graph.py +0 -155
  116. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_mincost.py +0 -475
  117. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_networksimplex.py +0 -481
  118. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/wlm3.gpickle.bz2 +0 -0
  119. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/__init__.py +0 -0
  120. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/iso_r01_s80.A99 +0 -0
  121. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/iso_r01_s80.B99 +0 -0
  122. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/si2_b06_m200.A99 +0 -0
  123. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/si2_b06_m200.B99 +0 -0
  124. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_ismags.py +0 -719
  125. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_isomorphism.py +0 -103
  126. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_isomorphvf2.py +0 -490
  127. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_match_helpers.py +0 -64
  128. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_temporalisomorphvf2.py +0 -212
  129. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_tree_isomorphism.py +0 -202
  130. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2pp.py +0 -1655
  131. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2pp_helpers.py +0 -3118
  132. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2userfunc.py +0 -196
  133. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/__init__.py +0 -0
  134. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/test_hits.py +0 -77
  135. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/test_pagerank.py +0 -213
  136. package/runtime/python/okstra_vendor/networkx/algorithms/minors/tests/test_contraction.py +0 -544
  137. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/__init__.py +0 -0
  138. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_all.py +0 -328
  139. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_binary.py +0 -451
  140. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_product.py +0 -491
  141. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_unary.py +0 -55
  142. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/__init__.py +0 -0
  143. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_astar.py +0 -254
  144. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_dense.py +0 -212
  145. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_dense_numpy.py +0 -88
  146. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_generic.py +0 -511
  147. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_unweighted.py +0 -149
  148. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_weighted.py +0 -983
  149. package/runtime/python/okstra_vendor/networkx/algorithms/tests/__init__.py +0 -0
  150. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_asteroidal.py +0 -23
  151. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_boundary.py +0 -154
  152. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_bridges.py +0 -144
  153. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_broadcasting.py +0 -109
  154. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_chains.py +0 -136
  155. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_chordal.py +0 -129
  156. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_clique.py +0 -300
  157. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cluster.py +0 -678
  158. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_communicability.py +0 -80
  159. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_core.py +0 -266
  160. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_covering.py +0 -85
  161. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cuts.py +0 -171
  162. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cycles.py +0 -984
  163. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_d_separation.py +0 -340
  164. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dag.py +0 -835
  165. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_distance_measures.py +0 -831
  166. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_distance_regular.py +0 -85
  167. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dominance.py +0 -299
  168. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dominating.py +0 -115
  169. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_efficiency.py +0 -58
  170. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_euler.py +0 -314
  171. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_graph_hashing.py +0 -872
  172. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_graphical.py +0 -163
  173. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_hierarchy.py +0 -46
  174. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_hybrid.py +0 -24
  175. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_isolate.py +0 -26
  176. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_link_prediction.py +0 -615
  177. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_lowest_common_ancestors.py +0 -459
  178. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_matching.py +0 -556
  179. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_max_weight_clique.py +0 -179
  180. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_mis.py +0 -62
  181. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_moral.py +0 -15
  182. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_node_classification.py +0 -140
  183. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_non_randomness.py +0 -60
  184. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_perfect_graph.py +0 -27
  185. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_planar_drawing.py +0 -274
  186. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_planarity.py +0 -556
  187. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_polynomials.py +0 -57
  188. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_reciprocity.py +0 -37
  189. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_regular.py +0 -88
  190. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_richclub.py +0 -149
  191. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_similarity.py +0 -1158
  192. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_simple_paths.py +0 -803
  193. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_smallworld.py +0 -76
  194. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_smetric.py +0 -8
  195. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_sparsifiers.py +0 -138
  196. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_structuralholes.py +0 -191
  197. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_summarization.py +0 -642
  198. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_swap.py +0 -179
  199. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_threshold.py +0 -270
  200. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_time_dependent.py +0 -431
  201. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_tournament.py +0 -161
  202. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_triads.py +0 -248
  203. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_vitality.py +0 -41
  204. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_voronoi.py +0 -103
  205. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_walks.py +0 -54
  206. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_wiener.py +0 -157
  207. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/__init__.py +0 -0
  208. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_beamsearch.py +0 -25
  209. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_bfs.py +0 -203
  210. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_dfs.py +0 -307
  211. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_edgebfs.py +0 -147
  212. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_edgedfs.py +0 -131
  213. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/__init__.py +0 -0
  214. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_branchings.py +0 -624
  215. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_coding.py +0 -114
  216. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_decomposition.py +0 -79
  217. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_distance_measures.py +0 -99
  218. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_mst.py +0 -934
  219. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_operations.py +0 -53
  220. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_recognition.py +0 -174
  221. package/runtime/python/okstra_vendor/networkx/classes/tests/__init__.py +0 -0
  222. package/runtime/python/okstra_vendor/networkx/classes/tests/dispatch_interface.py +0 -192
  223. package/runtime/python/okstra_vendor/networkx/classes/tests/historical_tests.py +0 -476
  224. package/runtime/python/okstra_vendor/networkx/classes/tests/test_coreviews.py +0 -362
  225. package/runtime/python/okstra_vendor/networkx/classes/tests/test_digraph.py +0 -331
  226. package/runtime/python/okstra_vendor/networkx/classes/tests/test_digraph_historical.py +0 -110
  227. package/runtime/python/okstra_vendor/networkx/classes/tests/test_filters.py +0 -177
  228. package/runtime/python/okstra_vendor/networkx/classes/tests/test_function.py +0 -1045
  229. package/runtime/python/okstra_vendor/networkx/classes/tests/test_graph.py +0 -950
  230. package/runtime/python/okstra_vendor/networkx/classes/tests/test_graph_historical.py +0 -12
  231. package/runtime/python/okstra_vendor/networkx/classes/tests/test_graphviews.py +0 -349
  232. package/runtime/python/okstra_vendor/networkx/classes/tests/test_multidigraph.py +0 -459
  233. package/runtime/python/okstra_vendor/networkx/classes/tests/test_multigraph.py +0 -528
  234. package/runtime/python/okstra_vendor/networkx/classes/tests/test_reportviews.py +0 -1421
  235. package/runtime/python/okstra_vendor/networkx/classes/tests/test_special.py +0 -131
  236. package/runtime/python/okstra_vendor/networkx/classes/tests/test_subgraphviews.py +0 -371
  237. package/runtime/python/okstra_vendor/networkx/conftest.py +0 -261
  238. package/runtime/python/okstra_vendor/networkx/drawing/tests/__init__.py +0 -0
  239. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_complex.png +0 -0
  240. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_empty_graph.png +0 -0
  241. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_house_with_colors.png +0 -0
  242. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_labels_and_colors.png +0 -0
  243. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_shortest_path.png +0 -0
  244. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_house_with_colors.png +0 -0
  245. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_agraph.py +0 -237
  246. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_image_comparison_pylab_mpl.py +0 -229
  247. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_latex.py +0 -285
  248. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_layout.py +0 -631
  249. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_pydot.py +0 -146
  250. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_pylab.py +0 -1582
  251. package/runtime/python/okstra_vendor/networkx/generators/tests/__init__.py +0 -0
  252. package/runtime/python/okstra_vendor/networkx/generators/tests/test_atlas.py +0 -75
  253. package/runtime/python/okstra_vendor/networkx/generators/tests/test_classic.py +0 -642
  254. package/runtime/python/okstra_vendor/networkx/generators/tests/test_cographs.py +0 -20
  255. package/runtime/python/okstra_vendor/networkx/generators/tests/test_community.py +0 -362
  256. package/runtime/python/okstra_vendor/networkx/generators/tests/test_degree_seq.py +0 -224
  257. package/runtime/python/okstra_vendor/networkx/generators/tests/test_directed.py +0 -189
  258. package/runtime/python/okstra_vendor/networkx/generators/tests/test_duplication.py +0 -103
  259. package/runtime/python/okstra_vendor/networkx/generators/tests/test_ego.py +0 -39
  260. package/runtime/python/okstra_vendor/networkx/generators/tests/test_expanders.py +0 -182
  261. package/runtime/python/okstra_vendor/networkx/generators/tests/test_geometric.py +0 -488
  262. package/runtime/python/okstra_vendor/networkx/generators/tests/test_harary_graph.py +0 -133
  263. package/runtime/python/okstra_vendor/networkx/generators/tests/test_internet_as_graphs.py +0 -221
  264. package/runtime/python/okstra_vendor/networkx/generators/tests/test_intersection.py +0 -28
  265. package/runtime/python/okstra_vendor/networkx/generators/tests/test_interval_graph.py +0 -144
  266. package/runtime/python/okstra_vendor/networkx/generators/tests/test_joint_degree_seq.py +0 -125
  267. package/runtime/python/okstra_vendor/networkx/generators/tests/test_lattice.py +0 -264
  268. package/runtime/python/okstra_vendor/networkx/generators/tests/test_line.py +0 -316
  269. package/runtime/python/okstra_vendor/networkx/generators/tests/test_mycielski.py +0 -30
  270. package/runtime/python/okstra_vendor/networkx/generators/tests/test_nonisomorphic_trees.py +0 -82
  271. package/runtime/python/okstra_vendor/networkx/generators/tests/test_random_clustered.py +0 -33
  272. package/runtime/python/okstra_vendor/networkx/generators/tests/test_random_graphs.py +0 -495
  273. package/runtime/python/okstra_vendor/networkx/generators/tests/test_small.py +0 -220
  274. package/runtime/python/okstra_vendor/networkx/generators/tests/test_spectral_graph_forge.py +0 -49
  275. package/runtime/python/okstra_vendor/networkx/generators/tests/test_stochastic.py +0 -72
  276. package/runtime/python/okstra_vendor/networkx/generators/tests/test_sudoku.py +0 -92
  277. package/runtime/python/okstra_vendor/networkx/generators/tests/test_time_series.py +0 -64
  278. package/runtime/python/okstra_vendor/networkx/generators/tests/test_trees.py +0 -195
  279. package/runtime/python/okstra_vendor/networkx/generators/tests/test_triads.py +0 -15
  280. package/runtime/python/okstra_vendor/networkx/linalg/tests/__init__.py +0 -0
  281. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_algebraic_connectivity.py +0 -400
  282. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_attrmatrix.py +0 -108
  283. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_bethehessian.py +0 -40
  284. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_graphmatrix.py +0 -275
  285. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_laplacian.py +0 -334
  286. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_modularity.py +0 -86
  287. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_spectrum.py +0 -70
  288. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/__init__.py +0 -0
  289. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_adjacency.py +0 -78
  290. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_cytoscape.py +0 -78
  291. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_node_link.py +0 -109
  292. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_tree.py +0 -48
  293. package/runtime/python/okstra_vendor/networkx/readwrite/tests/__init__.py +0 -0
  294. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_adjlist.py +0 -354
  295. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_edgelist.py +0 -318
  296. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_gexf.py +0 -612
  297. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_gml.py +0 -744
  298. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_graph6.py +0 -181
  299. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_graphml.py +0 -1531
  300. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_leda.py +0 -30
  301. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_p2g.py +0 -63
  302. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_pajek.py +0 -128
  303. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_sparse6.py +0 -166
  304. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_text.py +0 -1742
  305. package/runtime/python/okstra_vendor/networkx/tests/__init__.py +0 -0
  306. package/runtime/python/okstra_vendor/networkx/tests/test_all_random_functions.py +0 -248
  307. package/runtime/python/okstra_vendor/networkx/tests/test_convert.py +0 -321
  308. package/runtime/python/okstra_vendor/networkx/tests/test_convert_numpy.py +0 -531
  309. package/runtime/python/okstra_vendor/networkx/tests/test_convert_pandas.py +0 -349
  310. package/runtime/python/okstra_vendor/networkx/tests/test_convert_scipy.py +0 -281
  311. package/runtime/python/okstra_vendor/networkx/tests/test_exceptions.py +0 -40
  312. package/runtime/python/okstra_vendor/networkx/tests/test_import.py +0 -11
  313. package/runtime/python/okstra_vendor/networkx/tests/test_lazy_imports.py +0 -96
  314. package/runtime/python/okstra_vendor/networkx/tests/test_relabel.py +0 -349
  315. package/runtime/python/okstra_vendor/networkx/tests/test_removed_functions_exception_messages.py +0 -8
  316. package/runtime/python/okstra_vendor/networkx/utils/tests/__init__.py +0 -0
  317. package/runtime/python/okstra_vendor/networkx/utils/tests/test__init.py +0 -11
  318. package/runtime/python/okstra_vendor/networkx/utils/tests/test_backends.py +0 -225
  319. package/runtime/python/okstra_vendor/networkx/utils/tests/test_config.py +0 -263
  320. package/runtime/python/okstra_vendor/networkx/utils/tests/test_decorators.py +0 -510
  321. package/runtime/python/okstra_vendor/networkx/utils/tests/test_heaps.py +0 -131
  322. package/runtime/python/okstra_vendor/networkx/utils/tests/test_mapped_queue.py +0 -268
  323. package/runtime/python/okstra_vendor/networkx/utils/tests/test_misc.py +0 -393
  324. package/runtime/python/okstra_vendor/networkx/utils/tests/test_random_sequence.py +0 -53
  325. package/runtime/python/okstra_vendor/networkx/utils/tests/test_rcm.py +0 -63
  326. package/runtime/python/okstra_vendor/networkx/utils/tests/test_unionfind.py +0 -55
@@ -1,624 +0,0 @@
1
- import math
2
- from operator import itemgetter
3
-
4
- import pytest
5
-
6
- import networkx as nx
7
- from networkx.algorithms.tree import branchings, recognition
8
-
9
- np = pytest.importorskip("numpy")
10
-
11
- #
12
- # Explicitly discussed examples from Edmonds paper.
13
- #
14
-
15
- # Used in Figures A-F.
16
- #
17
- # fmt: off
18
- G_array = np.array([
19
- # 0 1 2 3 4 5 6 7 8
20
- [0, 0, 12, 0, 12, 0, 0, 0, 0], # 0
21
- [4, 0, 0, 0, 0, 13, 0, 0, 0], # 1
22
- [0, 17, 0, 21, 0, 12, 0, 0, 0], # 2
23
- [5, 0, 0, 0, 17, 0, 18, 0, 0], # 3
24
- [0, 0, 0, 0, 0, 0, 0, 12, 0], # 4
25
- [0, 0, 0, 0, 0, 0, 14, 0, 12], # 5
26
- [0, 0, 21, 0, 0, 0, 0, 0, 15], # 6
27
- [0, 0, 0, 19, 0, 0, 15, 0, 0], # 7
28
- [0, 0, 0, 0, 0, 0, 0, 18, 0], # 8
29
- ], dtype=int)
30
-
31
- # Two copies of the graph from the original paper as disconnected components
32
- G_big_array = np.zeros(np.array(G_array.shape) * 2, dtype=int)
33
- G_big_array[:G_array.shape[0], :G_array.shape[1]] = G_array
34
- G_big_array[G_array.shape[0]:, G_array.shape[1]:] = G_array
35
-
36
- # fmt: on
37
-
38
-
39
- def G1():
40
- G = nx.from_numpy_array(G_array, create_using=nx.MultiDiGraph)
41
- return G
42
-
43
-
44
- def G2():
45
- # Now we shift all the weights by -10.
46
- # Should not affect optimal arborescence, but does affect optimal branching.
47
- Garr = G_array.copy()
48
- Garr[np.nonzero(Garr)] -= 10
49
- G = nx.from_numpy_array(Garr, create_using=nx.MultiDiGraph)
50
- return G
51
-
52
-
53
- # An optimal branching for G1 that is also a spanning arborescence. So it is
54
- # also an optimal spanning arborescence.
55
- #
56
- optimal_arborescence_1 = [
57
- (0, 2, 12),
58
- (2, 1, 17),
59
- (2, 3, 21),
60
- (1, 5, 13),
61
- (3, 4, 17),
62
- (3, 6, 18),
63
- (6, 8, 15),
64
- (8, 7, 18),
65
- ]
66
-
67
- # For G2, the optimal branching of G1 (with shifted weights) is no longer
68
- # an optimal branching, but it is still an optimal spanning arborescence
69
- # (just with shifted weights). An optimal branching for G2 is similar to what
70
- # appears in figure G (this is greedy_subopt_branching_1a below), but with the
71
- # edge (3, 0, 5), which is now (3, 0, -5), removed. Thus, the optimal branching
72
- # is not a spanning arborescence. The code finds optimal_branching_2a.
73
- # An alternative and equivalent branching is optimal_branching_2b. We would
74
- # need to modify the code to iterate through all equivalent optimal branchings.
75
- #
76
- # These are maximal branchings or arborescences.
77
- optimal_branching_2a = [
78
- (5, 6, 4),
79
- (6, 2, 11),
80
- (6, 8, 5),
81
- (8, 7, 8),
82
- (2, 1, 7),
83
- (2, 3, 11),
84
- (3, 4, 7),
85
- ]
86
- optimal_branching_2b = [
87
- (8, 7, 8),
88
- (7, 3, 9),
89
- (3, 4, 7),
90
- (3, 6, 8),
91
- (6, 2, 11),
92
- (2, 1, 7),
93
- (1, 5, 3),
94
- ]
95
- optimal_arborescence_2 = [
96
- (0, 2, 2),
97
- (2, 1, 7),
98
- (2, 3, 11),
99
- (1, 5, 3),
100
- (3, 4, 7),
101
- (3, 6, 8),
102
- (6, 8, 5),
103
- (8, 7, 8),
104
- ]
105
-
106
- # Two suboptimal maximal branchings on G1 obtained from a greedy algorithm.
107
- # 1a matches what is shown in Figure G in Edmonds's paper.
108
- greedy_subopt_branching_1a = [
109
- (5, 6, 14),
110
- (6, 2, 21),
111
- (6, 8, 15),
112
- (8, 7, 18),
113
- (2, 1, 17),
114
- (2, 3, 21),
115
- (3, 0, 5),
116
- (3, 4, 17),
117
- ]
118
- greedy_subopt_branching_1b = [
119
- (8, 7, 18),
120
- (7, 6, 15),
121
- (6, 2, 21),
122
- (2, 1, 17),
123
- (2, 3, 21),
124
- (1, 5, 13),
125
- (3, 0, 5),
126
- (3, 4, 17),
127
- ]
128
-
129
-
130
- def build_branching(edges, double=False):
131
- G = nx.DiGraph()
132
- for u, v, weight in edges:
133
- G.add_edge(u, v, weight=weight)
134
- if double:
135
- G.add_edge(u + 9, v + 9, weight=weight)
136
- return G
137
-
138
-
139
- def sorted_edges(G, attr="weight", default=1):
140
- edges = [(u, v, data.get(attr, default)) for (u, v, data) in G.edges(data=True)]
141
- edges = sorted(edges, key=lambda x: (x[2], x[1], x[0]))
142
- return edges
143
-
144
-
145
- def assert_equal_branchings(G1, G2, attr="weight", default=1):
146
- edges1 = list(G1.edges(data=True))
147
- edges2 = list(G2.edges(data=True))
148
- assert len(edges1) == len(edges2)
149
-
150
- # Grab the weights only.
151
- e1 = sorted_edges(G1, attr, default)
152
- e2 = sorted_edges(G2, attr, default)
153
-
154
- for a, b in zip(e1, e2):
155
- assert a[:2] == b[:2]
156
- np.testing.assert_almost_equal(a[2], b[2])
157
-
158
-
159
- ################
160
-
161
-
162
- def test_optimal_branching1():
163
- G = build_branching(optimal_arborescence_1)
164
- assert recognition.is_arborescence(G), True
165
- assert branchings.branching_weight(G) == 131
166
-
167
-
168
- def test_optimal_branching2a():
169
- G = build_branching(optimal_branching_2a)
170
- assert recognition.is_arborescence(G), True
171
- assert branchings.branching_weight(G) == 53
172
-
173
-
174
- def test_optimal_branching2b():
175
- G = build_branching(optimal_branching_2b)
176
- assert recognition.is_arborescence(G), True
177
- assert branchings.branching_weight(G) == 53
178
-
179
-
180
- def test_optimal_arborescence2():
181
- G = build_branching(optimal_arborescence_2)
182
- assert recognition.is_arborescence(G), True
183
- assert branchings.branching_weight(G) == 51
184
-
185
-
186
- def test_greedy_suboptimal_branching1a():
187
- G = build_branching(greedy_subopt_branching_1a)
188
- assert recognition.is_arborescence(G), True
189
- assert branchings.branching_weight(G) == 128
190
-
191
-
192
- def test_greedy_suboptimal_branching1b():
193
- G = build_branching(greedy_subopt_branching_1b)
194
- assert recognition.is_arborescence(G), True
195
- assert branchings.branching_weight(G) == 127
196
-
197
-
198
- def test_greedy_max1():
199
- # Standard test.
200
- #
201
- G = G1()
202
- B = branchings.greedy_branching(G)
203
- # There are only two possible greedy branchings. The sorting is such
204
- # that it should equal the second suboptimal branching: 1b.
205
- B_ = build_branching(greedy_subopt_branching_1b)
206
- assert_equal_branchings(B, B_)
207
-
208
-
209
- def test_greedy_branching_kwarg_kind():
210
- G = G1()
211
- with pytest.raises(nx.NetworkXException, match="Unknown value for `kind`."):
212
- B = branchings.greedy_branching(G, kind="lol")
213
-
214
-
215
- def test_greedy_branching_for_unsortable_nodes():
216
- G = nx.DiGraph()
217
- G.add_weighted_edges_from([((2, 3), 5, 1), (3, "a", 1), (2, 4, 5)])
218
- edges = [(u, v, data.get("weight", 1)) for (u, v, data) in G.edges(data=True)]
219
- with pytest.raises(TypeError):
220
- edges.sort(key=itemgetter(2, 0, 1), reverse=True)
221
- B = branchings.greedy_branching(G, kind="max").edges(data=True)
222
- assert list(B) == [
223
- ((2, 3), 5, {"weight": 1}),
224
- (3, "a", {"weight": 1}),
225
- (2, 4, {"weight": 5}),
226
- ]
227
-
228
-
229
- def test_greedy_max2():
230
- # Different default weight.
231
- #
232
- G = G1()
233
- del G[1][0][0]["weight"]
234
- B = branchings.greedy_branching(G, default=6)
235
- # Chosen so that edge (3,0,5) is not selected and (1,0,6) is instead.
236
-
237
- edges = [
238
- (1, 0, 6),
239
- (1, 5, 13),
240
- (7, 6, 15),
241
- (2, 1, 17),
242
- (3, 4, 17),
243
- (8, 7, 18),
244
- (2, 3, 21),
245
- (6, 2, 21),
246
- ]
247
- B_ = build_branching(edges)
248
- assert_equal_branchings(B, B_)
249
-
250
-
251
- def test_greedy_max3():
252
- # All equal weights.
253
- #
254
- G = G1()
255
- B = branchings.greedy_branching(G, attr=None)
256
-
257
- # This is mostly arbitrary...the output was generated by running the algo.
258
- edges = [
259
- (2, 1, 1),
260
- (3, 0, 1),
261
- (3, 4, 1),
262
- (5, 8, 1),
263
- (6, 2, 1),
264
- (7, 3, 1),
265
- (7, 6, 1),
266
- (8, 7, 1),
267
- ]
268
- B_ = build_branching(edges)
269
- assert_equal_branchings(B, B_, default=1)
270
-
271
-
272
- def test_greedy_min():
273
- G = G1()
274
- B = branchings.greedy_branching(G, kind="min")
275
-
276
- edges = [
277
- (1, 0, 4),
278
- (0, 2, 12),
279
- (0, 4, 12),
280
- (2, 5, 12),
281
- (4, 7, 12),
282
- (5, 8, 12),
283
- (5, 6, 14),
284
- (7, 3, 19),
285
- ]
286
- B_ = build_branching(edges)
287
- assert_equal_branchings(B, B_)
288
-
289
-
290
- def test_edmonds1_maxbranch():
291
- G = G1()
292
- x = branchings.maximum_branching(G)
293
- x_ = build_branching(optimal_arborescence_1)
294
- assert_equal_branchings(x, x_)
295
-
296
-
297
- def test_edmonds1_maxarbor():
298
- G = G1()
299
- x = branchings.maximum_spanning_arborescence(G)
300
- x_ = build_branching(optimal_arborescence_1)
301
- assert_equal_branchings(x, x_)
302
-
303
-
304
- def test_edmonds1_minimal_branching():
305
- # graph will have something like a minimum arborescence but no spanning one
306
- G = nx.from_numpy_array(G_big_array, create_using=nx.DiGraph)
307
- B = branchings.minimal_branching(G)
308
- edges = [
309
- (3, 0, 5),
310
- (0, 2, 12),
311
- (0, 4, 12),
312
- (2, 5, 12),
313
- (4, 7, 12),
314
- (5, 8, 12),
315
- (5, 6, 14),
316
- (2, 1, 17),
317
- ]
318
- B_ = build_branching(edges, double=True)
319
- assert_equal_branchings(B, B_)
320
-
321
-
322
- def test_edmonds2_maxbranch():
323
- G = G2()
324
- x = branchings.maximum_branching(G)
325
- x_ = build_branching(optimal_branching_2a)
326
- assert_equal_branchings(x, x_)
327
-
328
-
329
- def test_edmonds2_maxarbor():
330
- G = G2()
331
- x = branchings.maximum_spanning_arborescence(G)
332
- x_ = build_branching(optimal_arborescence_2)
333
- assert_equal_branchings(x, x_)
334
-
335
-
336
- def test_edmonds2_minarbor():
337
- G = G1()
338
- x = branchings.minimum_spanning_arborescence(G)
339
- # This was obtained from algorithm. Need to verify it independently.
340
- # Branch weight is: 96
341
- edges = [
342
- (3, 0, 5),
343
- (0, 2, 12),
344
- (0, 4, 12),
345
- (2, 5, 12),
346
- (4, 7, 12),
347
- (5, 8, 12),
348
- (5, 6, 14),
349
- (2, 1, 17),
350
- ]
351
- x_ = build_branching(edges)
352
- assert_equal_branchings(x, x_)
353
-
354
-
355
- def test_edmonds3_minbranch1():
356
- G = G1()
357
- x = branchings.minimum_branching(G)
358
- edges = []
359
- x_ = build_branching(edges)
360
- assert_equal_branchings(x, x_)
361
-
362
-
363
- def test_edmonds3_minbranch2():
364
- G = G1()
365
- G.add_edge(8, 9, weight=-10)
366
- x = branchings.minimum_branching(G)
367
- edges = [(8, 9, -10)]
368
- x_ = build_branching(edges)
369
- assert_equal_branchings(x, x_)
370
-
371
-
372
- # Need more tests
373
-
374
-
375
- def test_mst():
376
- # Make sure we get the same results for undirected graphs.
377
- # Example from: https://en.wikipedia.org/wiki/Kruskal's_algorithm
378
- G = nx.Graph()
379
- edgelist = [
380
- (0, 3, [("weight", 5)]),
381
- (0, 1, [("weight", 7)]),
382
- (1, 3, [("weight", 9)]),
383
- (1, 2, [("weight", 8)]),
384
- (1, 4, [("weight", 7)]),
385
- (3, 4, [("weight", 15)]),
386
- (3, 5, [("weight", 6)]),
387
- (2, 4, [("weight", 5)]),
388
- (4, 5, [("weight", 8)]),
389
- (4, 6, [("weight", 9)]),
390
- (5, 6, [("weight", 11)]),
391
- ]
392
- G.add_edges_from(edgelist)
393
- G = G.to_directed()
394
- x = branchings.minimum_spanning_arborescence(G)
395
-
396
- edges = [
397
- ({0, 1}, 7),
398
- ({0, 3}, 5),
399
- ({3, 5}, 6),
400
- ({1, 4}, 7),
401
- ({4, 2}, 5),
402
- ({4, 6}, 9),
403
- ]
404
-
405
- assert x.number_of_edges() == len(edges)
406
- for u, v, d in x.edges(data=True):
407
- assert ({u, v}, d["weight"]) in edges
408
-
409
-
410
- def test_mixed_nodetypes():
411
- # Smoke test to make sure no TypeError is raised for mixed node types.
412
- G = nx.Graph()
413
- edgelist = [(0, 3, [("weight", 5)]), (0, "1", [("weight", 5)])]
414
- G.add_edges_from(edgelist)
415
- G = G.to_directed()
416
- x = branchings.minimum_spanning_arborescence(G)
417
-
418
-
419
- def test_edmonds1_minbranch():
420
- # Using -G_array and min should give the same as optimal_arborescence_1,
421
- # but with all edges negative.
422
- edges = [(u, v, -w) for (u, v, w) in optimal_arborescence_1]
423
-
424
- G = nx.from_numpy_array(-G_array, create_using=nx.DiGraph)
425
-
426
- # Quickly make sure max branching is empty.
427
- x = branchings.maximum_branching(G)
428
- x_ = build_branching([])
429
- assert_equal_branchings(x, x_)
430
-
431
- # Now test the min branching.
432
- x = branchings.minimum_branching(G)
433
- x_ = build_branching(edges)
434
- assert_equal_branchings(x, x_)
435
-
436
-
437
- def test_edge_attribute_preservation_normal_graph():
438
- # Test that edge attributes are preserved when finding an optimum graph
439
- # using the Edmonds class for normal graphs.
440
- G = nx.Graph()
441
-
442
- edgelist = [
443
- (0, 1, [("weight", 5), ("otherattr", 1), ("otherattr2", 3)]),
444
- (0, 2, [("weight", 5), ("otherattr", 2), ("otherattr2", 2)]),
445
- (1, 2, [("weight", 6), ("otherattr", 3), ("otherattr2", 1)]),
446
- ]
447
- G.add_edges_from(edgelist)
448
-
449
- B = branchings.maximum_branching(G, preserve_attrs=True)
450
-
451
- assert B[0][1]["otherattr"] == 1
452
- assert B[0][1]["otherattr2"] == 3
453
-
454
-
455
- def test_edge_attribute_preservation_multigraph():
456
- # Test that edge attributes are preserved when finding an optimum graph
457
- # using the Edmonds class for multigraphs.
458
- G = nx.MultiGraph()
459
-
460
- edgelist = [
461
- (0, 1, [("weight", 5), ("otherattr", 1), ("otherattr2", 3)]),
462
- (0, 2, [("weight", 5), ("otherattr", 2), ("otherattr2", 2)]),
463
- (1, 2, [("weight", 6), ("otherattr", 3), ("otherattr2", 1)]),
464
- ]
465
- G.add_edges_from(edgelist * 2) # Make sure we have duplicate edge paths
466
-
467
- B = branchings.maximum_branching(G, preserve_attrs=True)
468
-
469
- assert B[0][1][0]["otherattr"] == 1
470
- assert B[0][1][0]["otherattr2"] == 3
471
-
472
-
473
- def test_edge_attribute_discard():
474
- # Test that edge attributes are discarded if we do not specify to keep them
475
- G = nx.Graph()
476
-
477
- edgelist = [
478
- (0, 1, [("weight", 5), ("otherattr", 1), ("otherattr2", 3)]),
479
- (0, 2, [("weight", 5), ("otherattr", 2), ("otherattr2", 2)]),
480
- (1, 2, [("weight", 6), ("otherattr", 3), ("otherattr2", 1)]),
481
- ]
482
- G.add_edges_from(edgelist)
483
-
484
- B = branchings.maximum_branching(G, preserve_attrs=False)
485
-
486
- edge_dict = B[0][1]
487
- with pytest.raises(KeyError):
488
- _ = edge_dict["otherattr"]
489
-
490
-
491
- def test_partition_spanning_arborescence():
492
- """
493
- Test that we can generate minimum spanning arborescences which respect the
494
- given partition.
495
- """
496
- G = nx.from_numpy_array(G_array, create_using=nx.DiGraph)
497
- G[3][0]["partition"] = nx.EdgePartition.EXCLUDED
498
- G[2][3]["partition"] = nx.EdgePartition.INCLUDED
499
- G[7][3]["partition"] = nx.EdgePartition.EXCLUDED
500
- G[0][2]["partition"] = nx.EdgePartition.EXCLUDED
501
- G[6][2]["partition"] = nx.EdgePartition.INCLUDED
502
-
503
- actual_edges = [
504
- (0, 4, 12),
505
- (1, 0, 4),
506
- (1, 5, 13),
507
- (2, 3, 21),
508
- (4, 7, 12),
509
- (5, 6, 14),
510
- (5, 8, 12),
511
- (6, 2, 21),
512
- ]
513
-
514
- B = branchings.minimum_spanning_arborescence(G, partition="partition")
515
- assert_equal_branchings(build_branching(actual_edges), B)
516
-
517
-
518
- def test_arborescence_iterator_min():
519
- """
520
- Tests the arborescence iterator.
521
-
522
- A brute force method found 680 arborescences in this graph.
523
- This test will not verify all of them individually, but will check two
524
- things
525
-
526
- * The iterator returns 680 arborescences
527
- * The weight of the arborescences is non-strictly increasing
528
-
529
- for more information please visit
530
- https://mjschwenne.github.io/2021/06/10/implementing-the-iterators.html
531
- """
532
- G = nx.from_numpy_array(G_array, create_using=nx.DiGraph)
533
-
534
- arborescence_count = 0
535
- arborescence_weight = -math.inf
536
- for B in branchings.ArborescenceIterator(G):
537
- arborescence_count += 1
538
- new_arborescence_weight = B.size(weight="weight")
539
- assert new_arborescence_weight >= arborescence_weight
540
- arborescence_weight = new_arborescence_weight
541
-
542
- assert arborescence_count == 680
543
-
544
-
545
- def test_arborescence_iterator_max():
546
- """
547
- Tests the arborescence iterator.
548
-
549
- A brute force method found 680 arborescences in this graph.
550
- This test will not verify all of them individually, but will check two
551
- things
552
-
553
- * The iterator returns 680 arborescences
554
- * The weight of the arborescences is non-strictly decreasing
555
-
556
- for more information please visit
557
- https://mjschwenne.github.io/2021/06/10/implementing-the-iterators.html
558
- """
559
- G = nx.from_numpy_array(G_array, create_using=nx.DiGraph)
560
-
561
- arborescence_count = 0
562
- arborescence_weight = math.inf
563
- for B in branchings.ArborescenceIterator(G, minimum=False):
564
- arborescence_count += 1
565
- new_arborescence_weight = B.size(weight="weight")
566
- assert new_arborescence_weight <= arborescence_weight
567
- arborescence_weight = new_arborescence_weight
568
-
569
- assert arborescence_count == 680
570
-
571
-
572
- def test_arborescence_iterator_initial_partition():
573
- """
574
- Tests the arborescence iterator with three included edges and three excluded
575
- in the initial partition.
576
-
577
- A brute force method similar to the one used in the above tests found that
578
- there are 16 arborescences which contain the included edges and not the
579
- excluded edges.
580
- """
581
- G = nx.from_numpy_array(G_array, create_using=nx.DiGraph)
582
- included_edges = [(1, 0), (5, 6), (8, 7)]
583
- excluded_edges = [(0, 2), (3, 6), (1, 5)]
584
-
585
- arborescence_count = 0
586
- arborescence_weight = -math.inf
587
- for B in branchings.ArborescenceIterator(
588
- G, init_partition=(included_edges, excluded_edges)
589
- ):
590
- arborescence_count += 1
591
- new_arborescence_weight = B.size(weight="weight")
592
- assert new_arborescence_weight >= arborescence_weight
593
- arborescence_weight = new_arborescence_weight
594
- for e in included_edges:
595
- assert e in B.edges
596
- for e in excluded_edges:
597
- assert e not in B.edges
598
- assert arborescence_count == 16
599
-
600
-
601
- def test_branchings_with_default_weights():
602
- """
603
- Tests that various branching algorithms work on graphs without weights.
604
- For more information, see issue #7279.
605
- """
606
- graph = nx.erdos_renyi_graph(10, p=0.2, directed=True, seed=123)
607
-
608
- assert all("weight" not in d for (u, v, d) in graph.edges(data=True)), (
609
- "test is for graphs without a weight attribute"
610
- )
611
-
612
- # Calling these functions will modify graph inplace to add weights
613
- # copy the graph to avoid this.
614
- nx.minimum_spanning_arborescence(graph.copy())
615
- nx.maximum_spanning_arborescence(graph.copy())
616
- nx.minimum_branching(graph.copy())
617
- nx.maximum_branching(graph.copy())
618
- nx.algorithms.tree.minimal_branching(graph.copy())
619
- nx.algorithms.tree.branching_weight(graph.copy())
620
- nx.algorithms.tree.greedy_branching(graph.copy())
621
-
622
- assert all("weight" not in d for (u, v, d) in graph.edges(data=True)), (
623
- "The above calls should not modify the initial graph in-place"
624
- )