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,244 @@
1
+ import copy
2
+ from collections import defaultdict
3
+ from typing import List, Any, Dict, Tuple, Callable
4
+
5
+ from synkit.IO.debug import setup_logging
6
+ from synkit.Graph.Feature.wl_hash import WLHash
7
+ from synkit.Graph.Context.radius_expand import RadiusExpand
8
+ from synkit.Graph.Matcher.batch_cluster import BatchCluster
9
+
10
+ logger = setup_logging()
11
+
12
+
13
+ class HierContext(RadiusExpand):
14
+ """Hierarchical clustering class for reaction context graphs.
15
+
16
+ Extends RadiusExpand to build multi-level graph representations and
17
+ clusters them based on structural features such as Weisfeiler-Lehman
18
+ hashing.
19
+ """
20
+
21
+ def __init__(
22
+ self,
23
+ node_label_names: List[str] = ["element", "charge"],
24
+ node_label_default: List[Any] = ["*", 0],
25
+ edge_attribute: str = "order",
26
+ max_radius: int = 3,
27
+ ) -> None:
28
+ """Initializes the HierContext class for hierarchical clustering of
29
+ reaction context graphs.
30
+
31
+ :param node_label_names: A list of node attribute names used for matching.
32
+ :type node_label_names: List[str]
33
+ :param node_label_default: A list of default values for node attributes.
34
+ :type node_label_default: List[Any]
35
+ :param edge_attribute: The edge attribute used in matching.
36
+ :type edge_attribute: str
37
+ :param max_radius: The maximum hierarchical level (radius) to be considered.
38
+ :type max_radius: int
39
+ """
40
+ super().__init__()
41
+ self.radius: List[int] = list(range(max_radius + 1))
42
+ self.node_label_names: List[str] = node_label_names
43
+ self.node_label_default: List[Any] = node_label_default
44
+ self.edge_attribute: str = edge_attribute
45
+ self.cluster: BatchCluster = BatchCluster(
46
+ self.node_label_names, self.node_label_default, self.edge_attribute
47
+ )
48
+
49
+ @staticmethod
50
+ def _group_class(
51
+ data: List[Dict[str, Any]], key: str
52
+ ) -> Dict[Any, List[Dict[str, Any]]]:
53
+ """Groups a list of dictionaries into subgroups based on the specified
54
+ key.
55
+
56
+ :param data: A list of dictionaries to be grouped.
57
+ :type data: List[Dict[str, Any]]
58
+ :param key: The key used for grouping items.
59
+ :type key: str
60
+
61
+ :return: Dictionary grouping entries by the selected key value.
62
+ :rtype: Dict[Any, List[Dict[str, Any]]]
63
+ """
64
+ grouped_data: Dict[Any, List[Dict[str, Any]]] = defaultdict(list)
65
+ for item in data:
66
+ grouped_data[item.get(key)].append(item)
67
+ return dict(grouped_data)
68
+
69
+ @staticmethod
70
+ def _update_child_idx(
71
+ data: List[List[Dict[str, Any]]], cls_id: str = "class"
72
+ ) -> List[List[Dict[str, Any]]]:
73
+ """Updates hierarchical templates by assigning child IDs based on
74
+ parent–cluster relationships.
75
+
76
+ :param data: A list of layers, where each layer is a list of dictionaries
77
+ containing node data.
78
+ :type data: List[List[Dict[str, Any]]]
79
+ :param cls_id: The key used to identify the node's class or cluster ID (default is "class").
80
+ :type cls_id: str
81
+
82
+ :return: Hierarchical data whose nodes list their child class IDs.
83
+ :rtype: List[List[Dict[str, Any]]]
84
+ """
85
+ node_dict: Dict[str, Dict[str, Any]] = {}
86
+
87
+ # Initialize the "Child" list for each node and build a mapping based on layer index and class ID.
88
+ for layer_idx, layer in enumerate(data):
89
+ for node in layer:
90
+ node["Child"] = []
91
+ node_dict[f"{layer_idx}-{node[cls_id]}"] = node
92
+
93
+ # Update parent's "Child" list by linking child nodes to their respective parent(s).
94
+ for layer_idx, layer in enumerate(data[1:], 1):
95
+ for node in layer:
96
+ parents = node.get("Parent", [])
97
+ if isinstance(parents, (int, str)):
98
+ parents = [parents]
99
+ for parent_id in parents:
100
+ parent_key = f"{layer_idx - 1}-{parent_id}"
101
+ if parent_key in node_dict:
102
+ node_dict[parent_key]["Child"].append(node[cls_id])
103
+ return data
104
+
105
+ @staticmethod
106
+ def _process(
107
+ data: List[Dict[str, Any]],
108
+ k: int,
109
+ its_key: str,
110
+ context_key: str,
111
+ cls_func: Callable,
112
+ ) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]:
113
+ """Processes a list of graph data entries by extracting context
114
+ subgraphs and computing their hashes, then classifies the data using
115
+ the provided clustering function.
116
+
117
+ :param data: A list of dictionaries, each representing a graph or data entry.
118
+ :type data: List[Dict[str, Any]]
119
+ :param k: The number of nearest neighbors to include during context extraction.
120
+ :type k: int
121
+ :param its_key: The key corresponding to the ITS graph in each data entry.
122
+ :type its_key: str
123
+ :param context_key: The key under which the extracted context subgraph will be stored.
124
+ :type context_key: str
125
+ :param cls_func: The clustering function instance to be used for clustering.
126
+ :type cls_func: Callable
127
+
128
+ :return: A tuple containing:
129
+ The list of clustered data entries with updated cluster identifiers.
130
+ The list of processed template dictionaries.
131
+ :rtype: Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]
132
+ """
133
+ for item in data:
134
+ context = RadiusExpand.extract_k(item[its_key], n_knn=k)
135
+ item[context_key] = context
136
+ item["WLHash"] = WLHash().weisfeiler_lehman_graph_hash(context)
137
+
138
+ cluster_results, templates = cls_func.cluster(data, [], context_key, "WLHash")
139
+
140
+ for result in cluster_results:
141
+ result[f"R_{k}"] = result.pop("class")
142
+
143
+ templates_processed = [
144
+ {"R-id": tpl["R-id"], context_key: tpl[context_key], "class": tpl["class"]}
145
+ for tpl in templates
146
+ ]
147
+
148
+ return cluster_results, templates_processed
149
+
150
+ def _process_level(
151
+ self,
152
+ data: List[Dict[str, Any]],
153
+ its_key: str,
154
+ context_key: str,
155
+ cls_func: Callable,
156
+ radius: int = 1,
157
+ ) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]:
158
+ """Processes a specific hierarchical level by grouping data based on
159
+ parent cluster IDs, extracting context for child levels, and clustering
160
+ the data.
161
+
162
+ :param data: A list of dictionaries representing graph data entries.
163
+ :type data: List[Dict[str, Any]]
164
+ :param its_key: The key corresponding to the ITS graph in each entry.
165
+ :type its_key: str
166
+ :param context_key: The key under which the extracted context subgraph is stored.
167
+ :type context_key: str
168
+ :param cls_func: The clustering function instance to be used.
169
+ :type cls_func: Callable
170
+ :param radius: The current hierarchical level (radius) being processed (default is 1).
171
+ :type radius: int, optional
172
+
173
+ :return: A tuple containing:
174
+ The updated list of data entries with new cluster indices for this level.
175
+ The list of newly generated template dictionaries for this level.
176
+ :rtype: Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]
177
+ """
178
+ grouped_data: Dict[Any, List[Dict[str, Any]]] = self._group_class(
179
+ data, f"R_{radius - 1}"
180
+ )
181
+ templates: List[Dict[str, Any]] = []
182
+ cluster_indices_all: List[Dict[str, Any]] = []
183
+ template_offset: int = 0
184
+
185
+ for parent_class, group in grouped_data.items():
186
+ cluster_indices, new_templates = self._process(
187
+ group, radius, its_key, context_key, cls_func
188
+ )
189
+
190
+ for ci in cluster_indices:
191
+ ci[f"R_{radius}"] += template_offset
192
+
193
+ for tpl in new_templates:
194
+ tpl["class"] += template_offset
195
+ tpl["Parent"] = parent_class
196
+
197
+ cluster_indices_all.extend(cluster_indices)
198
+ templates.extend(new_templates)
199
+ template_offset = len(templates)
200
+
201
+ return cluster_indices_all, templates
202
+
203
+ def fit(
204
+ self,
205
+ original_data: List[Dict[str, Any]],
206
+ its_key: str = "ITS",
207
+ context_key: str = "K",
208
+ ) -> Tuple[List[Dict[str, Any]], List[List[Dict[str, Any]]]]:
209
+ """Processes a list of graph data entries, classifying each based on
210
+ hierarchical clustering. The method extracts context subgraphs,
211
+ computes graph hashes, and clusters the data at multiple hierarchical
212
+ levels. Finally, child node indices are updated based on parent–cluster
213
+ relationships.
214
+
215
+ :param original_data: A list of dictionaries, each representing a graph data entry
216
+ with an ITS graph.
217
+ :type original_data: List[Dict[str, Any]]
218
+ :param its_key: The key in each dictionary corresponding to the ITS graph (default is "ITS").
219
+ :type its_key: str
220
+ :param context_key: The key under which the extracted context subgraph is stored (default is "K").
221
+ :type context_key: str
222
+
223
+ :return: A tuple containing:
224
+ The updated list of graph data entries with hierarchical cluster indices.
225
+ A list (per hierarchical level) of template dictionaries that have been updated with child indices.
226
+ :rtype: Tuple[List[Dict[str, Any]], List[List[Dict[str, Any]]]]
227
+ """
228
+ data: List[Dict[str, Any]] = copy.deepcopy(original_data)
229
+
230
+ logger.info("Processing parent level (radius 0)")
231
+ cluster_indices, templates = self._process(
232
+ data, 0, its_key, context_key, self.cluster
233
+ )
234
+ templates_all: List[List[Dict[str, Any]]] = [templates]
235
+
236
+ for radius in self.radius[1:]:
237
+ logger.info(f"Processing child level with radius {radius}")
238
+ cluster_indices, templates_radius = self._process_level(
239
+ data, its_key, context_key, self.cluster, radius
240
+ )
241
+ templates_all.append(templates_radius)
242
+
243
+ templates_all = self._update_child_idx(templates_all)
244
+ return cluster_indices, templates_all
@@ -0,0 +1,252 @@
1
+ import copy
2
+ import networkx as nx
3
+ from itertools import chain
4
+ from joblib import Parallel, delayed
5
+ from typing import List, Set, Dict, Any, Tuple
6
+
7
+ from synkit.Graph.ITS.its_decompose import get_rc
8
+
9
+
10
+ class RadiusExpand:
11
+ """A utility class for extracting and expanding reaction contexts from
12
+ chemical reaction graphs.
13
+
14
+ This class provides methods to:
15
+ - Identify reaction center nodes based on unequal edge orders.
16
+ - Expand reaction centers by including n-level nearest neighbors.
17
+ - Extract subgraphs from larger graphs.
18
+ - Construct a reaction context subgraph (K graph) from an ITS graph.
19
+ - Retrieve the longest unique extension path from reaction centers using DFS.
20
+ - Perform parallel extraction of reaction contexts from multiple reaction dictionaries.
21
+ - Remove edges based on specified edge attribute values.
22
+ """
23
+
24
+ def __init__(self) -> None:
25
+ """Initializes an instance of the RadiusExpand class.
26
+
27
+ This class does not maintain any instance-specific state and
28
+ uses only static and class methods.
29
+ """
30
+ pass
31
+
32
+ @staticmethod
33
+ def find_unequal_order_edges(G: nx.Graph) -> List[int]:
34
+ """Identifies reaction center nodes in a graph based on the presence of
35
+ unequal order edges.
36
+
37
+ :param G: Graph to analyze for reaction centers.
38
+ :type G: nx.Graph
39
+
40
+ :return: A list of node indices identified as reaction centers based on unequal order edges.
41
+ :rtype: List[int]
42
+ """
43
+ reaction_center_nodes: Set[int] = set()
44
+ for u, v, data in G.edges(data=True):
45
+ order = data.get("order", (1, 1))
46
+ if (
47
+ isinstance(order, tuple)
48
+ and order[0] != order[1]
49
+ and data.get("standard_order", 1) != 0
50
+ ):
51
+ reaction_center_nodes.update([u, v])
52
+ return list(reaction_center_nodes)
53
+
54
+ @staticmethod
55
+ def find_nearest_neighbors(
56
+ G: nx.Graph, center_nodes: List[int], n_knn: int = 1
57
+ ) -> Set[int]:
58
+ """Finds the n-level nearest neighbors around the specified center
59
+ nodes in a graph.
60
+
61
+ :param G: The graph in which to search for neighboring nodes.
62
+ :type G: nx.Graph
63
+ :param center_nodes: Initial center node indices.
64
+ :type center_nodes: List[int]
65
+ :param n_knn: The number of neighbor levels to include (default is 1).
66
+ :type n_knn: int, optional
67
+
68
+ :return: A set of node indices including the original center nodes and their nearest neighbors.
69
+ :rtype: Set[int]
70
+ """
71
+ extended_nodes: Set[int] = set(center_nodes)
72
+ for _ in range(n_knn):
73
+ neighbors = set(
74
+ chain.from_iterable(G.neighbors(node) for node in extended_nodes)
75
+ )
76
+ extended_nodes.update(neighbors)
77
+ return extended_nodes
78
+
79
+ @staticmethod
80
+ def extract_subgraph(G: nx.Graph, node_indices: List[int]) -> nx.Graph:
81
+ """Extracts a subgraph from the original graph containing the specified
82
+ node indices.
83
+
84
+ :param G: The original graph.
85
+ :type G: nx.Graph
86
+ :param node_indices: A list of node indices to include in the subgraph.
87
+ :type node_indices: List[int]
88
+
89
+ :return: A new graph that is a copy of the subgraph containing only the specified nodes.
90
+ :rtype: nx.Graph
91
+ """
92
+ return G.subgraph(node_indices).copy()
93
+
94
+ @staticmethod
95
+ def extract_k(its: nx.Graph, n_knn: int = 0) -> Tuple[nx.Graph, Any]:
96
+ """Constructs the context subgraph (K graph) from an ITS graph based on
97
+ reaction centers, and computes the longest extension path from these
98
+ centers constrained by 'standard_order' edges.
99
+
100
+ :param its: The ITS graph representing the reaction network.
101
+ :type its: nx.Graph
102
+ :param n_knn: The number of neighbor levels to include in the context subgraph.
103
+ Default is 0.
104
+ :type n_knn: int, optional
105
+
106
+ :return: Extracted context graph. A zero radius returns the reaction
107
+ center; ``-1`` uses the maximum radius.
108
+ :rtype: Tuple[nx.Graph, Any]
109
+ """
110
+ rc = get_rc(its)
111
+ rc_nodes = list(rc.nodes())
112
+ if n_knn == 0:
113
+ return rc
114
+ elif n_knn == -1:
115
+ paths = RadiusExpand.longest_radius_extension(its, rc_nodes)
116
+ n_knn = len(paths)
117
+
118
+ expanded_nodes = RadiusExpand.find_nearest_neighbors(its, rc_nodes, n_knn)
119
+ context = RadiusExpand.extract_subgraph(its, list(expanded_nodes))
120
+ return context
121
+
122
+ @staticmethod
123
+ def context_extraction(
124
+ data: Dict[str, Any],
125
+ its_key: str = "ITS",
126
+ context_key: str = "K",
127
+ n_knn: int = 0,
128
+ ) -> Dict[str, Any]:
129
+ """Extracts the reaction context for a single reaction dictionary by
130
+ computing both the context subgraph and the longest extension path.
131
+
132
+ :param data: Reaction data containing at least an ITS graph.
133
+ :type data: Dict[str, Any]
134
+ :param its_key: Key in the dictionary for retrieving the ITS graph.
135
+ Default is ITS.
136
+ :type its_key: str, optional
137
+ :param context_key: Key under which to store the extracted context subgraph.
138
+ Default is K.
139
+ :type context_key: str, optional
140
+ :param n_knn: Number of neighbor levels to include for context extraction.
141
+ Default is 0.
142
+ :type n_knn: int, optional
143
+
144
+ :return: Reaction data containing the extracted context graph.
145
+ :rtype: Dict[str, Any]
146
+ """
147
+ context_data: Dict[str, Any] = copy.copy(data)
148
+ its = context_data[its_key]
149
+ context = RadiusExpand.extract_k(its, n_knn)
150
+ context_data[context_key] = context
151
+ return context_data
152
+
153
+ @classmethod
154
+ def paralle_context_extraction(
155
+ cls,
156
+ data: List[Dict[str, Any]],
157
+ its_key: str = "ITS",
158
+ context_key: str = "K",
159
+ n_jobs: int = 1,
160
+ verbose: int = 0,
161
+ n_knn: int = 0,
162
+ ) -> List[Dict[str, Any]]:
163
+ """Performs parallel extraction of reaction contexts for multiple
164
+ reaction dictionaries.
165
+
166
+ :param data: A list of reaction data dictionaries, each containing an ITS graph.
167
+ :type data: List[Dict[str, Any]]
168
+ :param its_key: Key in the dictionary for retrieving the ITS graph.
169
+ Default is ITS.
170
+ :type its_key: str, optional
171
+ :param context_key: Key under which to store the extracted context subgraph.
172
+ Default is K.
173
+ :type context_key: str, optional
174
+ :param n_jobs: Number of parallel jobs to use. Default is 1.
175
+ :type n_jobs: int, optional
176
+ :param verbose: Verbosity level for the parallel processing. Default is 0.
177
+ :type verbose: int, optional
178
+ :param n_knn: Number of neighbor levels to include for context extraction.
179
+ Default is 0.
180
+ :type n_knn: int, optional
181
+
182
+ :return: Reaction records augmented with their context graphs and
183
+ longest extension paths.
184
+ :rtype: List[Dict[str, Any]]
185
+ """
186
+ return Parallel(n_jobs=n_jobs, verbose=verbose)(
187
+ delayed(cls.context_extraction)(reaction, its_key, context_key, n_knn)
188
+ for reaction in data
189
+ )
190
+
191
+ @staticmethod
192
+ def remove_normal_edges(graph: nx.Graph, property_key: str) -> nx.Graph:
193
+ """Removes edges from a graph where the specified edge attribute has a
194
+ value of 0.
195
+
196
+ :param graph: The input graph to modify.
197
+ :type graph: nx.Graph
198
+ :param property_key: The key of the edge attribute to check for removal;
199
+ edges with a value of 0 will be removed.
200
+ :type property_key: str
201
+
202
+ :return: A copy of the input graph with the specified edges removed.
203
+ :rtype: nx.Graph
204
+ """
205
+ filtered_graph = graph.copy()
206
+ edges_to_remove = [
207
+ (u, v)
208
+ for u, v, attrs in filtered_graph.edges(data=True)
209
+ if attrs.get(property_key, 1) == 0
210
+ ]
211
+ filtered_graph.remove_edges_from(edges_to_remove)
212
+ return filtered_graph
213
+
214
+ @staticmethod
215
+ def longest_radius_extension(G: nx.Graph, rc_nodes: List[int]) -> List[int]:
216
+ """Computes the longest unique extension path in the graph starting
217
+ from the given reaction center nodes, constrained by traversing only
218
+ those edges where the 'standard_order' attribute equals 0.
219
+
220
+ This method uses a depth-first search (DFS) strategy to explore all possible
221
+ unique paths and returns the longest one.
222
+
223
+ :param G: The graph to search for extension paths.
224
+ :type G: nx.Graph
225
+ :param rc_nodes: A list of reaction center node indices to serve as starting points for the search.
226
+ :type rc_nodes: List[int]
227
+
228
+ :return: A list of node indices representing the longest unique extension path found.
229
+ :rtype: List[int]
230
+ """
231
+
232
+ def dfs(node: int, visited: Set[int], path: List[int]) -> List[int]:
233
+ visited.add(node)
234
+ longest_path = path.copy()
235
+ for neighbor in G.neighbors(node):
236
+ edge_data = G.get_edge_data(node, neighbor)
237
+ if edge_data.get("standard_order", 1) == 0 and neighbor not in visited:
238
+ current_path = dfs(neighbor, visited.copy(), path + [neighbor])
239
+ if len(current_path) > len(longest_path):
240
+ longest_path = current_path
241
+ return longest_path
242
+
243
+ longest_extension: List[int] = []
244
+ visited_overall: Set[int] = set()
245
+
246
+ for rc_node in rc_nodes:
247
+ if rc_node not in visited_overall:
248
+ path = dfs(rc_node, visited_overall.copy(), [rc_node])
249
+ visited_overall.update(path)
250
+ if len(path) > len(longest_extension):
251
+ longest_extension = path
252
+ return longest_extension
@@ -0,0 +1,19 @@
1
+ """Functional-group detection on SynKit molecular graphs."""
2
+
3
+ from .catalog import default_registry
4
+ from .audit import FunctionalGroupAudit, audit_reaction_smiles
5
+ from .api import FunctionalGroupLabels, smiles_to_graph_and_functional_groups
6
+ from .detector import FunctionalGroupDetector
7
+ from .model import FunctionalGroupMatch, FunctionalGroupPattern, FunctionalGroupRegistry
8
+
9
+ __all__ = [
10
+ "FunctionalGroupDetector",
11
+ "FunctionalGroupLabels",
12
+ "FunctionalGroupAudit",
13
+ "FunctionalGroupMatch",
14
+ "FunctionalGroupPattern",
15
+ "FunctionalGroupRegistry",
16
+ "default_registry",
17
+ "audit_reaction_smiles",
18
+ "smiles_to_graph_and_functional_groups",
19
+ ]
synkit/Graph/FG/api.py ADDED
@@ -0,0 +1,39 @@
1
+ from __future__ import annotations
2
+
3
+ import networkx as nx
4
+
5
+ from synkit.IO.chem_converter import smiles_to_graph
6
+
7
+ from .detector import FunctionalGroupDetector
8
+
9
+ FunctionalGroupLabels = list[tuple[str, tuple[int, ...]]]
10
+
11
+
12
+ def smiles_to_graph_and_functional_groups(
13
+ smiles: str,
14
+ *,
15
+ sanitize: bool = True,
16
+ ) -> tuple[nx.Graph, FunctionalGroupLabels]:
17
+ """Convert SMILES to a molecular graph and detect functional groups.
18
+
19
+ Atom-mapped SMILES keep their non-zero atom-map numbers as graph node IDs.
20
+ Unmapped atoms use their 1-based atom order as node IDs, so both mapped and
21
+ unmapped SMILES can be passed to the same API.
22
+
23
+ :param smiles: Input SMILES, with or without atom-map labels.
24
+ :type smiles: str
25
+ :param sanitize: If ``True``, sanitize the RDKit molecule during conversion.
26
+ :type sanitize: bool
27
+ :return: Molecular graph and detected ``(name, node_ids)`` FG labels.
28
+ :rtype: tuple[nx.Graph, list[tuple[str, tuple[int, ...]]]]
29
+ :raises ValueError: If the SMILES cannot be converted to a molecular graph.
30
+ """
31
+ graph = smiles_to_graph(
32
+ smiles,
33
+ drop_non_aam=False,
34
+ sanitize=sanitize,
35
+ use_index_as_atom_map=True,
36
+ )
37
+ if graph is None:
38
+ raise ValueError(f"Could not convert SMILES to molecular graph: {smiles!r}")
39
+ return graph, FunctionalGroupDetector().detect(graph)