synkit 1.6.5__py3-none-win_amd64.whl

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 (636) hide show
  1. synkit/CRN/Benchmark/__init__.py +53 -0
  2. synkit/CRN/Benchmark/crosschecks.py +13 -0
  3. synkit/CRN/Benchmark/kegg.py +12 -0
  4. synkit/CRN/Benchmark/networks.py +13 -0
  5. synkit/CRN/Benchmark/scaling.py +13 -0
  6. synkit/CRN/Benchmark/validate.py +13 -0
  7. synkit/CRN/Construct/__init__.py +16 -0
  8. synkit/CRN/Construct/abstract.py +668 -0
  9. synkit/CRN/Construct/arity.py +36 -0
  10. synkit/CRN/Construct/builder.py +619 -0
  11. synkit/CRN/Construct/derivation.py +63 -0
  12. synkit/CRN/Construct/flattener.py +100 -0
  13. synkit/CRN/Construct/keys.py +14 -0
  14. synkit/CRN/Construct/mixtures.py +117 -0
  15. synkit/CRN/Construct/rdkit_worker.py +69 -0
  16. synkit/CRN/Construct/smiles.py +99 -0
  17. synkit/CRN/Construct/state.py +31 -0
  18. synkit/CRN/Construct/strategy.py +75 -0
  19. synkit/CRN/Construct/worker.py +42 -0
  20. synkit/CRN/IO/__init__.py +36 -0
  21. synkit/CRN/IO/sbml.py +925 -0
  22. synkit/CRN/Pathway/__init__.py +72 -0
  23. synkit/CRN/Pathway/_adapter.py +333 -0
  24. synkit/CRN/Pathway/pathfinder.py +500 -0
  25. synkit/CRN/Pathway/reachability.py +796 -0
  26. synkit/CRN/Pathway/realizability.py +1322 -0
  27. synkit/CRN/Petrinet/__init__.py +93 -0
  28. synkit/CRN/Petrinet/analyzer.py +486 -0
  29. synkit/CRN/Petrinet/minimal_semiflows.py +436 -0
  30. synkit/CRN/Petrinet/net.py +1041 -0
  31. synkit/CRN/Petrinet/persistence.py +97 -0
  32. synkit/CRN/Petrinet/semiflows.py +483 -0
  33. synkit/CRN/Petrinet/siphon_search.py +402 -0
  34. synkit/CRN/Petrinet/structure.py +286 -0
  35. synkit/CRN/Props/__init__.py +130 -0
  36. synkit/CRN/Props/_rank.py +29 -0
  37. synkit/CRN/Props/deficiency.py +953 -0
  38. synkit/CRN/Props/dynamics.py +832 -0
  39. synkit/CRN/Props/helper.py +151 -0
  40. synkit/CRN/Props/stoich.py +751 -0
  41. synkit/CRN/Props/thermo.py +584 -0
  42. synkit/CRN/Query/__init__.py +66 -0
  43. synkit/CRN/Query/cache.py +41 -0
  44. synkit/CRN/Query/kegg_api.py +99 -0
  45. synkit/CRN/Query/kegg_extract.py +714 -0
  46. synkit/CRN/Query/kegg_impute.py +707 -0
  47. synkit/CRN/Query/kegg_parse.py +480 -0
  48. synkit/CRN/Query/to_syncrn.py +290 -0
  49. synkit/CRN/README.md +234 -0
  50. synkit/CRN/Structure/__init__.py +12 -0
  51. synkit/CRN/Structure/_graph_io.py +713 -0
  52. synkit/CRN/Structure/_matrices.py +88 -0
  53. synkit/CRN/Structure/_parse.py +544 -0
  54. synkit/CRN/Structure/reaction.py +237 -0
  55. synkit/CRN/Structure/rule.py +55 -0
  56. synkit/CRN/Structure/species.py +46 -0
  57. synkit/CRN/Structure/syncrn.py +929 -0
  58. synkit/CRN/Symmetry/__init__.py +20 -0
  59. synkit/CRN/Symmetry/_common.py +1059 -0
  60. synkit/CRN/Symmetry/_ir.py +940 -0
  61. synkit/CRN/Symmetry/automorphism.py +472 -0
  62. synkit/CRN/Symmetry/canon.py +441 -0
  63. synkit/CRN/Symmetry/isomorphism.py +412 -0
  64. synkit/CRN/Symmetry/symmetry.py +61 -0
  65. synkit/CRN/Symmetry/wl_canon.py +967 -0
  66. synkit/CRN/Visualize/__init__.py +11 -0
  67. synkit/CRN/Visualize/labels.py +113 -0
  68. synkit/CRN/Visualize/layout.py +708 -0
  69. synkit/CRN/Visualize/palette.py +292 -0
  70. synkit/CRN/Visualize/validation.py +122 -0
  71. synkit/CRN/Visualize/vis.py +1152 -0
  72. synkit/CRN/__init__.py +233 -0
  73. synkit/CRN/_build.py +50 -0
  74. synkit/CRN/_native_build.py +175 -0
  75. synkit/CRN/analysis.py +629 -0
  76. synkit/CRN/backend.py +74 -0
  77. synkit/CRN/cpp/CMakeLists.txt +58 -0
  78. synkit/CRN/cpp/algebra.cpp +46 -0
  79. synkit/CRN/cpp/closure.cpp +29 -0
  80. synkit/CRN/cpp/exact.h +55 -0
  81. synkit/CRN/cpp/pathway.cpp +46 -0
  82. synkit/CRN/cpp/semiflows.cpp +209 -0
  83. synkit/CRN/cpp/structural.cpp +240 -0
  84. synkit/CRN/cpp/symmetry.cpp +45 -0
  85. synkit/CRN/cpp/write_manifest.cmake +28 -0
  86. synkit/CRN/kinds.py +137 -0
  87. synkit/CRN/lib/synkit_crn.dll +0 -0
  88. synkit/CRN/lib/synkit_crn.json +33 -0
  89. synkit/CRN/native.py +388 -0
  90. synkit/CRN/native_analysis.py +459 -0
  91. synkit/Chem/Cluster/__init__.py +0 -0
  92. synkit/Chem/Cluster/butina.py +140 -0
  93. synkit/Chem/Fingerprint/__init__.py +0 -0
  94. synkit/Chem/Fingerprint/fp_calculator.py +155 -0
  95. synkit/Chem/Fingerprint/smiles_featurizer.py +258 -0
  96. synkit/Chem/Fingerprint/transformation_fp.py +139 -0
  97. synkit/Chem/Mapper/README.rst +43 -0
  98. synkit/Chem/Mapper/__init__.py +255 -0
  99. synkit/Chem/Mapper/_compat.py +130 -0
  100. synkit/Chem/Mapper/adapters/__init__.py +1 -0
  101. synkit/Chem/Mapper/adapters/prediction.py +126 -0
  102. synkit/Chem/Mapper/adapters/template.py +412 -0
  103. synkit/Chem/Mapper/chem/__init__.py +52 -0
  104. synkit/Chem/Mapper/chem/aam.py +673 -0
  105. synkit/Chem/Mapper/chem/blind.py +160 -0
  106. synkit/Chem/Mapper/chem/its.py +309 -0
  107. synkit/Chem/Mapper/chem/smiles.py +564 -0
  108. synkit/Chem/Mapper/graph/__init__.py +66 -0
  109. synkit/Chem/Mapper/graph/automorphism.py +395 -0
  110. synkit/Chem/Mapper/graph/blockcut.py +98 -0
  111. synkit/Chem/Mapper/graph/labeled_graph.py +104 -0
  112. synkit/Chem/Mapper/graph/refine.py +176 -0
  113. synkit/Chem/Mapper/graph/synkit_adapter.py +110 -0
  114. synkit/Chem/Mapper/io/__init__.py +13 -0
  115. synkit/Chem/Mapper/io/idxmapstr.py +82 -0
  116. synkit/Chem/Mapper/mapper.py +685 -0
  117. synkit/Chem/Mapper/reaction_search.py +554 -0
  118. synkit/Chem/Mapper/reporting/__init__.py +1 -0
  119. synkit/Chem/Mapper/reporting/alternatives.py +451 -0
  120. synkit/Chem/Mapper/reporting/analysis.py +681 -0
  121. synkit/Chem/Mapper/reporting/native_analysis.py +485 -0
  122. synkit/Chem/Mapper/reporting/spectrum.py +642 -0
  123. synkit/Chem/Mapper/solvers/__init__.py +1 -0
  124. synkit/Chem/Mapper/solvers/exact/__init__.py +141 -0
  125. synkit/Chem/Mapper/solvers/exact/assignment/__init__.py +1 -0
  126. synkit/Chem/Mapper/solvers/exact/assignment/assignment_certificate.py +113 -0
  127. synkit/Chem/Mapper/solvers/exact/assignment/assignment_domains.py +162 -0
  128. synkit/Chem/Mapper/solvers/exact/assignment/assignment_verification.py +58 -0
  129. synkit/Chem/Mapper/solvers/exact/assignment/incremental_assignment.py +247 -0
  130. synkit/Chem/Mapper/solvers/exact/certificate.py +128 -0
  131. synkit/Chem/Mapper/solvers/exact/core.py +183 -0
  132. synkit/Chem/Mapper/solvers/exact/distance_search/__init__.py +1 -0
  133. synkit/Chem/Mapper/solvers/exact/distance_search/bounds.py +319 -0
  134. synkit/Chem/Mapper/solvers/exact/distance_search/exhaustive.py +179 -0
  135. synkit/Chem/Mapper/solvers/exact/distance_search/inputs.py +283 -0
  136. synkit/Chem/Mapper/solvers/exact/distance_search/records.py +242 -0
  137. synkit/Chem/Mapper/solvers/exact/distance_search/search.py +1025 -0
  138. synkit/Chem/Mapper/solvers/exact/distance_search/verify.py +378 -0
  139. synkit/Chem/Mapper/solvers/exact/edit_support.py +375 -0
  140. synkit/Chem/Mapper/solvers/exact/hybrid.py +224 -0
  141. synkit/Chem/Mapper/solvers/exact/hydrogen.py +264 -0
  142. synkit/Chem/Mapper/solvers/exact/kernel_solvers/__init__.py +1 -0
  143. synkit/Chem/Mapper/solvers/exact/kernel_solvers/branching.py +499 -0
  144. synkit/Chem/Mapper/solvers/exact/kernel_solvers/enumerate.py +1050 -0
  145. synkit/Chem/Mapper/solvers/exact/kernel_solvers/enumeration_result.py +30 -0
  146. synkit/Chem/Mapper/solvers/exact/kernel_solvers/kernel.py +256 -0
  147. synkit/Chem/Mapper/solvers/exact/kernel_solvers/milp.py +194 -0
  148. synkit/Chem/Mapper/solvers/exact/native/__init__.py +1 -0
  149. synkit/Chem/Mapper/solvers/exact/native/build.py +154 -0
  150. synkit/Chem/Mapper/solvers/exact/native/candidates.py +593 -0
  151. synkit/Chem/Mapper/solvers/exact/native/canonical.py +396 -0
  152. synkit/Chem/Mapper/solvers/exact/native/disk_frontier.py +415 -0
  153. synkit/Chem/Mapper/solvers/exact/native/frontier.py +390 -0
  154. synkit/Chem/Mapper/solvers/exact/native/hydrogen_quotient.py +213 -0
  155. synkit/Chem/Mapper/solvers/exact/native/its.py +528 -0
  156. synkit/Chem/Mapper/solvers/exact/native/native_distance.cpp +2803 -0
  157. synkit/Chem/Mapper/solvers/exact/native/orbit_aggregation.py +328 -0
  158. synkit/Chem/Mapper/solvers/exact/native/parallel.py +205 -0
  159. synkit/Chem/Mapper/solvers/exact/native/pmcd.py +203 -0
  160. synkit/Chem/Mapper/solvers/exact/native/runtime.py +40 -0
  161. synkit/Chem/Mapper/solvers/exact/native/search.py +294 -0
  162. synkit/Chem/Mapper/solvers/exact/native/separator.py +224 -0
  163. synkit/Chem/Mapper/solvers/exact/native_build.py +12 -0
  164. synkit/Chem/Mapper/solvers/exact/pabs/__init__.py +1 -0
  165. synkit/Chem/Mapper/solvers/exact/pabs/cost_lattice.py +43 -0
  166. synkit/Chem/Mapper/solvers/exact/pabs/factor_spectrum.py +110 -0
  167. synkit/Chem/Mapper/solvers/exact/pabs/multi_shell.py +368 -0
  168. synkit/Chem/Mapper/solvers/exact/pabs/propagation.py +679 -0
  169. synkit/Chem/Mapper/solvers/exact/pabs/propagation_bounds.py +436 -0
  170. synkit/Chem/Mapper/solvers/exact/pabs/propagation_limits.py +13 -0
  171. synkit/Chem/Mapper/solvers/exact/pabs/propagation_search.py +856 -0
  172. synkit/Chem/Mapper/solvers/exact/pabs/propagation_symmetry.py +66 -0
  173. synkit/Chem/Mapper/solvers/exact/pabs/residual_typed_bonds.py +136 -0
  174. synkit/Chem/Mapper/solvers/exact/pabs/reward_frontier.py +201 -0
  175. synkit/Chem/Mapper/solvers/exact/pabs/separator_bound.py +258 -0
  176. synkit/Chem/Mapper/solvers/exact/pabs/separator_spectrum.py +308 -0
  177. synkit/Chem/Mapper/solvers/exact/pabs/sparse_reward_bound.py +207 -0
  178. synkit/Chem/Mapper/solvers/exact/pabs/suffix_spectrum.py +299 -0
  179. synkit/Chem/Mapper/solvers/exact/search.py +55 -0
  180. synkit/Chem/Mapper/solvers/exact/seeds/__init__.py +1 -0
  181. synkit/Chem/Mapper/solvers/exact/seeds/seed.py +104 -0
  182. synkit/Chem/Mapper/solvers/exact/seeds/seed_fragments.py +148 -0
  183. synkit/Chem/Mapper/solvers/exact/seeds/seed_relaxation.py +181 -0
  184. synkit/Chem/Mapper/solvers/exact/symmetry.py +223 -0
  185. synkit/Chem/Mapper/solvers/native/__init__.py +4 -0
  186. synkit/Chem/Mapper/solvers/native/assignment.py +99 -0
  187. synkit/Chem/Mapper/solvers/native/astar.py +22 -0
  188. synkit/Chem/Mapper/solvers/native/build.py +385 -0
  189. synkit/Chem/Mapper/solvers/native/classification.py +641 -0
  190. synkit/Chem/Mapper/solvers/native/core.py +378 -0
  191. synkit/Chem/Mapper/solvers/native/cpp/CMakeLists.txt +120 -0
  192. synkit/Chem/Mapper/solvers/native/cpp/examples/map_reaction.cpp +29 -0
  193. synkit/Chem/Mapper/solvers/native/cpp/examples/slap_graph.cpp +63 -0
  194. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/assignment/assignment.h +18 -0
  195. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/astar/astar.h +18 -0
  196. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/astar/bound.h +33 -0
  197. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/core/pmcd_witness.h +16 -0
  198. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/core/runtime.h +130 -0
  199. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/hydrogen/hydrogen.h +73 -0
  200. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/mapper.h +175 -0
  201. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/mces/mces.h +9 -0
  202. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/pabs/seed.h +34 -0
  203. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/reaction/reaction.h +30 -0
  204. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/sepdp/sepdp.h +21 -0
  205. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/slap.h +72 -0
  206. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/solvers/solvers.h +16 -0
  207. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/symmetry/classification.h +140 -0
  208. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/symmetry/cpabs.h +33 -0
  209. synkit/Chem/Mapper/solvers/native/cpp/src/assignment/abb.cpp +302 -0
  210. synkit/Chem/Mapper/solvers/native/cpp/src/astar/CMakeLists.txt +12 -0
  211. synkit/Chem/Mapper/solvers/native/cpp/src/astar/README.md +47 -0
  212. synkit/Chem/Mapper/solvers/native/cpp/src/astar/astar.cpp +228 -0
  213. synkit/Chem/Mapper/solvers/native/cpp/src/astar/astar_graph.cpp +37 -0
  214. synkit/Chem/Mapper/solvers/native/cpp/src/astar/bound.cpp +212 -0
  215. synkit/Chem/Mapper/solvers/native/cpp/src/core/dispatch.cpp +272 -0
  216. synkit/Chem/Mapper/solvers/native/cpp/src/core/pmcd_witness.cpp +36 -0
  217. synkit/Chem/Mapper/solvers/native/cpp/src/hydrogen/hydrogen.cpp +380 -0
  218. synkit/Chem/Mapper/solvers/native/cpp/src/mces/README.md +57 -0
  219. synkit/Chem/Mapper/solvers/native/cpp/src/mces/mces.cpp +287 -0
  220. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/bridge.cpp +334 -0
  221. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/chemical_floor.inc +181 -0
  222. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/endpoint_symmetry.inc +104 -0
  223. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/exact_helpers.h +20 -0
  224. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_assignment_certificate.h +165 -0
  225. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_certificate.h +125 -0
  226. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_model.h +365 -0
  227. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_provider.inc +319 -0
  228. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_rounding.inc +170 -0
  229. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_test_hooks.h +342 -0
  230. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/objective_reduction.inc +137 -0
  231. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/overlap_dual.inc +351 -0
  232. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/profile_seed.inc +214 -0
  233. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/seed_heuristics.inc +640 -0
  234. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/sparse_embedding.cpp +430 -0
  235. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/sparse_root_lp.h +176 -0
  236. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/test_hooks.inc +262 -0
  237. synkit/Chem/Mapper/solvers/native/cpp/src/reaction/reaction.cpp +611 -0
  238. synkit/Chem/Mapper/solvers/native/cpp/src/sepdp/README.md +61 -0
  239. synkit/Chem/Mapper/solvers/native/cpp/src/sepdp/sepdp.cpp +253 -0
  240. synkit/Chem/Mapper/solvers/native/cpp/src/slap.cpp +810 -0
  241. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/formulation.h +138 -0
  242. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/maxsat.cpp +526 -0
  243. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/ortools.cpp +475 -0
  244. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/seed.h +80 -0
  245. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/weighted_cnf.h +256 -0
  246. synkit/Chem/Mapper/solvers/native/cpp/src/supporting/README.md +43 -0
  247. synkit/Chem/Mapper/solvers/native/cpp/src/supporting/dfs.cpp +123 -0
  248. synkit/Chem/Mapper/solvers/native/cpp/src/supporting/edit_support.cpp +224 -0
  249. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification.cpp +553 -0
  250. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification_pipeline.cpp +124 -0
  251. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification_stream.h +13 -0
  252. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/cpabs.cpp +455 -0
  253. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/edge_deck.cpp +743 -0
  254. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/COPYRIGHT +44 -0
  255. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/LICENSE-2.0.txt +202 -0
  256. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naugraph.c +732 -0
  257. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naurng.c +94 -0
  258. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naurng.h +49 -0
  259. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nausparse.c +1771 -0
  260. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nausparse.h +133 -0
  261. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nautil.c +750 -0
  262. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naututil.h +355 -0
  263. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nauty.c +1256 -0
  264. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nauty.h +1544 -0
  265. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/schreier.c +1131 -0
  266. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/schreier.h +70 -0
  267. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/sorttemplates.c +580 -0
  268. synkit/Chem/Mapper/solvers/native/hydrogen.py +711 -0
  269. synkit/Chem/Mapper/solvers/native/implicit.py +506 -0
  270. synkit/Chem/Mapper/solvers/native/implicit_certificate.py +187 -0
  271. synkit/Chem/Mapper/solvers/native/implicit_preparation.py +309 -0
  272. synkit/Chem/Mapper/solvers/native/lib/synkit_mapper.dll +0 -0
  273. synkit/Chem/Mapper/solvers/native/mces.py +16 -0
  274. synkit/Chem/Mapper/solvers/native/reaction.py +179 -0
  275. synkit/Chem/Mapper/solvers/native/reaction_build.py +277 -0
  276. synkit/Chem/Mapper/solvers/native/reaction_text.py +26 -0
  277. synkit/Chem/Mapper/solvers/native/runtime.py +242 -0
  278. synkit/Chem/Mapper/solvers/native/sepdp.py +47 -0
  279. synkit/Chem/Mapper/solvers/native/slap.py +266 -0
  280. synkit/Chem/Mapper/solvers/native/solvers.py +67 -0
  281. synkit/Chem/Mapper/solvers/native/stereo.py +86 -0
  282. synkit/Chem/Mapper/solvers/native/supporting.py +34 -0
  283. synkit/Chem/Mapper/solvers/native/symmetry.py +91 -0
  284. synkit/Chem/Mapper/solvers/slap/__init__.py +29 -0
  285. synkit/Chem/Mapper/solvers/slap/lap.py +174 -0
  286. synkit/Chem/Mapper/solvers/slap/sequential.py +696 -0
  287. synkit/Chem/Mapper/validation/__init__.py +1 -0
  288. synkit/Chem/Mapper/validation/aam_validator.py +442 -0
  289. synkit/Chem/Mapper/validation/annotations.py +274 -0
  290. synkit/Chem/Mapper/validation/bonds.py +124 -0
  291. synkit/Chem/Mapper/validation/cohorts.py +72 -0
  292. synkit/Chem/Mapper/validation/identifiability.py +150 -0
  293. synkit/Chem/Mapper/validation/numerical_scope.py +36 -0
  294. synkit/Chem/Mapper/validation/orbits.py +137 -0
  295. synkit/Chem/Molecule/__init__.py +0 -0
  296. synkit/Chem/Molecule/_chirality_loci.py +165 -0
  297. synkit/Chem/Molecule/_chirality_types.py +231 -0
  298. synkit/Chem/Molecule/_helical_loci.py +167 -0
  299. synkit/Chem/Molecule/_stereo_axis_evidence.py +202 -0
  300. synkit/Chem/Molecule/_stereo_element_detection.py +193 -0
  301. synkit/Chem/Molecule/_stereo_orientation_constraints.py +511 -0
  302. synkit/Chem/Molecule/_tetrahedral_carriers.py +63 -0
  303. synkit/Chem/Molecule/atom_features.py +379 -0
  304. synkit/Chem/Molecule/chirality.py +1041 -0
  305. synkit/Chem/Molecule/cip_assignment.py +569 -0
  306. synkit/Chem/Molecule/cip_ranking.py +843 -0
  307. synkit/Chem/Molecule/coordinate_stereo.py +503 -0
  308. synkit/Chem/Molecule/derived_stereo_naming.py +165 -0
  309. synkit/Chem/Molecule/descriptors.py +452 -0
  310. synkit/Chem/Molecule/formula.py +249 -0
  311. synkit/Chem/Molecule/global_stereo.py +175 -0
  312. synkit/Chem/Molecule/graph_annotator.py +300 -0
  313. synkit/Chem/Molecule/standardize.py +817 -0
  314. synkit/Chem/Molecule/stereo_evidence.py +179 -0
  315. synkit/Chem/Molecule/stereo_perception.py +1032 -0
  316. synkit/Chem/Molecule/valence.py +123 -0
  317. synkit/Chem/Reaction/Mapper/__init__.py +44 -0
  318. synkit/Chem/Reaction/__init__.py +20 -0
  319. synkit/Chem/Reaction/aam_validator.py +5 -0
  320. synkit/Chem/Reaction/balance_check.py +138 -0
  321. synkit/Chem/Reaction/canon_rsmi.py +249 -0
  322. synkit/Chem/Reaction/cleaning.py +58 -0
  323. synkit/Chem/Reaction/deionize.py +199 -0
  324. synkit/Chem/Reaction/explicit_h_audit.py +232 -0
  325. synkit/Chem/Reaction/fix_aam.py +64 -0
  326. synkit/Chem/Reaction/neutralize.py +207 -0
  327. synkit/Chem/Reaction/radical_wildcard.py +224 -0
  328. synkit/Chem/Reaction/standardize.py +203 -0
  329. synkit/Chem/Reaction/tautomerize.py +205 -0
  330. synkit/Chem/__init__.py +1 -0
  331. synkit/Chem/utils.py +315 -0
  332. synkit/Data/__init__.py +0 -0
  333. synkit/Data/aldol.json.gz +1 -0
  334. synkit/Data/gen_partial_aam.py +147 -0
  335. synkit/Data/paracetamol.json.gz +1 -0
  336. synkit/Graph/Canon/__init__.py +16 -0
  337. synkit/Graph/Canon/_native/__init__.py +13 -0
  338. synkit/Graph/Canon/_native/build.py +93 -0
  339. synkit/Graph/Canon/_native/lib/synkit_canon.dll +0 -0
  340. synkit/Graph/Canon/_native/prepare.py +49 -0
  341. synkit/Graph/Canon/_native/runtime.py +140 -0
  342. synkit/Graph/Canon/_native/search.py +137 -0
  343. synkit/Graph/Canon/canon_algs.py +228 -0
  344. synkit/Graph/Canon/canon_graph.py +531 -0
  345. synkit/Graph/Canon/cpp/CMakeLists.txt +42 -0
  346. synkit/Graph/Canon/cpp/README.md +123 -0
  347. synkit/Graph/Canon/cpp/examples/canonical_graph.cpp +16 -0
  348. synkit/Graph/Canon/cpp/include/synkit_canon/canon.h +85 -0
  349. synkit/Graph/Canon/cpp/src/canonical.cpp +391 -0
  350. synkit/Graph/Canon/cpp/src/symmetry.h +83 -0
  351. synkit/Graph/Canon/cpp/tests/symmetry.cpp +93 -0
  352. synkit/Graph/Canon/exact.py +1020 -0
  353. synkit/Graph/Canon/exact_refinement.py +368 -0
  354. synkit/Graph/Canon/nauty.py +143 -0
  355. synkit/Graph/Context/__init__.py +0 -0
  356. synkit/Graph/Context/hier_context.py +244 -0
  357. synkit/Graph/Context/radius_expand.py +252 -0
  358. synkit/Graph/FG/__init__.py +19 -0
  359. synkit/Graph/FG/api.py +39 -0
  360. synkit/Graph/FG/audit.py +155 -0
  361. synkit/Graph/FG/catalog.py +919 -0
  362. synkit/Graph/FG/detector.py +288 -0
  363. synkit/Graph/FG/model.py +97 -0
  364. synkit/Graph/FG/recognizers.py +274 -0
  365. synkit/Graph/FG/ring_system.py +154 -0
  366. synkit/Graph/Feature/Descriptors/topology.py +857 -0
  367. synkit/Graph/Feature/Fingerprint/__init__.py +0 -0
  368. synkit/Graph/Feature/Fingerprint/wl_rxn_fps.py +222 -0
  369. synkit/Graph/Feature/__init__.py +5 -0
  370. synkit/Graph/Feature/graph_descriptors.py +323 -0
  371. synkit/Graph/Feature/graph_fps.py +96 -0
  372. synkit/Graph/Feature/graph_signature.py +239 -0
  373. synkit/Graph/Feature/hash_fps.py +133 -0
  374. synkit/Graph/Feature/morgan_fps.py +88 -0
  375. synkit/Graph/Feature/path_fps.py +81 -0
  376. synkit/Graph/Feature/wl_hash.py +134 -0
  377. synkit/Graph/Fusion/__init__.py +85 -0
  378. synkit/Graph/Fusion/candidate.py +559 -0
  379. synkit/Graph/Fusion/constructor.py +877 -0
  380. synkit/Graph/Fusion/identity.py +184 -0
  381. synkit/Graph/Fusion/interface.py +700 -0
  382. synkit/Graph/Fusion/search.py +241 -0
  383. synkit/Graph/Hyrogen/__init__.py +6 -0
  384. synkit/Graph/Hyrogen/_misc.py +591 -0
  385. synkit/Graph/Hyrogen/hcomplete.py +995 -0
  386. synkit/Graph/Hyrogen/hcomplete_legacy.py +368 -0
  387. synkit/Graph/Hyrogen/hcompletion_algorithms.py +713 -0
  388. synkit/Graph/Hyrogen/hextend.py +570 -0
  389. synkit/Graph/Hyrogen/hextend_legacy.py +215 -0
  390. synkit/Graph/ITS/__init__.py +4 -0
  391. synkit/Graph/ITS/its_builder.py +120 -0
  392. synkit/Graph/ITS/its_construction.py +719 -0
  393. synkit/Graph/ITS/its_decompose.py +572 -0
  394. synkit/Graph/ITS/its_destruction.py +331 -0
  395. synkit/Graph/ITS/its_expand.py +1251 -0
  396. synkit/Graph/ITS/its_relabel.py +187 -0
  397. synkit/Graph/ITS/its_reverter.py +356 -0
  398. synkit/Graph/ITS/normalize_aam.py +145 -0
  399. synkit/Graph/ITS/partial_its.py +238 -0
  400. synkit/Graph/ITS/rc_extractor.py +656 -0
  401. synkit/Graph/ITS/stereo.py +74 -0
  402. synkit/Graph/MTG/__init__.py +107 -0
  403. synkit/Graph/MTG/gluing.py +451 -0
  404. synkit/Graph/MTG/history.py +928 -0
  405. synkit/Graph/MTG/inventory.py +118 -0
  406. synkit/Graph/MTG/local.py +447 -0
  407. synkit/Graph/MTG/mcs_matcher.py +246 -0
  408. synkit/Graph/MTG/mtg.py +611 -0
  409. synkit/Graph/MTG/mtg_explore.py +74 -0
  410. synkit/Graph/MTG/observation.py +209 -0
  411. synkit/Graph/MTG/process.py +577 -0
  412. synkit/Graph/MTG/queries.py +66 -0
  413. synkit/Graph/MTG/realization.py +95 -0
  414. synkit/Graph/MTG/series_parallel.py +107 -0
  415. synkit/Graph/MTG/utils.py +424 -0
  416. synkit/Graph/Matcher/__init__.py +10 -0
  417. synkit/Graph/Matcher/approx_mcs.py +1264 -0
  418. synkit/Graph/Matcher/auto_est.py +736 -0
  419. synkit/Graph/Matcher/automorphism.py +314 -0
  420. synkit/Graph/Matcher/batch_cluster.py +224 -0
  421. synkit/Graph/Matcher/dedup_matches.py +247 -0
  422. synkit/Graph/Matcher/graph_cluster.py +191 -0
  423. synkit/Graph/Matcher/graph_matcher.py +312 -0
  424. synkit/Graph/Matcher/graph_morphism.py +421 -0
  425. synkit/Graph/Matcher/mcs_matcher.py +804 -0
  426. synkit/Graph/Matcher/multi_turbo_iso.py +186 -0
  427. synkit/Graph/Matcher/orbit.py +284 -0
  428. synkit/Graph/Matcher/partial_matcher.py +694 -0
  429. synkit/Graph/Matcher/sing.py +544 -0
  430. synkit/Graph/Matcher/subgraph_matcher.py +812 -0
  431. synkit/Graph/Matcher/turbo_iso.py +272 -0
  432. synkit/Graph/Matcher/wl_sel.py +537 -0
  433. synkit/Graph/Mech/__init__.py +26 -0
  434. synkit/Graph/Mech/conversion.py +1466 -0
  435. synkit/Graph/Mech/conversion_debug.py +237 -0
  436. synkit/Graph/Mech/electron_accounting.py +200 -0
  437. synkit/Graph/Mech/lwg_editor.py +406 -0
  438. synkit/Graph/Mech/lwg_ops.py +313 -0
  439. synkit/Graph/Morphism/__init__.py +99 -0
  440. synkit/Graph/Morphism/constraints.py +460 -0
  441. synkit/Graph/Morphism/llg.py +999 -0
  442. synkit/Graph/Morphism/morphism.py +349 -0
  443. synkit/Graph/Morphism/stereo.py +258 -0
  444. synkit/Graph/Morphism/stereo_morphism.py +383 -0
  445. synkit/Graph/Morphism/stereo_morphism_helpers.py +957 -0
  446. synkit/Graph/Morphism/stereo_morphism_types.py +117 -0
  447. synkit/Graph/Stereo/__init__.py +376 -0
  448. synkit/Graph/Stereo/_descriptor_core.py +207 -0
  449. synkit/Graph/Stereo/_descriptor_serialization.py +138 -0
  450. synkit/Graph/Stereo/canonical.py +648 -0
  451. synkit/Graph/Stereo/changes.py +964 -0
  452. synkit/Graph/Stereo/composition.py +391 -0
  453. synkit/Graph/Stereo/configured.py +946 -0
  454. synkit/Graph/Stereo/couplings.py +245 -0
  455. synkit/Graph/Stereo/descriptors.py +1030 -0
  456. synkit/Graph/Stereo/enumeration.py +597 -0
  457. synkit/Graph/Stereo/extended_descriptors.py +406 -0
  458. synkit/Graph/Stereo/global_configured.py +152 -0
  459. synkit/Graph/Stereo/global_stereo.py +304 -0
  460. synkit/Graph/Stereo/identity.py +648 -0
  461. synkit/Graph/Stereo/interchange.py +496 -0
  462. synkit/Graph/Stereo/legacy.py +460 -0
  463. synkit/Graph/Stereo/matching.py +899 -0
  464. synkit/Graph/Stereo/native.py +154 -0
  465. synkit/Graph/Stereo/orbits.py +668 -0
  466. synkit/Graph/Stereo/outcomes.py +99 -0
  467. synkit/Graph/Stereo/pairwise.py +350 -0
  468. synkit/Graph/Stereo/rdkit_adapter.py +662 -0
  469. synkit/Graph/Stereo/rdkit_identity.py +118 -0
  470. synkit/Graph/Stereo/rdkit_resonance.py +140 -0
  471. synkit/Graph/Stereo/reaction_interchange.py +266 -0
  472. synkit/Graph/Stereo/semantics.py +296 -0
  473. synkit/Graph/Stereo/supports.py +257 -0
  474. synkit/Graph/Stereo/wire.py +339 -0
  475. synkit/Graph/Wildcard/__init__.py +0 -0
  476. synkit/Graph/Wildcard/fuse_graph.py +156 -0
  477. synkit/Graph/Wildcard/graph_wc.py +303 -0
  478. synkit/Graph/Wildcard/its_merge.py +857 -0
  479. synkit/Graph/Wildcard/radwc.py +114 -0
  480. synkit/Graph/Wildcard/wc_matcher.py +576 -0
  481. synkit/Graph/Wildcard/wildcard.py +225 -0
  482. synkit/Graph/__init__.py +17 -0
  483. synkit/Graph/canon_graph.py +14 -0
  484. synkit/Graph/syn_graph.py +199 -0
  485. synkit/Graph/utils.py +324 -0
  486. synkit/IO/__init__.py +4 -0
  487. synkit/IO/chem_converter.py +1059 -0
  488. synkit/IO/combinatorial/__init__.py +8 -0
  489. synkit/IO/combinatorial/gml_to_graph.py +223 -0
  490. synkit/IO/combinatorial/graph_to_gml.py +280 -0
  491. synkit/IO/combinatorial/graph_to_smarts.py +186 -0
  492. synkit/IO/combinatorial/smarts_expander.py +147 -0
  493. synkit/IO/combinatorial/smarts_generalizer.py +133 -0
  494. synkit/IO/combinatorial/smarts_to_graph.py +179 -0
  495. synkit/IO/conversion.py +42 -0
  496. synkit/IO/data_io.py +269 -0
  497. synkit/IO/data_process.py +143 -0
  498. synkit/IO/debug.py +73 -0
  499. synkit/IO/gml_to_nx.py +150 -0
  500. synkit/IO/graph_to_mol.py +199 -0
  501. synkit/IO/mol_to_graph.py +1105 -0
  502. synkit/IO/mol_to_graph_chemistry.py +545 -0
  503. synkit/IO/nx_to_gml.py +209 -0
  504. synkit/IO/smiles_to_id.py +123 -0
  505. synkit/Mechanism/__init__.py +151 -0
  506. synkit/Mechanism/adapters.py +136 -0
  507. synkit/Mechanism/audit.py +323 -0
  508. synkit/Mechanism/benchmark.py +638 -0
  509. synkit/Mechanism/compatibility.py +13 -0
  510. synkit/Mechanism/drawing.py +85 -0
  511. synkit/Mechanism/electron_models.py +725 -0
  512. synkit/Mechanism/equivalence.py +521 -0
  513. synkit/Mechanism/evidence.py +262 -0
  514. synkit/Mechanism/interchange.py +141 -0
  515. synkit/Mechanism/model.py +918 -0
  516. synkit/Mechanism/neighbor_stereo.py +312 -0
  517. synkit/Mechanism/radical_data.py +740 -0
  518. synkit/Mechanism/replay.py +986 -0
  519. synkit/Mechanism/schema.py +264 -0
  520. synkit/Mechanism/stereo_state.py +416 -0
  521. synkit/Mechanism/symbols.py +91 -0
  522. synkit/Rule/Apply/__init__.py +35 -0
  523. synkit/Rule/Apply/conditions.py +45 -0
  524. synkit/Rule/Apply/dpo.py +998 -0
  525. synkit/Rule/Apply/rule_matcher.py +218 -0
  526. synkit/Rule/Apply/validation.py +354 -0
  527. synkit/Rule/Compose/__init__.py +106 -0
  528. synkit/Rule/Compose/_identity.py +43 -0
  529. synkit/Rule/Compose/composition.py +976 -0
  530. synkit/Rule/Compose/laws.py +439 -0
  531. synkit/Rule/Compose/search.py +771 -0
  532. synkit/Rule/Compose/synrule.py +170 -0
  533. synkit/Rule/Modify/__init__.py +0 -0
  534. synkit/Rule/Modify/implict_rule.py +56 -0
  535. synkit/Rule/Modify/longest_path.py +92 -0
  536. synkit/Rule/Modify/molecule_rule.py +115 -0
  537. synkit/Rule/Modify/prune_templates.py +78 -0
  538. synkit/Rule/Modify/rule_utils.py +194 -0
  539. synkit/Rule/Modify/strip_rule.py +97 -0
  540. synkit/Rule/__init__.py +28 -0
  541. synkit/Rule/generic_stereo.py +884 -0
  542. synkit/Rule/stereo_identity.py +271 -0
  543. synkit/Rule/syn_rule.py +1090 -0
  544. synkit/Synthesis/MSR/__init__.py +0 -0
  545. synkit/Synthesis/MSR/path_finder.py +239 -0
  546. synkit/Synthesis/Metrics/__init__.py +0 -0
  547. synkit/Synthesis/Metrics/_base.py +52 -0
  548. synkit/Synthesis/Metrics/_plot.py +129 -0
  549. synkit/Synthesis/Metrics/_ranking.py +179 -0
  550. synkit/Synthesis/RBL/__init__.py +80 -0
  551. synkit/Synthesis/RBL/engine.py +1249 -0
  552. synkit/Synthesis/RBL/matching.py +652 -0
  553. synkit/Synthesis/RBL/overlap.py +336 -0
  554. synkit/Synthesis/RBL/pipeline.py +376 -0
  555. synkit/Synthesis/RBL/policy.py +139 -0
  556. synkit/Synthesis/RBL/proof.py +370 -0
  557. synkit/Synthesis/RBL/reaction.py +506 -0
  558. synkit/Synthesis/RBL/state.py +169 -0
  559. synkit/Synthesis/RBL/validation.py +1060 -0
  560. synkit/Synthesis/Reactor/__init__.py +60 -0
  561. synkit/Synthesis/Reactor/core/__init__.py +1 -0
  562. synkit/Synthesis/Reactor/core/engine.py +967 -0
  563. synkit/Synthesis/Reactor/core/product.py +621 -0
  564. synkit/Synthesis/Reactor/core/rewrite.py +561 -0
  565. synkit/Synthesis/Reactor/core/strategy.py +44 -0
  566. synkit/Synthesis/Reactor/matching/__init__.py +1 -0
  567. synkit/Synthesis/Reactor/matching/mixin.py +920 -0
  568. synkit/Synthesis/Reactor/matching/policy.py +345 -0
  569. synkit/Synthesis/Reactor/matching/symmetry.py +309 -0
  570. synkit/Synthesis/Reactor/output/__init__.py +1 -0
  571. synkit/Synthesis/Reactor/output/deduplication.py +703 -0
  572. synkit/Synthesis/Reactor/output/policy.py +16 -0
  573. synkit/Synthesis/Reactor/output/serialization.py +485 -0
  574. synkit/Synthesis/Reactor/output/structural.py +893 -0
  575. synkit/Synthesis/Reactor/stereo/__init__.py +1 -0
  576. synkit/Synthesis/Reactor/stereo/assignment.py +35 -0
  577. synkit/Synthesis/Reactor/stereo/mixin.py +780 -0
  578. synkit/Synthesis/Reactor/variants/__init__.py +1 -0
  579. synkit/Synthesis/Reactor/variants/imbalanced.py +180 -0
  580. synkit/Synthesis/Reactor/variants/partial.py +84 -0
  581. synkit/Synthesis/Reactor/workflow/__init__.py +1 -0
  582. synkit/Synthesis/Reactor/workflow/batch.py +550 -0
  583. synkit/Synthesis/Reactor/workflow/benchmark.py +143 -0
  584. synkit/Synthesis/Reactor/workflow/postprocess.py +267 -0
  585. synkit/Synthesis/Reactor/workflow/rule_filter.py +210 -0
  586. synkit/Synthesis/__init__.py +0 -0
  587. synkit/Synthesis/reactor_utils.py +316 -0
  588. synkit/Utils/__init__.py +0 -0
  589. synkit/Utils/utils.py +172 -0
  590. synkit/Vis/__init__.py +91 -0
  591. synkit/Vis/crn/__init__.py +40 -0
  592. synkit/Vis/epd/__init__.py +20 -0
  593. synkit/Vis/epd/arrows.py +425 -0
  594. synkit/Vis/epd/chem.py +197 -0
  595. synkit/Vis/epd/constants.py +83 -0
  596. synkit/Vis/epd/layout.py +283 -0
  597. synkit/Vis/epd/mapping.py +51 -0
  598. synkit/Vis/epd/models.py +136 -0
  599. synkit/Vis/epd/render.py +543 -0
  600. synkit/Vis/epd/utils.py +108 -0
  601. synkit/Vis/epd/visualizer.py +811 -0
  602. synkit/Vis/graph_visualizer.py +375 -0
  603. synkit/Vis/its/__init__.py +19 -0
  604. synkit/Vis/its/drawer.py +615 -0
  605. synkit/Vis/its_drawer.py +35 -0
  606. synkit/Vis/molecule/__init__.py +31 -0
  607. synkit/Vis/molecule/drawer.py +563 -0
  608. synkit/Vis/molecule/reaction.py +285 -0
  609. synkit/Vis/molecule_drawer.py +33 -0
  610. synkit/Vis/mtg/__init__.py +17 -0
  611. synkit/Vis/mtg/drawer.py +769 -0
  612. synkit/Vis/mtg_drawer.py +34 -0
  613. synkit/Vis/pdf_writer.py +146 -0
  614. synkit/Vis/reaction/__init__.py +19 -0
  615. synkit/Vis/reaction/rule.py +141 -0
  616. synkit/Vis/reaction/rxn.py +532 -0
  617. synkit/Vis/reaction_drawer.py +41 -0
  618. synkit/Vis/space/__init__.py +17 -0
  619. synkit/Vis/space/chemical.py +80 -0
  620. synkit/Vis/space/embedding.py +87 -0
  621. synkit/Vis/vis_synedu/Vis/__init__.py +7 -0
  622. synkit/Vis/vis_synedu/Vis/dpo.py +862 -0
  623. synkit/Vis/vis_synedu/rxn_vis.py +377 -0
  624. synkit/Vis/vis_synedu/vis.py +501 -0
  625. synkit/Vis/visual_drawer.py +215 -0
  626. synkit/Vis/visual_model.py +520 -0
  627. synkit/__init__.py +3 -0
  628. synkit/_native.py +91 -0
  629. synkit/examples.py +50 -0
  630. synkit/version.py +23 -0
  631. synkit-1.6.5.dist-info/METADATA +156 -0
  632. synkit-1.6.5.dist-info/RECORD +636 -0
  633. synkit-1.6.5.dist-info/WHEEL +4 -0
  634. synkit-1.6.5.dist-info/licenses/LICENSE +21 -0
  635. synkit-1.6.5.dist-info/licenses/synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/COPYRIGHT +44 -0
  636. synkit-1.6.5.dist-info/licenses/synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/LICENSE-2.0.txt +202 -0
