okstra 0.108.0 → 0.110.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 (648) hide show
  1. package/README.kr.md +1 -1
  2. package/README.md +1 -1
  3. package/docs/kr/architecture.md +3 -3
  4. package/docs/kr/cli.md +2 -2
  5. package/docs/project-structure-overview.md +3 -3
  6. package/package.json +1 -1
  7. package/runtime/BUILD.json +2 -2
  8. package/runtime/prompts/profiles/_common-contract.md +1 -1
  9. package/runtime/python/okstra_ctl/graphify_cmd.py +225 -0
  10. package/runtime/python/okstra_ctl/resolve_task_key.py +15 -9
  11. package/runtime/python/okstra_ctl/worktree.py +14 -13
  12. package/runtime/python/okstra_project/__init__.py +2 -0
  13. package/runtime/python/okstra_project/state.py +36 -0
  14. package/runtime/python/okstra_vendor/__init__.py +41 -0
  15. package/runtime/python/okstra_vendor/graphify/.vendored-version +1 -0
  16. package/runtime/python/okstra_vendor/graphify/__init__.py +28 -0
  17. package/runtime/python/okstra_vendor/graphify/__main__.py +1371 -0
  18. package/runtime/python/okstra_vendor/graphify/analyze.py +540 -0
  19. package/runtime/python/okstra_vendor/graphify/benchmark.py +129 -0
  20. package/runtime/python/okstra_vendor/graphify/build.py +107 -0
  21. package/runtime/python/okstra_vendor/graphify/cache.py +169 -0
  22. package/runtime/python/okstra_vendor/graphify/cluster.py +137 -0
  23. package/runtime/python/okstra_vendor/graphify/detect.py +510 -0
  24. package/runtime/python/okstra_vendor/graphify/export.py +1014 -0
  25. package/runtime/python/okstra_vendor/graphify/extract.py +3277 -0
  26. package/runtime/python/okstra_vendor/graphify/hooks.py +220 -0
  27. package/runtime/python/okstra_vendor/graphify/ingest.py +297 -0
  28. package/runtime/python/okstra_vendor/graphify/manifest.py +4 -0
  29. package/runtime/python/okstra_vendor/graphify/report.py +175 -0
  30. package/runtime/python/okstra_vendor/graphify/security.py +203 -0
  31. package/runtime/python/okstra_vendor/graphify/serve.py +373 -0
  32. package/runtime/python/okstra_vendor/graphify/skill-aider.md +1184 -0
  33. package/runtime/python/okstra_vendor/graphify/skill-claw.md +1184 -0
  34. package/runtime/python/okstra_vendor/graphify/skill-codex.md +1242 -0
  35. package/runtime/python/okstra_vendor/graphify/skill-copilot.md +1268 -0
  36. package/runtime/python/okstra_vendor/graphify/skill-droid.md +1239 -0
  37. package/runtime/python/okstra_vendor/graphify/skill-kiro.md +1183 -0
  38. package/runtime/python/okstra_vendor/graphify/skill-opencode.md +1238 -0
  39. package/runtime/python/okstra_vendor/graphify/skill-trae.md +1208 -0
  40. package/runtime/python/okstra_vendor/graphify/skill-vscode.md +253 -0
  41. package/runtime/python/okstra_vendor/graphify/skill-windows.md +1245 -0
  42. package/runtime/python/okstra_vendor/graphify/skill.md +1319 -0
  43. package/runtime/python/okstra_vendor/graphify/transcribe.py +182 -0
  44. package/runtime/python/okstra_vendor/graphify/validate.py +72 -0
  45. package/runtime/python/okstra_vendor/graphify/watch.py +188 -0
  46. package/runtime/python/okstra_vendor/graphify/wiki.py +214 -0
  47. package/runtime/python/okstra_vendor/networkx/__init__.py +62 -0
  48. package/runtime/python/okstra_vendor/networkx/algorithms/__init__.py +134 -0
  49. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/__init__.py +26 -0
  50. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clique.py +259 -0
  51. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clustering_coefficient.py +71 -0
  52. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/connectivity.py +412 -0
  53. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/density.py +396 -0
  54. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/distance_measures.py +150 -0
  55. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/dominating_set.py +149 -0
  56. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/kcomponents.py +369 -0
  57. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/matching.py +44 -0
  58. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/maxcut.py +143 -0
  59. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/ramsey.py +53 -0
  60. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/steinertree.py +265 -0
  61. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/__init__.py +0 -0
  62. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_approx_clust_coeff.py +41 -0
  63. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_clique.py +112 -0
  64. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_connectivity.py +199 -0
  65. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_density.py +146 -0
  66. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_distance_measures.py +59 -0
  67. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_dominating_set.py +78 -0
  68. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_kcomponents.py +303 -0
  69. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_matching.py +8 -0
  70. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_maxcut.py +94 -0
  71. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_ramsey.py +31 -0
  72. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_steinertree.py +306 -0
  73. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_traveling_salesman.py +1014 -0
  74. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_treewidth.py +274 -0
  75. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_vertex_cover.py +68 -0
  76. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/traveling_salesman.py +1508 -0
  77. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/treewidth.py +255 -0
  78. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/vertex_cover.py +83 -0
  79. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/__init__.py +5 -0
  80. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/connectivity.py +122 -0
  81. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/correlation.py +302 -0
  82. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/mixing.py +255 -0
  83. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/neighbor_degree.py +160 -0
  84. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/pairs.py +127 -0
  85. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/__init__.py +0 -0
  86. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/base_test.py +81 -0
  87. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_connectivity.py +143 -0
  88. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_correlation.py +122 -0
  89. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_mixing.py +174 -0
  90. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_neighbor_degree.py +107 -0
  91. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_pairs.py +87 -0
  92. package/runtime/python/okstra_vendor/networkx/algorithms/asteroidal.py +164 -0
  93. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/__init__.py +88 -0
  94. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/basic.py +322 -0
  95. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/centrality.py +290 -0
  96. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/cluster.py +289 -0
  97. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/covering.py +57 -0
  98. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/edgelist.py +360 -0
  99. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/extendability.py +105 -0
  100. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/generators.py +603 -0
  101. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/link_analysis.py +316 -0
  102. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matching.py +590 -0
  103. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matrix.py +232 -0
  104. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/projection.py +526 -0
  105. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/redundancy.py +112 -0
  106. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/spectral.py +69 -0
  107. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/__init__.py +0 -0
  108. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_basic.py +125 -0
  109. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_centrality.py +192 -0
  110. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_cluster.py +84 -0
  111. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_covering.py +33 -0
  112. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_edgelist.py +240 -0
  113. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_extendability.py +334 -0
  114. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_generators.py +407 -0
  115. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_link_analysis.py +218 -0
  116. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_matching.py +327 -0
  117. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_matrix.py +138 -0
  118. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_project.py +409 -0
  119. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_redundancy.py +35 -0
  120. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_spectral_bipartivity.py +80 -0
  121. package/runtime/python/okstra_vendor/networkx/algorithms/boundary.py +168 -0
  122. package/runtime/python/okstra_vendor/networkx/algorithms/bridges.py +205 -0
  123. package/runtime/python/okstra_vendor/networkx/algorithms/broadcasting.py +164 -0
  124. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/__init__.py +20 -0
  125. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness.py +591 -0
  126. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness_subset.py +236 -0
  127. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/closeness.py +282 -0
  128. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness.py +364 -0
  129. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness_subset.py +227 -0
  130. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_closeness.py +96 -0
  131. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/degree_alg.py +150 -0
  132. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/dispersion.py +107 -0
  133. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/eigenvector.py +357 -0
  134. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/flow_matrix.py +130 -0
  135. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/group.py +787 -0
  136. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/harmonic.py +88 -0
  137. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/katz.py +331 -0
  138. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/laplacian.py +150 -0
  139. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/load.py +200 -0
  140. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/percolation.py +128 -0
  141. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/reaching.py +209 -0
  142. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/second_order.py +141 -0
  143. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/subgraph_alg.py +361 -0
  144. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/__init__.py +0 -0
  145. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_betweenness_centrality.py +923 -0
  146. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_betweenness_centrality_subset.py +354 -0
  147. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_closeness_centrality.py +274 -0
  148. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_betweenness_centrality.py +259 -0
  149. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_betweenness_centrality_subset.py +147 -0
  150. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_closeness.py +43 -0
  151. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_degree_centrality.py +144 -0
  152. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_dispersion.py +73 -0
  153. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_eigenvector_centrality.py +186 -0
  154. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_group.py +277 -0
  155. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_harmonic_centrality.py +122 -0
  156. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_katz_centrality.py +345 -0
  157. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_laplacian_centrality.py +220 -0
  158. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_load_centrality.py +344 -0
  159. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_percolation_centrality.py +87 -0
  160. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_reaching.py +140 -0
  161. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_second_order_centrality.py +82 -0
  162. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_subgraph.py +110 -0
  163. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_trophic.py +302 -0
  164. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_voterank.py +64 -0
  165. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/trophic.py +181 -0
  166. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/voterank_alg.py +95 -0
  167. package/runtime/python/okstra_vendor/networkx/algorithms/chains.py +172 -0
  168. package/runtime/python/okstra_vendor/networkx/algorithms/chordal.py +443 -0
  169. package/runtime/python/okstra_vendor/networkx/algorithms/clique.py +818 -0
  170. package/runtime/python/okstra_vendor/networkx/algorithms/cluster.py +732 -0
  171. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/__init__.py +4 -0
  172. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/equitable_coloring.py +505 -0
  173. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/greedy_coloring.py +565 -0
  174. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/tests/__init__.py +0 -0
  175. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/tests/test_coloring.py +863 -0
  176. package/runtime/python/okstra_vendor/networkx/algorithms/communicability_alg.py +163 -0
  177. package/runtime/python/okstra_vendor/networkx/algorithms/community/__init__.py +28 -0
  178. package/runtime/python/okstra_vendor/networkx/algorithms/community/asyn_fluid.py +153 -0
  179. package/runtime/python/okstra_vendor/networkx/algorithms/community/bipartitions.py +354 -0
  180. package/runtime/python/okstra_vendor/networkx/algorithms/community/centrality.py +171 -0
  181. package/runtime/python/okstra_vendor/networkx/algorithms/community/community_utils.py +30 -0
  182. package/runtime/python/okstra_vendor/networkx/algorithms/community/divisive.py +216 -0
  183. package/runtime/python/okstra_vendor/networkx/algorithms/community/kclique.py +79 -0
  184. package/runtime/python/okstra_vendor/networkx/algorithms/community/label_propagation.py +338 -0
  185. package/runtime/python/okstra_vendor/networkx/algorithms/community/leiden.py +162 -0
  186. package/runtime/python/okstra_vendor/networkx/algorithms/community/local.py +220 -0
  187. package/runtime/python/okstra_vendor/networkx/algorithms/community/louvain.py +384 -0
  188. package/runtime/python/okstra_vendor/networkx/algorithms/community/lukes.py +227 -0
  189. package/runtime/python/okstra_vendor/networkx/algorithms/community/modularity_max.py +452 -0
  190. package/runtime/python/okstra_vendor/networkx/algorithms/community/quality.py +347 -0
  191. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/__init__.py +0 -0
  192. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_asyn_fluid.py +147 -0
  193. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_bipartitions.py +157 -0
  194. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_centrality.py +85 -0
  195. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_divisive.py +106 -0
  196. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_kclique.py +91 -0
  197. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_label_propagation.py +241 -0
  198. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_leiden.py +138 -0
  199. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_local.py +76 -0
  200. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_louvain.py +264 -0
  201. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_lukes.py +152 -0
  202. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_modularity_max.py +340 -0
  203. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_quality.py +139 -0
  204. package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_utils.py +26 -0
  205. package/runtime/python/okstra_vendor/networkx/algorithms/components/__init__.py +6 -0
  206. package/runtime/python/okstra_vendor/networkx/algorithms/components/attracting.py +115 -0
  207. package/runtime/python/okstra_vendor/networkx/algorithms/components/biconnected.py +394 -0
  208. package/runtime/python/okstra_vendor/networkx/algorithms/components/connected.py +282 -0
  209. package/runtime/python/okstra_vendor/networkx/algorithms/components/semiconnected.py +71 -0
  210. package/runtime/python/okstra_vendor/networkx/algorithms/components/strongly_connected.py +359 -0
  211. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/__init__.py +0 -0
  212. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_attracting.py +70 -0
  213. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_biconnected.py +248 -0
  214. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_connected.py +138 -0
  215. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_semiconnected.py +55 -0
  216. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_strongly_connected.py +193 -0
  217. package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_weakly_connected.py +96 -0
  218. package/runtime/python/okstra_vendor/networkx/algorithms/components/weakly_connected.py +196 -0
  219. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/__init__.py +11 -0
  220. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/connectivity.py +811 -0
  221. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/cuts.py +616 -0
  222. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/disjoint_paths.py +408 -0
  223. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_augmentation.py +1270 -0
  224. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_kcomponents.py +592 -0
  225. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcomponents.py +220 -0
  226. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcutsets.py +235 -0
  227. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/stoerwagner.py +152 -0
  228. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/__init__.py +0 -0
  229. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_connectivity.py +421 -0
  230. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_cuts.py +309 -0
  231. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_disjoint_paths.py +249 -0
  232. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_edge_augmentation.py +502 -0
  233. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_edge_kcomponents.py +488 -0
  234. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_kcomponents.py +323 -0
  235. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_kcutsets.py +280 -0
  236. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_stoer_wagner.py +102 -0
  237. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/utils.py +88 -0
  238. package/runtime/python/okstra_vendor/networkx/algorithms/core.py +588 -0
  239. package/runtime/python/okstra_vendor/networkx/algorithms/covering.py +142 -0
  240. package/runtime/python/okstra_vendor/networkx/algorithms/cuts.py +416 -0
  241. package/runtime/python/okstra_vendor/networkx/algorithms/cycles.py +1234 -0
  242. package/runtime/python/okstra_vendor/networkx/algorithms/d_separation.py +677 -0
  243. package/runtime/python/okstra_vendor/networkx/algorithms/dag.py +1392 -0
  244. package/runtime/python/okstra_vendor/networkx/algorithms/distance_measures.py +1095 -0
  245. package/runtime/python/okstra_vendor/networkx/algorithms/distance_regular.py +272 -0
  246. package/runtime/python/okstra_vendor/networkx/algorithms/dominance.py +142 -0
  247. package/runtime/python/okstra_vendor/networkx/algorithms/dominating.py +268 -0
  248. package/runtime/python/okstra_vendor/networkx/algorithms/efficiency_measures.py +167 -0
  249. package/runtime/python/okstra_vendor/networkx/algorithms/euler.py +470 -0
  250. package/runtime/python/okstra_vendor/networkx/algorithms/flow/__init__.py +11 -0
  251. package/runtime/python/okstra_vendor/networkx/algorithms/flow/boykovkolmogorov.py +370 -0
  252. package/runtime/python/okstra_vendor/networkx/algorithms/flow/capacityscaling.py +407 -0
  253. package/runtime/python/okstra_vendor/networkx/algorithms/flow/dinitz_alg.py +238 -0
  254. package/runtime/python/okstra_vendor/networkx/algorithms/flow/edmondskarp.py +241 -0
  255. package/runtime/python/okstra_vendor/networkx/algorithms/flow/gomory_hu.py +178 -0
  256. package/runtime/python/okstra_vendor/networkx/algorithms/flow/maxflow.py +611 -0
  257. package/runtime/python/okstra_vendor/networkx/algorithms/flow/mincost.py +356 -0
  258. package/runtime/python/okstra_vendor/networkx/algorithms/flow/networksimplex.py +662 -0
  259. package/runtime/python/okstra_vendor/networkx/algorithms/flow/preflowpush.py +425 -0
  260. package/runtime/python/okstra_vendor/networkx/algorithms/flow/shortestaugmentingpath.py +300 -0
  261. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/__init__.py +0 -0
  262. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/gl1.gpickle.bz2 +0 -0
  263. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/gw1.gpickle.bz2 +0 -0
  264. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/netgen-2.gpickle.bz2 +0 -0
  265. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_gomory_hu.py +128 -0
  266. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_maxflow.py +573 -0
  267. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_maxflow_large_graph.py +155 -0
  268. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_mincost.py +475 -0
  269. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_networksimplex.py +481 -0
  270. package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/wlm3.gpickle.bz2 +0 -0
  271. package/runtime/python/okstra_vendor/networkx/algorithms/flow/utils.py +194 -0
  272. package/runtime/python/okstra_vendor/networkx/algorithms/graph_hashing.py +435 -0
  273. package/runtime/python/okstra_vendor/networkx/algorithms/graphical.py +483 -0
  274. package/runtime/python/okstra_vendor/networkx/algorithms/hierarchy.py +57 -0
  275. package/runtime/python/okstra_vendor/networkx/algorithms/hybrid.py +196 -0
  276. package/runtime/python/okstra_vendor/networkx/algorithms/isolate.py +107 -0
  277. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/__init__.py +7 -0
  278. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/ismags.py +1306 -0
  279. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorph.py +336 -0
  280. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorphvf2.py +1262 -0
  281. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/matchhelpers.py +352 -0
  282. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/temporalisomorphvf2.py +308 -0
  283. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/__init__.py +0 -0
  284. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/iso_r01_s80.A99 +0 -0
  285. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/iso_r01_s80.B99 +0 -0
  286. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/si2_b06_m200.A99 +0 -0
  287. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/si2_b06_m200.B99 +0 -0
  288. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_ismags.py +719 -0
  289. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_isomorphism.py +103 -0
  290. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_isomorphvf2.py +490 -0
  291. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_match_helpers.py +64 -0
  292. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_temporalisomorphvf2.py +212 -0
  293. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_tree_isomorphism.py +202 -0
  294. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2pp.py +1655 -0
  295. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2pp_helpers.py +3118 -0
  296. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2userfunc.py +196 -0
  297. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tree_isomorphism.py +264 -0
  298. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2pp.py +1102 -0
  299. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2userfunc.py +192 -0
  300. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/__init__.py +2 -0
  301. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/hits_alg.py +337 -0
  302. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/pagerank_alg.py +498 -0
  303. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/__init__.py +0 -0
  304. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/test_hits.py +77 -0
  305. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/test_pagerank.py +213 -0
  306. package/runtime/python/okstra_vendor/networkx/algorithms/link_prediction.py +687 -0
  307. package/runtime/python/okstra_vendor/networkx/algorithms/lowest_common_ancestors.py +280 -0
  308. package/runtime/python/okstra_vendor/networkx/algorithms/matching.py +1148 -0
  309. package/runtime/python/okstra_vendor/networkx/algorithms/minors/__init__.py +27 -0
  310. package/runtime/python/okstra_vendor/networkx/algorithms/minors/contraction.py +738 -0
  311. package/runtime/python/okstra_vendor/networkx/algorithms/minors/tests/test_contraction.py +544 -0
  312. package/runtime/python/okstra_vendor/networkx/algorithms/mis.py +78 -0
  313. package/runtime/python/okstra_vendor/networkx/algorithms/moral.py +59 -0
  314. package/runtime/python/okstra_vendor/networkx/algorithms/node_classification.py +219 -0
  315. package/runtime/python/okstra_vendor/networkx/algorithms/non_randomness.py +155 -0
  316. package/runtime/python/okstra_vendor/networkx/algorithms/operators/__init__.py +4 -0
  317. package/runtime/python/okstra_vendor/networkx/algorithms/operators/all.py +324 -0
  318. package/runtime/python/okstra_vendor/networkx/algorithms/operators/binary.py +468 -0
  319. package/runtime/python/okstra_vendor/networkx/algorithms/operators/product.py +633 -0
  320. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/__init__.py +0 -0
  321. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_all.py +328 -0
  322. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_binary.py +451 -0
  323. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_product.py +491 -0
  324. package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_unary.py +55 -0
  325. package/runtime/python/okstra_vendor/networkx/algorithms/operators/unary.py +77 -0
  326. package/runtime/python/okstra_vendor/networkx/algorithms/perfect_graph.py +73 -0
  327. package/runtime/python/okstra_vendor/networkx/algorithms/planar_drawing.py +464 -0
  328. package/runtime/python/okstra_vendor/networkx/algorithms/planarity.py +1463 -0
  329. package/runtime/python/okstra_vendor/networkx/algorithms/polynomials.py +306 -0
  330. package/runtime/python/okstra_vendor/networkx/algorithms/reciprocity.py +98 -0
  331. package/runtime/python/okstra_vendor/networkx/algorithms/regular.py +167 -0
  332. package/runtime/python/okstra_vendor/networkx/algorithms/richclub.py +138 -0
  333. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/__init__.py +5 -0
  334. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/astar.py +239 -0
  335. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/dense.py +264 -0
  336. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/generic.py +716 -0
  337. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/__init__.py +0 -0
  338. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_astar.py +254 -0
  339. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_dense.py +212 -0
  340. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_dense_numpy.py +88 -0
  341. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_generic.py +511 -0
  342. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_unweighted.py +149 -0
  343. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_weighted.py +983 -0
  344. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/unweighted.py +625 -0
  345. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/weighted.py +2542 -0
  346. package/runtime/python/okstra_vendor/networkx/algorithms/similarity.py +2107 -0
  347. package/runtime/python/okstra_vendor/networkx/algorithms/simple_paths.py +966 -0
  348. package/runtime/python/okstra_vendor/networkx/algorithms/smallworld.py +404 -0
  349. package/runtime/python/okstra_vendor/networkx/algorithms/smetric.py +30 -0
  350. package/runtime/python/okstra_vendor/networkx/algorithms/sparsifiers.py +296 -0
  351. package/runtime/python/okstra_vendor/networkx/algorithms/structuralholes.py +374 -0
  352. package/runtime/python/okstra_vendor/networkx/algorithms/summarization.py +564 -0
  353. package/runtime/python/okstra_vendor/networkx/algorithms/swap.py +406 -0
  354. package/runtime/python/okstra_vendor/networkx/algorithms/tests/__init__.py +0 -0
  355. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_asteroidal.py +23 -0
  356. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_boundary.py +154 -0
  357. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_bridges.py +144 -0
  358. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_broadcasting.py +109 -0
  359. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_chains.py +136 -0
  360. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_chordal.py +129 -0
  361. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_clique.py +300 -0
  362. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cluster.py +678 -0
  363. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_communicability.py +80 -0
  364. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_core.py +266 -0
  365. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_covering.py +85 -0
  366. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cuts.py +171 -0
  367. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cycles.py +984 -0
  368. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_d_separation.py +340 -0
  369. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dag.py +835 -0
  370. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_distance_measures.py +831 -0
  371. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_distance_regular.py +85 -0
  372. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dominance.py +299 -0
  373. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dominating.py +115 -0
  374. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_efficiency.py +58 -0
  375. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_euler.py +314 -0
  376. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_graph_hashing.py +872 -0
  377. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_graphical.py +163 -0
  378. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_hierarchy.py +46 -0
  379. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_hybrid.py +24 -0
  380. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_isolate.py +26 -0
  381. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_link_prediction.py +615 -0
  382. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_lowest_common_ancestors.py +459 -0
  383. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_matching.py +556 -0
  384. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_max_weight_clique.py +179 -0
  385. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_mis.py +62 -0
  386. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_moral.py +15 -0
  387. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_node_classification.py +140 -0
  388. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_non_randomness.py +60 -0
  389. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_perfect_graph.py +27 -0
  390. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_planar_drawing.py +274 -0
  391. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_planarity.py +556 -0
  392. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_polynomials.py +57 -0
  393. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_reciprocity.py +37 -0
  394. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_regular.py +88 -0
  395. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_richclub.py +149 -0
  396. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_similarity.py +1158 -0
  397. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_simple_paths.py +803 -0
  398. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_smallworld.py +76 -0
  399. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_smetric.py +8 -0
  400. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_sparsifiers.py +138 -0
  401. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_structuralholes.py +191 -0
  402. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_summarization.py +642 -0
  403. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_swap.py +179 -0
  404. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_threshold.py +270 -0
  405. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_time_dependent.py +431 -0
  406. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_tournament.py +161 -0
  407. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_triads.py +248 -0
  408. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_vitality.py +41 -0
  409. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_voronoi.py +103 -0
  410. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_walks.py +54 -0
  411. package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_wiener.py +157 -0
  412. package/runtime/python/okstra_vendor/networkx/algorithms/threshold.py +981 -0
  413. package/runtime/python/okstra_vendor/networkx/algorithms/time_dependent.py +142 -0
  414. package/runtime/python/okstra_vendor/networkx/algorithms/tournament.py +406 -0
  415. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/__init__.py +5 -0
  416. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/beamsearch.py +90 -0
  417. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/breadth_first_search.py +576 -0
  418. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/depth_first_search.py +529 -0
  419. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgebfs.py +185 -0
  420. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgedfs.py +182 -0
  421. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/__init__.py +0 -0
  422. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_beamsearch.py +25 -0
  423. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_bfs.py +203 -0
  424. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_dfs.py +307 -0
  425. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_edgebfs.py +147 -0
  426. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_edgedfs.py +131 -0
  427. package/runtime/python/okstra_vendor/networkx/algorithms/tree/__init__.py +7 -0
  428. package/runtime/python/okstra_vendor/networkx/algorithms/tree/branchings.py +1042 -0
  429. package/runtime/python/okstra_vendor/networkx/algorithms/tree/coding.py +413 -0
  430. package/runtime/python/okstra_vendor/networkx/algorithms/tree/decomposition.py +88 -0
  431. package/runtime/python/okstra_vendor/networkx/algorithms/tree/distance_measures.py +219 -0
  432. package/runtime/python/okstra_vendor/networkx/algorithms/tree/mst.py +1281 -0
  433. package/runtime/python/okstra_vendor/networkx/algorithms/tree/operations.py +106 -0
  434. package/runtime/python/okstra_vendor/networkx/algorithms/tree/recognition.py +273 -0
  435. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/__init__.py +0 -0
  436. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_branchings.py +624 -0
  437. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_coding.py +114 -0
  438. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_decomposition.py +79 -0
  439. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_distance_measures.py +99 -0
  440. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_mst.py +934 -0
  441. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_operations.py +53 -0
  442. package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_recognition.py +174 -0
  443. package/runtime/python/okstra_vendor/networkx/algorithms/triads.py +500 -0
  444. package/runtime/python/okstra_vendor/networkx/algorithms/vitality.py +76 -0
  445. package/runtime/python/okstra_vendor/networkx/algorithms/voronoi.py +86 -0
  446. package/runtime/python/okstra_vendor/networkx/algorithms/walks.py +77 -0
  447. package/runtime/python/okstra_vendor/networkx/algorithms/wiener.py +278 -0
  448. package/runtime/python/okstra_vendor/networkx/classes/__init__.py +13 -0
  449. package/runtime/python/okstra_vendor/networkx/classes/coreviews.py +435 -0
  450. package/runtime/python/okstra_vendor/networkx/classes/digraph.py +1363 -0
  451. package/runtime/python/okstra_vendor/networkx/classes/filters.py +95 -0
  452. package/runtime/python/okstra_vendor/networkx/classes/function.py +1549 -0
  453. package/runtime/python/okstra_vendor/networkx/classes/graph.py +2082 -0
  454. package/runtime/python/okstra_vendor/networkx/classes/graphviews.py +269 -0
  455. package/runtime/python/okstra_vendor/networkx/classes/multidigraph.py +977 -0
  456. package/runtime/python/okstra_vendor/networkx/classes/multigraph.py +1294 -0
  457. package/runtime/python/okstra_vendor/networkx/classes/reportviews.py +1447 -0
  458. package/runtime/python/okstra_vendor/networkx/classes/tests/__init__.py +0 -0
  459. package/runtime/python/okstra_vendor/networkx/classes/tests/dispatch_interface.py +192 -0
  460. package/runtime/python/okstra_vendor/networkx/classes/tests/historical_tests.py +476 -0
  461. package/runtime/python/okstra_vendor/networkx/classes/tests/test_coreviews.py +362 -0
  462. package/runtime/python/okstra_vendor/networkx/classes/tests/test_digraph.py +331 -0
  463. package/runtime/python/okstra_vendor/networkx/classes/tests/test_digraph_historical.py +110 -0
  464. package/runtime/python/okstra_vendor/networkx/classes/tests/test_filters.py +177 -0
  465. package/runtime/python/okstra_vendor/networkx/classes/tests/test_function.py +1045 -0
  466. package/runtime/python/okstra_vendor/networkx/classes/tests/test_graph.py +950 -0
  467. package/runtime/python/okstra_vendor/networkx/classes/tests/test_graph_historical.py +12 -0
  468. package/runtime/python/okstra_vendor/networkx/classes/tests/test_graphviews.py +349 -0
  469. package/runtime/python/okstra_vendor/networkx/classes/tests/test_multidigraph.py +459 -0
  470. package/runtime/python/okstra_vendor/networkx/classes/tests/test_multigraph.py +528 -0
  471. package/runtime/python/okstra_vendor/networkx/classes/tests/test_reportviews.py +1421 -0
  472. package/runtime/python/okstra_vendor/networkx/classes/tests/test_special.py +131 -0
  473. package/runtime/python/okstra_vendor/networkx/classes/tests/test_subgraphviews.py +371 -0
  474. package/runtime/python/okstra_vendor/networkx/conftest.py +261 -0
  475. package/runtime/python/okstra_vendor/networkx/convert.py +502 -0
  476. package/runtime/python/okstra_vendor/networkx/convert_matrix.py +1314 -0
  477. package/runtime/python/okstra_vendor/networkx/drawing/__init__.py +7 -0
  478. package/runtime/python/okstra_vendor/networkx/drawing/layout.py +2036 -0
  479. package/runtime/python/okstra_vendor/networkx/drawing/nx_agraph.py +470 -0
  480. package/runtime/python/okstra_vendor/networkx/drawing/nx_latex.py +570 -0
  481. package/runtime/python/okstra_vendor/networkx/drawing/nx_pydot.py +361 -0
  482. package/runtime/python/okstra_vendor/networkx/drawing/nx_pylab.py +2978 -0
  483. package/runtime/python/okstra_vendor/networkx/drawing/tests/__init__.py +0 -0
  484. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_complex.png +0 -0
  485. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_empty_graph.png +0 -0
  486. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_house_with_colors.png +0 -0
  487. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_labels_and_colors.png +0 -0
  488. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_shortest_path.png +0 -0
  489. package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_house_with_colors.png +0 -0
  490. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_agraph.py +237 -0
  491. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_image_comparison_pylab_mpl.py +229 -0
  492. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_latex.py +285 -0
  493. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_layout.py +631 -0
  494. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_pydot.py +146 -0
  495. package/runtime/python/okstra_vendor/networkx/drawing/tests/test_pylab.py +1582 -0
  496. package/runtime/python/okstra_vendor/networkx/exception.py +131 -0
  497. package/runtime/python/okstra_vendor/networkx/generators/__init__.py +34 -0
  498. package/runtime/python/okstra_vendor/networkx/generators/atlas.dat.gz +0 -0
  499. package/runtime/python/okstra_vendor/networkx/generators/atlas.py +227 -0
  500. package/runtime/python/okstra_vendor/networkx/generators/classic.py +1091 -0
  501. package/runtime/python/okstra_vendor/networkx/generators/cographs.py +68 -0
  502. package/runtime/python/okstra_vendor/networkx/generators/community.py +1070 -0
  503. package/runtime/python/okstra_vendor/networkx/generators/degree_seq.py +886 -0
  504. package/runtime/python/okstra_vendor/networkx/generators/directed.py +572 -0
  505. package/runtime/python/okstra_vendor/networkx/generators/duplication.py +174 -0
  506. package/runtime/python/okstra_vendor/networkx/generators/ego.py +66 -0
  507. package/runtime/python/okstra_vendor/networkx/generators/expanders.py +499 -0
  508. package/runtime/python/okstra_vendor/networkx/generators/geometric.py +1037 -0
  509. package/runtime/python/okstra_vendor/networkx/generators/harary_graph.py +163 -0
  510. package/runtime/python/okstra_vendor/networkx/generators/internet_as_graphs.py +443 -0
  511. package/runtime/python/okstra_vendor/networkx/generators/intersection.py +125 -0
  512. package/runtime/python/okstra_vendor/networkx/generators/interval_graph.py +70 -0
  513. package/runtime/python/okstra_vendor/networkx/generators/joint_degree_seq.py +664 -0
  514. package/runtime/python/okstra_vendor/networkx/generators/lattice.py +405 -0
  515. package/runtime/python/okstra_vendor/networkx/generators/line.py +501 -0
  516. package/runtime/python/okstra_vendor/networkx/generators/mycielski.py +110 -0
  517. package/runtime/python/okstra_vendor/networkx/generators/nonisomorphic_trees.py +259 -0
  518. package/runtime/python/okstra_vendor/networkx/generators/random_clustered.py +117 -0
  519. package/runtime/python/okstra_vendor/networkx/generators/random_graphs.py +1416 -0
  520. package/runtime/python/okstra_vendor/networkx/generators/small.py +1070 -0
  521. package/runtime/python/okstra_vendor/networkx/generators/social.py +554 -0
  522. package/runtime/python/okstra_vendor/networkx/generators/spectral_graph_forge.py +120 -0
  523. package/runtime/python/okstra_vendor/networkx/generators/stochastic.py +54 -0
  524. package/runtime/python/okstra_vendor/networkx/generators/sudoku.py +131 -0
  525. package/runtime/python/okstra_vendor/networkx/generators/tests/__init__.py +0 -0
  526. package/runtime/python/okstra_vendor/networkx/generators/tests/test_atlas.py +75 -0
  527. package/runtime/python/okstra_vendor/networkx/generators/tests/test_classic.py +642 -0
  528. package/runtime/python/okstra_vendor/networkx/generators/tests/test_cographs.py +20 -0
  529. package/runtime/python/okstra_vendor/networkx/generators/tests/test_community.py +362 -0
  530. package/runtime/python/okstra_vendor/networkx/generators/tests/test_degree_seq.py +224 -0
  531. package/runtime/python/okstra_vendor/networkx/generators/tests/test_directed.py +189 -0
  532. package/runtime/python/okstra_vendor/networkx/generators/tests/test_duplication.py +103 -0
  533. package/runtime/python/okstra_vendor/networkx/generators/tests/test_ego.py +39 -0
  534. package/runtime/python/okstra_vendor/networkx/generators/tests/test_expanders.py +182 -0
  535. package/runtime/python/okstra_vendor/networkx/generators/tests/test_geometric.py +488 -0
  536. package/runtime/python/okstra_vendor/networkx/generators/tests/test_harary_graph.py +133 -0
  537. package/runtime/python/okstra_vendor/networkx/generators/tests/test_internet_as_graphs.py +221 -0
  538. package/runtime/python/okstra_vendor/networkx/generators/tests/test_intersection.py +28 -0
  539. package/runtime/python/okstra_vendor/networkx/generators/tests/test_interval_graph.py +144 -0
  540. package/runtime/python/okstra_vendor/networkx/generators/tests/test_joint_degree_seq.py +125 -0
  541. package/runtime/python/okstra_vendor/networkx/generators/tests/test_lattice.py +264 -0
  542. package/runtime/python/okstra_vendor/networkx/generators/tests/test_line.py +316 -0
  543. package/runtime/python/okstra_vendor/networkx/generators/tests/test_mycielski.py +30 -0
  544. package/runtime/python/okstra_vendor/networkx/generators/tests/test_nonisomorphic_trees.py +82 -0
  545. package/runtime/python/okstra_vendor/networkx/generators/tests/test_random_clustered.py +33 -0
  546. package/runtime/python/okstra_vendor/networkx/generators/tests/test_random_graphs.py +495 -0
  547. package/runtime/python/okstra_vendor/networkx/generators/tests/test_small.py +220 -0
  548. package/runtime/python/okstra_vendor/networkx/generators/tests/test_spectral_graph_forge.py +49 -0
  549. package/runtime/python/okstra_vendor/networkx/generators/tests/test_stochastic.py +72 -0
  550. package/runtime/python/okstra_vendor/networkx/generators/tests/test_sudoku.py +92 -0
  551. package/runtime/python/okstra_vendor/networkx/generators/tests/test_time_series.py +64 -0
  552. package/runtime/python/okstra_vendor/networkx/generators/tests/test_trees.py +195 -0
  553. package/runtime/python/okstra_vendor/networkx/generators/tests/test_triads.py +15 -0
  554. package/runtime/python/okstra_vendor/networkx/generators/time_series.py +74 -0
  555. package/runtime/python/okstra_vendor/networkx/generators/trees.py +1070 -0
  556. package/runtime/python/okstra_vendor/networkx/generators/triads.py +94 -0
  557. package/runtime/python/okstra_vendor/networkx/lazy_imports.py +188 -0
  558. package/runtime/python/okstra_vendor/networkx/linalg/__init__.py +13 -0
  559. package/runtime/python/okstra_vendor/networkx/linalg/algebraicconnectivity.py +650 -0
  560. package/runtime/python/okstra_vendor/networkx/linalg/attrmatrix.py +466 -0
  561. package/runtime/python/okstra_vendor/networkx/linalg/bethehessianmatrix.py +77 -0
  562. package/runtime/python/okstra_vendor/networkx/linalg/graphmatrix.py +168 -0
  563. package/runtime/python/okstra_vendor/networkx/linalg/laplacianmatrix.py +512 -0
  564. package/runtime/python/okstra_vendor/networkx/linalg/modularitymatrix.py +166 -0
  565. package/runtime/python/okstra_vendor/networkx/linalg/spectrum.py +186 -0
  566. package/runtime/python/okstra_vendor/networkx/linalg/tests/__init__.py +0 -0
  567. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_algebraic_connectivity.py +400 -0
  568. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_attrmatrix.py +108 -0
  569. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_bethehessian.py +40 -0
  570. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_graphmatrix.py +275 -0
  571. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_laplacian.py +334 -0
  572. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_modularity.py +86 -0
  573. package/runtime/python/okstra_vendor/networkx/linalg/tests/test_spectrum.py +70 -0
  574. package/runtime/python/okstra_vendor/networkx/readwrite/__init__.py +17 -0
  575. package/runtime/python/okstra_vendor/networkx/readwrite/adjlist.py +330 -0
  576. package/runtime/python/okstra_vendor/networkx/readwrite/edgelist.py +489 -0
  577. package/runtime/python/okstra_vendor/networkx/readwrite/gexf.py +1084 -0
  578. package/runtime/python/okstra_vendor/networkx/readwrite/gml.py +879 -0
  579. package/runtime/python/okstra_vendor/networkx/readwrite/graph6.py +427 -0
  580. package/runtime/python/okstra_vendor/networkx/readwrite/graphml.py +1053 -0
  581. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/__init__.py +19 -0
  582. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/adjacency.py +156 -0
  583. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/cytoscape.py +190 -0
  584. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/node_link.py +261 -0
  585. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/__init__.py +0 -0
  586. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_adjacency.py +78 -0
  587. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_cytoscape.py +78 -0
  588. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_node_link.py +109 -0
  589. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_tree.py +48 -0
  590. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tree.py +137 -0
  591. package/runtime/python/okstra_vendor/networkx/readwrite/leda.py +108 -0
  592. package/runtime/python/okstra_vendor/networkx/readwrite/multiline_adjlist.py +393 -0
  593. package/runtime/python/okstra_vendor/networkx/readwrite/p2g.py +113 -0
  594. package/runtime/python/okstra_vendor/networkx/readwrite/pajek.py +286 -0
  595. package/runtime/python/okstra_vendor/networkx/readwrite/sparse6.py +379 -0
  596. package/runtime/python/okstra_vendor/networkx/readwrite/tests/__init__.py +0 -0
  597. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_adjlist.py +354 -0
  598. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_edgelist.py +318 -0
  599. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_gexf.py +612 -0
  600. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_gml.py +744 -0
  601. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_graph6.py +181 -0
  602. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_graphml.py +1531 -0
  603. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_leda.py +30 -0
  604. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_p2g.py +63 -0
  605. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_pajek.py +128 -0
  606. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_sparse6.py +166 -0
  607. package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_text.py +1742 -0
  608. package/runtime/python/okstra_vendor/networkx/readwrite/text.py +851 -0
  609. package/runtime/python/okstra_vendor/networkx/relabel.py +285 -0
  610. package/runtime/python/okstra_vendor/networkx/tests/__init__.py +0 -0
  611. package/runtime/python/okstra_vendor/networkx/tests/test_all_random_functions.py +248 -0
  612. package/runtime/python/okstra_vendor/networkx/tests/test_convert.py +321 -0
  613. package/runtime/python/okstra_vendor/networkx/tests/test_convert_numpy.py +531 -0
  614. package/runtime/python/okstra_vendor/networkx/tests/test_convert_pandas.py +349 -0
  615. package/runtime/python/okstra_vendor/networkx/tests/test_convert_scipy.py +281 -0
  616. package/runtime/python/okstra_vendor/networkx/tests/test_exceptions.py +40 -0
  617. package/runtime/python/okstra_vendor/networkx/tests/test_import.py +11 -0
  618. package/runtime/python/okstra_vendor/networkx/tests/test_lazy_imports.py +96 -0
  619. package/runtime/python/okstra_vendor/networkx/tests/test_relabel.py +349 -0
  620. package/runtime/python/okstra_vendor/networkx/tests/test_removed_functions_exception_messages.py +8 -0
  621. package/runtime/python/okstra_vendor/networkx/utils/__init__.py +8 -0
  622. package/runtime/python/okstra_vendor/networkx/utils/backends.py +2171 -0
  623. package/runtime/python/okstra_vendor/networkx/utils/configs.py +396 -0
  624. package/runtime/python/okstra_vendor/networkx/utils/decorators.py +1233 -0
  625. package/runtime/python/okstra_vendor/networkx/utils/heaps.py +338 -0
  626. package/runtime/python/okstra_vendor/networkx/utils/mapped_queue.py +297 -0
  627. package/runtime/python/okstra_vendor/networkx/utils/misc.py +703 -0
  628. package/runtime/python/okstra_vendor/networkx/utils/random_sequence.py +198 -0
  629. package/runtime/python/okstra_vendor/networkx/utils/rcm.py +159 -0
  630. package/runtime/python/okstra_vendor/networkx/utils/tests/__init__.py +0 -0
  631. package/runtime/python/okstra_vendor/networkx/utils/tests/test__init.py +11 -0
  632. package/runtime/python/okstra_vendor/networkx/utils/tests/test_backends.py +225 -0
  633. package/runtime/python/okstra_vendor/networkx/utils/tests/test_config.py +263 -0
  634. package/runtime/python/okstra_vendor/networkx/utils/tests/test_decorators.py +510 -0
  635. package/runtime/python/okstra_vendor/networkx/utils/tests/test_heaps.py +131 -0
  636. package/runtime/python/okstra_vendor/networkx/utils/tests/test_mapped_queue.py +268 -0
  637. package/runtime/python/okstra_vendor/networkx/utils/tests/test_misc.py +393 -0
  638. package/runtime/python/okstra_vendor/networkx/utils/tests/test_random_sequence.py +53 -0
  639. package/runtime/python/okstra_vendor/networkx/utils/tests/test_rcm.py +63 -0
  640. package/runtime/python/okstra_vendor/networkx/utils/tests/test_unionfind.py +55 -0
  641. package/runtime/python/okstra_vendor/networkx/utils/union_find.py +106 -0
  642. package/runtime/skills/okstra-graphify/SKILL.md +161 -0
  643. package/runtime/skills/okstra-inspect/SKILL.md +17 -9
  644. package/runtime/templates/reports/settings.template.json +4 -0
  645. package/src/cli-registry.mjs +7 -0
  646. package/src/commands/graphify.mjs +32 -0
  647. package/src/commands/lifecycle/doctor.mjs +9 -0
  648. package/src/lib/skill-catalog.mjs +1 -0
