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,648 @@
1
+ """Exact canonicalization of configured permutation-labelled stereographs.
2
+
3
+ The public entry points in this module cover SynKit's complete configured
4
+ stereo catalogue. The tetrahedral-specific functions are retained as narrow
5
+ compatibility helpers, not as a separate stereograph model.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from collections.abc import Callable, Iterable, Mapping, Sequence
11
+ from dataclasses import dataclass
12
+ from enum import Enum
13
+ from typing import Any, Hashable, Literal
14
+
15
+ import networkx as nx
16
+
17
+ from synkit.Graph.Canon.exact import (
18
+ AutomorphismWitness,
19
+ ExactCanonicalResult,
20
+ )
21
+
22
+ from .descriptors import (
23
+ Reference,
24
+ StereoValue,
25
+ TetrahedralStereo,
26
+ )
27
+ from .orbits import SHAPE_DEFINITIONS
28
+
29
+ # ``/2`` is the persisted wire-schema revision of the complete configured
30
+ # certificate. It is deliberately not exposed as a second scientific model.
31
+ STEREOGRAPH_SCHEMA = "synkit.canonical-stereograph/2"
32
+
33
+ _DEFAULT_ATOM_COLOR_KEYS = (
34
+ "element",
35
+ "isotope",
36
+ "charge",
37
+ "formal_charge",
38
+ "radical",
39
+ "radical_electrons",
40
+ "aromatic",
41
+ "hcount",
42
+ "lone_pairs",
43
+ )
44
+ _DEFAULT_BOND_COLOR_KEYS = (
45
+ "order",
46
+ "standard_order",
47
+ "bond_type",
48
+ "aromatic",
49
+ )
50
+
51
+ AttributeSelector = str | Sequence[str] | Callable[[Mapping[str, Any]], Any]
52
+
53
+
54
+ @dataclass(frozen=True)
55
+ class AtomVertex:
56
+ """Auxiliary-graph handle for one base-graph atom."""
57
+
58
+ reference: Hashable
59
+
60
+
61
+ @dataclass(frozen=True)
62
+ class BondVertex:
63
+ """Auxiliary-graph handle for one base-graph bond/resource."""
64
+
65
+ index: int
66
+
67
+
68
+ @dataclass(frozen=True)
69
+ class StereoLocusVertex:
70
+ """Auxiliary-graph handle for one configured stereo locus."""
71
+
72
+ index: int
73
+
74
+
75
+ @dataclass(frozen=True)
76
+ class StereoPortVertex:
77
+ """One owner-specific ligand incidence at a stereo locus."""
78
+
79
+ locus: int
80
+ position: int
81
+
82
+
83
+ @dataclass(frozen=True)
84
+ class StereoTupleVertex:
85
+ """One allowed ordered tuple in a local configuration orbit."""
86
+
87
+ locus: int
88
+ index: int
89
+
90
+
91
+ @dataclass(frozen=True)
92
+ class StereoSlotVertex:
93
+ """Position-coloured connection between a tuple and one port."""
94
+
95
+ locus: int
96
+ tuple_index: int
97
+ position: int
98
+
99
+
100
+ @dataclass(frozen=True)
101
+ class VirtualResourceVertex:
102
+ """Owner-scoped hidden hydrogen or lone-pair resource."""
103
+
104
+ locus: int
105
+ position: int
106
+ kind: str
107
+
108
+
109
+ @dataclass(frozen=True)
110
+ class CanonicalStereographResult:
111
+ """Complete configured-stereograph identity and projected witnesses.
112
+
113
+ ``canonical_code`` is the deterministic, versioned exact certificate.
114
+ Atom/bond orders and projected automorphisms retain input handles and are
115
+ witnesses modulo configured-stereograph automorphism, not unique choices
116
+ among constitutionally symmetric atoms or ports.
117
+ """
118
+
119
+ schema: str
120
+ canonical_code: str
121
+ canonical_digest: str
122
+ atom_order: tuple[Hashable, ...]
123
+ bond_order: tuple[tuple[Hashable, Hashable], ...]
124
+ locus_order: tuple[int, ...]
125
+ port_order: tuple[StereoPortVertex, ...]
126
+ atom_automorphisms: tuple[AutomorphismWitness, ...]
127
+ locus_automorphisms: tuple[AutomorphismWitness, ...]
128
+ port_automorphisms: tuple[AutomorphismWitness, ...]
129
+ auxiliary: ExactCanonicalResult
130
+ identity_profile: str = "attributed_graph"
131
+
132
+ @property
133
+ def complete(self) -> bool:
134
+ return self.auxiliary.complete
135
+
136
+ @property
137
+ def exact(self) -> bool:
138
+ return self.auxiliary.exact
139
+
140
+ @property
141
+ def canonical_certificate(self) -> str:
142
+ """Return the exact, versioned stereograph serialization."""
143
+ return self.canonical_code
144
+
145
+ def same_stereograph(self, other: object) -> bool:
146
+ """Compare exact versioned certificates, not finite digests."""
147
+ return (
148
+ isinstance(other, CanonicalStereographResult)
149
+ and self.schema == other.schema
150
+ and self.identity_profile == other.identity_profile
151
+ and self.auxiliary.same_canonical_graph(other.auxiliary)
152
+ )
153
+
154
+
155
+ class StereographMirrorStatus(str, Enum):
156
+ """Exact mirror-comparison outcome for a configured stereograph."""
157
+
158
+ ACHIRAL = "achiral"
159
+ CHIRAL = "chiral"
160
+ INCOMPLETE = "incomplete"
161
+ UNSUPPORTED = "unsupported"
162
+
163
+
164
+ @dataclass(frozen=True)
165
+ class StereographMirrorResult:
166
+ """Evidence for exact comparison with a geometry-specific mirror.
167
+
168
+ Definitive results retain both complete exact certificates. Incomplete
169
+ or unsupported inputs deliberately return no plausible partial identity.
170
+ """
171
+
172
+ status: StereographMirrorStatus
173
+ descriptor_count: int
174
+ original: CanonicalStereographResult | None = None
175
+ mirror: CanonicalStereographResult | None = None
176
+ mirrored_descriptors: tuple[StereoValue, ...] = ()
177
+ atom_mirror_isomorphism: tuple[tuple[Hashable, Hashable], ...] | None = None
178
+ incomplete_loci: tuple[str, ...] = ()
179
+ unsupported_loci: tuple[str, ...] = ()
180
+ unsupported_families: tuple[str, ...] = ()
181
+ method: str = "exact_canonical_stereograph_mirror_comparison"
182
+ identity_profile: str = "attributed_graph"
183
+ original_identity: Any | None = None
184
+ mirror_identity: Any | None = None
185
+
186
+ @property
187
+ def is_definitive(self) -> bool:
188
+ return self.status in {
189
+ StereographMirrorStatus.ACHIRAL,
190
+ StereographMirrorStatus.CHIRAL,
191
+ }
192
+
193
+ @property
194
+ def is_chiral(self) -> bool | None:
195
+ if not self.is_definitive:
196
+ return None
197
+ return self.status is StereographMirrorStatus.CHIRAL
198
+
199
+
200
+ @dataclass(frozen=True)
201
+ class _Expansion:
202
+ graph: nx.Graph
203
+ bond_endpoints: tuple[tuple[Hashable, Hashable], ...]
204
+
205
+
206
+ def _selected(
207
+ attributes: Mapping[str, Any],
208
+ selector: AttributeSelector,
209
+ ) -> Any:
210
+ if isinstance(selector, str):
211
+ return attributes.get(selector)
212
+ if callable(selector):
213
+ return selector(attributes)
214
+ return tuple(attributes.get(key) for key in selector)
215
+
216
+
217
+ def _add_coloured_node(
218
+ graph: nx.Graph,
219
+ node: Hashable,
220
+ color: tuple[Any, ...],
221
+ ) -> None:
222
+ graph.add_node(node, color=color)
223
+
224
+
225
+ def _validate_base_graph(graph: nx.Graph) -> None:
226
+ if not isinstance(graph, nx.Graph) or graph.is_directed():
227
+ raise TypeError(
228
+ "Configured molecular stereographs currently require an "
229
+ "undirected NetworkX Graph."
230
+ )
231
+ if graph.is_multigraph():
232
+ raise TypeError(
233
+ "Parallel resources must already be represented as typed "
234
+ "incidence vertices."
235
+ )
236
+
237
+
238
+ def _material_port_resource(
239
+ base: nx.Graph,
240
+ bonds: Mapping[tuple[Hashable, Hashable], BondVertex],
241
+ owner: Hashable,
242
+ reference: Reference,
243
+ *,
244
+ geometry: str,
245
+ ) -> BondVertex:
246
+ if reference not in base:
247
+ raise ValueError(f"{geometry} ligand reference {reference!r} is absent.")
248
+ if not base.has_edge(owner, reference):
249
+ raise ValueError(
250
+ f"{geometry} ligand {reference!r} is not bonded to owner {owner!r}."
251
+ )
252
+ return bonds[(owner, reference)]
253
+
254
+
255
+ def _add_configuration_orbit(
256
+ auxiliary: nx.Graph,
257
+ locus: StereoLocusVertex,
258
+ descriptor: StereoValue,
259
+ locus_index: int,
260
+ targets: Mapping[Reference, Hashable],
261
+ frame_positions: Sequence[int],
262
+ ) -> None:
263
+ definition = SHAPE_DEFINITIONS[descriptor.descriptor_class]
264
+ orbit = definition.preserving_group.orbit(descriptor.configuration.frame)
265
+ for tuple_index, frame in enumerate(orbit):
266
+ relation = StereoTupleVertex(locus_index, tuple_index)
267
+ _add_coloured_node(
268
+ auxiliary,
269
+ relation,
270
+ ("stereo_tuple", descriptor.descriptor_class),
271
+ )
272
+ auxiliary.add_edge(locus, relation)
273
+ for slot_position, frame_position in enumerate(frame_positions):
274
+ reference = frame[frame_position]
275
+ slot = StereoSlotVertex(locus_index, tuple_index, slot_position)
276
+ _add_coloured_node(
277
+ auxiliary,
278
+ slot,
279
+ (
280
+ "stereo_slot",
281
+ descriptor.descriptor_class,
282
+ slot_position,
283
+ ),
284
+ )
285
+ auxiliary.add_edge(relation, slot)
286
+ auxiliary.add_edge(slot, targets[reference])
287
+
288
+
289
+ def expand_tetrahedral_stereograph(
290
+ base_graph: nx.Graph,
291
+ descriptors: Iterable[TetrahedralStereo],
292
+ *,
293
+ atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
294
+ bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
295
+ ) -> nx.Graph:
296
+ """Expand tetrahedral stereo through the unified stereograph engine."""
297
+ fixed = _require_tetrahedral(tuple(descriptors))
298
+ return expand_stereograph(
299
+ base_graph,
300
+ fixed,
301
+ atom_color=atom_color,
302
+ bond_color=bond_color,
303
+ )
304
+
305
+
306
+ def expand_stereograph(
307
+ base_graph: nx.Graph,
308
+ descriptors: Iterable[StereoValue],
309
+ *,
310
+ atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
311
+ bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
312
+ ) -> nx.Graph:
313
+ """Expand a complete configured stereograph."""
314
+ from .configured import expand_configured_stereograph
315
+
316
+ return expand_configured_stereograph(
317
+ base_graph,
318
+ tuple(descriptors),
319
+ atom_color=atom_color,
320
+ bond_color=bond_color,
321
+ )
322
+
323
+
324
+ def _require_tetrahedral(
325
+ descriptors: tuple[StereoValue, ...],
326
+ ) -> tuple[TetrahedralStereo, ...]:
327
+ if any(not isinstance(item, TetrahedralStereo) for item in descriptors):
328
+ raise TypeError(
329
+ "This tetrahedral compatibility API accepts only "
330
+ "TetrahedralStereo descriptors."
331
+ )
332
+ return descriptors # type: ignore[return-value]
333
+
334
+
335
+ def _expand_base_graph(
336
+ base_graph: nx.Graph,
337
+ *,
338
+ atom_color: AttributeSelector,
339
+ bond_color: AttributeSelector,
340
+ ) -> _Expansion:
341
+ _validate_base_graph(base_graph)
342
+ base = base_graph.copy()
343
+ auxiliary = nx.Graph()
344
+ atom_vertices = {reference: AtomVertex(reference) for reference in base}
345
+ for reference, vertex in atom_vertices.items():
346
+ _add_coloured_node(
347
+ auxiliary,
348
+ vertex,
349
+ ("atom", _selected(base.nodes[reference], atom_color)),
350
+ )
351
+
352
+ endpoints = []
353
+ for index, (left, right, attributes) in enumerate(base.edges(data=True)):
354
+ vertex = BondVertex(index)
355
+ endpoints.append((left, right))
356
+ _add_coloured_node(
357
+ auxiliary,
358
+ vertex,
359
+ ("bond_resource", _selected(attributes, bond_color)),
360
+ )
361
+ auxiliary.add_edge(atom_vertices[left], vertex)
362
+ auxiliary.add_edge(vertex, atom_vertices[right])
363
+ return _Expansion(auxiliary, tuple(endpoints))
364
+
365
+
366
+ def _project_witnesses(
367
+ result: ExactCanonicalResult,
368
+ vertex_type: type[AtomVertex] | type[StereoLocusVertex] | type[StereoPortVertex],
369
+ ) -> tuple[AutomorphismWitness, ...]:
370
+ projected = []
371
+ for witness in result.automorphisms:
372
+ mapping = witness.as_dict()
373
+ pairs = []
374
+ for source, target in mapping.items():
375
+ if not isinstance(source, vertex_type):
376
+ continue
377
+ if not isinstance(target, vertex_type):
378
+ raise RuntimeError(
379
+ "Auxiliary automorphism changed a semantic vertex role."
380
+ )
381
+ if isinstance(source, AtomVertex):
382
+ pairs.append((source.reference, target.reference))
383
+ elif isinstance(source, StereoLocusVertex):
384
+ pairs.append((source.index, target.index))
385
+ else:
386
+ pairs.append((source, target))
387
+ projected.append(AutomorphismWitness(tuple(pairs)))
388
+ return tuple(projected)
389
+
390
+
391
+ def canonicalize_tetrahedral_stereograph(
392
+ base_graph: nx.Graph,
393
+ descriptors: Iterable[TetrahedralStereo],
394
+ *,
395
+ atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
396
+ bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
397
+ ) -> CanonicalStereographResult:
398
+ """Return exact stereograph identity for configured tetrahedral stereo."""
399
+ fixed = _require_tetrahedral(tuple(descriptors))
400
+ return canonicalize_stereograph(
401
+ base_graph,
402
+ fixed,
403
+ atom_color=atom_color,
404
+ bond_color=bond_color,
405
+ )
406
+
407
+
408
+ def canonicalize_stereograph(
409
+ base_graph: nx.Graph,
410
+ descriptors: Iterable[StereoValue],
411
+ *,
412
+ atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
413
+ bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
414
+ enumerate_automorphism_group: bool = True,
415
+ ) -> CanonicalStereographResult:
416
+ """Return exact identity for a complete configured stereograph."""
417
+ from .configured import canonicalize_configured_stereograph
418
+
419
+ return canonicalize_configured_stereograph(
420
+ base_graph,
421
+ tuple(descriptors),
422
+ atom_color=atom_color,
423
+ bond_color=bond_color,
424
+ enumerate_automorphism_group=enumerate_automorphism_group,
425
+ )
426
+
427
+
428
+ def canonicalize_tetrahedral_registry(
429
+ base_graph: nx.Graph,
430
+ registry: Mapping[str, StereoValue],
431
+ *,
432
+ atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
433
+ bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
434
+ ) -> CanonicalStereographResult:
435
+ """Canonicalize a registry only when every entry is tetrahedral.
436
+
437
+ Rejecting other configured families is deliberate: silently omitting an
438
+ E/Z, axial, or coordination descriptor would produce an incomplete
439
+ stereochemical identity.
440
+ """
441
+ descriptors = tuple(registry.values())
442
+ unsupported = tuple(
443
+ descriptor.descriptor_class
444
+ for descriptor in descriptors
445
+ if not isinstance(descriptor, TetrahedralStereo)
446
+ )
447
+ if unsupported:
448
+ families = ", ".join(sorted(set(unsupported)))
449
+ raise TypeError(
450
+ "Tetrahedral canonicalization cannot omit configured stereo "
451
+ f"families: {families}."
452
+ )
453
+ return canonicalize_tetrahedral_stereograph(
454
+ base_graph,
455
+ descriptors,
456
+ atom_color=atom_color,
457
+ bond_color=bond_color,
458
+ )
459
+
460
+
461
+ def canonicalize_stereo_registry(
462
+ base_graph: nx.Graph,
463
+ registry: Mapping[str, StereoValue],
464
+ *,
465
+ atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
466
+ bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
467
+ enumerate_automorphism_group: bool = True,
468
+ ) -> CanonicalStereographResult:
469
+ """Canonicalize a registry across the complete configured catalogue."""
470
+ from .configured import canonicalize_configured_registry
471
+
472
+ return canonicalize_configured_registry(
473
+ base_graph,
474
+ registry,
475
+ atom_color=atom_color,
476
+ bond_color=bond_color,
477
+ enumerate_automorphism_group=enumerate_automorphism_group,
478
+ )
479
+
480
+
481
+ def mirror_stereo_descriptor(
482
+ descriptor: StereoValue,
483
+ ) -> StereoValue:
484
+ """Apply the geometry-specific spatial-reflection action."""
485
+ from .configured import mirror_configured_descriptor
486
+
487
+ return mirror_configured_descriptor(descriptor) # type: ignore[arg-type]
488
+
489
+
490
+ def mirror_stereo_registry(
491
+ registry: Mapping[str, StereoValue],
492
+ ) -> dict[str, StereoValue]:
493
+ """Return the geometry-specific mirror without changing loci."""
494
+ return {
495
+ identifier: mirror_stereo_descriptor(descriptor)
496
+ for identifier, descriptor in registry.items()
497
+ }
498
+
499
+
500
+ def classify_stereograph_mirror(
501
+ base_graph: nx.Graph,
502
+ registry: Mapping[str, StereoValue],
503
+ *,
504
+ incomplete_loci: Iterable[str] = (),
505
+ unsupported_loci: Iterable[str] = (),
506
+ atom_color: AttributeSelector = _DEFAULT_ATOM_COLOR_KEYS,
507
+ bond_color: AttributeSelector = _DEFAULT_BOND_COLOR_KEYS,
508
+ ) -> StereographMirrorResult:
509
+ """Compare a complete configured stereograph with its exact mirror.
510
+
511
+ ``incomplete_loci`` and ``unsupported_loci`` let a perception boundary
512
+ declare missing configured information without inventing descriptors.
513
+ Unsupported evidence takes precedence over incomplete evidence.
514
+ """
515
+ from .configured import classify_configured_stereograph_mirror
516
+
517
+ return classify_configured_stereograph_mirror(
518
+ base_graph,
519
+ registry,
520
+ incomplete_loci=incomplete_loci,
521
+ unsupported_loci=unsupported_loci,
522
+ atom_color=atom_color,
523
+ bond_color=bond_color,
524
+ )
525
+
526
+
527
+ def _rdkit_graph(molecule: Any) -> nx.Graph:
528
+ """Return a defensive attributed graph in the RDKit atom namespace."""
529
+ from rdkit import Chem
530
+
531
+ from synkit.IO.mol_to_graph import MolToGraph
532
+
533
+ if not isinstance(molecule, Chem.Mol):
534
+ raise TypeError("RDKit stereograph canonicalization requires Chem.Mol.")
535
+ working = Chem.Mol(molecule)
536
+ atom_maps = tuple(int(atom.GetAtomMapNum()) for atom in working.GetAtoms())
537
+ fully_mapped = all(value > 0 for value in atom_maps) and len(set(atom_maps)) == len(
538
+ atom_maps
539
+ )
540
+ return MolToGraph(include_stereo_descriptors=False).transform(
541
+ working,
542
+ use_index_as_atom_map=fully_mapped,
543
+ )
544
+
545
+
546
+ def _rdkit_graph_and_registry(
547
+ molecule: Any,
548
+ ) -> tuple[nx.Graph, Mapping[str, StereoValue]]:
549
+ """Return one RDKit graph/descriptor identifier namespace."""
550
+ from rdkit import Chem
551
+
552
+ from .rdkit_adapter import descriptors_from_rdkit
553
+
554
+ graph = _rdkit_graph(molecule)
555
+ working = Chem.Mol(molecule)
556
+ atom_maps = tuple(int(atom.GetAtomMapNum()) for atom in working.GetAtoms())
557
+ fully_mapped = all(value > 0 for value in atom_maps) and len(set(atom_maps)) == len(
558
+ atom_maps
559
+ )
560
+ registry = descriptors_from_rdkit(
561
+ working,
562
+ require_atom_maps=fully_mapped,
563
+ )
564
+ return graph, registry
565
+
566
+
567
+ def canonicalize_rdkit_tetrahedral_stereograph(
568
+ molecule: Any,
569
+ ) -> CanonicalStereographResult:
570
+ """Canonicalize RDKit constitution plus its configured tetrahedral stereo.
571
+
572
+ A defensive molecule copy is converted with atom-map node IDs only when
573
+ every atom has a unique positive map. Otherwise both the molecular graph
574
+ and descriptors use one-based RDKit-index IDs. Atom maps, CIP labels,
575
+ coordinates, and RDKit local chiral tags do not enter semantic colours.
576
+ """
577
+ graph, registry = _rdkit_graph_and_registry(molecule)
578
+ return canonicalize_tetrahedral_registry(graph, registry)
579
+
580
+
581
+ def canonicalize_rdkit_stereograph(
582
+ molecule: Any,
583
+ *,
584
+ identity_profile: Literal["chemical", "lewis_state", "acs_topology"] = "lewis_state",
585
+ ):
586
+ """Canonicalize configured RDKit stereo under an explicit identity profile.
587
+
588
+ The compatibility default is the supplied Lewis drawing. Chemical
589
+ identity returns a versioned resonance-family certificate; it is not a
590
+ single drawing's certificate. Mirror classification defaults to chemical
591
+ identity, so select the same profile when comparing the operations.
592
+ """
593
+ from .configured import canonicalize_rdkit_configured_stereograph
594
+
595
+ return canonicalize_rdkit_configured_stereograph(molecule, identity_profile=identity_profile)
596
+
597
+
598
+ def classify_rdkit_stereograph_mirror(
599
+ molecule: Any,
600
+ *,
601
+ require_complete: bool = True,
602
+ identity_profile: Literal[
603
+ "chemical",
604
+ "lewis_state",
605
+ "acs_topology",
606
+ ] = "chemical",
607
+ ) -> StereographMirrorResult:
608
+ """Classify configured RDKit input through exact molecular mirror identity.
609
+
610
+ The chemical default compares the exact resonance family while preserving
611
+ genuine bond-order distinctions. ``lewis_state`` audits one supplied
612
+ Lewis drawing; ``acs_topology`` is connectivity-only benchmark
613
+ compatibility.
614
+ """
615
+ from .configured import classify_rdkit_configured_stereograph_mirror
616
+
617
+ return classify_rdkit_configured_stereograph_mirror(
618
+ molecule,
619
+ require_complete=require_complete,
620
+ identity_profile=identity_profile,
621
+ )
622
+
623
+
624
+ __all__ = [
625
+ "AtomVertex",
626
+ "BondVertex",
627
+ "CanonicalStereographResult",
628
+ "STEREOGRAPH_SCHEMA",
629
+ "StereographMirrorResult",
630
+ "StereographMirrorStatus",
631
+ "StereoLocusVertex",
632
+ "StereoPortVertex",
633
+ "StereoSlotVertex",
634
+ "StereoTupleVertex",
635
+ "VirtualResourceVertex",
636
+ "classify_rdkit_stereograph_mirror",
637
+ "classify_stereograph_mirror",
638
+ "canonicalize_rdkit_stereograph",
639
+ "canonicalize_rdkit_tetrahedral_stereograph",
640
+ "canonicalize_stereo_registry",
641
+ "canonicalize_stereograph",
642
+ "canonicalize_tetrahedral_registry",
643
+ "canonicalize_tetrahedral_stereograph",
644
+ "expand_stereograph",
645
+ "expand_tetrahedral_stereograph",
646
+ "mirror_stereo_descriptor",
647
+ "mirror_stereo_registry",
648
+ ]