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,570 @@
1
+ from collections import Counter
2
+ from operator import eq
3
+ from typing import Any, Dict, Iterator, List, Optional, Tuple
4
+
5
+ import networkx as nx
6
+ from joblib import Parallel, delayed
7
+ from networkx.algorithms.isomorphism import generic_node_match
8
+
9
+ from synkit.Graph.Matcher.graph_cluster import GraphCluster
10
+ from synkit.Graph.Hyrogen.hcomplete import HComplete, ITSFormatInput
11
+ from synkit.Graph.Stereo.matching import stereo_isomorphic
12
+
13
+ from synkit.Graph.Hyrogen._misc import check_hcount_change
14
+
15
+ cluster = GraphCluster()
16
+ _ANCHOR_ATTRIBUTE = "_synkit_hextend_anchor"
17
+ _anchored_node_match = generic_node_match(
18
+ ["element", "charge", _ANCHOR_ATTRIBUTE],
19
+ ["*", 0, None],
20
+ [eq, eq, eq],
21
+ )
22
+
23
+ ColourDistance = Tuple[int, int]
24
+ RootedDistanceProfile = Tuple[Tuple[ColourDistance, int], ...]
25
+ HydrogenDistanceInvariant = Tuple[RootedDistanceProfile, ...]
26
+
27
+
28
+ def _invariant_order_key(value: Any) -> Tuple[Any, ...]:
29
+ """Totally order supported frozen comparison values without coercion."""
30
+ if isinstance(value, tuple):
31
+ return ("tuple", tuple(_invariant_order_key(item) for item in value))
32
+ return (
33
+ "atom",
34
+ type(value).__module__,
35
+ type(value).__qualname__,
36
+ repr(value),
37
+ )
38
+
39
+
40
+ class HExtend(HComplete):
41
+
42
+ @staticmethod
43
+ def get_unique_graphs_for_clusters(
44
+ graphs: List[nx.Graph], cluster_indices: List[set]
45
+ ) -> List[nx.Graph]:
46
+ """Retrieve a unique graph for each cluster from a list of graphs based
47
+ on cluster indices.
48
+
49
+ This method selects one graph per cluster using the smallest index in
50
+ each cluster set. Clusters are expected to be represented as sets of
51
+ indices, each corresponding to a graph in the `graphs` list.
52
+
53
+ :param graphs: List of networkx graphs.
54
+ :type graphs: List[nx.Graph]
55
+ :param cluster_indices: List of sets, each containing indices representing graphs
56
+ that belong to the same cluster.
57
+ :type cluster_indices: List[set]
58
+
59
+ :return: A list containing one unique graph from each cluster.
60
+ :rtype: List[nx.Graph]
61
+
62
+ :raises ValueError: If any index in `cluster_indices` is out of the range of `graphs`.
63
+ :raises TypeError: If `cluster_indices` is not a list of sets.
64
+ """
65
+ if not all(isinstance(cluster, set) for cluster in cluster_indices):
66
+ raise TypeError("Each cluster index must be a set of integers.")
67
+ if any(
68
+ min(cluster) < 0 or max(cluster) >= len(graphs)
69
+ for cluster in cluster_indices
70
+ if cluster
71
+ ):
72
+ raise ValueError("Cluster indices are out of the range of the graphs list.")
73
+
74
+ unique_graphs = [graphs[min(cluster)] for cluster in cluster_indices if cluster]
75
+ return unique_graphs
76
+
77
+ @staticmethod
78
+ def extend_its(
79
+ its: nx.Graph,
80
+ ignore_aromaticity: bool = False,
81
+ balance_its: bool = True,
82
+ format: ITSFormatInput = "auto",
83
+ max_candidates: Optional[int] = None,
84
+ ) -> Tuple[List[nx.Graph], List[nx.Graph], List[str]]:
85
+ """Extend a bare ITS graph into all valid hydrogen-completed variants.
86
+
87
+ :param its: The initial transition state graph to be processed.
88
+ :type its: nx.Graph
89
+ :param ignore_aromaticity: Flag to ignore aromaticity in graph construction.
90
+ :type ignore_aromaticity: bool
91
+ :param balance_its: Flag to balance the ITS graph during processing.
92
+ :type balance_its: bool
93
+ :param format: ITS representation: "auto", "typesGH", or "tuple".
94
+ :type format: str
95
+ :param max_candidates: Optional cap for enumerated hydrogen assignments.
96
+ :type max_candidates: Optional[int]
97
+
98
+ :return: Tuple containing lists of processed reaction graphs, ITS graphs, and their signatures.
99
+ :rtype: Tuple[List[nx.Graph], List[nx.Graph], List[str]]
100
+ """
101
+ if not isinstance(its, nx.Graph) or its.number_of_nodes() == 0:
102
+ return [], [], []
103
+
104
+ resolved_format = HComplete._resolve_format(its, format)
105
+ react_graph, prod_graph = HComplete._decompose_its(its, resolved_format)
106
+ hcount_change = check_hcount_change(react_graph, prod_graph)
107
+ if hcount_change == 0:
108
+ rc = HComplete._extract_rc(its, resolved_format)
109
+ if not HComplete._valid_rc(rc):
110
+ return [], [], []
111
+ its_list = [its]
112
+ rc_list = [rc]
113
+ sigs = [HComplete._rc_signature(rc, resolved_format)]
114
+ return rc_list, its_list, sigs
115
+
116
+ combinations_solution = HComplete._iter_hydrogen_node_completions(
117
+ react_graph,
118
+ prod_graph,
119
+ ignore_aromaticity,
120
+ balance_its,
121
+ format=resolved_format,
122
+ max_candidates=max_candidates,
123
+ )
124
+
125
+ rc_list, its_list, rc_sig = [], [], []
126
+ for _, _, its, rc, sig in combinations_solution:
127
+ if HComplete._valid_rc(rc):
128
+ rc_list.append(rc)
129
+ its_list.append(its)
130
+ rc_sig.append(sig)
131
+ return rc_list, its_list, rc_sig
132
+
133
+ @staticmethod
134
+ def _extend(
135
+ its: nx.Graph,
136
+ ignore_aromaticity: bool,
137
+ balance_its: bool,
138
+ format: ITSFormatInput = "auto",
139
+ max_candidates: Optional[int] = None,
140
+ ) -> Tuple[List[nx.Graph], List[nx.Graph], List[str]]:
141
+ """Compatibility wrapper for :meth:`extend_its`."""
142
+ return HExtend.extend_its(
143
+ its,
144
+ ignore_aromaticity=ignore_aromaticity,
145
+ balance_its=balance_its,
146
+ format=format,
147
+ max_candidates=max_candidates,
148
+ )
149
+
150
+ @staticmethod
151
+ def _extend_unique(
152
+ its: nx.Graph,
153
+ ignore_aromaticity: bool = False,
154
+ balance_its: bool = True,
155
+ format: ITSFormatInput = "auto",
156
+ max_candidates: Optional[int] = None,
157
+ ) -> Tuple[List[nx.Graph], List[nx.Graph], List[str]]:
158
+ """Extend an ITS graph and retain exact RC-class representatives."""
159
+ representatives = list(
160
+ HExtend.iter_unique_completions(
161
+ its,
162
+ ignore_aromaticity=ignore_aromaticity,
163
+ balance_its=balance_its,
164
+ format=format,
165
+ max_candidates=max_candidates,
166
+ )
167
+ )
168
+ return (
169
+ [item[0] for item in representatives],
170
+ [item[1] for item in representatives],
171
+ [item[2] for item in representatives],
172
+ )
173
+
174
+ @staticmethod
175
+ def cluster_full_its(
176
+ its_list: List[nx.Graph],
177
+ signatures: List[str],
178
+ ) -> Tuple[List[set], Dict[int, int]]:
179
+ """Cluster complete ITS graphs with necessary-condition prefilters.
180
+
181
+ Full-ITS isomorphism implies reaction-centre isomorphism, so unequal
182
+ RC-invariant signatures conclusively rule out equivalence. Candidates
183
+ that collide on that signature receive a second invariant describing
184
+ distances from hydrogen atoms to coloured atoms. Equal signatures
185
+ remain only prefilters: the final decision is made by chemistry- and
186
+ stereo-aware full-graph isomorphism.
187
+ """
188
+ if len(its_list) != len(signatures):
189
+ raise ValueError("ITS graphs and signatures must have equal lengths.")
190
+ if not its_list:
191
+ return [], {}
192
+
193
+ signature_counts = Counter(signatures)
194
+ invariant_blocks: Dict[
195
+ Tuple[str, HydrogenDistanceInvariant],
196
+ List[int],
197
+ ] = {}
198
+ for index, (its, signature) in enumerate(zip(its_list, signatures)):
199
+ # A unique RC invariant already forms a singleton block. Compute
200
+ # the more expensive rooted-distance invariant only on collisions.
201
+ distance_invariant = (
202
+ ()
203
+ if signature_counts[signature] == 1
204
+ else HExtend.hydrogen_distance_invariant(its)
205
+ )
206
+ invariant_blocks.setdefault(
207
+ (signature, distance_invariant),
208
+ [],
209
+ ).append(index)
210
+
211
+ exact_clusters = []
212
+ for indices in invariant_blocks.values():
213
+ exact_clusters.extend(
214
+ HExtend._cluster_invariant_block(
215
+ indices,
216
+ its_list,
217
+ )
218
+ )
219
+
220
+ exact_clusters.sort(key=min)
221
+ rule_to_cluster = {
222
+ index: cluster_index
223
+ for cluster_index, indices in enumerate(exact_clusters)
224
+ for index in indices
225
+ }
226
+ return exact_clusters, rule_to_cluster
227
+
228
+ @staticmethod
229
+ def _cluster_invariant_block(
230
+ indices: List[int],
231
+ its_list: List[nx.Graph],
232
+ ) -> List[set]:
233
+ """Exactly quotient one necessary-invariant block."""
234
+ exact_clusters: List[set] = []
235
+ for index in indices:
236
+ for exact_cluster in exact_clusters:
237
+ representative = min(exact_cluster)
238
+ if HExtend._anchored_full_its_isomorphic(
239
+ its_list[representative],
240
+ its_list[index],
241
+ ):
242
+ exact_cluster.add(index)
243
+ break
244
+ else:
245
+ exact_clusters.append({index})
246
+ return exact_clusters
247
+
248
+ @staticmethod
249
+ def _anchored_full_its_isomorphic(
250
+ left: nx.Graph,
251
+ right: nx.Graph,
252
+ ) -> bool:
253
+ """Decide full ITS isomorphism by changed-core anchor extension.
254
+
255
+ Every full ITS isomorphism restricts to an isomorphism of the subgraph
256
+ induced by changed bonds, because the full edge matcher preserves the
257
+ paired bond-order attribute. Conversely, a full isomorphism extending
258
+ any enumerated core isomorphism is a valid witness. Exhaustive anchor
259
+ extension is therefore equivalent to unconstrained full isomorphism.
260
+ """
261
+ left_rc = HExtend._changed_bond_core(left)
262
+ right_rc = HExtend._changed_bond_core(right)
263
+ if (
264
+ left_rc.is_directed() != right_rc.is_directed()
265
+ or left_rc.is_multigraph() != right_rc.is_multigraph()
266
+ ):
267
+ return False
268
+ if (
269
+ left_rc.number_of_nodes() != right_rc.number_of_nodes()
270
+ or left_rc.number_of_edges() != right_rc.number_of_edges()
271
+ ):
272
+ return False
273
+ if left_rc.number_of_nodes() == 0:
274
+ return stereo_isomorphic(
275
+ left,
276
+ right,
277
+ node_match=cluster.nodeMatch,
278
+ edge_match=cluster.edgeMatch,
279
+ )
280
+ if left_rc.is_directed():
281
+ matcher_type = (
282
+ nx.algorithms.isomorphism.MultiDiGraphMatcher
283
+ if left_rc.is_multigraph()
284
+ else nx.algorithms.isomorphism.DiGraphMatcher
285
+ )
286
+ else:
287
+ matcher_type = (
288
+ nx.algorithms.isomorphism.MultiGraphMatcher
289
+ if left_rc.is_multigraph()
290
+ else nx.algorithms.isomorphism.GraphMatcher
291
+ )
292
+ matcher = matcher_type(
293
+ left_rc,
294
+ right_rc,
295
+ node_match=cluster.nodeMatch,
296
+ edge_match=cluster.edgeMatch,
297
+ )
298
+ anchored_left = left.copy()
299
+ anchored_right = right.copy()
300
+ nx.set_node_attributes(anchored_left, None, _ANCHOR_ATTRIBUTE)
301
+ nx.set_node_attributes(anchored_right, None, _ANCHOR_ATTRIBUTE)
302
+ for rc_mapping in matcher.isomorphisms_iter():
303
+ for anchor, (left_node, right_node) in enumerate(rc_mapping.items()):
304
+ anchored_left.nodes[left_node][_ANCHOR_ATTRIBUTE] = anchor
305
+ anchored_right.nodes[right_node][_ANCHOR_ATTRIBUTE] = anchor
306
+ if stereo_isomorphic(
307
+ anchored_left,
308
+ anchored_right,
309
+ node_match=_anchored_node_match,
310
+ edge_match=cluster.edgeMatch,
311
+ ):
312
+ return True
313
+ return False
314
+
315
+ @staticmethod
316
+ def _changed_bond_core(its: nx.Graph) -> nx.Graph:
317
+ """Return the isomorphism-invariant subgraph of changed ITS bonds."""
318
+ core = its.__class__()
319
+ for left, right, attributes in its.edges(data=True):
320
+ order = attributes.get("order")
321
+ if (
322
+ not isinstance(order, (tuple, list))
323
+ or len(order) != 2
324
+ or order[0] == order[1]
325
+ ):
326
+ continue
327
+ if left not in core:
328
+ core.add_node(left, **its.nodes[left])
329
+ if right not in core:
330
+ core.add_node(right, **its.nodes[right])
331
+ core.add_edge(left, right, **attributes)
332
+ return core
333
+
334
+ @staticmethod
335
+ def hydrogen_distance_invariant(its: nx.Graph) -> HydrogenDistanceInvariant:
336
+ r"""Return the exact hydrogen-rooted distance multiset ``I_H(G)``.
337
+
338
+ For every hydrogen vertex ``h``, its profile is
339
+ ``D_G(h) = multiset((colour(v), distance(h, v)) for v in C_G(h))``,
340
+ where ``C_G(h)`` is the connected component containing ``h``.
341
+ ``I_H(G)`` is the multiset of all ``D_G(h)``. Any colour-preserving
342
+ graph isomorphism preserves connected components, vertex colours,
343
+ shortest-path distances, and the hydrogen vertex set, hence preserves
344
+ this value exactly.
345
+ """
346
+ resolved_format = HComplete._resolve_format(its, "auto")
347
+ comparison = HComplete._comparison_graph(its, resolved_format)
348
+ ordered_colours = sorted(
349
+ {attributes["cmp_node"] for _, attributes in comparison.nodes(data=True)},
350
+ key=_invariant_order_key,
351
+ )
352
+ colour_rank = {colour: rank for rank, colour in enumerate(ordered_colours)}
353
+ profiles: List[RootedDistanceProfile] = []
354
+ for hydrogen, attributes in comparison.nodes(data=True):
355
+ if attributes["cmp_element"] != "H":
356
+ continue
357
+ distances = nx.single_source_shortest_path_length(
358
+ comparison,
359
+ hydrogen,
360
+ )
361
+ histogram = Counter(
362
+ (colour_rank[comparison.nodes[node]["cmp_node"]], distance)
363
+ for node, distance in distances.items()
364
+ )
365
+ profiles.append(tuple(sorted(histogram.items())))
366
+ return tuple(sorted(profiles))
367
+
368
+ @staticmethod
369
+ def hydrogen_distance_signature(its: nx.Graph) -> HydrogenDistanceInvariant:
370
+ """Compatibility alias for :meth:`hydrogen_distance_invariant`."""
371
+ return HExtend.hydrogen_distance_invariant(its)
372
+
373
+ @staticmethod
374
+ def extend_unique_full_its(
375
+ its: nx.Graph,
376
+ ignore_aromaticity: bool = False,
377
+ balance_its: bool = True,
378
+ format: ITSFormatInput = "auto",
379
+ max_candidates: Optional[int] = None,
380
+ ) -> Tuple[List[nx.Graph], List[nx.Graph], List[str]]:
381
+ """Return one representative per exact complete-ITS class."""
382
+ rc_list, its_list, signatures = HExtend.extend_its(
383
+ its,
384
+ ignore_aromaticity=ignore_aromaticity,
385
+ balance_its=balance_its,
386
+ format=format,
387
+ max_candidates=max_candidates,
388
+ )
389
+ clusters, _ = HExtend.cluster_full_its(its_list, signatures)
390
+ indices = [min(items) for items in clusters if items]
391
+ return (
392
+ [rc_list[index] for index in indices],
393
+ [its_list[index] for index in indices],
394
+ [signatures[index] for index in indices],
395
+ )
396
+
397
+ @staticmethod
398
+ def iter_unique_completions(
399
+ its: nx.Graph,
400
+ ignore_aromaticity: bool = False,
401
+ balance_its: bool = True,
402
+ format: ITSFormatInput = "auto",
403
+ max_candidates: Optional[int] = None,
404
+ ) -> Iterator[Tuple[nx.Graph, nx.Graph, str]]:
405
+ """Yield one completed ``(RC, ITS, signature)`` per exact RC class."""
406
+ if not isinstance(its, nx.Graph) or its.number_of_nodes() == 0:
407
+ return
408
+
409
+ resolved_format = HComplete._resolve_format(its, format)
410
+ react_graph, prod_graph = HComplete._decompose_its(its, resolved_format)
411
+ hcount_change = check_hcount_change(react_graph, prod_graph)
412
+ if hcount_change == 0:
413
+ rc = HComplete._extract_rc(its, resolved_format)
414
+ if not HComplete._valid_rc(rc):
415
+ return
416
+ yield rc, its, HComplete._rc_signature(rc, resolved_format)
417
+ return
418
+
419
+ representatives = []
420
+ for (
421
+ _,
422
+ _,
423
+ completed_its,
424
+ rc,
425
+ signature,
426
+ ) in HComplete._iter_hydrogen_node_completions(
427
+ react_graph,
428
+ prod_graph,
429
+ ignore_aromaticity,
430
+ balance_its,
431
+ format=resolved_format,
432
+ max_candidates=max_candidates,
433
+ ):
434
+ if not HComplete._valid_rc(rc):
435
+ continue
436
+
437
+ duplicate = False
438
+ for representative_rc, representative_signature in representatives:
439
+ if signature != representative_signature:
440
+ continue
441
+ if (
442
+ HComplete._equivariant_count(
443
+ [representative_rc, rc], resolved_format
444
+ )
445
+ == 1
446
+ ):
447
+ duplicate = True
448
+ break
449
+ if not duplicate:
450
+ representatives.append((rc, signature))
451
+ yield rc, completed_its, signature
452
+
453
+ @staticmethod
454
+ def _process(
455
+ data_dict: Dict,
456
+ its_key: str,
457
+ rc_key: str,
458
+ ignore_aromaticity: bool,
459
+ balance_its: bool,
460
+ format: ITSFormatInput = "auto",
461
+ max_candidates: Optional[int] = None,
462
+ ) -> Dict:
463
+ """Processes a dictionary of graphs using specific graph processing
464
+ functions and updates the dictionary with new graph data.
465
+
466
+ :param data_dict: Dictionary containing the graphs and their keys.
467
+ :type data_dict: Dict
468
+ :param its_key: Key in the dictionary for the ITS graph.
469
+ :type its_key: str
470
+ :param rc_key: Key in the dictionary for the reaction graph.
471
+ :type rc_key: str
472
+ :param ignore_aromaticity: Whether to ignore aromaticity
473
+ during graph processing.
474
+ :type ignore_aromaticity: bool
475
+ :param balance_its: Whether to balance the ITS graph.
476
+ :type balance_its: bool
477
+ :param format: ITS representation: "auto", "typesGH", or "tuple".
478
+ :type format: str
479
+ :param max_candidates: Optional cap for enumerated hydrogen assignments.
480
+ :type max_candidates: Optional[int]
481
+
482
+ :return: The updated dictionary containing new ITS and reaction graphs.
483
+ :rtype: Dict
484
+ """
485
+ its = data_dict[its_key]
486
+ resolved_format = HComplete._resolve_format(its, format)
487
+ rc_list, its_list, _ = HExtend._extend_unique(
488
+ its, ignore_aromaticity, balance_its, resolved_format, max_candidates
489
+ )
490
+ if not rc_list:
491
+ data_dict[rc_key] = []
492
+ data_dict[its_key] = []
493
+ return data_dict
494
+ data_dict[rc_key] = rc_list
495
+ data_dict[its_key] = its_list
496
+ return data_dict
497
+
498
+ @staticmethod
499
+ def fit(
500
+ data,
501
+ its_key: str,
502
+ rc_key: str,
503
+ ignore_aromaticity: bool = False,
504
+ balance_its: bool = True,
505
+ n_jobs: int = 1,
506
+ verbose: int = 0,
507
+ format: ITSFormatInput = "auto",
508
+ max_candidates: Optional[int] = None,
509
+ backend: Optional[str] = None,
510
+ ) -> List:
511
+ """Fit the model to the data in parallel, processing each entry to
512
+ generate new graph data based on the ITS and reaction graph keys.
513
+
514
+ :param data: Data to be processed.
515
+ :type data: iterable
516
+ :param its_key: Key for the ITS graphs in the data.
517
+ :type its_key: str
518
+ :param rc_key: Key for the reaction graphs in the data.
519
+ :type rc_key: str
520
+ :param ignore_aromaticity: Whether to ignore aromaticity during processing.
521
+ Default to False.
522
+ :type ignore_aromaticity: bool
523
+ :param balance_its: Whether to balance the ITS during processing.
524
+ Default to True.
525
+ :type balance_its: bool
526
+ :param n_jobs: Number of jobs to run in parallel. Default to 1.
527
+ :type n_jobs: int
528
+ :param verbose: Verbosity level for parallel processing. Default to 0.
529
+ :type verbose: int
530
+ :param format: ITS representation: "auto", "typesGH", or "tuple".
531
+ :type format: str
532
+ :param max_candidates: Optional cap for enumerated hydrogen assignments.
533
+ :type max_candidates: Optional[int]
534
+ :param backend: Optional joblib backend.
535
+ :type backend: Optional[str]
536
+
537
+ :return: A list containing the results of the processed data.
538
+ :rtype: List
539
+ """
540
+ if n_jobs == 1 and backend is None:
541
+ return [
542
+ HExtend._process(
543
+ item,
544
+ its_key,
545
+ rc_key,
546
+ ignore_aromaticity,
547
+ balance_its,
548
+ format,
549
+ max_candidates,
550
+ )
551
+ for item in data
552
+ ]
553
+
554
+ parallel_kwargs = {"n_jobs": n_jobs, "verbose": verbose}
555
+ if backend is not None:
556
+ parallel_kwargs["backend"] = backend
557
+
558
+ results = Parallel(**parallel_kwargs)(
559
+ delayed(HExtend._process)(
560
+ item,
561
+ its_key,
562
+ rc_key,
563
+ ignore_aromaticity,
564
+ balance_its,
565
+ format,
566
+ max_candidates,
567
+ )
568
+ for item in data
569
+ )
570
+ return results