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,402 @@
1
+ """Branch-and-bound enumeration of minimal siphons and traps.
2
+
3
+ Enumerating siphons by testing all :math:`2^n` place subsets is only viable for
4
+ toy networks: a 25-species network already takes about a minute, and the cost
5
+ multiplies by roughly eight for every three further species.
6
+
7
+ This module instead builds on the *closure* operator: for any set of places
8
+ ``A`` there is a unique **maximal siphon contained in** ``A``, and it can be
9
+ computed in polynomial time by repeatedly discarding places that break the
10
+ siphon condition (:func:`max_siphon_within`). Minimal siphons are then reached
11
+ by starting from the maximal siphon of the whole net and repeatedly removing
12
+ one place and re-closing.
13
+
14
+ That descent is complete. If ``M`` is a minimal siphon and ``S`` is any siphon
15
+ with ``M`` a strict subset of ``S``, then for a place ``p`` in ``S`` but not in
16
+ ``M`` the set ``S \\ {p}`` still contains ``M``; since ``M`` is itself a siphon,
17
+ it survives the closure, so ``max_siphon_within(S \\ {p})`` still contains
18
+ ``M``. Every minimal siphon is therefore reachable from the top by successive
19
+ delete-and-close steps.
20
+
21
+ Traps are the exact dual (every transition consuming from the set also produces
22
+ back into it) and are handled by the same machinery.
23
+
24
+ .. rubric:: Example
25
+
26
+ .. code-block:: python
27
+
28
+ from synkit.CRN.Structure import SynCRN
29
+ from synkit.CRN.Petrinet import PetriNet
30
+ from synkit.CRN.Petrinet.siphon_search import minimal_siphons
31
+
32
+ net = PetriNet.from_syncrn(SynCRN.from_reaction_strings(["A>>B", "B>>A"]))
33
+ print(minimal_siphons(net))
34
+ """
35
+
36
+ from __future__ import annotations
37
+
38
+ from typing import Dict, FrozenSet, List, Optional, Sequence, Set, Tuple
39
+
40
+ from .net import PetriNet
41
+
42
+ __all__ = [
43
+ "max_siphon_within",
44
+ "max_trap_within",
45
+ "minimal_siphons",
46
+ "minimal_traps",
47
+ "SiphonSearchLimit",
48
+ ]
49
+
50
+ #: Default ceiling on explored search nodes, so a pathological network degrades
51
+ #: into a truncated result rather than an apparent hang.
52
+ DEFAULT_MAX_NODES = 200_000
53
+
54
+
55
+ class SiphonSearchLimit(RuntimeError):
56
+ """Raised when a siphon or trap search exceeds its exploration budget."""
57
+
58
+
59
+ def _incidence(
60
+ net: PetriNet,
61
+ ) -> Tuple[Dict[str, Set[str]], Dict[str, Set[str]]]:
62
+ """Index a Petri net as ``transition -> consumed`` / ``transition -> produced``.
63
+
64
+ :param net:
65
+ Petri net to index.
66
+ :type net: PetriNet
67
+
68
+ :return:
69
+ Pair ``(pre, post)`` mapping each transition id to the set of places it
70
+ consumes from and produces into, with zero-weight arcs dropped.
71
+ :rtype: Tuple[Dict[str, Set[str]], Dict[str, Set[str]]]
72
+ """
73
+ pre: Dict[str, Set[str]] = {}
74
+ post: Dict[str, Set[str]] = {}
75
+
76
+ for tid in net.transition_order:
77
+ t = net.transitions[tid]
78
+ pre[tid] = {p for p, w in t.pre.items() if w > 0}
79
+ post[tid] = {p for p, w in t.post.items() if w > 0}
80
+
81
+ return pre, post
82
+
83
+
84
+ def _max_closed_within(
85
+ allowed: Set[str],
86
+ *,
87
+ trigger: Dict[str, Set[str]],
88
+ required: Dict[str, Set[str]],
89
+ transition_order: Sequence[str],
90
+ ) -> Set[str]:
91
+ """Compute the maximal subset of ``allowed`` closed under a incidence rule.
92
+
93
+ A set ``S`` is closed when, for every transition ``t``, ``trigger[t]``
94
+ meeting ``S`` implies ``required[t]`` also meets ``S``. Choosing
95
+ ``trigger=post`` and ``required=pre`` yields siphons; swapping them yields
96
+ traps.
97
+
98
+ Places are removed until a fixed point is reached, which is the unique
99
+ maximal closed subset.
100
+
101
+ :param allowed:
102
+ Candidate place set. Not mutated.
103
+ :type allowed: Set[str]
104
+
105
+ :param trigger:
106
+ Transition-to-places map that activates the condition.
107
+ :type trigger: Dict[str, Set[str]]
108
+
109
+ :param required:
110
+ Transition-to-places map that must then also be met.
111
+ :type required: Dict[str, Set[str]]
112
+
113
+ :param transition_order:
114
+ Deterministic transition iteration order.
115
+ :type transition_order: Sequence[str]
116
+
117
+ :return:
118
+ Maximal closed subset of ``allowed``, possibly empty.
119
+ :rtype: Set[str]
120
+ """
121
+ current = set(allowed)
122
+
123
+ changed = True
124
+ while changed and current:
125
+ changed = False
126
+ for tid in transition_order:
127
+ hit = trigger[tid] & current
128
+ if not hit:
129
+ continue
130
+ if required[tid] & current:
131
+ continue
132
+ # This transition breaks the condition: every place it triggers on
133
+ # must leave the set.
134
+ current -= hit
135
+ changed = True
136
+ if not current:
137
+ break
138
+
139
+ return current
140
+
141
+
142
+ def max_siphon_within(net: PetriNet, allowed: Set[str]) -> Set[str]:
143
+ """Return the unique maximal siphon contained in ``allowed``.
144
+
145
+ :param net:
146
+ Petri net to analyse.
147
+ :type net: PetriNet
148
+
149
+ :param allowed:
150
+ Places the siphon may draw from.
151
+ :type allowed: Set[str]
152
+
153
+ :return:
154
+ Maximal siphon inside ``allowed``, empty if there is none.
155
+ :rtype: Set[str]
156
+
157
+ .. rubric:: Example
158
+
159
+ .. code-block:: python
160
+
161
+ max_siphon_within(net, set(net.place_order))
162
+ """
163
+ pre, post = _incidence(net)
164
+ return _max_closed_within(
165
+ allowed,
166
+ trigger=post,
167
+ required=pre,
168
+ transition_order=net.transition_order,
169
+ )
170
+
171
+
172
+ def max_trap_within(net: PetriNet, allowed: Set[str]) -> Set[str]:
173
+ """Return the unique maximal trap contained in ``allowed``.
174
+
175
+ :param net:
176
+ Petri net to analyse.
177
+ :type net: PetriNet
178
+
179
+ :param allowed:
180
+ Places the trap may draw from.
181
+ :type allowed: Set[str]
182
+
183
+ :return:
184
+ Maximal trap inside ``allowed``, empty if there is none.
185
+ :rtype: Set[str]
186
+
187
+ .. rubric:: Example
188
+
189
+ .. code-block:: python
190
+
191
+ max_trap_within(net, set(net.place_order))
192
+ """
193
+ pre, post = _incidence(net)
194
+ return _max_closed_within(
195
+ allowed,
196
+ trigger=pre,
197
+ required=post,
198
+ transition_order=net.transition_order,
199
+ )
200
+
201
+
202
+ def _enumerate_minimal(
203
+ net: PetriNet,
204
+ *,
205
+ trigger: Dict[str, Set[str]],
206
+ required: Dict[str, Set[str]],
207
+ max_size: Optional[int],
208
+ max_nodes: int,
209
+ strict_limit: bool,
210
+ ) -> List[Set[str]]:
211
+ """Enumerate inclusion-minimal closed sets by delete-and-close descent.
212
+
213
+ :param net:
214
+ Petri net to analyse.
215
+ :type net: PetriNet
216
+
217
+ :param trigger:
218
+ Transition-to-places map activating the closure condition.
219
+ :type trigger: Dict[str, Set[str]]
220
+
221
+ :param required:
222
+ Transition-to-places map that must also be met.
223
+ :type required: Dict[str, Set[str]]
224
+
225
+ :param max_size:
226
+ Optional ceiling on the size of returned sets.
227
+ :type max_size: Optional[int]
228
+
229
+ :param max_nodes:
230
+ Maximum number of closure evaluations before giving up.
231
+ :type max_nodes: int
232
+
233
+ :param strict_limit:
234
+ Whether exceeding ``max_nodes`` raises instead of truncating.
235
+ :type strict_limit: bool
236
+
237
+ :return:
238
+ Inclusion-minimal closed sets.
239
+ :rtype: List[Set[str]]
240
+
241
+ :raises SiphonSearchLimit:
242
+ If the budget is exhausted and ``strict_limit`` is set.
243
+ """
244
+ places = list(net.place_order)
245
+ order = net.transition_order
246
+
247
+ root = _max_closed_within(
248
+ set(places), trigger=trigger, required=required, transition_order=order
249
+ )
250
+ if not root:
251
+ return []
252
+
253
+ seen: Set[FrozenSet[str]] = set()
254
+ minimal: List[Set[str]] = []
255
+ stack: List[FrozenSet[str]] = [frozenset(root)]
256
+ seen.add(frozenset(root))
257
+ nodes = 0
258
+ truncated = False
259
+
260
+ while stack:
261
+ current = stack.pop()
262
+
263
+ is_minimal = True
264
+ for p in sorted(current):
265
+ if nodes >= max_nodes:
266
+ truncated = True
267
+ break
268
+ nodes += 1
269
+
270
+ child = _max_closed_within(
271
+ set(current) - {p},
272
+ trigger=trigger,
273
+ required=required,
274
+ transition_order=order,
275
+ )
276
+ if not child:
277
+ continue
278
+
279
+ # A non-empty proper closed subset exists, so `current` is not
280
+ # inclusion-minimal.
281
+ is_minimal = False
282
+ key = frozenset(child)
283
+ if key not in seen:
284
+ seen.add(key)
285
+ stack.append(key)
286
+
287
+ if truncated:
288
+ break
289
+ if is_minimal:
290
+ minimal.append(set(current))
291
+
292
+ if truncated and strict_limit:
293
+ raise SiphonSearchLimit(
294
+ f"Search exceeded {max_nodes} closure evaluations. Raise max_nodes, "
295
+ f"set max_size, or pass strict_limit=False to accept a partial result."
296
+ )
297
+
298
+ # The descent can surface a set that strictly contains another minimal one
299
+ # when the budget truncates a branch; filter defensively.
300
+ result = [
301
+ s
302
+ for s in minimal
303
+ if not any(t < s for t in minimal)
304
+ and (max_size is None or len(s) <= max_size)
305
+ ]
306
+ result.sort(key=lambda s: (len(s), sorted(s)))
307
+ return result
308
+
309
+
310
+ def minimal_siphons(
311
+ net: PetriNet,
312
+ *,
313
+ max_size: Optional[int] = None,
314
+ max_nodes: int = DEFAULT_MAX_NODES,
315
+ strict_limit: bool = False,
316
+ ) -> List[Set[str]]:
317
+ """Enumerate the inclusion-minimal siphons of a Petri net.
318
+
319
+ :param net:
320
+ Petri net to analyse.
321
+ :type net: PetriNet
322
+
323
+ :param max_size:
324
+ Optional ceiling on siphon size. Filtering happens after enumeration,
325
+ so the result is exactly the minimal siphons no larger than the bound.
326
+ :type max_size: Optional[int]
327
+
328
+ :param max_nodes:
329
+ Maximum number of closure evaluations before the search stops.
330
+ :type max_nodes: int
331
+
332
+ :param strict_limit:
333
+ Raise :class:`SiphonSearchLimit` instead of returning a partial result
334
+ when the budget is exhausted.
335
+ :type strict_limit: bool
336
+
337
+ :return:
338
+ Minimal siphons, ordered by size then lexicographically.
339
+ :rtype: List[Set[str]]
340
+
341
+ .. rubric:: Example
342
+
343
+ .. code-block:: python
344
+
345
+ minimal_siphons(net, max_size=4)
346
+ """
347
+ pre, post = _incidence(net)
348
+ return _enumerate_minimal(
349
+ net,
350
+ trigger=post,
351
+ required=pre,
352
+ max_size=max_size,
353
+ max_nodes=max_nodes,
354
+ strict_limit=strict_limit,
355
+ )
356
+
357
+
358
+ def minimal_traps(
359
+ net: PetriNet,
360
+ *,
361
+ max_size: Optional[int] = None,
362
+ max_nodes: int = DEFAULT_MAX_NODES,
363
+ strict_limit: bool = False,
364
+ ) -> List[Set[str]]:
365
+ """Enumerate the inclusion-minimal traps of a Petri net.
366
+
367
+ :param net:
368
+ Petri net to analyse.
369
+ :type net: PetriNet
370
+
371
+ :param max_size:
372
+ Optional ceiling on trap size.
373
+ :type max_size: Optional[int]
374
+
375
+ :param max_nodes:
376
+ Maximum number of closure evaluations before the search stops.
377
+ :type max_nodes: int
378
+
379
+ :param strict_limit:
380
+ Raise :class:`SiphonSearchLimit` instead of returning a partial result
381
+ when the budget is exhausted.
382
+ :type strict_limit: bool
383
+
384
+ :return:
385
+ Minimal traps, ordered by size then lexicographically.
386
+ :rtype: List[Set[str]]
387
+
388
+ .. rubric:: Example
389
+
390
+ .. code-block:: python
391
+
392
+ minimal_traps(net)
393
+ """
394
+ pre, post = _incidence(net)
395
+ return _enumerate_minimal(
396
+ net,
397
+ trigger=pre,
398
+ required=post,
399
+ max_size=max_size,
400
+ max_nodes=max_nodes,
401
+ strict_limit=strict_limit,
402
+ )
@@ -0,0 +1,286 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Dict, List, Optional, Set
4
+
5
+ from .net import PetriNet
6
+ from .siphon_search import DEFAULT_MAX_NODES, minimal_siphons, minimal_traps
7
+
8
+
9
+ def _as_petri(crn: Any) -> PetriNet:
10
+ """Convert a SynCRN-like object into a :class:`PetriNet`.
11
+
12
+ If ``crn`` is already a :class:`PetriNet`, it is returned unchanged.
13
+ Otherwise, the object is converted using :meth:`PetriNet.from_syncrn`.
14
+
15
+ :param crn: SynCRN-like object or an existing :class:`PetriNet`.
16
+ :type crn: Any
17
+ :return: Petri-net representation of the input object.
18
+ :rtype: PetriNet
19
+ """
20
+ return crn if isinstance(crn, PetriNet) else PetriNet.from_syncrn(crn)
21
+
22
+
23
+ def _is_siphon(net: PetriNet, places: Set[str]) -> bool:
24
+ """Test whether a set of places is a siphon.
25
+
26
+ A place set ``S`` is a siphon if every transition that produces tokens into
27
+ ``S`` also consumes at least one token from ``S``.
28
+
29
+ :param net: Petri net to inspect.
30
+ :type net: PetriNet
31
+ :param places: Candidate place set.
32
+ :type places: Set[str]
33
+ :return:
34
+ ``True`` if ``places`` is a non-empty siphon, otherwise ``False``.
35
+ :rtype: bool
36
+ """
37
+ if not places:
38
+ return False
39
+ for tid in net.transition_order:
40
+ t = net.transitions[tid]
41
+ produces_into_s = any(p in places and w > 0 for p, w in t.post.items())
42
+ if not produces_into_s:
43
+ continue
44
+ consumes_from_s = any(p in places and w > 0 for p, w in t.pre.items())
45
+ if not consumes_from_s:
46
+ return False
47
+ return True
48
+
49
+
50
+ def _is_trap(net: PetriNet, places: Set[str]) -> bool:
51
+ """Test whether a set of places is a trap.
52
+
53
+ A place set ``S`` is a trap if every transition that consumes tokens from
54
+ ``S`` also produces at least one token back into ``S``.
55
+
56
+ :param net: Petri net to inspect.
57
+ :type net: PetriNet
58
+ :param places: Candidate place set.
59
+ :type places: Set[str]
60
+ :return:
61
+ ``True`` if ``places`` is a non-empty trap, otherwise ``False``.
62
+ :rtype: bool
63
+ """
64
+ if not places:
65
+ return False
66
+ for tid in net.transition_order:
67
+ t = net.transitions[tid]
68
+ consumes_from_s = any(p in places and w > 0 for p, w in t.pre.items())
69
+ if not consumes_from_s:
70
+ continue
71
+ produces_into_s = any(p in places and w > 0 for p, w in t.post.items())
72
+ if not produces_into_s:
73
+ return False
74
+ return True
75
+
76
+
77
+ def _minimal_sets(candidates: List[Set[str]]) -> List[Set[str]]:
78
+ """Reduce a collection of candidate sets to inclusion-minimal sets.
79
+
80
+ The result contains only those sets for which no strict subset is also
81
+ present among the candidates.
82
+
83
+ :param candidates: Candidate place sets.
84
+ :type candidates: List[Set[str]]
85
+ :return: Inclusion-minimal subset of the input candidates.
86
+ :rtype: List[Set[str]]
87
+ """
88
+ candidates = sorted(candidates, key=lambda s: (len(s), sorted(s)))
89
+ out: List[Set[str]] = []
90
+ for s in candidates:
91
+ if any(t.issubset(s) for t in out):
92
+ continue
93
+ out = [t for t in out if not s.issubset(t)]
94
+ out.append(s)
95
+ return out
96
+
97
+
98
+ def _render_place_sets(
99
+ net: PetriNet,
100
+ sets_: List[Set[str]],
101
+ *,
102
+ names: str,
103
+ ) -> List[Set[str]]:
104
+ """Render place sets either by internal ids or by place labels.
105
+
106
+ :param net: Petri net providing place-name lookup.
107
+ :type net: PetriNet
108
+ :param sets_: Place sets expressed in internal place ids.
109
+ :type sets_: List[Set[str]]
110
+ :param names:
111
+ Output naming mode. Supported values are ``"id"`` and ``"label"``.
112
+ :type names: str
113
+ :return:
114
+ Place sets rendered according to the requested naming convention.
115
+ :rtype: List[Set[str]]
116
+ :raises ValueError: If ``names`` is not ``"id"`` or ``"label"``.
117
+ """
118
+ if names == "id":
119
+ return [set(s) for s in sets_]
120
+ if names == "label":
121
+ return [{net.place_name(p) for p in s} for s in sets_]
122
+ raise ValueError("names must be 'id' or 'label'")
123
+
124
+
125
+ def find_siphons(
126
+ crn: Any,
127
+ *,
128
+ max_size: Optional[int] = None,
129
+ names: str = "label",
130
+ max_nodes: int = DEFAULT_MAX_NODES,
131
+ strict_limit: bool = False,
132
+ ) -> List[Set[str]]:
133
+ """Enumerate inclusion-minimal siphons of a SynCRN Petri-net view.
134
+
135
+ The search uses the maximal-siphon closure operator with branch-and-bound
136
+ descent rather than brute-force subset enumeration; see
137
+ :mod:`synkit.CRN.Petrinet.siphon_search`.
138
+
139
+ :param crn: SynCRN-like object or :class:`PetriNet`.
140
+ :type crn: Any
141
+ :param max_size:
142
+ Maximum siphon size to consider. ``None`` means all sizes.
143
+ :type max_size: int | None
144
+ :param names:
145
+ Whether to return internal place ids or species labels.
146
+ Supported values are ``"id"`` and ``"label"``.
147
+ :type names: str
148
+ :param max_nodes:
149
+ Exploration budget for the branch-and-bound search.
150
+ :type max_nodes: int
151
+ :param strict_limit:
152
+ Raise :class:`~synkit.CRN.Petrinet.siphon_search.SiphonSearchLimit`
153
+ instead of returning a partial result when the budget is exhausted.
154
+ :type strict_limit: bool
155
+ :return: Inclusion-minimal siphons.
156
+ :rtype: List[Set[str]]
157
+ """
158
+ from ..backend import resolve_backend
159
+
160
+ backend, library = resolve_backend()
161
+ if backend == "cpp":
162
+ from ..native import enumerate_structural_sets
163
+ from .siphon_search import SiphonSearchLimit
164
+
165
+ net = _as_petri(crn)
166
+ result = enumerate_structural_sets(
167
+ net, kind="siphon", backend="cpp", library_path=library, max_nodes=max_nodes
168
+ )
169
+ if not result.complete:
170
+ error = SiphonSearchLimit(result.termination_reason)
171
+ error.result = result
172
+ raise error
173
+ sets_ = [
174
+ set(group)
175
+ for group in result.value["sets"]
176
+ if max_size is None or len(group) <= max_size
177
+ ]
178
+ return _render_place_sets(net, sets_, names=names)
179
+ net = _as_petri(crn)
180
+ sets_ = minimal_siphons(
181
+ net,
182
+ max_size=max_size,
183
+ max_nodes=max_nodes,
184
+ strict_limit=strict_limit,
185
+ )
186
+ return _render_place_sets(net, sets_, names=names)
187
+
188
+
189
+ def find_traps(
190
+ crn: Any,
191
+ *,
192
+ max_size: Optional[int] = None,
193
+ names: str = "label",
194
+ max_nodes: int = DEFAULT_MAX_NODES,
195
+ strict_limit: bool = False,
196
+ ) -> List[Set[str]]:
197
+ """Enumerate inclusion-minimal traps of a SynCRN Petri-net view.
198
+
199
+ The search uses the maximal-siphon closure operator with branch-and-bound
200
+ descent rather than brute-force subset enumeration; see
201
+ :mod:`synkit.CRN.Petrinet.siphon_search`.
202
+
203
+ :param crn: SynCRN-like object or :class:`PetriNet`.
204
+ :type crn: Any
205
+ :param max_size:
206
+ Maximum trap size to consider. ``None`` means all sizes.
207
+ :type max_size: int | None
208
+ :param names:
209
+ Whether to return internal place ids or species labels.
210
+ Supported values are ``"id"`` and ``"label"``.
211
+ :type names: str
212
+ :param max_nodes:
213
+ Exploration budget for the branch-and-bound search.
214
+ :type max_nodes: int
215
+ :param strict_limit:
216
+ Raise :class:`~synkit.CRN.Petrinet.siphon_search.SiphonSearchLimit`
217
+ instead of returning a partial result when the budget is exhausted.
218
+ :type strict_limit: bool
219
+ :return: Inclusion-minimal traps.
220
+ :rtype: List[Set[str]]
221
+ """
222
+ from ..backend import resolve_backend
223
+
224
+ backend, library = resolve_backend()
225
+ if backend == "cpp":
226
+ from ..native import enumerate_structural_sets
227
+ from .siphon_search import SiphonSearchLimit
228
+
229
+ net = _as_petri(crn)
230
+ result = enumerate_structural_sets(
231
+ net, kind="trap", backend="cpp", library_path=library, max_nodes=max_nodes
232
+ )
233
+ if not result.complete:
234
+ error = SiphonSearchLimit(result.termination_reason)
235
+ error.result = result
236
+ raise error
237
+ sets_ = [
238
+ set(group)
239
+ for group in result.value["sets"]
240
+ if max_size is None or len(group) <= max_size
241
+ ]
242
+ return _render_place_sets(net, sets_, names=names)
243
+ net = _as_petri(crn)
244
+ sets_ = minimal_traps(
245
+ net,
246
+ max_size=max_size,
247
+ max_nodes=max_nodes,
248
+ strict_limit=strict_limit,
249
+ )
250
+ return _render_place_sets(net, sets_, names=names)
251
+
252
+
253
+ def species_transition_neighborhoods(crn: Any) -> Dict[str, Dict[str, List[str]]]:
254
+ """Return per-species producer and consumer transition neighborhoods.
255
+
256
+ This is a small structural helper that is often useful when debugging
257
+ siphons, traps, and reachability issues.
258
+
259
+ The returned dictionary is keyed by internal place id. For each place, the
260
+ value contains the display label, the transitions that produce tokens into
261
+ the place, and the transitions that consume tokens from it.
262
+
263
+ :param crn: SynCRN-like object or :class:`PetriNet`.
264
+ :type crn: Any
265
+ :return:
266
+ Mapping from place id to a dictionary with keys ``"label"``,
267
+ ``"producer_transitions"``, and ``"consumer_transitions"``.
268
+ :rtype: Dict[str, Dict[str, List[str]]]
269
+ """
270
+ net = _as_petri(crn)
271
+ out: Dict[str, Dict[str, List[str]]] = {}
272
+ for p in net.place_order:
273
+ producers: List[str] = []
274
+ consumers: List[str] = []
275
+ for tid in net.transition_order:
276
+ t = net.transitions[tid]
277
+ if p in t.post:
278
+ producers.append(tid)
279
+ if p in t.pre:
280
+ consumers.append(tid)
281
+ out[p] = {
282
+ "label": net.place_name(p),
283
+ "producer_transitions": producers,
284
+ "consumer_transitions": consumers,
285
+ }
286
+ return out