@@ -0,0 +1,95 @@
1
+ """Realize fixed-carrier material-port histories as coordinate histories."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+
7
+ import networkx as nx
8
+
9
+ from .history import OccurrenceMTG
10
+ from .local import (
11
+ GroundedLocalEvent,
12
+ LocalCoordinateHistory,
13
+ LocalHistoryError,
14
+ build_local_coordinate_history,
15
+ )
16
+
17
+
18
+ def _same_raw_world(first, second):
19
+ return (
20
+ first.schema == second.schema
21
+ and first.node_ids == second.node_ids
22
+ and first.edge_keys == second.edge_keys
23
+ and all(
24
+ first.node_labels(node, semantic=True)
25
+ == second.node_labels(node, semantic=True)
26
+ for node in first.node_ids
27
+ )
28
+ and all(
29
+ first.edge_labels(pair, semantic=True)
30
+ == second.edge_labels(pair, semantic=True)
31
+ for pair in first.edge_keys
32
+ )
33
+ )
34
+
35
+
36
+ @dataclass(frozen=True)
37
+ class CoordinateRealization:
38
+ """Original copy bindings and their exact fixed-carrier source realization."""
39
+
40
+ source: OccurrenceMTG
41
+ history: LocalCoordinateHistory
42
+
43
+ def replay(self) -> bool:
44
+ """Revalidate bindings, transported matches, order and realized prefix worlds."""
45
+ try:
46
+ return realize_coordinate_history(self.source) == self
47
+ except (ValueError, TypeError, KeyError):
48
+ return False
49
+
50
+
51
+ def realize_coordinate_history(source: OccurrenceMTG) -> CoordinateRealization:
52
+ """Transport a supported material-port history into its persistent atom universe.
53
+
54
+ Every primitive rule must meet the unguarded fixed-carrier locality profile.
55
+ Declared port precedence is retained, and every extracted access dependency
56
+ must already be implied by that order. No copy binding, physical independence
57
+ or alternative mechanism is inferred. All canonical prefix worlds are checked
58
+ against the original occurrence construction.
59
+
60
+ :param source: A replayable material-port occurrence history.
61
+ :return: Original history and its anchored coordinate-poset realization.
62
+ :raises LocalHistoryError: If profile, order or prefix-world agreement fails.
63
+ """
64
+ if not source.replay().valid:
65
+ raise LocalHistoryError("The material-port source history is not replayable.")
66
+ graph = source.to_process().causal_graph
67
+ order = tuple(nx.lexicographical_topological_sort(graph))
68
+ initial = source.configuration_cut(()).world
69
+ events = []
70
+ for event_id in order:
71
+ event = source.event_by_id[event_id]
72
+ match = {
73
+ rule_node: source.node_lineage_by_carrier[
74
+ binding.material_id, material_node
75
+ ]
76
+ for binding in event.inputs
77
+ for rule_node, material_node in binding.mapping
78
+ }
79
+ events.append(GroundedLocalEvent(event_id, event.rule, match))
80
+ local = build_local_coordinate_history(initial, events, precedence=graph.edges)
81
+ if any(not nx.has_path(graph, a, b) for a, b in local.causal_pairs):
82
+ raise LocalHistoryError(
83
+ "The port order does not cover every grounded coordinate dependency."
84
+ )
85
+ completed = set()
86
+ if not _same_raw_world(initial, local.initial):
87
+ raise LocalHistoryError("The initial anchored worlds disagree.")
88
+ for record in local.records:
89
+ completed.add(record.event.event_id)
90
+ original = source.configuration_cut(completed).world
91
+ if not _same_raw_world(record.application.result, original):
92
+ raise LocalHistoryError(
93
+ "A realized source prefix has a different raw world."
94
+ )
95
+ return CoordinateRealization(source, local)
@@ -0,0 +1,107 @@
1
+ """Optional exact series/parallel decomposition of an occurrence poset."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import itertools
6
+ from dataclasses import dataclass
7
+
8
+ import networkx as nx
9
+
10
+ from .process import OccurrenceProcess, ProcessError, ProcessIssue, ProcessIssueCode
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class SeriesParallelDecomposition:
15
+ """A detected decomposition; absence never changes process semantics."""
16
+
17
+ kind: str
18
+ events: frozenset[str]
19
+ children: tuple["SeriesParallelDecomposition", ...] = ()
20
+
21
+
22
+ def detect_series_parallel(
23
+ process: OccurrenceProcess,
24
+ *,
25
+ max_partition_states: int = 100_000,
26
+ ) -> SeriesParallelDecomposition | None:
27
+ """Return an exact recursive decomposition or ``None`` for a general poset."""
28
+ if max_partition_states <= 0:
29
+ raise ValueError("max_partition_states must be positive.")
30
+ events = frozenset(process.event_by_id)
31
+ relation = set(process.causal_pairs)
32
+ explored = 0
33
+
34
+ def comparable(left: str, right: str) -> bool:
35
+ return (left, right) in relation or (right, left) in relation
36
+
37
+ def visit(current: frozenset[str]) -> SeriesParallelDecomposition | None:
38
+ nonlocal explored
39
+ explored += 1
40
+ if explored > max_partition_states:
41
+ raise ProcessError(
42
+ ProcessIssue(
43
+ ProcessIssueCode.SERIES_PARALLEL_LIMIT,
44
+ "Series/parallel detection exceeded its explicit partition bound.",
45
+ {"limit": max_partition_states},
46
+ )
47
+ )
48
+ if len(current) <= 1:
49
+ return SeriesParallelDecomposition("event", current)
50
+
51
+ comparability = nx.Graph()
52
+ comparability.add_nodes_from(current)
53
+ comparability.add_edges_from(
54
+ (left, right)
55
+ for left in current
56
+ for right in current
57
+ if repr(left) < repr(right) and comparable(left, right)
58
+ )
59
+ components = tuple(
60
+ frozenset(component) for component in nx.connected_components(comparability)
61
+ )
62
+ if len(components) > 1:
63
+ children = tuple(visit(component) for component in components)
64
+ if all(child is not None for child in children):
65
+ return SeriesParallelDecomposition(
66
+ "parallel",
67
+ current,
68
+ tuple(child for child in children if child is not None),
69
+ )
70
+
71
+ ordered = tuple(sorted(current, key=repr))
72
+ anchor = ordered[0]
73
+ for size in range(1, len(ordered)):
74
+ for selected in itertools.combinations(ordered[1:], size - 1):
75
+ explored += 1
76
+ if explored > max_partition_states:
77
+ raise ProcessError(
78
+ ProcessIssue(
79
+ ProcessIssueCode.SERIES_PARALLEL_LIMIT,
80
+ "Series/parallel detection exceeded its partition bound.",
81
+ {"limit": max_partition_states},
82
+ )
83
+ )
84
+ first = frozenset((anchor, *selected))
85
+ second = current - first
86
+ orientations = (
87
+ all(
88
+ (left, right) in relation for left in first for right in second
89
+ ),
90
+ all(
91
+ (right, left) in relation for left in first for right in second
92
+ ),
93
+ )
94
+ if not any(orientations):
95
+ continue
96
+ lower, upper = (first, second) if orientations[0] else (second, first)
97
+ lower_tree, upper_tree = visit(lower), visit(upper)
98
+ if lower_tree is not None and upper_tree is not None:
99
+ return SeriesParallelDecomposition(
100
+ "series", current, (lower_tree, upper_tree)
101
+ )
102
+ return None
103
+
104
+ return visit(events)
105
+
106
+
107
+ __all__ = ["SeriesParallelDecomposition", "detect_series_parallel"]
@@ -0,0 +1,424 @@
1
+ import networkx as nx
2
+ import copy
3
+ from typing import Tuple, Any, Optional, Sequence, Set, Union
4
+
5
+ OrderPair = Tuple[float, float]
6
+ MissingOrder = Tuple[Set[float], Set[float]]
7
+
8
+ GraphType = Union[nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph]
9
+ TypesGHTuple = Tuple[Any, ...] # e.g., ('H', 0, 0, 0, ['C'])
10
+
11
+
12
+ def _extract_leaf_candidates(orig_th: Tuple[Any, ...]) -> Tuple[TypesGHTuple, ...]:
13
+ """
14
+ Flatten one level: if an element is a sequence whose elements are themselves sequences,
15
+ treat those inner sequences as candidates; otherwise the element itself is a candidate.
16
+ """
17
+ candidates: list[TypesGHTuple] = []
18
+ for item in orig_th:
19
+ if (
20
+ isinstance(item, (list, tuple))
21
+ and item
22
+ and all(isinstance(inner, (list, tuple)) for inner in item)
23
+ ):
24
+ # e.g., (('H',...), ('H',...)) -> take inner tuples
25
+ for inner in item:
26
+ if isinstance(inner, (list, tuple)):
27
+ candidates.append(tuple(inner))
28
+ else:
29
+ if isinstance(item, (list, tuple)):
30
+ candidates.append(tuple(item))
31
+ else:
32
+ # non-sequence fallback, wrap to tuple for uniformity
33
+ candidates.append((item,))
34
+ return tuple(candidates)
35
+
36
+
37
+ def normalize_hcount_and_typesGH(G: GraphType) -> GraphType:
38
+ """Return a fresh copy of G where:
39
+ * each node's `hcount` attribute is set to 0
40
+ * each node's `typesGH` is processed as follows:
41
+ 1. Flatten one level so that nested tuples-of-tuples are expanded.
42
+ 2. Drop any tuple that contains a `set` anywhere.
43
+ 3. From the remaining tuples, keep only the first and last (if more than two).
44
+ 4. Zero indices 1 and 2 in each kept tuple (if they exist).
45
+ 5. If nothing remains after dropping, result is an empty tuple.
46
+
47
+ :param G: input NetworkX graph
48
+ :type G: nx.Graph or nx.DiGraph or nx.MultiGraph or nx.MultiDiGraph
49
+ :return: a new graph with normalized hcount and typesGH
50
+ :rtype: same type as G
51
+ :raises TypeError: If G is not a supported NetworkX graph or if typesGH is malformed.
52
+ """
53
+ if not isinstance(G, (nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph)):
54
+ raise TypeError(f"Expected a NetworkX graph, got {type(G)!r}")
55
+
56
+ H = G.__class__()
57
+ H.graph.update(copy.deepcopy(G.graph))
58
+
59
+ for node, data in G.nodes(data=True):
60
+ new_data = data.copy()
61
+ new_data["hcount"] = 0
62
+
63
+ orig_th = data.get("typesGH", ())
64
+ if not isinstance(orig_th, (list, tuple)):
65
+ raise TypeError(
66
+ f"Node {node} has typesGH of unexpected type {type(orig_th)}; expected sequence"
67
+ )
68
+
69
+ # Step 1: flatten one level of nested tuples-of-tuples
70
+ candidates = _extract_leaf_candidates(tuple(orig_th))
71
+
72
+ # Step 2: drop any tuple containing a set
73
+ filtered = [
74
+ t for t in candidates if not any(isinstance(elem, set) for elem in t)
75
+ ]
76
+
77
+ # Step 3: select first and last (or whatever remains)
78
+ if not filtered:
79
+ selected: Tuple[TypesGHTuple, ...] = ()
80
+ elif len(filtered) > 2:
81
+ selected = (filtered[0], filtered[-1])
82
+ else:
83
+ selected = tuple(filtered) # 1 or 2 elements
84
+
85
+ # Step 4: zero indices 1 and 2
86
+ normalized: list[TypesGHTuple] = []
87
+ for inner in selected:
88
+ if not isinstance(inner, (list, tuple)):
89
+ raise TypeError(
90
+ f"Inner element of typesGH for node {node} is not tuple-like: {inner!r}"
91
+ )
92
+ inner_list = list(inner)
93
+ if len(inner_list) > 1:
94
+ inner_list[1] = 0
95
+ if len(inner_list) > 2:
96
+ inner_list[2] = 0
97
+ normalized.append(tuple(inner_list))
98
+
99
+ new_data["typesGH"] = tuple(normalized)
100
+ H.add_node(node, **new_data)
101
+
102
+ # Copy edges appropriately
103
+ if G.is_multigraph():
104
+ for u, v, key, edata in G.edges(keys=True, data=True):
105
+ H.add_edge(u, v, key=key, **copy.deepcopy(edata))
106
+ else:
107
+ for u, v, edata in G.edges(data=True):
108
+ H.add_edge(u, v, **copy.deepcopy(edata))
109
+
110
+ return H
111
+
112
+
113
+ def extract_order_norm(
114
+ order_sequence: Sequence[Union[OrderPair, MissingOrder]],
115
+ ) -> Optional[OrderPair]:
116
+ """Extract a normalized bond-order pair from orders and placeholders.
117
+
118
+ The left value is taken from the first non-placeholder pair. The right value
119
+ is taken from the last non-placeholder pair.
120
+
121
+ The input sequence must have length >= 2.
122
+
123
+ :param order_sequence: Sequence of order tuples or placeholders.
124
+ :type order_sequence: Sequence[tuple[float, float]] or Sequence[MissingOrder]
125
+ :return: Pair ``(left, right)`` if found; otherwise ``None``.
126
+ :rtype: tuple[float, float] or None
127
+ :raises ValueError: If the sequence contains fewer than two items.
128
+
129
+ .. rubric:: Examples
130
+
131
+ >>> seq = [({1}, {2}), (3.0, 4.0), ({5}, {6}), (7.0, 8.0)]
132
+ >>> extract_order_norm(seq)
133
+ (3.0, 8.0)
134
+ """
135
+ if not isinstance(order_sequence, Sequence) or len(order_sequence) < 2:
136
+ raise ValueError("order_sequence must be a sequence of length >= 2")
137
+
138
+ left: Any = None
139
+ right: Any = None
140
+ # Find first non-placeholder for left
141
+ for entry in order_sequence:
142
+ a, b = entry
143
+ if not (isinstance(a, set) and isinstance(b, set)):
144
+ left = a
145
+ break
146
+ # Find last non-placeholder for right
147
+ for entry in reversed(order_sequence):
148
+ a, b = entry
149
+ if not (isinstance(a, set) and isinstance(b, set)):
150
+ right = b
151
+ break
152
+ if left is not None and right is not None:
153
+ return (left, right)
154
+ return None
155
+
156
+
157
+ def normalize_order(G: nx.Graph) -> nx.Graph:
158
+ """Return a copy of the graph with each edge's 'order' attribute normalized.
159
+ If an edge has an 'order' attribute that is a sequence of length >= 2,
160
+ it is replaced by the 2-tuple returned by :func:`extract_order_norm`,
161
+ if that function returns a non-None result.
162
+
163
+ :param G: Input NetworkX graph
164
+ :type G: nx.Graph, nx.DiGraph, nx.MultiGraph, or nx.MultiDiGraph
165
+ :return: A new graph of the same type with normalized edge 'order'
166
+ :rtype: same as G
167
+ :raises TypeError: If G is not a NetworkX graph
168
+
169
+ .. rubric:: Examples
170
+
171
+ >>> import networkx as nx
172
+ >>> G = nx.Graph()
173
+ >>> G.add_edge(1, 2, order=[(1,2), ({3},{4}), (5,6)])
174
+ >>> H = normalize_order(G)
175
+ >>> H.edges[1,2]['order']
176
+ (1, 6)
177
+ """
178
+ from copy import deepcopy
179
+
180
+ if not isinstance(G, (nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph)):
181
+ raise TypeError(f"Expected a NetworkX graph, got {type(G)}")
182
+
183
+ H = deepcopy(G)
184
+ # Iterate edges appropriately
185
+ if H.is_multigraph():
186
+ edge_iter = H.edges(keys=True, data=True)
187
+ for _, _, _, attr in edge_iter:
188
+ order = attr.get("order")
189
+ if isinstance(order, (list, tuple)) and len(order) >= 2:
190
+ norm = extract_order_norm(order)
191
+ if norm is not None:
192
+ attr["order"] = norm
193
+ else:
194
+ for _, _, attr in H.edges(data=True):
195
+ order = attr.get("order")
196
+ if isinstance(order, (list, tuple)) and len(order) >= 2:
197
+ norm = extract_order_norm(order)
198
+ if norm is not None:
199
+ attr["order"] = norm
200
+ return H
201
+
202
+
203
+ # def normalize_hcount_and_typesGH(G):
204
+ # """
205
+ # Return a fresh copy of G where:
206
+ # - each node's `hcount` attribute is set to 0
207
+ # - in each tuple of `typesGH`, indices 1 and 2 are set to 0
208
+
209
+ # :param G: input NetworkX graph
210
+ # :type G: nx.Graph or nx.DiGraph or nx.MultiGraph or nx.MultiDiGraph
211
+ # :returns: a new graph with normalized hcount and typesGH
212
+ # :rtype: same type as G
213
+ # :raises: TypeError if G is not a NetworkX graph
214
+
215
+ # :example:
216
+ # >>> G = nx.Graph()
217
+ # >>> G.add_node(1, hcount=2, typesGH=(("C", 1, 2), ("O", 0, 1)))
218
+ # >>> H = normalize_hcount_and_typesGH(G)
219
+ # >>> H.nodes[1]['hcount']
220
+ # 0
221
+ # >>> H.nodes[1]['typesGH']
222
+ # (('C', 0, 0), ('O', 0, 0))
223
+ # """
224
+ # if not isinstance(G, (nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph)):
225
+ # raise TypeError(f"Expected NetworkX graph, got {type(G)}")
226
+
227
+ # # Create empty graph of same class and copy graph-level attributes
228
+ # H = G.__class__()
229
+ # H.graph.update(copy.deepcopy(G.graph))
230
+
231
+ # # Copy and normalize node data
232
+ # for node, data in G.nodes(data=True):
233
+ # new_data = data.copy()
234
+ # new_data["hcount"] = 0
235
+ # orig_th = data.get("typesGH", ())
236
+ # new_th = []
237
+ # for inner in orig_th:
238
+ # inner_list = list(inner)
239
+ # # Zero the aromatic slot (index 1) and the hcountGH slot (index 2)
240
+ # if len(inner_list) > 1:
241
+ # inner_list[1] = 0
242
+ # if len(inner_list) > 2:
243
+ # inner_list[2] = 0
244
+ # new_th.append(tuple(inner_list))
245
+ # new_data["typesGH"] = tuple(new_th)
246
+ # H.add_node(node, **new_data)
247
+
248
+ # # Copy edges (with keys for multigraphs)
249
+ # if G.is_multigraph():
250
+ # for u, v, key, edata in G.edges(keys=True, data=True):
251
+ # H.add_edge(u, v, key=key, **copy.deepcopy(edata))
252
+ # else:
253
+ # for u, v, edata in G.edges(data=True):
254
+ # H.add_edge(u, v, **copy.deepcopy(edata))
255
+
256
+ # return H
257
+
258
+
259
+ def label_mtg_edges(G: nx.Graph, inplace: bool = False) -> nx.Graph:
260
+ """Label each edge in the MTG graph with a boolean 'is_mtg' attribute based on two criteria:
261
+ 1. There are at least two steps where the standard order (order[0] - order[1]) is non-zero.
262
+ 2. The sum of all non-None standard orders is zero.
263
+
264
+ :param G: Input MTG graph with 'order' history per edge
265
+ :type G: nx.Graph or nx.DiGraph
266
+ :param inplace: If True, modify G in place; otherwise work on a copy
267
+ :type inplace: bool
268
+ :return: Graph with 'is_mtg' boolean attribute on each edge
269
+ :rtype: same type as G
270
+ :raises TypeError: If G is not a NetworkX Graph
271
+
272
+ .. rubric:: Examples
273
+
274
+ >>> import networkx as nx
275
+ >>> G = nx.Graph()
276
+ >>> # Single change only -> less than 2 non-zero steps => False
277
+ >>> G.add_edge(7,3, order=((1.0,1.0),(1.0,0)))
278
+ >>> H = label_mtg_edges(G)
279
+ >>> H.edges[7,3]['is_mtg']
280
+ False
281
+ >>> # Two-step equal but opposite changes -> sum zero and count>=2 => True
282
+ >>> G = nx.Graph()
283
+ >>> G.add_edge(2,1, order=((1.0,2.0),(2.0,1.0)))
284
+ >>> H = label_mtg_edges(G)
285
+ >>> H.edges[2,1]['is_mtg']
286
+ True
287
+ """
288
+ if not isinstance(G, (nx.Graph, nx.DiGraph)):
289
+ raise TypeError(f"Expected a NetworkX Graph, got {type(G)}")
290
+ graph = G if inplace else G.copy()
291
+ for u, v, attr in graph.edges(data=True):
292
+ history = attr.get("order")
293
+ # Extract numeric standard orders
294
+ std_vals: list[float] = []
295
+ if isinstance(history, (list, tuple)) and len(history) >= 2:
296
+ for entry in history:
297
+ if (
298
+ isinstance(entry, tuple)
299
+ and len(entry) == 2
300
+ and all(isinstance(x, (int, float)) for x in entry)
301
+ ):
302
+ std_vals.append(entry[0] - entry[1])
303
+ # Apply criteria
304
+ non_zero_count = sum(1 for v in std_vals if v != 0)
305
+ total = sum(std_vals)
306
+ attr["is_mtg"] = non_zero_count >= 2 and total == 0
307
+ return graph
308
+
309
+
310
+ def compute_standard_order(G: nx.Graph, inplace: bool = False) -> nx.Graph:
311
+ """Compute and assign the 'standard_order' attribute for each edge in the graph.
312
+ 'standard_order' is defined as the difference order[0] - order[1]
313
+ for edges whose 'order' attribute is a 2-tuple of numeric values.
314
+
315
+ :param G: Input NetworkX graph
316
+ :type G: nx.Graph, nx.DiGraph, nx.MultiGraph, or nx.MultiDiGraph
317
+ :param inplace: If True, modify G in-place; otherwise operate on a copy
318
+ :type inplace: bool
319
+ :return: Graph with 'standard_order' attributes set
320
+ :rtype: same type as G
321
+ :raises TypeError: If G is not a NetworkX graph
322
+
323
+ .. rubric:: Examples
324
+
325
+ >>> import networkx as nx
326
+ >>> G = nx.Graph()
327
+ >>> G.add_edge(7, 3, order=(1.0, 0))
328
+ >>> H = compute_standard_order(G)
329
+ >>> H.edges[7,3]['standard_order']
330
+ 1.0
331
+ """
332
+ if not isinstance(G, (nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph)):
333
+ raise TypeError(f"Expected a NetworkX graph, got {type(G)}")
334
+
335
+ graph = G if inplace else G.copy()
336
+ if graph.is_multigraph():
337
+ for u, v, key, attr in graph.edges(keys=True, data=True):
338
+ order = attr.get("order")
339
+ if isinstance(order, tuple) and len(order) == 2:
340
+ a, b = order
341
+ try:
342
+ attr["standard_order"] = a - b
343
+ except Exception:
344
+ attr["standard_order"] = None
345
+ else:
346
+ for u, v, attr in graph.edges(data=True):
347
+ order = attr.get("order")
348
+ if isinstance(order, tuple) and len(order) == 2:
349
+ a, b = order
350
+ try:
351
+ attr["standard_order"] = a - b
352
+ except Exception:
353
+ attr["standard_order"] = None
354
+ return graph
355
+
356
+
357
+ # def extract_order_norm(order_tuple):
358
+ # """
359
+ # Given a sequence of four 2-element tuples (order data), return the normalized order:
360
+ # - left: first element of the first tuple that is not both sets
361
+ # - right: second element of the last tuple that is not both sets
362
+
363
+ # :param order_tuple: tuple of four 2-element tuples
364
+ # :type order_tuple: tuple(tuple, tuple, tuple, tuple)
365
+ # :returns: normalized (left, right) or None if not found
366
+ # :rtype: tuple or None
367
+ # :raises: ValueError if order_tuple is not length 4
368
+
369
+ # :example:
370
+ # >>> ot = (({1}, {2}), (3, 4), ({5}, {6}), (7, 8))
371
+ # >>> extract_order_norm(ot)
372
+ # (3, 8)
373
+ # """
374
+ # if not (isinstance(order_tuple, tuple) and len(order_tuple) == 4):
375
+ # raise ValueError("order_tuple must be a tuple of length 4")
376
+
377
+ # left = None
378
+ # right = None
379
+ # # Find first non-all-set tuple for left
380
+ # for a, b in order_tuple:
381
+ # if not (isinstance(a, set) and isinstance(b, set)):
382
+ # left = a
383
+ # break
384
+ # # Find last non-all-set tuple for right
385
+ # for a, b in reversed(order_tuple):
386
+ # if not (isinstance(a, set) and isinstance(b, set)):
387
+ # right = b
388
+ # break
389
+ # return (left, right) if (left is not None and right is not None) else None
390
+
391
+
392
+ # def normalize_order(G):
393
+ # """
394
+ # Return a copy of G with edge attribute 'order' normalized.
395
+ # For each edge, if the 'order' attribute is a 4-tuple, replace it with the
396
+ # normalized 2-tuple returned by extract_order_norm.
397
+
398
+ # :param G: input NetworkX graph
399
+ # :type G: nx.Graph or nx.DiGraph or nx.MultiGraph or nx.MultiDiGraph
400
+ # :returns: a new graph with normalized edge orders
401
+ # :rtype: same type as G
402
+ # :raises: TypeError if G is not a NetworkX graph
403
+
404
+ # :example:
405
+ # >>> G = nx.Graph()
406
+ # >>> G.add_edge(1, 2, order=((1,2), ({3},{4}), ({5},{6}), (7,8)))
407
+ # >>> H = copy_and_normalize_order(G)
408
+ # >>> H.edges[1,2]['order']
409
+ # (1, 8)
410
+ # """
411
+ # if not isinstance(G, (nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph)):
412
+ # raise TypeError(f"Expected NetworkX graph, got {type(G)}")
413
+ # H = G.copy()
414
+ # for _, _, _, attr in (
415
+ # H.edges(keys=True, data=True)
416
+ # if H.is_multigraph()
417
+ # else [(u, v, None, attr) for u, v, attr in H.edges(data=True)]
418
+ # ):
419
+ # order = attr.get("order")
420
+ # if isinstance(order, tuple) and len(order) == 4:
421
+ # norm = extract_order_norm(order)
422
+ # if norm is not None:
423
+ # attr["order"] = norm
424
+ # return H
@@ -0,0 +1,10 @@
1
+ # from .graph_matcher import GraphMatcherEngine
2
+ # from .subgraph_matcher import SubgraphMatch, SubgraphSearchEngine
3
+ # from .graph_cluster import GraphCluster
4
+
5
+ # __all__ = [
6
+ # "GraphMatcherEngine",
7
+ # "SubgraphMatch",
8
+ # "SubgraphSearchEngine",
9
+ # "GraphCluster",
10
+ # ]