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
File without changes
@@ -0,0 +1,239 @@
1
+ """Route search over rounds of reaction SMILES for multi-step retrosynthesis.
2
+
3
+ This is the *synthesis-planning* path finder: it consumes the round-structured
4
+ reaction SMILES produced by an MSR expansion and searches molecule-to-molecule
5
+ routes under a carbon-count constraint. It has no notion of stoichiometry,
6
+ markings or reaction networks.
7
+
8
+ For pathway search over a reaction *network* —
9
+ :class:`~synkit.CRN.Structure.syncrn.SynCRN` incidence, reaction flows, and
10
+ Petri-net realizability of a candidate route — use
11
+ :class:`synkit.CRN.Pathway.pathfinder.PathwayFinder` instead. The two solve
12
+ different problems and are not alternative implementations of one algorithm.
13
+ """
14
+
15
+ import heapq
16
+ from collections import deque
17
+ from typing import List, Dict, Optional
18
+ from synkit.Chem.utils import count_carbons
19
+
20
+
21
+ class PathFinder:
22
+ """Search synthesis routes through rounds of reaction SMILES.
23
+
24
+ See the module docstring for how this relates to
25
+ :class:`synkit.CRN.Pathway.pathfinder.PathwayFinder`.
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ reaction_rounds: List[Dict[str, List[str]]],
31
+ ):
32
+ """Initialize with a list of dictionaries, each representing a reaction
33
+ round, plus an optional random state for reproducible Monte Carlo
34
+ search.
35
+
36
+ :param reaction_rounds: A list where each dictionary
37
+ contains the reaction SMILES strings for a given round
38
+ (e.g. {"Round 1": [...] }).
39
+ :type reaction_rounds: List[Dict[str, List[str]]]
40
+ """
41
+ self.reaction_rounds = reaction_rounds
42
+
43
+ # Build adjacency structure:
44
+ # self._adjacency[round_idx] => { reactant_smiles: [(reaction_smiles, [products])] }
45
+ self._adjacency = []
46
+ for round_idx, round_dict in enumerate(self.reaction_rounds):
47
+ round_key = f"Round {round_idx + 1}"
48
+ reactions = round_dict.get(round_key, [])
49
+ adjacency_map = {}
50
+ for rxn in reactions:
51
+ reactants, products = rxn.split(">>")
52
+ reactant_list = reactants.split(".")
53
+ product_list = products.split(".")
54
+ for rct in reactant_list:
55
+ adjacency_map.setdefault(rct, []).append((rxn, product_list))
56
+ self._adjacency.append(adjacency_map)
57
+
58
+ def _valid_intermediate(
59
+ self, smiles: str, input_smiles: str, target_smiles: str
60
+ ) -> bool:
61
+ """
62
+ Checks whether the given molecule satisfies the carbon_distance constraint:
63
+ n_C(input_smiles) <= n_C(smiles) <= n_C(target_smiles)
64
+ """
65
+ return (
66
+ count_carbons(input_smiles)
67
+ <= count_carbons(smiles)
68
+ <= count_carbons(target_smiles)
69
+ )
70
+
71
+ def search_paths(
72
+ self,
73
+ input_smiles: str,
74
+ target_smiles: str,
75
+ method: str = "bfs",
76
+ max_solutions: Optional[int] = None,
77
+ cheapest: bool = True,
78
+ ) -> List[List[str]]:
79
+ """Search for reaction pathways from the input molecule to the target
80
+ molecule using a specified method, optionally limiting the number of
81
+ solutions.
82
+
83
+ Additionally, `cheapest` can be set to True or False:
84
+ - If cheapest=True, BFS uses a visited set and A* prunes costlier routes (typical approach).
85
+ - If cheapest=False, BFS does *not* track visited states (returns more solutions),
86
+ and A* does *not* prune costlier routes (also returns more solutions).
87
+ (May lead to duplicates or many solutions if cycles exist.)
88
+
89
+ :param input_smiles: SMILES of the starting molecule.
90
+ :type input_smiles: str
91
+ :param target_smiles: SMILES of the target molecule.
92
+ :type target_smiles: str
93
+ :param method: 'bfs', 'astar', or 'mc'.
94
+ :type method: str, optional
95
+ :param max_solutions: If set, stop after finding this many solutions.
96
+ :type max_solutions: int, optional
97
+ :param cheapest: Controls pruning.
98
+ Default True => standard BFS/A*; False => "unrestricted" BFS/A*.
99
+ :type cheapest: bool, optional
100
+
101
+ :return: Each solution path is a list of reaction SMILES from start to target.
102
+ :rtype: List[List[str]]
103
+ """
104
+ if method == "bfs":
105
+ return self._bfs(input_smiles, target_smiles, max_solutions, cheapest)
106
+ elif method == "astar":
107
+ return self._astar(input_smiles, target_smiles, max_solutions, cheapest)
108
+ else:
109
+ raise ValueError("Invalid method. Choose 'bfs', 'astar', or 'mc'.")
110
+
111
+ def _bfs(
112
+ self,
113
+ input_smiles: str,
114
+ target_smiles: str,
115
+ max_solutions: Optional[int],
116
+ cheapest: bool,
117
+ ) -> List[List[str]]:
118
+ """Perform a BFS search. If cheapest=True, use a visited set to avoid
119
+ re-processing the same (molecule, round_index). If cheapest=False, skip
120
+ that pruning and collect *all* possible solutions (potentially large if
121
+ cycles exist).
122
+
123
+ Returns a list of successful reaction pathways, up to
124
+ max_solutions if specified.
125
+ """
126
+
127
+ queue = deque([(input_smiles, [], 0)])
128
+ pathways = []
129
+ visited = set() if cheapest else None # Only track visited if cheapest=True
130
+
131
+ while queue:
132
+ current_smiles, current_path, round_index = queue.popleft()
133
+ if round_index >= len(self._adjacency):
134
+ continue
135
+
136
+ # For BFS with cheapest=True, skip repeated states
137
+ if cheapest:
138
+ if (current_smiles, round_index) in visited:
139
+ continue
140
+ visited.add((current_smiles, round_index))
141
+
142
+ adjacency_map = self._adjacency[round_index]
143
+ if current_smiles not in adjacency_map:
144
+ continue
145
+
146
+ for rxn_string, product_list in adjacency_map[current_smiles]:
147
+ updated_path = current_path + [rxn_string]
148
+ # If any product is the target, record a solution
149
+ if target_smiles in product_list:
150
+ pathways.append(updated_path)
151
+ if max_solutions is not None and len(pathways) >= max_solutions:
152
+ return pathways
153
+ # Otherwise queue each valid product
154
+ for product in product_list:
155
+ if self._valid_intermediate(product, input_smiles, target_smiles):
156
+ queue.append((product, updated_path, round_index + 1))
157
+
158
+ return pathways
159
+
160
+ def _heuristic(self, smiles: str, target_smiles: str) -> int:
161
+ """Heuristic function for A* search.
162
+
163
+ Returns difference in SMILES lengths as a stand-in for
164
+ "distance."
165
+ """
166
+ return abs(len(smiles) - len(target_smiles))
167
+
168
+ def _astar(
169
+ self,
170
+ input_smiles: str,
171
+ target_smiles: str,
172
+ max_solutions: Optional[int],
173
+ cheapest: bool,
174
+ ) -> List[List[str]]:
175
+ """A* search. If cheapest=True, we track the best cost visited for each
176
+ state and prune costlier paths. If cheapest=False, we do not prune, so
177
+ we collect all solutions (but it may be large).
178
+
179
+ Returns a list of successful reaction pathways, up to
180
+ max_solutions if specified.
181
+ """
182
+ start_cost = self._heuristic(input_smiles, target_smiles)
183
+ # Heap stores (cost, current_smiles, current_path, round_index)
184
+ heap = [(start_cost, input_smiles, [], 0)]
185
+ pathways = []
186
+ visited_cost = {} if cheapest else None
187
+
188
+ while heap:
189
+ cost, current_smiles, current_path, round_index = heapq.heappop(heap)
190
+
191
+ if cheapest and visited_cost is not None:
192
+ # If we've seen this state with a cheaper or equal cost, skip
193
+ if (current_smiles, round_index) in visited_cost:
194
+ if visited_cost[(current_smiles, round_index)] <= cost:
195
+ continue
196
+ visited_cost[(current_smiles, round_index)] = cost
197
+
198
+ if round_index >= len(self._adjacency):
199
+ continue
200
+
201
+ adjacency_map = self._adjacency[round_index]
202
+ if current_smiles not in adjacency_map:
203
+ continue
204
+
205
+ for rxn_string, product_list in adjacency_map[current_smiles]:
206
+ updated_path = current_path + [rxn_string]
207
+
208
+ # If any product is the target, record a solution
209
+ if target_smiles in product_list:
210
+ pathways.append(updated_path)
211
+ if max_solutions is not None and len(pathways) >= max_solutions:
212
+ return pathways
213
+ else:
214
+ # Otherwise expand each product
215
+ next_round = round_index + 1
216
+ for product in product_list:
217
+ if self._valid_intermediate(
218
+ product, input_smiles, target_smiles
219
+ ):
220
+ new_cost = len(updated_path) + self._heuristic(
221
+ product, target_smiles
222
+ )
223
+ if cheapest and visited_cost is not None:
224
+ old_cost = visited_cost.get(
225
+ (product, next_round), float("inf")
226
+ )
227
+ # Only push if cheaper route
228
+ if new_cost < old_cost:
229
+ heapq.heappush(
230
+ heap,
231
+ (new_cost, product, updated_path, next_round),
232
+ )
233
+ else:
234
+ # cheapest=False => always push
235
+ heapq.heappush(
236
+ heap, (new_cost, product, updated_path, next_round)
237
+ )
238
+
239
+ return pathways
File without changes
@@ -0,0 +1,52 @@
1
+ from typing import List, Dict
2
+ from ._ranking import (
3
+ _novelty_rate,
4
+ _coverage,
5
+ _recognition_rate,
6
+ _top_k_accuracy,
7
+ _calculate_f_beta_score,
8
+ )
9
+
10
+
11
+ def _compute_metrics(
12
+ reactions_data: List[Dict[str, any]],
13
+ key_ground_truth: str,
14
+ key_prediction: str,
15
+ k: int = 5,
16
+ beta: float = 1,
17
+ ) -> Dict[str, float]:
18
+ """Computes the metrics for a list of reactions data.
19
+
20
+ :param reactions_data: List of dictionaries containing RSMI strings.
21
+ :type reactions_data: List[Dict[str, any]]
22
+ :param key_ground_truth: Key in the dictionary for the ground truth RSMI.
23
+ :type key_ground_truth: str
24
+ :param key_prediction: Key in the dictionary for the predicted RSMIs
25
+ (list of predictions).
26
+ :type key_prediction: str
27
+ :param k: The number of top predictions to consider. Defaults to 5.
28
+ :type k: int, optional
29
+ :param beta: Beta parameter for the F-beta score. Defaults to 1.
30
+ :type beta: float, optional
31
+
32
+ :return: A dictionary with the metrics.
33
+ :rtype: Dict[str, float]
34
+ """
35
+ return {
36
+ "Novelty": _novelty_rate(reactions_data, key_ground_truth, key_prediction)
37
+ / 100,
38
+ "Coverage": _coverage(reactions_data, key_ground_truth, key_prediction) / 100,
39
+ "Recognition": _recognition_rate(
40
+ reactions_data, key_ground_truth, key_prediction
41
+ )
42
+ / 100,
43
+ f"Top_{k}_Accuracy": _top_k_accuracy(
44
+ reactions_data, key_ground_truth, key_prediction, k
45
+ )
46
+ / 100,
47
+ f"F{beta}_score": _calculate_f_beta_score(
48
+ _recognition_rate(reactions_data, key_ground_truth, key_prediction),
49
+ _coverage(reactions_data, key_ground_truth, key_prediction),
50
+ beta,
51
+ ),
52
+ }
@@ -0,0 +1,129 @@
1
+ import pandas as pd
2
+ import matplotlib.pyplot as plt
3
+ import seaborn as sns
4
+ import matplotlib
5
+
6
+ # Enable LaTeX rendering in Matplotlib
7
+ matplotlib.rcParams["text.usetex"] = True
8
+ matplotlib.rcParams["text.latex.preamble"] = r"\usepackage{amsmath}"
9
+
10
+
11
+ def plot_recognition_coverage_curve(
12
+ data,
13
+ coverage_col="Coverage",
14
+ recognition_col="Recognition",
15
+ f2_score_col="F2_score",
16
+ figsize=(8, 6),
17
+ show_f2=True,
18
+ show_legend=True,
19
+ ):
20
+ """Plots a Recognition-Coverage curve using provided data, including
21
+ optional F2 scores annotated. Styled with Seaborn for enhanced visual
22
+ appearance.
23
+
24
+ :param data: Nested dictionary containing the data for each radii,
25
+ formatted as shown in example.
26
+ :type data: dict
27
+ :param coverage_col: Key name for the coverage data in the dictionary.
28
+ :type coverage_col: str
29
+ :param recognition_col: Key name for the recognition data in the dictionary.
30
+ :type recognition_col: str
31
+ :param f2_score_col: Key name for the F2 score data in the dictionary.
32
+ :type f2_score_col: str
33
+ :param figsize: Figure size for the plot, default is (8, 6).
34
+ :type figsize: tuple
35
+ :param show_f2: Whether to show F2 scores on the curve, default is True.
36
+
37
+ Example Data format:
38
+ {'radii_0': {'Novelty': 96.44, 'Coverage': 93.98, 'Recognition': 3.55, ...}}
39
+ :type show_f2: bool
40
+ """
41
+ df = pd.DataFrame(data).T
42
+
43
+ sns.set_theme(style="whitegrid")
44
+
45
+ plt.figure(figsize=figsize)
46
+ ax = sns.lineplot(
47
+ data=df,
48
+ x=coverage_col,
49
+ y=recognition_col,
50
+ marker="o",
51
+ label="Recognition-Coverage Curve" if show_legend else None,
52
+ )
53
+
54
+ if show_f2:
55
+ for i, txt in enumerate(df[f2_score_col]):
56
+ ax.annotate(
57
+ r"$F_2=" + f"{txt:.2f}" + "$",
58
+ (df[coverage_col].iloc[i], df[recognition_col].iloc[i]),
59
+ textcoords="offset points",
60
+ xytext=(0, 10),
61
+ ha="center",
62
+ )
63
+
64
+ # Adding labels, title, and legend with LaTeX
65
+ plt.xlabel(r"$\mathrm{{Coverage\%}}$", fontsize=18)
66
+ plt.ylabel(r"$\mathrm{{Recognition\%}}$", fontsize=18)
67
+ plt.title(r"Recognition-Coverage Curve", fontsize=24)
68
+ plt.legend()
69
+ plt.grid(True)
70
+ plt.show()
71
+
72
+
73
+ def plot_f2_scores_line(data, figsize=(8, 6), show_f2=True, show_legend=True):
74
+ """Plots F2 scores across different radii using a line plot, showing the
75
+ trend of F2 score changes, and annotated with optional F2 scores.
76
+
77
+ :param data: Dictionary containing nested dictionaries with 'F2_score'
78
+ and possibly other metrics.
79
+ :type data: dict
80
+ :param figsize: Figure size for the plot, default is (8, 6).
81
+ :type figsize: tuple
82
+ :param show_f2: Whether to show F2 scores on the curve, default is True.
83
+ :type show_f2: bool
84
+ :param show_legend: Whether to show the legend on the plot, default is True.
85
+
86
+ Example Data format:
87
+ {'radii_0': {'Novelty': 96.44, 'Coverage': 93.98, 'Recognition': 3.55,
88
+ 'F2_score': 0.15}, ...}
89
+ :type show_legend: bool
90
+ """
91
+ # Convert the nested dictionary into a DataFrame and prepare for plotting
92
+ df = pd.DataFrame(data).T
93
+ df["Radii"] = [int(key.split("_")[1]) for key in data.keys()]
94
+ df.sort_values("Radii", inplace=True) # Ensure data is sorted by radii
95
+
96
+ # Setting up Seaborn for enhanced plotting style
97
+ sns.set_theme(style="whitegrid")
98
+
99
+ # Create the plot
100
+ plt.figure(figsize=figsize)
101
+ sns.lineplot(
102
+ data=df,
103
+ x="Radii",
104
+ y="F2_score",
105
+ marker="o",
106
+ label="F2 Score Trend" if show_legend else None,
107
+ )
108
+
109
+ # Optionally annotate each point with its F2 score
110
+ if show_f2:
111
+ for i in range(len(df)):
112
+ plt.text(
113
+ df.iloc[i]["Radii"],
114
+ df.iloc[i]["F2_score"] + 0.01,
115
+ r"$F_2=" + f'{df.iloc[i]["F2_score"]:.2f}' + "$",
116
+ color="black",
117
+ ha="center",
118
+ va="bottom",
119
+ )
120
+
121
+ # Adding labels, title, and legend with LaTeX
122
+ plt.xlabel(r"$\text{Radii}$", fontsize=18)
123
+ plt.ylabel(r"$F_2\ \text{Score}$", fontsize=18)
124
+ plt.title(r"$F_2\ \text{Score}$ Across Different Radii", fontsize=24)
125
+ if show_legend:
126
+ plt.legend()
127
+
128
+ plt.grid(True)
129
+ plt.show()
@@ -0,0 +1,179 @@
1
+ import statistics
2
+ from typing import List, Dict
3
+
4
+
5
+ def _coverage(
6
+ reactions_data: List[Dict[str, str]], key_ground_truth: str, key_prediction: str
7
+ ) -> float:
8
+ """Calculates the coverage percentage, which measures how many of the
9
+ predicted reactions exactly match the ground truth reactions given in a
10
+ list of dictionaries.
11
+
12
+ :param reactions_data: List of dictionaries containing
13
+ reaction SMILES strings.
14
+ :type reactions_data: List[Dict[str, str]]
15
+ :param key_ground_truth: Key in the dictionary for the ground truth reaction SMILES.
16
+ :type key_ground_truth: str
17
+ :param key_prediction: Key in the dictionary for the predicted reaction SMILES.
18
+ :type key_prediction: str
19
+
20
+ :return: The coverage percentage.
21
+ :rtype: float
22
+ """
23
+ correct_matches = sum(
24
+ 1
25
+ for reaction in reactions_data
26
+ if reaction.get(key_ground_truth) in reaction.get(key_prediction)
27
+ )
28
+ return (correct_matches / len(reactions_data)) * 100 if reactions_data else 0
29
+
30
+
31
+ def _novelty_rate(
32
+ reactions_data: List[Dict[str, any]], key_ground_truth: str, key_prediction: str
33
+ ) -> float:
34
+ """Calculates the False Positive Rate (FPR) for each observation and then
35
+ averages these values across all observations. The FPR represents the
36
+ proportion of predictions that do not match the ground truth for each
37
+ individual entry in the dataset.
38
+
39
+ :param reactions_data: List of dictionaries containing
40
+ the ground truth and predicted reactions, where predictions are given as
41
+ a list of RSMIs.
42
+ :type reactions_data: List[Dict[str, any]]
43
+ :param key_ground_truth: Dictionary key to access the ground truth reaction RSMI.
44
+ :type key_ground_truth: str
45
+ :param key_prediction: Dictionary key to access the list of predicted reaction RSMIs.
46
+ :type key_prediction: str
47
+
48
+ :return: Average false-positive rate as a percentage.
49
+ :rtype: float
50
+ """
51
+ fpr_list = [] # List to store FPR for each observation
52
+
53
+ for entry in reactions_data:
54
+ ground_truth = entry.get(key_ground_truth)
55
+ predictions = entry.get(key_prediction, [])
56
+
57
+ if not predictions: # Skip if no predictions
58
+ continue
59
+
60
+ # Calculate FPR for this entry
61
+ false_positives = sum(1 for pred in predictions if pred != ground_truth)
62
+ total_predictions = len(predictions)
63
+ fpr_list.append((false_positives / total_predictions) * 100)
64
+
65
+ # Calculate and return the mean FPR
66
+ return statistics.mean(fpr_list) if fpr_list else 0.0
67
+
68
+
69
+ def _recognition_rate(
70
+ reactions_data: List[Dict[str, any]], key_ground_truth: str, key_prediction: str
71
+ ) -> float:
72
+ """Calculates the recognition rate for each observation and averages these
73
+ rates across all observations. The recognition rate measures the proportion
74
+ of the prediction list that matches the single ground truth reaction for
75
+ each entry.
76
+
77
+ :param reactions_data: List of dictionaries containing
78
+ the ground truth
79
+ and predicted reactions, where the ground truth is a single RSMI and predictions
80
+ are lists of RSMIs.
81
+ :type reactions_data: List[Dict[str, any]]
82
+ :param key_ground_truth: Dictionary key to access the ground truth reaction RSMIs.
83
+ :type key_ground_truth: str
84
+ :param key_prediction: Dictionary key to access the list of predicted reaction RSMIs.
85
+ :type key_prediction: str
86
+
87
+ :return: Average recognition rate as a percentage.
88
+ :rtype: float
89
+ """
90
+ recognition_rates = []
91
+
92
+ for entry in reactions_data:
93
+ ground_truth = entry.get(key_ground_truth)
94
+ predictions = entry.get(key_prediction, [])
95
+
96
+ if predictions:
97
+
98
+ matches = sum(1 for pred in predictions if pred == ground_truth)
99
+
100
+ recognition_rate = (matches / len(predictions)) * 100
101
+ recognition_rates.append(recognition_rate)
102
+ else:
103
+ recognition_rates.append(0.0)
104
+
105
+ return statistics.mean(recognition_rates) if recognition_rates else 0.0
106
+
107
+
108
+ def _top_k_accuracy(
109
+ reactions_data: List[Dict[str, any]],
110
+ key_ground_truth: str,
111
+ key_prediction: str,
112
+ k: int,
113
+ ) -> float:
114
+ """Calculates the Top-K accuracy by using the coverage function on the top
115
+ K predictions. This measures the probability that the true reaction is
116
+ within the top K predictions.
117
+
118
+ :param reactions_data: List of dictionaries containing
119
+ RSMI strings.
120
+ :type reactions_data: List[Dict[str, any]]
121
+ :param key_ground_truth: Key in the dictionary for the ground truth RSMI.
122
+ :type key_ground_truth: str
123
+ :param key_prediction: Key in the dictionary for the predicted RSMIs
124
+ (list of predictions).
125
+ :type key_prediction: str
126
+ :param k: The number of top predictions to consider.
127
+ :type k: int
128
+
129
+ :return: The Top-K accuracy percentage.
130
+ :rtype: float
131
+ """
132
+ modified_data = [
133
+ {**entry, "Top_K_Predictions": entry[key_prediction][:k]}
134
+ for entry in reactions_data
135
+ ]
136
+ return _coverage(modified_data, key_ground_truth, "Top_K_Predictions")
137
+
138
+
139
+ def _calculate_f_beta_score(
140
+ recognition_rate: float, # This serves as the precision
141
+ coverage_rate: float, # This serves as the recall
142
+ beta: float = 1.0, # Beta factor, default is 1.0 for F1 score
143
+ ) -> float:
144
+ """Computes the F-beta Score, which is a weighted harmonic mean of
145
+ recognition rate and coverage rate. The recognition rate (precision) and
146
+ coverage rate (recall) must be expressed as percentages. A beta value of
147
+ 1.0 means equal importance to precision and recall (F1 Score), greater than
148
+ 1.0 gives more importance to recall (e.g., F2 Score), and less than 1.0
149
+ prioritizes precision (e.g., F0.5 Score).
150
+
151
+ :param recognition_rate: The recognition rate of the predictions,
152
+ acting as precision, expected to be between 0 and 100.
153
+ :type recognition_rate: float
154
+ :param coverage_rate: The coverage rate of the predictions, acting as recall,
155
+ expected to be between 0 and 100.
156
+ :type coverage_rate: float
157
+ :param beta: The weight emphasizing recall over precision. Default is 1.0.
158
+ :type beta: float
159
+
160
+ :return: The F-beta Score as a percentage, which balances precision and recall based on the beta factor.
161
+ :rtype: float
162
+ """
163
+ if recognition_rate == 0 or coverage_rate == 0:
164
+ return 0 # If either rate is zero, F-beta is zero to avoid division by zero
165
+
166
+ # Calculate precision and recall
167
+ precision = recognition_rate / 100
168
+ recall = coverage_rate / 100
169
+
170
+ # Calculate F-beta Score using the formula:
171
+ # F-beta = (1 + beta^2) * (precision * recall) / (beta^2 * precision + recall)
172
+ beta_squared = beta**2
173
+ f_beta_score = (
174
+ (1 + beta_squared)
175
+ * (precision * recall)
176
+ / ((beta_squared * precision) + recall)
177
+ )
178
+
179
+ return f_beta_score
@@ -0,0 +1,80 @@
1
+ """Radical-based linking search, validation, and replayable proofs."""
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from .overlap import (
6
+ TypedOverlapCertificate,
7
+ TypedOverlapLimits,
8
+ TypedOverlapResult,
9
+ enumerate_typed_overlaps,
10
+ )
11
+ from .policy import (
12
+ AcceptanceTask,
13
+ OverlapScope,
14
+ ProofLevel,
15
+ RBLSearchPolicy,
16
+ SearchOutcomeStatus,
17
+ SearchScope,
18
+ TerminationPolicy,
19
+ )
20
+ from .proof import (
21
+ RBL_PROOF_SCHEMA,
22
+ RBLProofReplay,
23
+ RBLReplayCertificate,
24
+ read_rbl_proof,
25
+ )
26
+ from .state import RBL_RESULT_SCHEMA
27
+ from .validation import (
28
+ FusionIssue,
29
+ FusionIssueCode,
30
+ FusionValidation,
31
+ WildcardRole,
32
+ certify_fusion_postprocessing,
33
+ validate_endpoint_preservation,
34
+ validate_fusion_rsmi,
35
+ validate_rbl_candidate,
36
+ validate_strict_rbl_candidate,
37
+ validate_wildcard_mapping_roles,
38
+ )
39
+
40
+ if TYPE_CHECKING:
41
+ from .engine import RBLEngine
42
+
43
+ __all__ = [
44
+ "AcceptanceTask",
45
+ "FusionIssue",
46
+ "FusionIssueCode",
47
+ "FusionValidation",
48
+ "OverlapScope",
49
+ "ProofLevel",
50
+ "RBLEngine",
51
+ "RBLProofReplay",
52
+ "RBLReplayCertificate",
53
+ "RBLSearchPolicy",
54
+ "RBL_PROOF_SCHEMA",
55
+ "RBL_RESULT_SCHEMA",
56
+ "SearchOutcomeStatus",
57
+ "SearchScope",
58
+ "TerminationPolicy",
59
+ "TypedOverlapCertificate",
60
+ "TypedOverlapLimits",
61
+ "TypedOverlapResult",
62
+ "WildcardRole",
63
+ "certify_fusion_postprocessing",
64
+ "enumerate_typed_overlaps",
65
+ "read_rbl_proof",
66
+ "validate_endpoint_preservation",
67
+ "validate_fusion_rsmi",
68
+ "validate_rbl_candidate",
69
+ "validate_strict_rbl_candidate",
70
+ "validate_wildcard_mapping_roles",
71
+ ]
72
+
73
+
74
+ def __getattr__(name: str) -> object:
75
+ """Load the engine lazily so lightweight policy imports stay cheap."""
76
+ if name == "RBLEngine":
77
+ from .engine import RBLEngine
78
+
79
+ return RBLEngine
80
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")