@@ -0,0 +1,1102 @@
1
+ """
2
+ ***************
3
+ VF2++ Algorithm
4
+ ***************
5
+
6
+ An implementation of the VF2++ algorithm [1]_ for Graph Isomorphism testing.
7
+
8
+ The simplest interface to use this module is to call:
9
+
10
+ `vf2pp_is_isomorphic`: to check whether two graphs are isomorphic.
11
+ `vf2pp_isomorphism`: to obtain the node mapping between two graphs,
12
+ in case they are isomorphic.
13
+ `vf2pp_all_isomorphisms`: to generate all possible mappings between two graphs,
14
+ if isomorphic.
15
+
16
+ Introduction
17
+ ------------
18
+ The VF2++ algorithm, follows a similar logic to that of VF2, while also
19
+ introducing new easy-to-check cutting rules and determining the optimal access
20
+ order of nodes. It is also implemented in a non-recursive manner, which saves
21
+ both time and space, when compared to its previous counterpart.
22
+
23
+ The optimal node ordering is obtained after taking into consideration both the
24
+ degree but also the label rarity of each node.
25
+ This way we place the nodes that are more likely to match, first in the order,
26
+ thus examining the most promising branches in the beginning.
27
+ The rules also consider node labels, making it easier to prune unfruitful
28
+ branches early in the process.
29
+
30
+ Examples
31
+ --------
32
+
33
+ Suppose G1 and G2 are Isomorphic Graphs. Verification is as follows:
34
+
35
+ Without node labels:
36
+
37
+ >>> import networkx as nx
38
+ >>> G1 = nx.path_graph(4)
39
+ >>> G2 = nx.path_graph(4)
40
+ >>> nx.vf2pp_is_isomorphic(G1, G2, node_label=None)
41
+ True
42
+ >>> nx.vf2pp_isomorphism(G1, G2, node_label=None)
43
+ {1: 1, 2: 2, 0: 0, 3: 3}
44
+
45
+ With node labels:
46
+
47
+ >>> G1 = nx.path_graph(4)
48
+ >>> G2 = nx.path_graph(4)
49
+ >>> mapped = {1: 1, 2: 2, 3: 3, 0: 0}
50
+ >>> nx.set_node_attributes(
51
+ ... G1, dict(zip(G1, ["blue", "red", "green", "yellow"])), "label"
52
+ ... )
53
+ >>> nx.set_node_attributes(
54
+ ... G2,
55
+ ... dict(zip([mapped[u] for u in G1], ["blue", "red", "green", "yellow"])),
56
+ ... "label",
57
+ ... )
58
+ >>> nx.vf2pp_is_isomorphic(G1, G2, node_label="label")
59
+ True
60
+ >>> nx.vf2pp_isomorphism(G1, G2, node_label="label")
61
+ {1: 1, 2: 2, 0: 0, 3: 3}
62
+
63
+ References
64
+ ----------
65
+ .. [1] Jüttner, Alpár & Madarasi, Péter. (2018). "VF2++—An improved subgraph
66
+ isomorphism algorithm". Discrete Applied Mathematics. 242.
67
+ https://doi.org/10.1016/j.dam.2018.02.018
68
+
69
+ """
70
+
71
+ import collections
72
+
73
+ import networkx as nx
74
+
75
+ __all__ = ["vf2pp_isomorphism", "vf2pp_is_isomorphic", "vf2pp_all_isomorphisms"]
76
+
77
+ _GraphParameters = collections.namedtuple(
78
+ "_GraphParameters",
79
+ [
80
+ "G1",
81
+ "G2",
82
+ "G1_labels",
83
+ "G2_labels",
84
+ "nodes_of_G1Labels",
85
+ "nodes_of_G2Labels",
86
+ "G2_nodes_of_degree",
87
+ ],
88
+ )
89
+
90
+ _StateParameters = collections.namedtuple(
91
+ "_StateParameters",
92
+ [
93
+ "mapping",
94
+ "reverse_mapping",
95
+ "T1",
96
+ "T1_in",
97
+ "T1_tilde",
98
+ "T1_tilde_in",
99
+ "T2",
100
+ "T2_in",
101
+ "T2_tilde",
102
+ "T2_tilde_in",
103
+ ],
104
+ )
105
+
106
+
107
+ @nx._dispatchable(graphs={"G1": 0, "G2": 1}, node_attrs={"node_label": "default_label"})
108
+ def vf2pp_isomorphism(G1, G2, node_label=None, default_label=None):
109
+ """Return an isomorphic mapping between `G1` and `G2` if it exists.
110
+
111
+ Parameters
112
+ ----------
113
+ G1, G2 : NetworkX Graph or MultiGraph instances.
114
+ The two graphs to check for isomorphism.
115
+
116
+ node_label : str, optional
117
+ The name of the node attribute to be used when comparing nodes.
118
+ The default is `None`, meaning node attributes are not considered
119
+ in the comparison. Any node that doesn't have the `node_label`
120
+ attribute uses `default_label` instead.
121
+
122
+ default_label : scalar
123
+ Default value to use when a node doesn't have an attribute
124
+ named `node_label`. Default is `None`.
125
+
126
+ Returns
127
+ -------
128
+ dict or None
129
+ Node mapping if the two graphs are isomorphic. None otherwise.
130
+ """
131
+ try:
132
+ mapping = next(vf2pp_all_isomorphisms(G1, G2, node_label, default_label))
133
+ return mapping
134
+ except StopIteration:
135
+ return None
136
+
137
+
138
+ @nx._dispatchable(graphs={"G1": 0, "G2": 1}, node_attrs={"node_label": "default_label"})
139
+ def vf2pp_is_isomorphic(G1, G2, node_label=None, default_label=None):
140
+ """Examines whether G1 and G2 are isomorphic.
141
+
142
+ Parameters
143
+ ----------
144
+ G1, G2 : NetworkX Graph or MultiGraph instances.
145
+ The two graphs to check for isomorphism.
146
+
147
+ node_label : str, optional
148
+ The name of the node attribute to be used when comparing nodes.
149
+ The default is `None`, meaning node attributes are not considered
150
+ in the comparison. Any node that doesn't have the `node_label`
151
+ attribute uses `default_label` instead.
152
+
153
+ default_label : scalar
154
+ Default value to use when a node doesn't have an attribute
155
+ named `node_label`. Default is `None`.
156
+
157
+ Returns
158
+ -------
159
+ bool
160
+ True if the two graphs are isomorphic, False otherwise.
161
+ """
162
+ if vf2pp_isomorphism(G1, G2, node_label, default_label) is not None:
163
+ return True
164
+ return False
165
+
166
+
167
+ @nx._dispatchable(graphs={"G1": 0, "G2": 1}, node_attrs={"node_label": "default_label"})
168
+ def vf2pp_all_isomorphisms(G1, G2, node_label=None, default_label=None):
169
+ """Yields all the possible mappings between G1 and G2.
170
+
171
+ Parameters
172
+ ----------
173
+ G1, G2 : NetworkX Graph or MultiGraph instances.
174
+ The two graphs to check for isomorphism.
175
+
176
+ node_label : str, optional
177
+ The name of the node attribute to be used when comparing nodes.
178
+ The default is `None`, meaning node attributes are not considered
179
+ in the comparison. Any node that doesn't have the `node_label`
180
+ attribute uses `default_label` instead.
181
+
182
+ default_label : scalar
183
+ Default value to use when a node doesn't have an attribute
184
+ named `node_label`. Default is `None`.
185
+
186
+ Yields
187
+ ------
188
+ dict
189
+ Isomorphic mapping between the nodes in `G1` and `G2`.
190
+ """
191
+ if G1.number_of_nodes() == 0 or G2.number_of_nodes() == 0:
192
+ return False
193
+
194
+ # Create the degree dicts based on graph type
195
+ if G1.is_directed():
196
+ G1_degree = {
197
+ n: (in_degree, out_degree)
198
+ for (n, in_degree), (_, out_degree) in zip(G1.in_degree, G1.out_degree)
199
+ }
200
+ G2_degree = {
201
+ n: (in_degree, out_degree)
202
+ for (n, in_degree), (_, out_degree) in zip(G2.in_degree, G2.out_degree)
203
+ }
204
+ else:
205
+ G1_degree = dict(G1.degree)
206
+ G2_degree = dict(G2.degree)
207
+
208
+ if not G1.is_directed():
209
+ find_candidates = _find_candidates
210
+ restore_Tinout = _restore_Tinout
211
+ else:
212
+ find_candidates = _find_candidates_Di
213
+ restore_Tinout = _restore_Tinout_Di
214
+
215
+ # Check that both graphs have the same number of nodes and degree sequence
216
+ if G1.order() != G2.order():
217
+ return False
218
+ if sorted(G1_degree.values()) != sorted(G2_degree.values()):
219
+ return False
220
+
221
+ # Initialize parameters and cache necessary information about degree and labels
222
+ graph_params, state_params = _initialize_parameters(
223
+ G1, G2, G2_degree, node_label, default_label
224
+ )
225
+
226
+ # Check if G1 and G2 have the same labels, and that number of nodes per label
227
+ # is equal between the two graphs
228
+ if not _precheck_label_properties(graph_params):
229
+ return False
230
+
231
+ # Calculate the optimal node ordering
232
+ node_order = _matching_order(graph_params)
233
+
234
+ # Initialize the stack
235
+ stack = []
236
+ candidates = iter(
237
+ find_candidates(node_order[0], graph_params, state_params, G1_degree)
238
+ )
239
+ stack.append((node_order[0], candidates))
240
+
241
+ mapping = state_params.mapping
242
+ reverse_mapping = state_params.reverse_mapping
243
+
244
+ # Index of the node from the order, currently being examined
245
+ matching_node = 1
246
+
247
+ while stack:
248
+ current_node, candidate_nodes = stack[-1]
249
+
250
+ try:
251
+ candidate = next(candidate_nodes)
252
+ except StopIteration:
253
+ # If no remaining candidates, return to a previous state, and follow another branch
254
+ stack.pop()
255
+ matching_node -= 1
256
+ if stack:
257
+ # Pop the previously added u-v pair, and look for a different candidate _v for u
258
+ popped_node1, _ = stack[-1]
259
+ popped_node2 = mapping[popped_node1]
260
+ mapping.pop(popped_node1)
261
+ reverse_mapping.pop(popped_node2)
262
+ restore_Tinout(popped_node1, popped_node2, graph_params, state_params)
263
+ continue
264
+
265
+ if _feasibility(current_node, candidate, graph_params, state_params):
266
+ # Terminate if mapping is extended to its full
267
+ if len(mapping) == G2.number_of_nodes() - 1:
268
+ cp_mapping = mapping.copy()
269
+ cp_mapping[current_node] = candidate
270
+ yield cp_mapping
271
+ continue
272
+
273
+ # Feasibility rules pass, so extend the mapping and update the parameters
274
+ mapping[current_node] = candidate
275
+ reverse_mapping[candidate] = current_node
276
+ _update_Tinout(current_node, candidate, graph_params, state_params)
277
+ # Append the next node and its candidates to the stack
278
+ candidates = iter(
279
+ find_candidates(
280
+ node_order[matching_node], graph_params, state_params, G1_degree
281
+ )
282
+ )
283
+ stack.append((node_order[matching_node], candidates))
284
+ matching_node += 1
285
+
286
+
287
+ def _precheck_label_properties(graph_params):
288
+ G1, G2, G1_labels, G2_labels, nodes_of_G1Labels, nodes_of_G2Labels, _ = graph_params
289
+ if any(
290
+ label not in nodes_of_G1Labels or len(nodes_of_G1Labels[label]) != len(nodes)
291
+ for label, nodes in nodes_of_G2Labels.items()
292
+ ):
293
+ return False
294
+ return True
295
+
296
+
297
+ def _initialize_parameters(G1, G2, G2_degree, node_label=None, default_label=-1):
298
+ """Initializes all the necessary parameters for VF2++
299
+
300
+ Parameters
301
+ ----------
302
+ G1,G2: NetworkX Graph or MultiGraph instances.
303
+ The two graphs to check for isomorphism or monomorphism
304
+
305
+ G1_labels,G2_labels: dict
306
+ The label of every node in G1 and G2 respectively
307
+
308
+ Returns
309
+ -------
310
+ graph_params: namedtuple
311
+ Contains all the Graph-related parameters:
312
+
313
+ G1,G2
314
+ G1_labels,G2_labels: dict
315
+
316
+ state_params: namedtuple
317
+ Contains all the State-related parameters:
318
+
319
+ mapping: dict
320
+ The mapping as extended so far. Maps nodes of G1 to nodes of G2
321
+
322
+ reverse_mapping: dict
323
+ The reverse mapping as extended so far. Maps nodes from G2 to nodes of G1.
324
+ It's basically "mapping" reversed
325
+
326
+ T1, T2: set
327
+ Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes
328
+ that are not in the mapping, but are neighbors of nodes that are.
329
+
330
+ T1_out, T2_out: set
331
+ Ti_out contains all the nodes from Gi, that are neither in the mapping
332
+ nor in Ti
333
+ """
334
+ G1_labels = dict(G1.nodes(data=node_label, default=default_label))
335
+ G2_labels = dict(G2.nodes(data=node_label, default=default_label))
336
+
337
+ graph_params = _GraphParameters(
338
+ G1,
339
+ G2,
340
+ G1_labels,
341
+ G2_labels,
342
+ nx.utils.groups(G1_labels),
343
+ nx.utils.groups(G2_labels),
344
+ nx.utils.groups(G2_degree),
345
+ )
346
+
347
+ T1, T1_in = set(), set()
348
+ T2, T2_in = set(), set()
349
+ if G1.is_directed():
350
+ T1_tilde, T1_tilde_in = (
351
+ set(G1.nodes()),
352
+ set(),
353
+ ) # todo: do we need Ti_tilde_in? What nodes does it have?
354
+ T2_tilde, T2_tilde_in = set(G2.nodes()), set()
355
+ else:
356
+ T1_tilde, T1_tilde_in = set(G1.nodes()), set()
357
+ T2_tilde, T2_tilde_in = set(G2.nodes()), set()
358
+
359
+ state_params = _StateParameters(
360
+ {},
361
+ {},
362
+ T1,
363
+ T1_in,
364
+ T1_tilde,
365
+ T1_tilde_in,
366
+ T2,
367
+ T2_in,
368
+ T2_tilde,
369
+ T2_tilde_in,
370
+ )
371
+
372
+ return graph_params, state_params
373
+
374
+
375
+ def _matching_order(graph_params):
376
+ """The node ordering as introduced in VF2++.
377
+
378
+ Notes
379
+ -----
380
+ Taking into account the structure of the Graph and the node labeling, the
381
+ nodes are placed in an order such that, most of the unfruitful/infeasible
382
+ branches of the search space can be pruned on high levels, significantly
383
+ decreasing the number of visited states. The premise is that, the algorithm
384
+ will be able to recognize inconsistencies early, proceeding to go deep into
385
+ the search tree only if it's needed.
386
+
387
+ Parameters
388
+ ----------
389
+ graph_params: namedtuple
390
+ Contains:
391
+
392
+ G1,G2: NetworkX Graph or MultiGraph instances.
393
+ The two graphs to check for isomorphism or monomorphism.
394
+
395
+ G1_labels,G2_labels: dict
396
+ The label of every node in G1 and G2 respectively.
397
+
398
+ Returns
399
+ -------
400
+ node_order: list
401
+ The ordering of the nodes.
402
+ """
403
+ G1, G2, G1_labels, _, _, nodes_of_G2Labels, _ = graph_params
404
+ if not G1 and not G2:
405
+ return {}
406
+
407
+ if G1.is_directed():
408
+ G1 = G1.to_undirected(as_view=True)
409
+
410
+ V1_unordered = set(G1.nodes())
411
+ label_rarity = {label: len(nodes) for label, nodes in nodes_of_G2Labels.items()}
412
+ used_degrees = {node: 0 for node in G1}
413
+ node_order = []
414
+
415
+ while V1_unordered:
416
+ max_rarity = min(label_rarity[G1_labels[x]] for x in V1_unordered)
417
+ rarest_nodes = [
418
+ n for n in V1_unordered if label_rarity[G1_labels[n]] == max_rarity
419
+ ]
420
+ max_node = max(rarest_nodes, key=G1.degree)
421
+
422
+ for dlevel_nodes in nx.bfs_layers(G1, max_node):
423
+ nodes_to_add = dlevel_nodes.copy()
424
+ while nodes_to_add:
425
+ max_used_degree = max(used_degrees[n] for n in nodes_to_add)
426
+ max_used_degree_nodes = [
427
+ n for n in nodes_to_add if used_degrees[n] == max_used_degree
428
+ ]
429
+ max_degree = max(G1.degree[n] for n in max_used_degree_nodes)
430
+ max_degree_nodes = [
431
+ n for n in max_used_degree_nodes if G1.degree[n] == max_degree
432
+ ]
433
+ next_node = min(
434
+ max_degree_nodes, key=lambda x: label_rarity[G1_labels[x]]
435
+ )
436
+
437
+ node_order.append(next_node)
438
+ for node in G1.neighbors(next_node):
439
+ used_degrees[node] += 1
440
+
441
+ nodes_to_add.remove(next_node)
442
+ label_rarity[G1_labels[next_node]] -= 1
443
+ V1_unordered.discard(next_node)
444
+
445
+ return node_order
446
+
447
+
448
+ def _find_candidates(
449
+ u, graph_params, state_params, G1_degree
450
+ ): # todo: make the 4th argument the degree of u
451
+ """Given node u of G1, finds the candidates of u from G2.
452
+
453
+ Parameters
454
+ ----------
455
+ u: Graph node
456
+ The node from G1 for which to find the candidates from G2.
457
+
458
+ graph_params: namedtuple
459
+ Contains all the Graph-related parameters:
460
+
461
+ G1,G2: NetworkX Graph or MultiGraph instances.
462
+ The two graphs to check for isomorphism or monomorphism
463
+
464
+ G1_labels,G2_labels: dict
465
+ The label of every node in G1 and G2 respectively
466
+
467
+ state_params: namedtuple
468
+ Contains all the State-related parameters:
469
+
470
+ mapping: dict
471
+ The mapping as extended so far. Maps nodes of G1 to nodes of G2
472
+
473
+ reverse_mapping: dict
474
+ The reverse mapping as extended so far. Maps nodes from G2 to nodes
475
+ of G1. It's basically "mapping" reversed
476
+
477
+ T1, T2: set
478
+ Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes
479
+ that are not in the mapping, but are neighbors of nodes that are.
480
+
481
+ T1_tilde, T2_tilde: set
482
+ Ti_tilde contains all the nodes from Gi, that are neither in the
483
+ mapping nor in Ti
484
+
485
+ Returns
486
+ -------
487
+ candidates: set
488
+ The nodes from G2 which are candidates for u.
489
+ """
490
+ G1, G2, G1_labels, _, _, nodes_of_G2Labels, G2_nodes_of_degree = graph_params
491
+ mapping, reverse_mapping, _, _, _, _, _, _, T2_tilde, _ = state_params
492
+
493
+ covered_nbrs = [nbr for nbr in G1[u] if nbr in mapping]
494
+ if not covered_nbrs:
495
+ candidates = set(nodes_of_G2Labels[G1_labels[u]])
496
+ candidates.intersection_update(G2_nodes_of_degree[G1_degree[u]])
497
+ candidates.intersection_update(T2_tilde)
498
+ candidates.difference_update(reverse_mapping)
499
+ if G1.is_multigraph():
500
+ candidates.difference_update(
501
+ {
502
+ node
503
+ for node in candidates
504
+ if G1.number_of_edges(u, u) != G2.number_of_edges(node, node)
505
+ }
506
+ )
507
+ return candidates
508
+
509
+ nbr1 = covered_nbrs[0]
510
+ common_nodes = set(G2[mapping[nbr1]])
511
+
512
+ for nbr1 in covered_nbrs[1:]:
513
+ common_nodes.intersection_update(G2[mapping[nbr1]])
514
+
515
+ common_nodes.difference_update(reverse_mapping)
516
+ common_nodes.intersection_update(G2_nodes_of_degree[G1_degree[u]])
517
+ common_nodes.intersection_update(nodes_of_G2Labels[G1_labels[u]])
518
+ if G1.is_multigraph():
519
+ common_nodes.difference_update(
520
+ {
521
+ node
522
+ for node in common_nodes
523
+ if G1.number_of_edges(u, u) != G2.number_of_edges(node, node)
524
+ }
525
+ )
526
+ return common_nodes
527
+
528
+
529
+ def _find_candidates_Di(u, graph_params, state_params, G1_degree):
530
+ G1, G2, G1_labels, _, _, nodes_of_G2Labels, G2_nodes_of_degree = graph_params
531
+ mapping, reverse_mapping, _, _, _, _, _, _, T2_tilde, _ = state_params
532
+
533
+ covered_successors = [succ for succ in G1[u] if succ in mapping]
534
+ covered_predecessors = [pred for pred in G1.pred[u] if pred in mapping]
535
+
536
+ if not (covered_successors or covered_predecessors):
537
+ candidates = set(nodes_of_G2Labels[G1_labels[u]])
538
+ candidates.intersection_update(G2_nodes_of_degree[G1_degree[u]])
539
+ candidates.intersection_update(T2_tilde)
540
+ candidates.difference_update(reverse_mapping)
541
+ if G1.is_multigraph():
542
+ candidates.difference_update(
543
+ {
544
+ node
545
+ for node in candidates
546
+ if G1.number_of_edges(u, u) != G2.number_of_edges(node, node)
547
+ }
548
+ )
549
+ return candidates
550
+
551
+ if covered_successors:
552
+ succ1 = covered_successors[0]
553
+ common_nodes = set(G2.pred[mapping[succ1]])
554
+
555
+ for succ1 in covered_successors[1:]:
556
+ common_nodes.intersection_update(G2.pred[mapping[succ1]])
557
+ else:
558
+ pred1 = covered_predecessors.pop()
559
+ common_nodes = set(G2[mapping[pred1]])
560
+
561
+ for pred1 in covered_predecessors:
562
+ common_nodes.intersection_update(G2[mapping[pred1]])
563
+
564
+ common_nodes.difference_update(reverse_mapping)
565
+ common_nodes.intersection_update(G2_nodes_of_degree[G1_degree[u]])
566
+ common_nodes.intersection_update(nodes_of_G2Labels[G1_labels[u]])
567
+ if G1.is_multigraph():
568
+ common_nodes.difference_update(
569
+ {
570
+ node
571
+ for node in common_nodes
572
+ if G1.number_of_edges(u, u) != G2.number_of_edges(node, node)
573
+ }
574
+ )
575
+ return common_nodes
576
+
577
+
578
+ def _feasibility(node1, node2, graph_params, state_params):
579
+ """Given a candidate pair of nodes u and v from G1 and G2 respectively,
580
+ checks if it's feasible to extend the mapping, i.e. if u and v can be matched.
581
+
582
+ Notes
583
+ -----
584
+ This function performs all the necessary checking by applying both consistency
585
+ and cutting rules.
586
+
587
+ Parameters
588
+ ----------
589
+ node1, node2: Graph node
590
+ The candidate pair of nodes being checked for matching
591
+
592
+ graph_params: namedtuple
593
+ Contains all the Graph-related parameters:
594
+
595
+ G1,G2: NetworkX Graph or MultiGraph instances.
596
+ The two graphs to check for isomorphism or monomorphism
597
+
598
+ G1_labels,G2_labels: dict
599
+ The label of every node in G1 and G2 respectively
600
+
601
+ state_params: namedtuple
602
+ Contains all the State-related parameters:
603
+
604
+ mapping: dict
605
+ The mapping as extended so far. Maps nodes of G1 to nodes of G2
606
+
607
+ reverse_mapping: dict
608
+ The reverse mapping as extended so far. Maps nodes from G2 to nodes
609
+ of G1. It's basically "mapping" reversed
610
+
611
+ T1, T2: set
612
+ Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes
613
+ that are not in the mapping, but are neighbors of nodes that are.
614
+
615
+ T1_out, T2_out: set
616
+ Ti_out contains all the nodes from Gi, that are neither in the mapping
617
+ nor in Ti
618
+
619
+ Returns
620
+ -------
621
+ True if all checks are successful, False otherwise.
622
+ """
623
+ G1 = graph_params.G1
624
+
625
+ if _cut_PT(node1, node2, graph_params, state_params):
626
+ return False
627
+
628
+ if G1.is_multigraph():
629
+ if not _consistent_PT(node1, node2, graph_params, state_params):
630
+ return False
631
+
632
+ return True
633
+
634
+
635
+ def _cut_PT(u, v, graph_params, state_params):
636
+ """Implements the cutting rules for the ISO problem.
637
+
638
+ Parameters
639
+ ----------
640
+ u, v: Graph node
641
+ The two candidate nodes being examined.
642
+
643
+ graph_params: namedtuple
644
+ Contains all the Graph-related parameters:
645
+
646
+ G1,G2: NetworkX Graph or MultiGraph instances.
647
+ The two graphs to check for isomorphism or monomorphism
648
+
649
+ G1_labels,G2_labels: dict
650
+ The label of every node in G1 and G2 respectively
651
+
652
+ state_params: namedtuple
653
+ Contains all the State-related parameters:
654
+
655
+ mapping: dict
656
+ The mapping as extended so far. Maps nodes of G1 to nodes of G2
657
+
658
+ reverse_mapping: dict
659
+ The reverse mapping as extended so far. Maps nodes from G2 to nodes
660
+ of G1. It's basically "mapping" reversed
661
+
662
+ T1, T2: set
663
+ Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes
664
+ that are not in the mapping, but are neighbors of nodes that are.
665
+
666
+ T1_tilde, T2_tilde: set
667
+ Ti_out contains all the nodes from Gi, that are neither in the
668
+ mapping nor in Ti
669
+
670
+ Returns
671
+ -------
672
+ True if we should prune this branch, i.e. the node pair failed the cutting checks. False otherwise.
673
+ """
674
+ G1, G2, G1_labels, G2_labels, _, _, _ = graph_params
675
+ (
676
+ _,
677
+ _,
678
+ T1,
679
+ T1_in,
680
+ T1_tilde,
681
+ _,
682
+ T2,
683
+ T2_in,
684
+ T2_tilde,
685
+ _,
686
+ ) = state_params
687
+
688
+ u_labels_predecessors, v_labels_predecessors = {}, {}
689
+ if G1.is_directed():
690
+ u_labels_predecessors = nx.utils.groups(
691
+ {n1: G1_labels[n1] for n1 in G1.pred[u]}
692
+ )
693
+ v_labels_predecessors = nx.utils.groups(
694
+ {n2: G2_labels[n2] for n2 in G2.pred[v]}
695
+ )
696
+
697
+ if set(u_labels_predecessors.keys()) != set(v_labels_predecessors.keys()):
698
+ return True
699
+
700
+ u_labels_successors = nx.utils.groups({n1: G1_labels[n1] for n1 in G1[u]})
701
+ v_labels_successors = nx.utils.groups({n2: G2_labels[n2] for n2 in G2[v]})
702
+
703
+ # if the neighbors of u, do not have the same labels as those of v, NOT feasible.
704
+ if set(u_labels_successors.keys()) != set(v_labels_successors.keys()):
705
+ return True
706
+
707
+ for label, G1_nbh in u_labels_successors.items():
708
+ G2_nbh = v_labels_successors[label]
709
+
710
+ if G1.is_multigraph():
711
+ # Check for every neighbor in the neighborhood, if u-nbr1 has same edges as v-nbr2
712
+ u_nbrs_edges = sorted(G1.number_of_edges(u, x) for x in G1_nbh)
713
+ v_nbrs_edges = sorted(G2.number_of_edges(v, x) for x in G2_nbh)
714
+ if any(
715
+ u_nbr_edges != v_nbr_edges
716
+ for u_nbr_edges, v_nbr_edges in zip(u_nbrs_edges, v_nbrs_edges)
717
+ ):
718
+ return True
719
+
720
+ if len(T1.intersection(G1_nbh)) != len(T2.intersection(G2_nbh)):
721
+ return True
722
+ if len(T1_tilde.intersection(G1_nbh)) != len(T2_tilde.intersection(G2_nbh)):
723
+ return True
724
+ if G1.is_directed() and len(T1_in.intersection(G1_nbh)) != len(
725
+ T2_in.intersection(G2_nbh)
726
+ ):
727
+ return True
728
+
729
+ if not G1.is_directed():
730
+ return False
731
+
732
+ for label, G1_pred in u_labels_predecessors.items():
733
+ G2_pred = v_labels_predecessors[label]
734
+
735
+ if G1.is_multigraph():
736
+ # Check for every neighbor in the neighborhood, if u-nbr1 has same edges as v-nbr2
737
+ u_pred_edges = sorted(G1.number_of_edges(u, x) for x in G1_pred)
738
+ v_pred_edges = sorted(G2.number_of_edges(v, x) for x in G2_pred)
739
+ if any(
740
+ u_nbr_edges != v_nbr_edges
741
+ for u_nbr_edges, v_nbr_edges in zip(u_pred_edges, v_pred_edges)
742
+ ):
743
+ return True
744
+
745
+ if len(T1.intersection(G1_pred)) != len(T2.intersection(G2_pred)):
746
+ return True
747
+ if len(T1_tilde.intersection(G1_pred)) != len(T2_tilde.intersection(G2_pred)):
748
+ return True
749
+ if len(T1_in.intersection(G1_pred)) != len(T2_in.intersection(G2_pred)):
750
+ return True
751
+
752
+ return False
753
+
754
+
755
+ def _consistent_PT(u, v, graph_params, state_params):
756
+ """Checks the consistency of extending the mapping using the current node pair.
757
+
758
+ Parameters
759
+ ----------
760
+ u, v: Graph node
761
+ The two candidate nodes being examined.
762
+
763
+ graph_params: namedtuple
764
+ Contains all the Graph-related parameters:
765
+
766
+ G1,G2: NetworkX Graph or MultiGraph instances.
767
+ The two graphs to check for isomorphism or monomorphism
768
+
769
+ G1_labels,G2_labels: dict
770
+ The label of every node in G1 and G2 respectively
771
+
772
+ state_params: namedtuple
773
+ Contains all the State-related parameters:
774
+
775
+ mapping: dict
776
+ The mapping as extended so far. Maps nodes of G1 to nodes of G2
777
+
778
+ reverse_mapping: dict
779
+ The reverse mapping as extended so far. Maps nodes from G2 to nodes of G1.
780
+ It's basically "mapping" reversed
781
+
782
+ T1, T2: set
783
+ Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes
784
+ that are not in the mapping, but are neighbors of nodes that are.
785
+
786
+ T1_out, T2_out: set
787
+ Ti_out contains all the nodes from Gi, that are neither in the mapping
788
+ nor in Ti
789
+
790
+ Returns
791
+ -------
792
+ True if the pair passes all the consistency checks successfully. False otherwise.
793
+ """
794
+ G1, G2 = graph_params.G1, graph_params.G2
795
+ mapping, reverse_mapping = state_params.mapping, state_params.reverse_mapping
796
+
797
+ for neighbor in G1[u]:
798
+ if neighbor in mapping:
799
+ if G1.number_of_edges(u, neighbor) != G2.number_of_edges(
800
+ v, mapping[neighbor]
801
+ ):
802
+ return False
803
+
804
+ for neighbor in G2[v]:
805
+ if neighbor in reverse_mapping:
806
+ if G1.number_of_edges(u, reverse_mapping[neighbor]) != G2.number_of_edges(
807
+ v, neighbor
808
+ ):
809
+ return False
810
+
811
+ if not G1.is_directed():
812
+ return True
813
+
814
+ for predecessor in G1.pred[u]:
815
+ if predecessor in mapping:
816
+ if G1.number_of_edges(predecessor, u) != G2.number_of_edges(
817
+ mapping[predecessor], v
818
+ ):
819
+ return False
820
+
821
+ for predecessor in G2.pred[v]:
822
+ if predecessor in reverse_mapping:
823
+ if G1.number_of_edges(
824
+ reverse_mapping[predecessor], u
825
+ ) != G2.number_of_edges(predecessor, v):
826
+ return False
827
+
828
+ return True
829
+
830
+
831
+ def _update_Tinout(new_node1, new_node2, graph_params, state_params):
832
+ """Updates the Ti/Ti_out (i=1,2) when a new node pair u-v is added to the mapping.
833
+
834
+ Notes
835
+ -----
836
+ This function should be called right after the feasibility checks are passed,
837
+ and node1 is mapped to node2. The purpose of this function is to avoid brute
838
+ force computing of Ti/Ti_out by iterating over all nodes of the graph and
839
+ checking which nodes satisfy the necessary conditions. Instead, in every step
840
+ of the algorithm we focus exclusively on the two nodes that are being added
841
+ to the mapping, incrementally updating Ti/Ti_out.
842
+
843
+ Parameters
844
+ ----------
845
+ new_node1, new_node2: Graph node
846
+ The two new nodes, added to the mapping.
847
+
848
+ graph_params: namedtuple
849
+ Contains all the Graph-related parameters:
850
+
851
+ G1,G2: NetworkX Graph or MultiGraph instances.
852
+ The two graphs to check for isomorphism or monomorphism
853
+
854
+ G1_labels,G2_labels: dict
855
+ The label of every node in G1 and G2 respectively
856
+
857
+ state_params: namedtuple
858
+ Contains all the State-related parameters:
859
+
860
+ mapping: dict
861
+ The mapping as extended so far. Maps nodes of G1 to nodes of G2
862
+
863
+ reverse_mapping: dict
864
+ The reverse mapping as extended so far. Maps nodes from G2 to nodes of G1.
865
+ It's basically "mapping" reversed
866
+
867
+ T1, T2: set
868
+ Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes
869
+ that are not in the mapping, but are neighbors of nodes that are.
870
+
871
+ T1_tilde, T2_tilde: set
872
+ Ti_out contains all the nodes from Gi, that are neither in the mapping nor in Ti
873
+ """
874
+ G1, G2, _, _, _, _, _ = graph_params
875
+ (
876
+ mapping,
877
+ reverse_mapping,
878
+ T1,
879
+ T1_in,
880
+ T1_tilde,
881
+ T1_tilde_in,
882
+ T2,
883
+ T2_in,
884
+ T2_tilde,
885
+ T2_tilde_in,
886
+ ) = state_params
887
+
888
+ uncovered_successors_G1 = {succ for succ in G1[new_node1] if succ not in mapping}
889
+ uncovered_successors_G2 = {
890
+ succ for succ in G2[new_node2] if succ not in reverse_mapping
891
+ }
892
+
893
+ # Add the uncovered neighbors of node1 and node2 in T1 and T2 respectively
894
+ T1.update(uncovered_successors_G1)
895
+ T2.update(uncovered_successors_G2)
896
+ T1.discard(new_node1)
897
+ T2.discard(new_node2)
898
+
899
+ T1_tilde.difference_update(uncovered_successors_G1)
900
+ T2_tilde.difference_update(uncovered_successors_G2)
901
+ T1_tilde.discard(new_node1)
902
+ T2_tilde.discard(new_node2)
903
+
904
+ if not G1.is_directed():
905
+ return
906
+
907
+ uncovered_predecessors_G1 = {
908
+ pred for pred in G1.pred[new_node1] if pred not in mapping
909
+ }
910
+ uncovered_predecessors_G2 = {
911
+ pred for pred in G2.pred[new_node2] if pred not in reverse_mapping
912
+ }
913
+
914
+ T1_in.update(uncovered_predecessors_G1)
915
+ T2_in.update(uncovered_predecessors_G2)
916
+ T1_in.discard(new_node1)
917
+ T2_in.discard(new_node2)
918
+
919
+ T1_tilde.difference_update(uncovered_predecessors_G1)
920
+ T2_tilde.difference_update(uncovered_predecessors_G2)
921
+ T1_tilde.discard(new_node1)
922
+ T2_tilde.discard(new_node2)
923
+
924
+
925
+ def _restore_Tinout(popped_node1, popped_node2, graph_params, state_params):
926
+ """Restores the previous version of Ti/Ti_out when a node pair is deleted
927
+ from the mapping.
928
+
929
+ Parameters
930
+ ----------
931
+ popped_node1, popped_node2: Graph node
932
+ The two nodes deleted from the mapping.
933
+
934
+ graph_params: namedtuple
935
+ Contains all the Graph-related parameters:
936
+
937
+ G1,G2: NetworkX Graph or MultiGraph instances.
938
+ The two graphs to check for isomorphism or monomorphism
939
+
940
+ G1_labels,G2_labels: dict
941
+ The label of every node in G1 and G2 respectively
942
+
943
+ state_params: namedtuple
944
+ Contains all the State-related parameters:
945
+
946
+ mapping: dict
947
+ The mapping as extended so far. Maps nodes of G1 to nodes of G2
948
+
949
+ reverse_mapping: dict
950
+ The reverse mapping as extended so far. Maps nodes from G2 to nodes of G1.
951
+ It's basically "mapping" reversed
952
+
953
+ T1, T2: set
954
+ Ti contains uncovered neighbors of covered nodes from Gi, i.e. nodes
955
+ that are not in the mapping, but are neighbors of nodes that are.
956
+
957
+ T1_tilde, T2_tilde: set
958
+ Ti_out contains all the nodes from Gi, that are neither in the mapping
959
+ nor in Ti
960
+ """
961
+ # If the node we want to remove from the mapping, has at least one covered
962
+ # neighbor, add it to T1.
963
+ G1, G2, _, _, _, _, _ = graph_params
964
+ (
965
+ mapping,
966
+ reverse_mapping,
967
+ T1,
968
+ T1_in,
969
+ T1_tilde,
970
+ T1_tilde_in,
971
+ T2,
972
+ T2_in,
973
+ T2_tilde,
974
+ T2_tilde_in,
975
+ ) = state_params
976
+
977
+ is_added = False
978
+ for neighbor in G1[popped_node1]:
979
+ if neighbor in mapping:
980
+ # if a neighbor of the excluded node1 is in the mapping, keep node1 in T1
981
+ is_added = True
982
+ T1.add(popped_node1)
983
+ else:
984
+ # check if its neighbor has another connection with a covered node.
985
+ # If not, only then exclude it from T1
986
+ if any(nbr in mapping for nbr in G1[neighbor]):
987
+ continue
988
+ T1.discard(neighbor)
989
+ T1_tilde.add(neighbor)
990
+
991
+ # Case where the node is not present in neither the mapping nor T1.
992
+ # By definition, it should belong to T1_tilde
993
+ if not is_added:
994
+ T1_tilde.add(popped_node1)
995
+
996
+ is_added = False
997
+ for neighbor in G2[popped_node2]:
998
+ if neighbor in reverse_mapping:
999
+ is_added = True
1000
+ T2.add(popped_node2)
1001
+ else:
1002
+ if any(nbr in reverse_mapping for nbr in G2[neighbor]):
1003
+ continue
1004
+ T2.discard(neighbor)
1005
+ T2_tilde.add(neighbor)
1006
+
1007
+ if not is_added:
1008
+ T2_tilde.add(popped_node2)
1009
+
1010
+
1011
+ def _restore_Tinout_Di(popped_node1, popped_node2, graph_params, state_params):
1012
+ # If the node we want to remove from the mapping, has at least one covered neighbor, add it to T1.
1013
+ G1, G2, _, _, _, _, _ = graph_params
1014
+ (
1015
+ mapping,
1016
+ reverse_mapping,
1017
+ T1,
1018
+ T1_in,
1019
+ T1_tilde,
1020
+ T1_tilde_in,
1021
+ T2,
1022
+ T2_in,
1023
+ T2_tilde,
1024
+ T2_tilde_in,
1025
+ ) = state_params
1026
+
1027
+ is_added = False
1028
+ for successor in G1[popped_node1]:
1029
+ if successor in mapping:
1030
+ # if a neighbor of the excluded node1 is in the mapping, keep node1 in T1
1031
+ is_added = True
1032
+ T1_in.add(popped_node1)
1033
+ else:
1034
+ # check if its neighbor has another connection with a covered node.
1035
+ # If not, only then exclude it from T1
1036
+ if not any(pred in mapping for pred in G1.pred[successor]):
1037
+ T1.discard(successor)
1038
+
1039
+ if not any(succ in mapping for succ in G1[successor]):
1040
+ T1_in.discard(successor)
1041
+
1042
+ if successor not in T1:
1043
+ if successor not in T1_in:
1044
+ T1_tilde.add(successor)
1045
+
1046
+ for predecessor in G1.pred[popped_node1]:
1047
+ if predecessor in mapping:
1048
+ # if a neighbor of the excluded node1 is in the mapping, keep node1 in T1
1049
+ is_added = True
1050
+ T1.add(popped_node1)
1051
+ else:
1052
+ # check if its neighbor has another connection with a covered node.
1053
+ # If not, only then exclude it from T1
1054
+ if not any(pred in mapping for pred in G1.pred[predecessor]):
1055
+ T1.discard(predecessor)
1056
+
1057
+ if not any(succ in mapping for succ in G1[predecessor]):
1058
+ T1_in.discard(predecessor)
1059
+
1060
+ if not (predecessor in T1 or predecessor in T1_in):
1061
+ T1_tilde.add(predecessor)
1062
+
1063
+ # Case where the node is not present in neither the mapping nor T1.
1064
+ # By definition it should belong to T1_tilde
1065
+ if not is_added:
1066
+ T1_tilde.add(popped_node1)
1067
+
1068
+ is_added = False
1069
+ for successor in G2[popped_node2]:
1070
+ if successor in reverse_mapping:
1071
+ is_added = True
1072
+ T2_in.add(popped_node2)
1073
+ else:
1074
+ if not any(pred in reverse_mapping for pred in G2.pred[successor]):
1075
+ T2.discard(successor)
1076
+
1077
+ if not any(succ in reverse_mapping for succ in G2[successor]):
1078
+ T2_in.discard(successor)
1079
+
1080
+ if successor not in T2:
1081
+ if successor not in T2_in:
1082
+ T2_tilde.add(successor)
1083
+
1084
+ for predecessor in G2.pred[popped_node2]:
1085
+ if predecessor in reverse_mapping:
1086
+ # if a neighbor of the excluded node1 is in the mapping, keep node1 in T1
1087
+ is_added = True
1088
+ T2.add(popped_node2)
1089
+ else:
1090
+ # check if its neighbor has another connection with a covered node.
1091
+ # If not, only then exclude it from T1
1092
+ if not any(pred in reverse_mapping for pred in G2.pred[predecessor]):
1093
+ T2.discard(predecessor)
1094
+
1095
+ if not any(succ in reverse_mapping for succ in G2[predecessor]):
1096
+ T2_in.discard(predecessor)
1097
+
1098
+ if not (predecessor in T2 or predecessor in T2_in):
1099
+ T2_tilde.add(predecessor)
1100
+
1101
+ if not is_added:
1102
+ T2_tilde.add(popped_node2)