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,459 @@
1
+ """Python interfaces to native exact algebra, CRNT and Petri-net searches."""
2
+
3
+ from __future__ import annotations
4
+ import ctypes as ct
5
+ import json
6
+ from math import gcd
7
+ from functools import reduce
8
+ import numpy as np
9
+ from .native import _load_library
10
+ from .analysis import AnalysisResult
11
+ from .Petrinet.minimal_semiflows import _integer_stoichiometry
12
+
13
+ PTR = ct.POINTER(ct.c_int64)
14
+
15
+
16
+ class NativeSearchLimit(RuntimeError):
17
+ def __init__(self, result):
18
+ self.result = result
19
+ super().__init__("Native CRN analysis incomplete: " + result.termination_reason)
20
+
21
+
22
+ def _call(library_path, name, types, values):
23
+ library = _load_library(library_path)
24
+ if not hasattr(library, name):
25
+ raise RuntimeError(f"Rebuild the CRN library: missing native operation {name}")
26
+ from .backend import record_operation
27
+
28
+ record_operation(name.removeprefix("synkit_crn_"))
29
+ function = getattr(library, name)
30
+ function.argtypes = [*types, ct.POINTER(ct.c_void_p)]
31
+ function.restype = ct.c_int
32
+ library.synkit_crn_free_text.argtypes = [ct.c_void_p]
33
+ library.synkit_crn_free_text.restype = None
34
+ output = ct.c_void_p()
35
+ try:
36
+ code = function(*values, ct.byref(output))
37
+ if code or not output.value:
38
+ raise RuntimeError(f"Native CRN operation failed: {name}")
39
+ result = json.loads(ct.string_at(output).decode("ascii"))
40
+ finally:
41
+ if output.value:
42
+ library.synkit_crn_free_text(output)
43
+ if result.get("termination_reason") not in {
44
+ "complete",
45
+ "certificate",
46
+ "exhausted",
47
+ "depth_limit",
48
+ "state_limit",
49
+ "frontier_limit",
50
+ "time_limit",
51
+ "count_limit",
52
+ "allocation_failure",
53
+ }:
54
+ raise RuntimeError(f"Invalid native result: {result}")
55
+ return result
56
+
57
+
58
+ def _array(matrix):
59
+ return np.ascontiguousarray(_integer_stoichiometry(matrix), dtype=np.int64)
60
+
61
+
62
+ def _seconds(seconds):
63
+ if not np.isfinite(seconds) or not 0 < seconds <= 1e9:
64
+ raise ValueError("time_limit must be finite, positive and at most 1e9 seconds")
65
+ return seconds
66
+
67
+
68
+ def matrix_analysis(matrix, *, library_path, kernels="left", time_limit=30.0):
69
+ s = _array(matrix)
70
+ flags = {"none": 0, "left": 1, "right": 2, "both": 3}
71
+ if kernels not in flags:
72
+ raise ValueError("Invalid kernel selection")
73
+ result = _call(
74
+ library_path,
75
+ "synkit_crn_matrix",
76
+ [ct.c_size_t, ct.c_size_t, PTR, ct.c_int, ct.c_double],
77
+ [*s.shape, s.ctypes.data_as(PTR), flags[kernels], _seconds(time_limit)],
78
+ )
79
+ if result["termination_reason"] != "complete":
80
+ raise NativeSearchLimit(
81
+ AnalysisResult(
82
+ None,
83
+ "inconclusive",
84
+ False,
85
+ "native rational algebra",
86
+ termination_reason=result["termination_reason"],
87
+ )
88
+ )
89
+ for name, matrix in [("left", s.T), ("right", s)]:
90
+ if name not in kernels and kernels != "both":
91
+ continue
92
+ basis = result[name]
93
+ if len(basis) != matrix.shape[1] - result["rank"]:
94
+ raise RuntimeError("Invalid native nullity")
95
+ for row in basis:
96
+ if len(row) != matrix.shape[1] or reduce(gcd, row, 0) != 1:
97
+ raise RuntimeError("Invalid native primitive kernel vector")
98
+ if any(sum(int(v) * c for v, c in zip(r, row)) for r in matrix):
99
+ raise RuntimeError("Native kernel witness failed exact verification")
100
+ return result
101
+
102
+
103
+ def crnt_summary_native(crn, *, library_path, time_limit=30.0):
104
+ from .Props.stoich import build_S_minus_plus
105
+ from .Props.deficiency import (
106
+ CRNTSummary,
107
+ Complex,
108
+ _species_labels,
109
+ _deficiency_zero_values,
110
+ _deficiency_one_values,
111
+ )
112
+
113
+ _, _, minus, plus = build_S_minus_plus(crn)
114
+ pre, post = _array(minus), _array(plus)
115
+ result = _call(
116
+ library_path,
117
+ "synkit_crn_crnt",
118
+ [ct.c_size_t, ct.c_size_t, PTR, PTR, ct.c_double],
119
+ [
120
+ *pre.shape,
121
+ pre.ctypes.data_as(PTR),
122
+ post.ctypes.data_as(PTR),
123
+ _seconds(time_limit),
124
+ ],
125
+ )
126
+ if result["termination_reason"] != "complete":
127
+ raise NativeSearchLimit(
128
+ AnalysisResult(
129
+ None,
130
+ "inconclusive",
131
+ False,
132
+ "native exact CRNT",
133
+ termination_reason=result["termination_reason"],
134
+ )
135
+ )
136
+ result.pop("termination_reason")
137
+ labels = tuple(_species_labels(crn))
138
+ result["complexes"] = [
139
+ str(Complex(coefficients=tuple(c), species_labels=labels))
140
+ for c in result.pop("complex_coefficients")
141
+ ]
142
+ terminals = result.pop("terminal_counts")
143
+ result["deficiency_zero"] = _deficiency_zero_values(
144
+ result["deficiency"], result["is_weakly_reversible"]
145
+ )
146
+ result["deficiency_one"] = _deficiency_one_values(
147
+ result["deficiency"],
148
+ result["linkage_class_deficiencies"],
149
+ result["is_weakly_reversible"],
150
+ terminals,
151
+ )
152
+ return CRNTSummary(**result)
153
+
154
+
155
+ def petri_reachability(
156
+ net,
157
+ initial,
158
+ goal_exact,
159
+ goal_atleast,
160
+ *,
161
+ library_path,
162
+ max_states=100000,
163
+ max_depth=10000,
164
+ time_limit=30.0,
165
+ qualitative=False,
166
+ ):
167
+ if (
168
+ not isinstance(max_states, int)
169
+ or not 0 < max_states < 2**59
170
+ or not isinstance(max_depth, int)
171
+ or not 0 <= max_depth < 2**59
172
+ ):
173
+ raise ValueError("Invalid state/depth budget")
174
+ places, transitions = net.place_order, net.transition_order
175
+ pre = np.zeros((len(places), len(transitions)), dtype=np.int64)
176
+ post = pre.copy()
177
+ for j, t in enumerate(transitions):
178
+ for i, s in enumerate(places):
179
+ pre[i, j] = net.transitions[t].pre.get(s, 0)
180
+ post[i, j] = net.transitions[t].post.get(s, 0)
181
+ m = _array([[initial.get(s, 0) for s in places]]).ravel()
182
+ exact = _array([[goal_exact.get(s, -1) for s in places]]).ravel()
183
+ atleast = _array([[goal_atleast.get(s, 0) for s in places]]).ravel()
184
+ result = _call(
185
+ library_path,
186
+ "synkit_crn_pathway",
187
+ [
188
+ ct.c_size_t,
189
+ ct.c_size_t,
190
+ PTR,
191
+ PTR,
192
+ PTR,
193
+ PTR,
194
+ PTR,
195
+ ct.c_size_t,
196
+ ct.c_size_t,
197
+ ct.c_double,
198
+ ct.c_int,
199
+ ],
200
+ [
201
+ len(places),
202
+ len(transitions),
203
+ pre.ctypes.data_as(PTR),
204
+ post.ctypes.data_as(PTR),
205
+ m.ctypes.data_as(PTR),
206
+ exact.ctypes.data_as(PTR),
207
+ atleast.ctypes.data_as(PTR),
208
+ max_states,
209
+ max_depth,
210
+ _seconds(time_limit),
211
+ int(qualitative),
212
+ ],
213
+ )
214
+ if result["certificate"] is not None:
215
+ certificate = [transitions[i] for i in result["certificate"]]
216
+ marking = dict(initial)
217
+ for t in certificate:
218
+ if qualitative:
219
+ if not set(net.transitions[t].pre) <= {
220
+ s for s, n in marking.items() if n > 0
221
+ }:
222
+ raise RuntimeError("Invalid native qualitative certificate")
223
+ marking.update({s: 1 for s in net.transitions[t].post})
224
+ else:
225
+ if not net.enabled(marking, t):
226
+ raise RuntimeError("Invalid native firing certificate")
227
+ marking = net.fire(marking, t)
228
+ if any(marking.get(s, 0) != n for s, n in goal_exact.items()) or any(
229
+ marking.get(s, 0) < n for s, n in goal_atleast.items()
230
+ ):
231
+ raise RuntimeError("Native certificate misses its goal")
232
+ result["certificate"] = certificate
233
+ return result
234
+
235
+
236
+ def graph_symmetry(
237
+ crn, *, library_path, time_limit=30.0, max_states=1000000, max_count=1000000
238
+ ):
239
+ from .Petrinet.net import extract_syncrn_incidence
240
+ import hashlib
241
+
242
+ incidence = extract_syncrn_incidence(crn)
243
+ nodes = list(incidence.species_order) + list(incidence.reaction_order)
244
+ n = len(nodes)
245
+ index = {s: i for i, s in enumerate(nodes)}
246
+ adjacency = np.zeros((n, n), dtype=np.int64)
247
+ for rid in incidence.reaction_order:
248
+ for sid, value in incidence.pre[rid].items():
249
+ adjacency[index[sid], index[rid]] = value
250
+ for sid, value in incidence.post[rid].items():
251
+ adjacency[index[rid], index[sid]] = value
252
+ kinds = np.array(
253
+ [0] * len(incidence.species_order) + [1] * len(incidence.reaction_order),
254
+ dtype=np.int64,
255
+ )
256
+ result = _call(
257
+ library_path,
258
+ "synkit_crn_symmetry",
259
+ [ct.c_size_t, PTR, PTR, ct.c_double, ct.c_size_t, ct.c_size_t],
260
+ [
261
+ n,
262
+ kinds.ctypes.data_as(PTR),
263
+ adjacency.ctypes.data_as(PTR),
264
+ _seconds(time_limit),
265
+ max_states,
266
+ max_count,
267
+ ],
268
+ )
269
+ complete = result["termination_reason"] == "complete"
270
+ if complete:
271
+ order = result["order"]
272
+ # Sparse canonical certificate avoids storing an n*n matrix in evidence.
273
+ inverse = {v: i for i, v in enumerate(order)}
274
+ edges = sorted(
275
+ (inverse[int(i)], inverse[int(j)], int(adjacency[i, j]))
276
+ for i, j in zip(*adjacency.nonzero())
277
+ )
278
+ certificate = ([int(kinds[i]) for i in order], edges)
279
+ result["canonical_key"] = hashlib.sha256(
280
+ json.dumps(certificate, separators=(",", ":")).encode()
281
+ ).hexdigest()
282
+ result["canonical_order"] = [nodes[i] for i in order]
283
+ result["orbits"] = [[nodes[i] for i in group] for group in result["orbits"]]
284
+ else:
285
+ result["canonical_key"] = None
286
+ return AnalysisResult(
287
+ result,
288
+ "complete" if complete else "inconclusive",
289
+ complete,
290
+ "native exact individualization/refinement",
291
+ termination_reason=result["termination_reason"],
292
+ )
293
+
294
+
295
+ def exhaustive_siphons(crn, *, library_path, max_species=22, time_limit=30.0):
296
+ from .Petrinet.net import PetriNet
297
+
298
+ net = crn if isinstance(crn, PetriNet) else PetriNet.from_syncrn(crn)
299
+ places, transitions = net.place_order, net.transition_order
300
+ if len(places) > min(max_species, 24):
301
+ raise ValueError("Exhaustive enumeration exceeds species limit")
302
+ pre = np.zeros(len(transitions), dtype=np.uint64)
303
+ post = pre.copy()
304
+ index = {s: i for i, s in enumerate(places)}
305
+ for j, t in enumerate(transitions):
306
+ for s in net.transitions[t].pre:
307
+ pre[j] |= np.uint64(1 << index[s])
308
+ for s in net.transitions[t].post:
309
+ post[j] |= np.uint64(1 << index[s])
310
+ pointer = ct.POINTER(ct.c_uint64)
311
+ result = _call(
312
+ library_path,
313
+ "synkit_crn_exhaustive_siphons",
314
+ [ct.c_size_t, ct.c_size_t, pointer, pointer, ct.c_double],
315
+ [
316
+ len(places),
317
+ len(transitions),
318
+ pre.ctypes.data_as(pointer),
319
+ post.ctypes.data_as(pointer),
320
+ _seconds(time_limit),
321
+ ],
322
+ )
323
+ if result["termination_reason"] != "complete":
324
+ raise NativeSearchLimit(
325
+ AnalysisResult(
326
+ result,
327
+ "inconclusive",
328
+ False,
329
+ "native exhaustive subsets",
330
+ termination_reason=result["termination_reason"],
331
+ )
332
+ )
333
+ return [{places[i] for i in group} for group in result["sets"]]
334
+
335
+
336
+ def qualitative_path(
337
+ crn,
338
+ seeds,
339
+ targets,
340
+ *,
341
+ library_path,
342
+ max_states=100000,
343
+ max_depth=100,
344
+ time_limit=30.0,
345
+ ):
346
+ from .Petrinet.net import PetriNet
347
+
348
+ net = PetriNet.from_syncrn(crn)
349
+ result = petri_reachability(
350
+ net,
351
+ {s: 1 for s in seeds},
352
+ {},
353
+ {s: 1 for s in targets},
354
+ library_path=library_path,
355
+ max_states=max_states,
356
+ max_depth=max_depth,
357
+ time_limit=time_limit,
358
+ qualitative=True,
359
+ )
360
+ return result
361
+
362
+
363
+ def positive_kernel_certificate(crn, *, kind="p", include_problem=False):
364
+ """Decide strict positive-kernel feasibility only with an exact witness.
365
+
366
+ A negative answer carries a separating vector y with A.T @ y >= 0 and
367
+ at least one strictly positive component (Gordan's alternative). Set
368
+ include_problem to record the integer matrix for standalone verification.
369
+ """
370
+ from scipy.optimize import linprog
371
+ from fractions import Fraction
372
+ from .Props.stoich import stoichiometric_matrix, _primitive_integer_vector
373
+ from .backend import record_operation
374
+
375
+ if kind not in {"p", "t"}:
376
+ raise ValueError("kind must be p or t")
377
+ s = _array(stoichiometric_matrix(crn))
378
+ a = s.T if kind == "p" else s
379
+ record_operation("highs_positive_kernel")
380
+ rows, columns = a.shape
381
+ problem = {"kind": kind, "shape": [rows, columns]}
382
+ if include_problem:
383
+ problem["problem_matrix"] = a.tolist()
384
+ unknown = {**problem, "holds": None, "exact": False}
385
+ if columns == 0 or rows == 0:
386
+ return {
387
+ **problem,
388
+ "holds": True,
389
+ "exact": True,
390
+ "primal_witness": [1] * columns,
391
+ }
392
+ result = linprog(
393
+ np.zeros(columns),
394
+ A_eq=a,
395
+ b_eq=np.zeros(rows),
396
+ bounds=(1, None),
397
+ method="highs",
398
+ )
399
+ if result.success:
400
+ try:
401
+ witness = _primitive_integer_vector(
402
+ [Fraction(float(v)).limit_denominator(10**6) for v in result.x]
403
+ )
404
+ except (ValueError, OverflowError):
405
+ return unknown
406
+ if all(v > 0 for v in witness) and all(
407
+ sum(int(x) * v for x, v in zip(row, witness)) == 0 for row in a
408
+ ):
409
+ return {
410
+ **problem,
411
+ "holds": True,
412
+ "exact": True,
413
+ "primal_witness": witness,
414
+ }
415
+ return unknown
416
+ if result.status != 2:
417
+ return unknown
418
+ # A floating infeasibility status alone is insufficient. Find and verify a
419
+ # rational separator instead, normalized by sum(A.T @ y) = 1.
420
+ column_sums = np.array([sum(int(v) for v in row) for row in a], dtype=float)
421
+ dual = linprog(
422
+ np.zeros(rows),
423
+ A_ub=-a.astype(float).T,
424
+ b_ub=np.zeros(columns),
425
+ A_eq=column_sums.reshape(1, -1),
426
+ b_eq=np.ones(1),
427
+ bounds=[(None, None)] * rows,
428
+ method="highs",
429
+ )
430
+ if not dual.success:
431
+ return unknown
432
+ try:
433
+ witness = [Fraction(float(v)).limit_denominator(10**6) for v in dual.x]
434
+ except (ValueError, OverflowError):
435
+ return unknown
436
+ image = [
437
+ sum(int(a[i, j]) * witness[i] for i in range(rows)) for j in range(columns)
438
+ ]
439
+ if all(v >= 0 for v in image) and any(v > 0 for v in image):
440
+ return {
441
+ **problem,
442
+ "holds": False,
443
+ "exact": True,
444
+ "dual_witness": [str(v) for v in witness],
445
+ "dual_image": [str(v) for v in image],
446
+ }
447
+ return unknown
448
+
449
+
450
+ def positive_kernel(crn, *, kind="p"):
451
+ """Compatibility interface backed by exactly verified certificates."""
452
+ from fractions import Fraction
453
+
454
+ certificate = positive_kernel_certificate(crn, kind=kind)
455
+ witness = certificate.get("primal_witness")
456
+ if certificate["holds"] is True and witness:
457
+ total = sum(witness)
458
+ return True, np.array([float(Fraction(v, total)) for v in witness])
459
+ return certificate["holds"], None
File without changes
@@ -0,0 +1,140 @@
1
+ from __future__ import annotations
2
+ from typing import List, Optional
3
+
4
+ import numpy as np
5
+ from rdkit.DataStructs import cDataStructs, CreateFromBitString, BulkTanimotoSimilarity
6
+ from rdkit.ML.Cluster import Butina
7
+ from sklearn.manifold import TSNE
8
+ import matplotlib.pyplot as plt
9
+
10
+
11
+ class ButinaCluster:
12
+ """Cluster chemical fingerprint vectors using the Butina algorithm from
13
+ RDKit, with integrated t-SNE visualization of clusters.
14
+
15
+ Key features
16
+ ------------
17
+ * **Butina clustering** – fast hierarchical clustering with a similarity cutoff.
18
+ * **t-SNE visualization** – 2D embedding of fingerprints, highlighting top‑k clusters.
19
+ * **NumPy support** – accepts 2D arrays of 0/1 fingerprint data.
20
+ * **Configurable** – user‑defined cutoff, perplexity, and top‑k highlight.
21
+
22
+ Quick start
23
+ -----------
24
+ >>> from synkit.Chem.Fingerprint.fingerprint_clusterer import ButinaCluster
25
+ >>> clusters = ButinaCluster.cluster(arr, cutoff=0.3)
26
+ >>> ButinaCluster.visualize(arr, clusters, k=5)
27
+ """
28
+
29
+ @staticmethod
30
+ def cluster(arr: np.ndarray, cutoff: float = 0.2) -> List[List[int]]:
31
+ """Perform Butina clustering on fingerprint bit-vectors.
32
+
33
+ :param arr: 2D array of shape (n_samples, n_bits) with 0/1
34
+ dtype.
35
+ :type arr: np.ndarray
36
+ :param cutoff: Distance cutoff (1 – similarity) to form
37
+ clusters. Defaults to 0.2.
38
+ :type cutoff: float
39
+ :return: List of clusters, each a list of sample indices.
40
+ :rtype: list of list of int
41
+ """
42
+ # Convert rows to RDKit ExplicitBitVect
43
+ fps: List[cDataStructs.ExplicitBitVect] = []
44
+ for row in arr:
45
+ bitstr = "".join(str(int(b)) for b in row.tolist())
46
+ fps.append(CreateFromBitString(bitstr))
47
+
48
+ n = len(fps)
49
+ # Build flattened upper‐triangular distance list
50
+ distances: List[float] = []
51
+ for i in range(n):
52
+ # fmt: off
53
+ sims = BulkTanimotoSimilarity(fps[i], fps[i + 1:])
54
+ # fmt: on
55
+ distances.extend((1.0 - np.array(sims, dtype=float)).tolist())
56
+
57
+ # Cluster: ClusterData(distanceList, nPts, cutoff, isDistData)
58
+ clusters = Butina.ClusterData(distances, n, cutoff, True)
59
+ return clusters
60
+
61
+ @staticmethod
62
+ def visualize(
63
+ arr: np.ndarray,
64
+ clusters: List[List[int]],
65
+ k: Optional[int] = None,
66
+ perplexity: float = 30.0,
67
+ random_state: int = 42,
68
+ ) -> None:
69
+ """Visualize clusters in 2D via t-SNE embedding.
70
+
71
+ :param arr: 2D array of shape (n_samples, n_features) with fingerprint data.
72
+ :type arr: np.ndarray
73
+ :param clusters: Clusters as returned by `cluster()`.
74
+ :type clusters: list of list of int
75
+ :param k: If provided, highlight only the top‑k largest clusters; others shown as 'Other'.
76
+ :type k: int or None
77
+ :param perplexity: t-SNE perplexity parameter. Defaults to 30.0.
78
+ :type perplexity: float
79
+ :param random_state: Random seed for reproducibility. Defaults to 42.
80
+ :type random_state: int
81
+ :return: None
82
+ :rtype: NoneType
83
+
84
+ .. rubric:: Examples
85
+
86
+ >>> clusters = ButinaCluster.cluster(arr, cutoff=0.3)
87
+ >>> ButinaCluster.visualize(arr, clusters, k=5)
88
+ """
89
+ n = arr.shape[0]
90
+ # assign labels: cluster idx or -1 for 'Other'
91
+ labels = np.full(n, -1, dtype=int)
92
+ # sort clusters by size
93
+ sorted_idx = sorted(
94
+ range(len(clusters)), key=lambda i: len(clusters[i]), reverse=True
95
+ )
96
+ top = set(sorted_idx[:k]) if k is not None else set(sorted_idx)
97
+ for idx, cluster in enumerate(clusters):
98
+ for i in cluster:
99
+ labels[i] = idx if idx in top else -1
100
+
101
+ # compute t-SNE embedding
102
+ tsne = TSNE(n_components=2, perplexity=perplexity, random_state=random_state)
103
+ emb = tsne.fit_transform(arr)
104
+
105
+ # plot
106
+ plt.figure(figsize=(8, 6))
107
+ unique = sorted(set(labels))
108
+ for lab in unique:
109
+ mask = labels == lab
110
+ if lab == -1:
111
+ plt.scatter(
112
+ emb[mask, 0], emb[mask, 1], color="gray", alpha=0.3, label="Other"
113
+ )
114
+ else:
115
+ plt.scatter(
116
+ emb[mask, 0], emb[mask, 1], alpha=0.7, label=f"Cluster {lab}"
117
+ )
118
+ plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
119
+ plt.title("t-SNE visualization of Butina clusters")
120
+ plt.xlabel("t-SNE dim 1")
121
+ plt.ylabel("t-SNE dim 2")
122
+ plt.tight_layout()
123
+ plt.show()
124
+
125
+ def __str__(self) -> str:
126
+ """Short description of the clusterer.
127
+
128
+ :return: Class name.
129
+ :rtype: str
130
+ """
131
+ return "<ButinaCluster>"
132
+
133
+ def help(self) -> None:
134
+ """Print usage summary for clustering and visualization.
135
+
136
+ :return: None
137
+ :rtype: NoneType
138
+ """
139
+ print("ButinaCluster.cluster(arr, cutoff=0.2)")
140
+ print("ButinaCluster.visualize(arr, clusters, k=None, perplexity=30.0)")
File without changes