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,309 @@
1
+ """Reference-blind implicit-H Lewis proofs with exact H-component offsets.
2
+
3
+ This preparation does not call a mapper or expand H. Product isotope-zero H
4
+ may be ordinary neutral terminal H, isolated isotope-zero H, or isolated
5
+ ordinary H2. Free positive-electron H is matched by sorted electron counts
6
+ when positive-electron isotope-zero source H is also isolated. Source
7
+ free/charged/radical/H2/isotopic H is supported by separating its
8
+ mapping-independent objective terms. Matched
9
+ ordinary H2 bonds contribute a constant alongside attached-H counts. It returns
10
+ prepared heavy graphs and an **integer doubled-CD offset**, never H classes.
11
+ """
12
+
13
+ from collections import Counter
14
+
15
+ from rdkit import Chem
16
+
17
+ from synkit.Chem.Mapper.graph.labeled_graph import LabeledGraph
18
+ from synkit.IO.mol_to_graph import MolToGraph
19
+
20
+ from .reaction_text import split_reaction_fields
21
+
22
+
23
+ class UnsupportedImplicitHydrogen(ValueError):
24
+ """The stated constant/count reduction cannot prove this model."""
25
+
26
+ def __init__(self, reason):
27
+ self.reason = reason
28
+ super().__init__(reason)
29
+
30
+
31
+ def _weight2(bond):
32
+ value = bond.GetBondTypeAsDouble() * 2
33
+ encoded = round(value)
34
+ if abs(value - encoded) > 1e-9 or encoded < 0:
35
+ raise UnsupportedImplicitHydrogen("non_half_integer_bond_weight")
36
+ return encoded
37
+
38
+
39
+ def _electrons(atom):
40
+ return 2 * MolToGraph.estimate_lone_pairs(atom) + atom.GetNumRadicalElectrons()
41
+
42
+
43
+ # Model guards and reduction offsets must remain paired with their endpoint data.
44
+ def prepare_implicit_problem(reaction, *, balance="dummy"): # noqa: C901
45
+ """Return ``(heavy_graphs, offset2, metadata)`` for a mapless reaction.
46
+
47
+ Native proof costs for these graphs are in CD units; add offset2/2 once to
48
+ minimum/incumbent costs, or offset2 once to their doubled-CD counterparts.
49
+ This reduction is numeric/proof-only: it does not infer reference H truth
50
+ or enumerate H/class output. All map tags are forbidden at this blind API.
51
+
52
+ ``UnsupportedImplicitHydrogen.reason`` gives an explicit unsupported-model
53
+ code. Invalid SMILES, maps, wildcards and strict inventory mismatch raise
54
+ ordinary ValueError. A caller may then use a separately labeled full-H
55
+ native proof with the remaining original budget.
56
+ """
57
+ if not isinstance(reaction, str):
58
+ raise TypeError("reaction must be mapless reaction SMILES")
59
+ if balance not in {"dummy", "strict"}:
60
+ raise ValueError("balance must be 'dummy' or 'strict'")
61
+ parts = split_reaction_fields(
62
+ reaction,
63
+ error_message="Expected reactants>agents>products or reactants>>products",
64
+ )
65
+ if not parts[0] or not parts[2]:
66
+ raise ValueError("Expected reactants>agents>products or reactants>>products")
67
+ params = Chem.SmilesParserParams()
68
+ params.removeHs = False
69
+ mols = [Chem.MolFromSmiles(parts[i], params) for i in (0, 2)]
70
+ if any(mol is None for mol in mols):
71
+ raise ValueError("Could not parse reaction endpoint")
72
+ if any(atom.GetAtomMapNum() for mol in mols for atom in mol.GetAtoms()):
73
+ raise ValueError("Reference-blind PMCD preparation requires mapless endpoints")
74
+ if any(atom.GetAtomicNum() == 0 for mol in mols for atom in mol.GetAtoms()):
75
+ raise ValueError("Wildcard atoms require a concrete element")
76
+
77
+ heavy = [[atom for atom in mol.GetAtoms() if atom.GetAtomicNum() != 1] for mol in mols]
78
+ counts = [[MolToGraph._non_neighbor_h_count(atom) for atom in atoms] for atoms in heavy]
79
+ positions = [{atom.GetIdx(): i for i, atom in enumerate(atoms)} for atoms in heavy]
80
+ hydrogen_inventories = []
81
+ for side, mol in enumerate(mols):
82
+ inventory = Counter({0: sum(counts[side])})
83
+ for atom in mol.GetAtoms():
84
+ if atom.GetAtomicNum() == 1:
85
+ inventory[atom.GetIsotope()] += 1
86
+ hydrogen_inventories.append(+inventory)
87
+
88
+ # Positive-electron isotope-zero H must be free on both endpoints.
89
+ # Sorted electron matching is disjoint from attached-H and H2 matches.
90
+ product_positive_free_ids = set()
91
+ product_free_electrons = []
92
+ for atom in mols[1].GetAtoms():
93
+ if atom.GetAtomicNum() != 1 or atom.GetIsotope() or not _electrons(atom):
94
+ continue
95
+ if atom.GetDegree() or MolToGraph._non_neighbor_h_count(atom):
96
+ raise UnsupportedImplicitHydrogen("product_nonfree_positive_electron_hydrogen")
97
+ product_positive_free_ids.add(atom.GetIdx())
98
+ product_free_electrons.append(_electrons(atom))
99
+ source_free_electrons = []
100
+ if product_free_electrons:
101
+ for atom in mols[0].GetAtoms():
102
+ if atom.GetAtomicNum() != 1 or atom.GetIsotope() or not _electrons(atom):
103
+ continue
104
+ if atom.GetDegree() or MolToGraph._non_neighbor_h_count(atom):
105
+ raise UnsupportedImplicitHydrogen(
106
+ "source_nonfree_positive_electron_hydrogen_for_product_free_H_extension"
107
+ )
108
+ source_free_electrons.append(_electrons(atom))
109
+ source_free_electrons.sort(reverse=True)
110
+ product_free_electrons.sort(reverse=True)
111
+ preserved_free_electrons = sum(min(a, b) for a, b in zip(source_free_electrons, product_free_electrons))
112
+ # H2 components and heavy-attached H use disjoint vertices on both sides.
113
+ # Thus maximum preserved H-H bonds and maximum preserved heavy-H bonds
114
+ # can be attained simultaneously for every fixed typed heavy bijection.
115
+ # Isotopic source H-H bonds cannot match isotope-zero product dimers.
116
+ product_h2_atoms = set()
117
+ product_h2 = source_h2 = 0
118
+ for bond in mols[1].GetBonds():
119
+ pair = (bond.GetBeginAtom(), bond.GetEndAtom())
120
+ if not all(atom.GetAtomicNum() == 1 for atom in pair):
121
+ continue
122
+ if any(atom.GetIsotope() for atom in pair):
123
+ raise UnsupportedImplicitHydrogen("product_isotopic_hydrogen")
124
+ if _weight2(bond) != 2 or any(
125
+ atom.GetFormalCharge()
126
+ or atom.GetNumRadicalElectrons()
127
+ or atom.GetDegree() != 1
128
+ or _electrons(atom)
129
+ or MolToGraph._non_neighbor_h_count(atom)
130
+ for atom in pair
131
+ ):
132
+ raise UnsupportedImplicitHydrogen("product_nonordinary_hydrogen_H2_component")
133
+ product_h2 += 1
134
+ product_h2_atoms.update(atom.GetIdx() for atom in pair)
135
+ if product_h2:
136
+ for bond in mols[0].GetBonds():
137
+ pair = (bond.GetBeginAtom(), bond.GetEndAtom())
138
+ if not all(atom.GetAtomicNum() == 1 for atom in pair):
139
+ continue
140
+ if _weight2(bond) != 2 or any(atom.GetDegree() != 1 for atom in pair):
141
+ raise UnsupportedImplicitHydrogen("source_nonisolated_or_nonunit_HH_for_H2_extension")
142
+ if all(atom.GetIsotope() == 0 for atom in pair):
143
+ if any(atom.GetFormalCharge() or atom.GetNumRadicalElectrons() or _electrons(atom) for atom in pair):
144
+ raise UnsupportedImplicitHydrogen("source_nonordinary_H2_for_product_H2_extension")
145
+ source_h2 += 1
146
+
147
+ offset_hh2 = offset_electrons2 = offset_isotope_edges2 = 0
148
+ source_free0 = source_isotope = source_attached0 = product_free0 = 0
149
+ for side, mol in enumerate(mols):
150
+ for atom in mol.GetAtoms():
151
+ if atom.GetAtomicNum() != 1:
152
+ continue
153
+ if MolToGraph._non_neighbor_h_count(atom):
154
+ raise UnsupportedImplicitHydrogen("non_neighbor_hydrogen_on_hydrogen")
155
+ neighbors = [
156
+ (bond.GetOtherAtom(atom), bond)
157
+ for bond in atom.GetBonds()
158
+ if bond.GetOtherAtom(atom).GetAtomicNum() != 1
159
+ ]
160
+ if side == 1:
161
+ if atom.GetIdx() in product_positive_free_ids:
162
+ product_free0 += 1
163
+ continue
164
+ if atom.GetIdx() in product_h2_atoms:
165
+ continue
166
+ if atom.GetIsotope():
167
+ raise UnsupportedImplicitHydrogen("product_isotopic_hydrogen")
168
+ # Isolated isotope-zero product H with zero modeled electron
169
+ # weight is a free reservoir, like a zero-incidence typed H
170
+ # dummy. In particular H+ needs no vertex expansion. Its
171
+ # endpoint charge/state remains in the caller's raw molecule.
172
+ if not atom.GetBonds() and not atom.GetNumRadicalElectrons() and not _electrons(atom):
173
+ product_free0 += 1
174
+ continue
175
+ if (
176
+ atom.GetFormalCharge()
177
+ or atom.GetNumRadicalElectrons()
178
+ or len(atom.GetBonds()) != 1
179
+ or len(neighbors) != 1
180
+ or _weight2(neighbors[0][1]) != 2
181
+ ):
182
+ raise UnsupportedImplicitHydrogen("product_nonordinary_hydrogen")
183
+ if _electrons(atom):
184
+ raise UnsupportedImplicitHydrogen("product_nonzero_hydrogen_electrons")
185
+ counts[side][positions[side][neighbors[0][0].GetIdx()]] += 1
186
+ continue
187
+
188
+ # Begin with source H electron loss. When positive-electron
189
+ # product H is supported, subtract the optimal free-H overlap
190
+ # after both endpoints have been counted.
191
+ offset_electrons2 += _electrons(atom)
192
+ if atom.GetIsotope():
193
+ # Product has no real isotope-H: all such source atoms map to
194
+ # typed zero-state dummies. Their heavy edges are all lost.
195
+ source_isotope += 1
196
+ offset_isotope_edges2 += sum(_weight2(bond) for _, bond in neighbors)
197
+ elif not neighbors:
198
+ source_free0 += 1
199
+ elif len(neighbors) == 1 and _weight2(neighbors[0][1]) == 2:
200
+ counts[side][positions[side][neighbors[0][0].GetIdx()]] += 1
201
+ source_attached0 += 1
202
+ else:
203
+ raise UnsupportedImplicitHydrogen("source_nonunit_or_multiple_heavy_hydrogen_incidence")
204
+ if side == 0:
205
+ offset_hh2 = sum(
206
+ _weight2(bond)
207
+ for bond in mol.GetBonds()
208
+ if bond.GetBeginAtom().GetAtomicNum() == bond.GetEndAtom().GetAtomicNum() == 1
209
+ )
210
+
211
+ source_hh2 = offset_hh2
212
+ offset_hh2 += 2 * product_h2 - 4 * min(source_h2, product_h2)
213
+ if sum(counts[1]) + product_free0 + 2 * product_h2 != hydrogen_inventories[1].get(0, 0):
214
+ raise UnsupportedImplicitHydrogen("product_hydrogen_count_model_mismatch")
215
+ inventories = [Counter((atom.GetAtomicNum(), atom.GetIsotope()) for atom in atoms) for atoms in heavy]
216
+ if balance == "strict" and (inventories[0] != inventories[1] or hydrogen_inventories[0] != hydrogen_inventories[1]):
217
+ raise ValueError("Unbalanced atom inventories; select balance='dummy' explicitly")
218
+ universe = inventories[0] | inventories[1]
219
+ graphs = []
220
+ for side, atoms in enumerate(heavy):
221
+ missing = sorted((universe - inventories[side]).elements())
222
+ labels = [(atom.GetAtomicNum(), atom.GetIsotope()) for atom in atoms] + missing
223
+ hcounts = counts[side] + [0] * len(missing)
224
+ electrons = [_electrons(atom) for atom in atoms] + [0] * len(missing)
225
+ n = len(labels)
226
+ adjacency = {i: {} for i in range(n + 2)}
227
+ for bond in mols[side].GetBonds():
228
+ left, right = bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()
229
+ if left in positions[side] and right in positions[side]:
230
+ i, j = positions[side][left], positions[side][right]
231
+ adjacency[i][j] = adjacency[j][i] = _weight2(bond) / 2
232
+ for i, (hydrogen, electron) in enumerate(zip(hcounts, electrons)):
233
+ if hydrogen:
234
+ adjacency[i][n + 1] = adjacency[n + 1][i] = hydrogen
235
+ if electron:
236
+ adjacency[i][n] = adjacency[n][i] = electron / 2
237
+ graph = LabeledGraph(adjacency, labels + [(0, -1), (0, -2)])
238
+ graph.props["hcounts"] = hcounts + [0, 0]
239
+ graph.props["electrons"] = electrons + [0, 0]
240
+ graphs.append(graph)
241
+
242
+ offset_electrons2 += sum(product_free_electrons) - 2 * preserved_free_electrons
243
+ offset2 = offset_hh2 + offset_electrons2 + offset_isotope_edges2
244
+ metadata = {
245
+ "model": (
246
+ "full_lewis_pmcd_source_H_constant_and_product_H_counts_with_free_zero_electron_reservoir"
247
+ if product_free0
248
+ else "full_lewis_pmcd_source_H_constant_and_ordinary_product_H_counts"
249
+ ),
250
+ "objective": "normalized_full_lewis_distance",
251
+ "balance": balance,
252
+ "references_used": False,
253
+ "offset_units": "doubled_chemical_distance",
254
+ "offset2": offset2,
255
+ "offset_HH2": offset_hh2,
256
+ "offset_H_electrons2": offset_electrons2,
257
+ "offset_isotope_H_heavy2": offset_isotope_edges2,
258
+ "heavy_atoms_r": len(heavy[0]),
259
+ "heavy_atoms_p": len(heavy[1]),
260
+ "heavy_original_indices_r": [atom.GetIdx() for atom in heavy[0]],
261
+ "heavy_original_indices_p": [atom.GetIdx() for atom in heavy[1]],
262
+ "hydrogens_r": sum(hydrogen_inventories[0].values()),
263
+ "hydrogens_p": sum(hydrogen_inventories[1].values()),
264
+ "source_explicit_isotope0_attached": source_attached0,
265
+ "source_explicit_isotope0_zero_heavy_incidence": source_free0,
266
+ "source_explicit_isotopic_H": source_isotope,
267
+ "product_explicit_isotope0_zero_heavy_incidence": product_free0,
268
+ "product_H_ordinary": product_free0 == 0,
269
+ "product_H_supported_domain": ("ordinary_terminal_or_isolated_zero_electron_isotope0"),
270
+ "search_atoms": len(graphs[0].labels),
271
+ "hydrogen_nodes_added": 0,
272
+ "hydrogen_vertices_searched": 0,
273
+ "scope": "numeric_PMCD_proof_only_no_H_or_class_enumeration",
274
+ }
275
+ if product_h2:
276
+ metadata.update(
277
+ model="full_lewis_pmcd_attached_H_counts_and_isolated_ordinary_H2_v1",
278
+ product_H_supported_domain="ordinary_terminal_or_isolated_zero_electron_isotope0_or_ordinary_H2",
279
+ product_H_ordinary=False,
280
+ product_explicit_isotope0_zero_heavy_incidence=product_free0 + 2 * product_h2,
281
+ product_isolated_zero_electron_reservoir=product_free0,
282
+ product_H2_molecules=product_h2,
283
+ source_ordinary_H2_molecules=source_h2,
284
+ source_HH_bond_weight2=source_hh2,
285
+ preserved_H2_bonds=min(source_h2, product_h2),
286
+ H2_reduction="disjoint_attached_H_and_ordinary_H2_matching_v1",
287
+ )
288
+ if product_free_electrons:
289
+ metadata.update(
290
+ model="full_lewis_pmcd_free_H_electron_reservoir_with_attached_H_and_H2_v1",
291
+ product_H_supported_domain=metadata["product_H_supported_domain"] + "_or_free_positive_electron_isotope0_H",
292
+ product_H_ordinary=False,
293
+ source_free_H_electrons=source_free_electrons,
294
+ product_free_H_electrons=product_free_electrons,
295
+ preserved_free_H_electron_overlap=preserved_free_electrons,
296
+ product_isolated_zero_electron_reservoir=product_free0 - len(product_free_electrons),
297
+ free_H_electron_reduction="descending_positive_free_H_electron_matching_v1",
298
+ )
299
+ return tuple(graphs), offset2, metadata
300
+
301
+
302
+ # The experiment API retains the same callable and exception identities.
303
+ prepare_implicit_pmcd = prepare_implicit_problem
304
+
305
+ __all__ = [
306
+ "UnsupportedImplicitHydrogen",
307
+ "prepare_implicit_pmcd",
308
+ "prepare_implicit_problem",
309
+ ]
@@ -0,0 +1,16 @@
1
+ """Weighted common-edge overlap mapping through a native association graph."""
2
+
3
+ from .core import enumerate_core_mappings, map_reaction_core
4
+
5
+
6
+ def enumerate_mces_mappings(lgp, *, library_path, **options):
7
+ """Enumerate full-bijection minimum/exact/at-most weighted Lewis mappings."""
8
+ return enumerate_core_mappings(
9
+ lgp, library_path=library_path, backend="mces", **options
10
+ )
11
+
12
+
13
+ def map_reaction_mces(reaction, *, library_path, **options):
14
+ return map_reaction_core(
15
+ reaction, library_path=library_path, backend="mces", **options
16
+ )
@@ -0,0 +1,179 @@
1
+ """Thin bindings for the complete optional RDKit C++ reaction pipeline."""
2
+
3
+ import ctypes as ct
4
+ import json
5
+ import math
6
+ from functools import lru_cache
7
+ from numbers import Integral
8
+ from pathlib import Path
9
+
10
+ from ..exact.distance_search.records import normalize_distance_target
11
+ from .runtime import BACKENDS, Request
12
+
13
+
14
+ class _Options(ct.Structure):
15
+ _fields_ = [
16
+ (name, ct.c_int32)
17
+ for name in (
18
+ "abi_version",
19
+ "explicit_hydrogens",
20
+ "lewis_objective",
21
+ "dummy_balance",
22
+ "binary",
23
+ "hydrogen_quotient",
24
+ "empty_numeric_shell",
25
+ )
26
+ ] + [("max_canonical_nodes", ct.c_int64), ("max_hydrogen_plans", ct.c_int64)]
27
+
28
+
29
+ @lru_cache(maxsize=8)
30
+ def _load(path):
31
+ library = ct.CDLL(str(Path(path).resolve()))
32
+ if library.synkit_mapper_reaction_abi() != 1:
33
+ raise RuntimeError("Unsupported native reaction ABI")
34
+ library.synkit_mapper_reaction_error.restype = ct.c_char_p
35
+ library.synkit_mapper_rdkit_version.restype = ct.c_char_p
36
+ library.synkit_mapper_reaction_solve.argtypes = [
37
+ ct.c_char_p,
38
+ ct.POINTER(_Options),
39
+ ct.POINTER(Request),
40
+ ct.POINTER(ct.c_void_p),
41
+ ]
42
+ library.synkit_mapper_reaction_free.argtypes = [ct.c_void_p]
43
+ return library
44
+
45
+
46
+ def _cap(value, name):
47
+ if value is None:
48
+ return -1
49
+ if (
50
+ isinstance(value, bool)
51
+ or not isinstance(value, Integral)
52
+ or not 0 < value < 2**63
53
+ ):
54
+ raise ValueError(f"{name} must be a positive int64 or None")
55
+ return int(value)
56
+
57
+
58
+ # ABI option checks and hydrogen fallback share the native reaction deadline.
59
+ def map_reaction_native( # noqa: C901
60
+ reaction,
61
+ *,
62
+ library_path,
63
+ backend="pabs",
64
+ CD="minimal",
65
+ CD_mode="exact",
66
+ objective="lewis",
67
+ hydrogen=None,
68
+ balance="strict",
69
+ binary=False,
70
+ hydrogen_quotient=False,
71
+ time_limit_seconds=10,
72
+ max_mappings=100000,
73
+ max_classes=None,
74
+ max_states=None,
75
+ max_frontier=None,
76
+ memory_limit_bytes=None,
77
+ classification_max_search_nodes=100000,
78
+ max_hydrogen_plans=10000,
79
+ proof_only=False,
80
+ cancel_token=None,
81
+ ):
82
+ """Return native JSON records after C++ parsing, search and mapped rendering.
83
+
84
+ This adapter imports no Python RDKit chemistry functions. It loads the
85
+ explicitly built reaction library, converts options and decodes its JSON.
86
+ Unsupported H quotient states fall back to full explicit native search on
87
+ the remaining shared budget; the result records that fallback and its reason.
88
+ """
89
+ if not isinstance(reaction, str):
90
+ raise TypeError("reaction must be reaction SMILES")
91
+ if "\x00" in reaction:
92
+ raise ValueError("reaction cannot contain a NUL character")
93
+ if backend not in BACKENDS:
94
+ raise ValueError(f"Unknown native backend: {backend}")
95
+ if objective not in {"lewis", "bond"} or balance not in {"strict", "dummy"}:
96
+ raise ValueError("objective must be lewis/bond and balance strict/dummy")
97
+ hydrogen = hydrogen or ("explicit" if objective == "lewis" else "heavy")
98
+ if hydrogen not in {"explicit", "heavy"}:
99
+ raise ValueError(
100
+ "Native reaction frontend requires explicit or heavy hydrogens"
101
+ )
102
+ for name, flag in (
103
+ ("binary", binary),
104
+ ("hydrogen_quotient", hydrogen_quotient),
105
+ ("proof_only", proof_only),
106
+ ):
107
+ if not isinstance(flag, bool):
108
+ raise TypeError(f"{name} must be boolean")
109
+ if objective == "lewis" and (hydrogen != "explicit" or binary):
110
+ raise ValueError("Lewis objective requires explicit H and weighted bonds")
111
+ if time_limit_seconds is not None and (
112
+ isinstance(time_limit_seconds, bool)
113
+ or not isinstance(time_limit_seconds, (int, float))
114
+ or not math.isfinite(time_limit_seconds)
115
+ or time_limit_seconds < 0
116
+ ):
117
+ raise ValueError("time_limit_seconds must be finite and nonnegative or None")
118
+ target = normalize_distance_target(CD)
119
+ if CD_mode not in {"exact", "at_most"} or (
120
+ CD_mode == "at_most" and target == "minimal"
121
+ ):
122
+ raise ValueError("at_most requires numeric CD; otherwise use exact")
123
+ if proof_only and target != "minimal":
124
+ raise ValueError("proof_only requires minimal CD")
125
+ query = (
126
+ 3
127
+ if proof_only
128
+ else 0
129
+ if target == "minimal"
130
+ else 2
131
+ if CD_mode == "at_most"
132
+ else 1
133
+ )
134
+ empty = False
135
+ target2 = 0
136
+ if target != "minimal":
137
+ scaled = min(target * 2, 2**62)
138
+ target2 = math.floor(scaled + 1e-9) if query == 2 else round(scaled)
139
+ empty = query == 1 and abs(target - target2 / 2) > 1e-9
140
+ request = Request()
141
+ request.abi_version = 1
142
+ request.backend = BACKENDS[backend]
143
+ request.query = query
144
+ request.symmetry = int(backend in {"pabs", "cpabs"})
145
+ request.workers = 1
146
+ request.target2 = target2
147
+ request.seconds = -1 if time_limit_seconds is None else time_limit_seconds
148
+ request.slap_max_fingerprints = 10000
149
+ for name, value in (
150
+ ("max_states", max_states),
151
+ ("max_candidates", max_mappings),
152
+ ("max_classes", max_classes),
153
+ ("max_frontier", max_frontier),
154
+ ("memory_limit_bytes", memory_limit_bytes),
155
+ ):
156
+ setattr(request, name, _cap(value, name))
157
+ request.cancel_token = None if cancel_token is None else cancel_token.pointer
158
+ options = _Options(
159
+ 1,
160
+ hydrogen == "explicit",
161
+ objective == "lewis",
162
+ balance == "dummy",
163
+ binary,
164
+ hydrogen_quotient,
165
+ empty,
166
+ _cap(classification_max_search_nodes, "classification_max_search_nodes"),
167
+ _cap(max_hydrogen_plans, "max_hydrogen_plans"),
168
+ )
169
+ library = _load(str(library_path))
170
+ output = ct.c_void_p()
171
+ result = library.synkit_mapper_reaction_solve(
172
+ reaction.encode(), ct.byref(options), ct.byref(request), ct.byref(output)
173
+ )
174
+ if result:
175
+ raise ValueError(library.synkit_mapper_reaction_error().decode())
176
+ try:
177
+ return json.loads(ct.string_at(output))
178
+ finally:
179
+ library.synkit_mapper_reaction_free(output)