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 @@
1
+ [{"R-id": 1, "aam": "[c:4]1([H:11])[cH:5][cH:6][cH:7][cH:8][cH:9]1.[CH3:1][CH:2]([CH3:3])[Cl:10]>>[CH3:1][CH:2]([CH3:3])[c:4]1[cH:5][cH:6][cH:7][cH:8][cH:9]1.[H:11][Cl:10]"}, {"R-id": 2, "aam": "[CH3:1][C:2]([H:12])([CH3:3])[c:6]1[cH:7][cH:8][cH:9][cH:10][cH:11]1.[O:4]=[O:5]>>[CH3:1][C:2]([CH3:3])([O:4][O:5][H:12])[c:6]1[cH:7][cH:8][cH:9][cH:10][cH:11]1"}, {"R-id": 3, "aam": "[CH3:8][C:9]([CH3:11])([O:10][OH:1])[c:2]1[cH:3][cH:4][cH:5][cH:6][cH:7]1>>[OH:1][c:2]1[cH:3][cH:4][cH:5][cH:6][cH:7]1.[CH3:8][C:9](=[O:10])[CH3:11]"}, {"R-id": 4, "aam": "[H:12][O:4][c:5]1[cH:6][cH:7][cH:8][cH:9][cH:10]1.[CH3:1][C:2](=[O:3])[Cl:11]>>[CH3:1][C:2](=[O:3])[O:4][c:5]1[cH:6][cH:7][cH:8][cH:9][cH:10]1.[Cl:11][H:12]"}, {"R-id": 5, "aam": "[CH3:11][C:9](=[O:10])[O:8][c:7]1[cH:6][cH:5][c:4]([H:15])[cH:13][cH:12]1.[O:1]=[N+:2]([O-:3])[OH:14]>>[O:1]=[N+:2]([O-:3])[c:4]1[cH:5][cH:6][c:7]([O:8][C:9](=[O:10])[CH3:11])[cH:12][cH:13]1.[OH:14][H:15]"}, {"R-id": 6, "aam": "[O:12]=[N+:1]([O-:13])[c:2]1[cH:3][cH:4][c:5]([O:6][C:7](=[O:8])[CH3:9])[cH:10][cH:11]1.[H:14][H:15].[H:16][H:18].[H:17][H:19]>>[N:1]([H:18])([H:19])[c:2]1[cH:3][cH:4][c:5]([O:6][C:7](=[O:8])[CH3:9])[cH:10][cH:11]1.[H:14][O:12][H:15].[H:16][O:13][H:17]"}, {"R-id": 7, "aam": "[NH2:1][c:2]1[cH:3][cH:4][c:5]([O:6][C:10](=[O:11])[CH3:9])[cH:7][cH:8]1.[OH:12][H:13]>>[NH2:1][c:2]1[cH:3][cH:4][c:5]([O:6][H:13])[cH:7][cH:8]1.[CH3:9][C:10](=[O:11])[OH:12]"}, {"R-id": 8, "aam": "[H:13][NH:4][c:5]1[cH:6][cH:7][c:8]([OH:9])[cH:10][cH:11]1.[CH3:1][C:2](=[O:3])[Cl:12]>>[CH3:1][C:2](=[O:3])[NH:4][c:5]1[cH:6][cH:7][c:8]([OH:9])[cH:10][cH:11]1.[Cl:12][H:13]"}, {"R-id": 9, "aam": "[CH3:19][C:17](=[O:18])[NH:16][c:13]1[cH:12][cH:11][c:10]([O:9][H:21])[cH:15][cH:14]1.[CH3:1][CH2:2][N:3]([CH2:4][CH3:5])[CH2:6][C:7](=[O:8])[Cl:20]>>[CH3:1][CH2:2][N:3]([CH2:4][CH3:5])[CH2:6][C:7](=[O:8])[O:9][C:10]1=[CH:11][CH:12]=[C:13]([NH:16][C:17](=[O:18])[CH3:19])[CH:14]=[CH:15]1.[Cl:20][H:21]"}]
@@ -0,0 +1,16 @@
1
+ from .canon_graph import GraphCanonicaliser, CanonicalGraph
2
+ from .exact import (
3
+ CanonicalSearchIncomplete,
4
+ ExactCanonicalResult,
5
+ ExactColoredGraphCanonicalizer,
6
+ IncompleteCanonicalResult,
7
+ )
8
+
9
+ __all__ = [
10
+ "CanonicalGraph",
11
+ "CanonicalSearchIncomplete",
12
+ "ExactCanonicalResult",
13
+ "ExactColoredGraphCanonicalizer",
14
+ "GraphCanonicaliser",
15
+ "IncompleteCanonicalResult",
16
+ ]
@@ -0,0 +1,13 @@
1
+ """Opt-in native graph backend using a bundled or explicitly built library."""
2
+
3
+ from .build import build_native_canon
4
+ from .runtime import CancellationToken, bundled_native_canon
5
+ from .search import NativeCanonicalResult, canonicalize_native_graph
6
+
7
+ __all__ = [
8
+ "build_native_canon",
9
+ "bundled_native_canon",
10
+ "CancellationToken",
11
+ "NativeCanonicalResult",
12
+ "canonicalize_native_graph",
13
+ ]
@@ -0,0 +1,93 @@
1
+ """Explicit immutable CMake builds of the dependency-free C++17 graph core."""
2
+
3
+ import hashlib
4
+ import json
5
+ import os
6
+ from pathlib import Path
7
+ import platform
8
+ import shutil
9
+ import subprocess
10
+ import sys
11
+ import tempfile
12
+
13
+
14
+ def _digest(path):
15
+ return hashlib.sha256(Path(path).read_bytes()).hexdigest()
16
+
17
+
18
+ def _verify(path):
19
+ probe = subprocess.run(
20
+ [sys.executable, "-c", "import ctypes,sys; assert ctypes.CDLL(sys.argv[1]).synkit_canon_abi()==1", str(path)],
21
+ capture_output=True, text=True,
22
+ )
23
+ if probe.returncode:
24
+ raise RuntimeError("Built graph core advertises an incompatible ABI")
25
+
26
+
27
+ def _run(command):
28
+ result = subprocess.run(command, capture_output=True, text=True)
29
+ if result.returncode:
30
+ raise RuntimeError("Native graph build failed:\n" + (result.stdout + result.stderr)[-6000:])
31
+
32
+
33
+ def build_native_canon(output_dir, *, compiler=None):
34
+ """Build explicitly and return a content-addressed library with provenance.
35
+
36
+ No native build or dependency download occurs during package import.
37
+ CMake and a C++17 compiler are developer requirements, not runtime SDKs.
38
+ """
39
+ cmake = shutil.which("cmake")
40
+ if cmake is None:
41
+ raise RuntimeError("CMake is required for an explicit native graph build")
42
+ if compiler is not None:
43
+ compiler = shutil.which(compiler)
44
+ if compiler is None:
45
+ raise RuntimeError("Requested C++ compiler is unavailable")
46
+ source = Path(__file__).resolve().parents[1] / "cpp"
47
+ inputs = [p for p in source.rglob("*") if p.is_file()
48
+ and (p.name in {"CMakeLists.txt", "README.md"}
49
+ or p.relative_to(source).parts[0] in {"include", "src", "examples", "tests"})]
50
+ detected_compiler = compiler or shutil.which(os.environ.get("CXX", "cl" if os.name == "nt" else "c++"))
51
+ compiler_info = subprocess.run([detected_compiler, "--version"], capture_output=True, text=True) \
52
+ if detected_compiler else None
53
+ config = {
54
+ "abi": 1, "builder_sha256": _digest(__file__),
55
+ "sources": {str(p.relative_to(source)): _digest(p) for p in sorted(inputs)},
56
+ "cmake": subprocess.check_output([cmake, "--version"], text=True),
57
+ "compiler": compiler, "platform": sys.platform, "machine": platform.machine(),
58
+ "detected_compiler": detected_compiler,
59
+ "compiler_version": (compiler_info.stdout + compiler_info.stderr) if compiler_info else None,
60
+ "environment": {k: os.environ.get(k) for k in ("CXX", "CXXFLAGS", "CMAKE_GENERATOR")},
61
+ }
62
+ key = hashlib.sha256(json.dumps(config, sort_keys=True).encode()).hexdigest()
63
+ output = Path(output_dir).expanduser().resolve()
64
+ output.mkdir(parents=True, exist_ok=True)
65
+ suffix = ".dll" if os.name == "nt" else ".dylib" if sys.platform == "darwin" else ".so"
66
+ library = output / ("libsynkit_canon_" + key[:20] + suffix)
67
+ manifest = library.with_suffix(".json")
68
+ if library.exists():
69
+ if not manifest.exists():
70
+ raise RuntimeError("Existing graph library has no build manifest")
71
+ saved = json.loads(manifest.read_text())
72
+ if saved.get("configuration") != config or saved.get("library_sha256") != _digest(library):
73
+ raise RuntimeError("Native graph build integrity verification failed")
74
+ _verify(library)
75
+ return library
76
+ with tempfile.TemporaryDirectory(prefix="synkit-canon-build-", dir=output) as name:
77
+ work = Path(name)
78
+ configure = [cmake, "-S", str(source), "-B", str(work), "-DCMAKE_BUILD_TYPE=Release"]
79
+ if compiler:
80
+ configure.append("-DCMAKE_CXX_COMPILER=" + compiler)
81
+ _run(configure)
82
+ _run([cmake, "--build", str(work), "--config", "Release", "--parallel", "2"])
83
+ built = list(work.rglob("*synkit_canon" + suffix))
84
+ if len(built) != 1:
85
+ raise RuntimeError(f"Expected one native graph library, found {built}")
86
+ _verify(built[0])
87
+ cache = (work / "CMakeCache.txt").read_text()
88
+ shutil.copy2(built[0], library)
89
+ manifest.write_text(json.dumps({
90
+ "configuration": config, "library_sha256": _digest(library),
91
+ "cmake_cache": cache,
92
+ }, indent=2) + "\n")
93
+ return library
@@ -0,0 +1,49 @@
1
+ """Snapshot exact typed colors and simple graph incidence for the native core."""
2
+
3
+ from dataclasses import dataclass
4
+ import json
5
+
6
+ import networkx as nx
7
+
8
+ from ..exact import _encode_color, _selector_value
9
+
10
+
11
+ @dataclass(frozen=True)
12
+ class PreparedGraph:
13
+ """Immutable Python-owned CSR snapshot; input handles are output witnesses."""
14
+
15
+ nodes: tuple
16
+ offsets: tuple[int, ...]
17
+ neighbors: tuple[int, ...]
18
+ colors: tuple[int, ...]
19
+ palette_bytes: bytes
20
+
21
+
22
+ def prepare_graph(graph, *, node_color="color", edge_color=None):
23
+ """Prepare a simple undirected vertex-colored graph without normalization.
24
+
25
+ Edge attributes are intentionally outside this prepared graph contract.
26
+ An explicit edge-color selector is refused; encode typed edges as colored
27
+ incidence vertices first, as the stereo expansion already does.
28
+ """
29
+ if not isinstance(graph, nx.Graph) or graph.is_directed() or graph.is_multigraph():
30
+ raise TypeError("Native graph search requires a simple undirected graph")
31
+ if edge_color is not None:
32
+ raise NotImplementedError("Encode edge colors as incidence vertices before native search")
33
+ if nx.number_of_selfloops(graph):
34
+ raise ValueError("Native graph search does not support self loops")
35
+ nodes = tuple(graph)
36
+ if len(nodes) > 2**31 - 1:
37
+ raise ValueError("Native graph dimensions exceed int32 vertex capacity")
38
+ tokens = tuple(_encode_color(_selector_value(graph.nodes[v], node_color)) for v in nodes)
39
+ palette = sorted(set(tokens))
40
+ ranks = {token: i for i, token in enumerate(palette)}
41
+ indices = {v: i for i, v in enumerate(nodes)}
42
+ offsets, neighbors = [0], []
43
+ for v in nodes:
44
+ neighbors.extend(sorted(indices[w] for w in graph[v]))
45
+ offsets.append(len(neighbors))
46
+ return PreparedGraph(
47
+ nodes, tuple(offsets), tuple(neighbors), tuple(ranks[t] for t in tokens),
48
+ json.dumps(palette, separators=(",", ":"), ensure_ascii=True).encode("ascii"),
49
+ )
@@ -0,0 +1,140 @@
1
+ """Versioned ctypes declarations and cancellation ownership for graph search."""
2
+
3
+ import ctypes as ct
4
+ from contextlib import contextmanager
5
+ from functools import lru_cache
6
+ from pathlib import Path
7
+ from threading import Lock
8
+
9
+ from synkit._native import bundled_library, verify_wheel_library
10
+
11
+
12
+ def bundled_native_canon():
13
+ """Return the graph/stereograph library installed with a platform wheel."""
14
+ return bundled_library(Path(__file__).parent, "synkit_canon")
15
+
16
+
17
+ def resolve_library_path(library_path=None):
18
+ return (Path(library_path).expanduser().resolve()
19
+ if library_path is not None else bundled_native_canon())
20
+
21
+
22
+ class Request(ct.Structure):
23
+ _fields_ = [
24
+ ("abi_version", ct.c_int32), ("struct_size", ct.c_int32),
25
+ ("n", ct.c_int64), ("arcs", ct.c_int64),
26
+ ("offsets", ct.POINTER(ct.c_int64)),
27
+ ("neighbors", ct.POINTER(ct.c_int32)),
28
+ ("colors", ct.POINTER(ct.c_int32)), ("seconds", ct.c_double),
29
+ ("max_nodes", ct.c_int64), ("workspace_bytes", ct.c_int64),
30
+ ("output_bytes", ct.c_int64), ("max_depth", ct.c_int32),
31
+ ("cancel_token", ct.c_void_p),
32
+ ]
33
+
34
+
35
+ class Statistics(ct.Structure):
36
+ _fields_ = [
37
+ ("complete", ct.c_int32), ("reason", ct.c_int32),
38
+ ("nodes", ct.c_int64), ("leaves", ct.c_int64),
39
+ ("refinement_rounds", ct.c_int64), ("peak_workspace_bytes", ct.c_int64),
40
+ ("elapsed_seconds", ct.c_double),
41
+ ("validation_seconds", ct.c_double), ("search_seconds", ct.c_double),
42
+ ("serialization_seconds", ct.c_double),
43
+ ]
44
+
45
+
46
+ class PruningStatistics(ct.Structure):
47
+ _fields_ = [(name, ct.c_int64) for name in (
48
+ "implicit_twin_factors", "twin_vertices", "automorphism_generators", "orbit_rebuilds",
49
+ "symmetry_pruned_branches", "stabilizer_calls", "stabilizer_fallbacks",
50
+ )]
51
+
52
+
53
+ @lru_cache(maxsize=8)
54
+ def load_library(path):
55
+ """Load a selected library without compiling or selecting a fallback."""
56
+ path = Path(path).expanduser().resolve()
57
+ if path.parent == Path(__file__).resolve().parent / "lib":
58
+ verify_wheel_library(path)
59
+ lib = ct.CDLL(str(path))
60
+ if lib.synkit_canon_abi() != 1:
61
+ raise RuntimeError("Unsupported graph canonicalization ABI")
62
+ lib.synkit_canon_error.restype = ct.c_char_p
63
+ lib.synkit_canon_search.argtypes = [ct.POINTER(Request), ct.POINTER(ct.c_void_p)]
64
+ lib.synkit_canon_search.restype = ct.c_int
65
+ lib.synkit_canon_statistics.argtypes = [ct.c_void_p]
66
+ lib.synkit_canon_statistics.restype = ct.POINTER(Statistics)
67
+ if hasattr(lib, "synkit_canon_pruning_statistics"):
68
+ lib.synkit_canon_pruning_statistics.argtypes = [ct.c_void_p]
69
+ lib.synkit_canon_pruning_statistics.restype = ct.POINTER(PruningStatistics)
70
+ lib.synkit_canon_bytes.argtypes = [ct.c_void_p, ct.POINTER(ct.c_int64)]
71
+ lib.synkit_canon_bytes.restype = ct.POINTER(ct.c_uint8)
72
+ lib.synkit_canon_order.argtypes = [ct.c_void_p, ct.POINTER(ct.c_int64)]
73
+ lib.synkit_canon_order.restype = ct.POINTER(ct.c_int32)
74
+ lib.synkit_canon_free.argtypes = [ct.c_void_p]
75
+ lib.synkit_canon_free.restype = None
76
+ lib.synkit_canon_cancel_create.restype = ct.c_void_p
77
+ for name in ("synkit_canon_cancel_request", "synkit_canon_cancel_free"):
78
+ getattr(lib, name).argtypes = [ct.c_void_p]
79
+ getattr(lib, name).restype = None
80
+ return lib
81
+
82
+
83
+ class CancellationToken:
84
+ """Own a one-shot native cancellation flag shared by explicitly chosen calls."""
85
+
86
+ def __init__(self, library_path=None):
87
+ self.library = load_library(str(resolve_library_path(library_path)))
88
+ self._lock = Lock()
89
+ self._active = 0
90
+ self._cancelled = False
91
+ self._handle = self.library.synkit_canon_cancel_create()
92
+ if not self._handle:
93
+ raise MemoryError("Cannot allocate native cancellation token")
94
+
95
+ @contextmanager
96
+ def borrow(self, library):
97
+ """Keep the token alive until the native call has returned."""
98
+ with self._lock:
99
+ if not self._handle:
100
+ raise RuntimeError("Cancellation token is closed")
101
+ if library is not self.library:
102
+ raise ValueError("Cancellation token belongs to a different library")
103
+ self._active += 1
104
+ handle = self._handle
105
+ try:
106
+ yield handle
107
+ finally:
108
+ with self._lock:
109
+ self._active -= 1
110
+
111
+ def cancel(self):
112
+ """Request cancellation without waiting for the active search."""
113
+ with self._lock:
114
+ if not self._handle:
115
+ raise RuntimeError("Cancellation token is closed")
116
+ self._cancelled = True
117
+ self.library.synkit_canon_cancel_request(self._handle)
118
+
119
+ @property
120
+ def cancelled(self):
121
+ return self._cancelled
122
+
123
+ def close(self):
124
+ """Free an idle token; refuse to invalidate a running call's pointer."""
125
+ with self._lock:
126
+ if self._active:
127
+ raise RuntimeError("Cancellation token is in use")
128
+ if self._handle:
129
+ self.library.synkit_canon_cancel_free(self._handle)
130
+ self._handle = None
131
+
132
+ def __enter__(self):
133
+ return self
134
+
135
+ def __exit__(self, *unused):
136
+ self.close()
137
+
138
+ def __del__(self):
139
+ if getattr(self, "_handle", None) and not getattr(self, "_active", 0):
140
+ self.library.synkit_canon_cancel_free(self._handle)
@@ -0,0 +1,137 @@
1
+ """Bounded sparse graph canonicalization under an explicit native convention."""
2
+
3
+ from contextlib import nullcontext
4
+ import ctypes as ct
5
+ from dataclasses import dataclass
6
+ import hashlib
7
+ import math
8
+ from numbers import Integral, Real
9
+ import struct
10
+ from time import perf_counter
11
+
12
+ from ..exact import CanonicalSearchIncomplete
13
+ from .prepare import prepare_graph
14
+ from .runtime import Request, load_library
15
+
16
+ SCHEMA = "synkit.native-sparse-canonical-graph/1"
17
+ REASONS = {0: None, 1: "time_limit", 2: "node_limit", 3: "workspace_limit",
18
+ 4: "output_limit", 5: "cancelled", 6: "depth_limit"}
19
+
20
+
21
+ @dataclass(frozen=True)
22
+ class NativeCanonicalResult:
23
+ """Exact native certificate or a stopped request without any usable key."""
24
+
25
+ complete: bool
26
+ reason: str | None
27
+ canonical_code: bytes | None
28
+ canonical_order: tuple
29
+ statistics: dict
30
+ schema: str = SCHEMA
31
+
32
+ @property
33
+ def exact(self):
34
+ return self.complete
35
+
36
+ @property
37
+ def canonical_digest(self):
38
+ return hashlib.sha256(self.canonical_code).hexdigest() if self.complete else None
39
+
40
+ def require_complete(self):
41
+ """Refuse promotion of bounded-search evidence to an identity key."""
42
+ if not self.complete:
43
+ raise CanonicalSearchIncomplete(f"Native canonical search is incomplete: {self.reason}")
44
+ return self
45
+
46
+ def same_canonical_graph(self, other):
47
+ """Compare full same-convention bytes; unfinished requests raise."""
48
+ self.require_complete()
49
+ if not isinstance(other, NativeCanonicalResult) or other.schema != self.schema:
50
+ raise TypeError("Cannot compare different canonical conventions")
51
+ other.require_complete()
52
+ return self.canonical_code == other.canonical_code
53
+
54
+
55
+ def _cap(value, name):
56
+ if value is None:
57
+ return -1
58
+ if isinstance(value, bool) or not isinstance(value, Integral) or not 0 < value < 2**63:
59
+ raise ValueError(f"{name} must be a positive int64 or None")
60
+ return int(value)
61
+
62
+
63
+ def _timeout(value):
64
+ if value is None:
65
+ return -1.0
66
+ if isinstance(value, bool) or not isinstance(value, Real) or not math.isfinite(value) or value < 0:
67
+ raise ValueError("timeout_seconds must be finite and nonnegative, or None")
68
+ return float(value)
69
+
70
+
71
+ def canonicalize_native_graph(
72
+ graph, *, library_path=None, node_color="color", edge_color=None,
73
+ timeout_seconds=None, max_search_nodes=None, max_workspace_bytes=None,
74
+ max_output_bytes=None, max_depth=1024, cancel_token=None,
75
+ ):
76
+ """Canonicalize a simple colored graph with an explicitly selected library.
77
+
78
+ The new sparse byte convention is NOT interchangeable with the reference
79
+ JSON certificate. The deadline includes Python preparation but its checks
80
+ there are cooperative (before/after stages). Workspace bounds tracked
81
+ native allocations, not Python/NetworkX or process RSS. No group is emitted.
82
+ """
83
+ started = perf_counter()
84
+ seconds = _timeout(timeout_seconds)
85
+ caps = [_cap(v, n) for v, n in (
86
+ (max_search_nodes, "max_search_nodes"), (max_workspace_bytes, "max_workspace_bytes"),
87
+ (max_output_bytes, "max_output_bytes"),
88
+ )]
89
+ if isinstance(max_depth, bool) or not isinstance(max_depth, Integral) or not 0 <= max_depth <= 1024:
90
+ raise ValueError("max_depth must be an integer between zero and 1024")
91
+ from .runtime import resolve_library_path
92
+
93
+ library = load_library(str(resolve_library_path(library_path)))
94
+ prepared = prepare_graph(graph, node_color=node_color, edge_color=edge_color)
95
+ preparation = perf_counter() - started
96
+ n = len(prepared.nodes)
97
+ offsets = (ct.c_int64 * (n + 1))(*prepared.offsets)
98
+ neighbors = (ct.c_int32 * len(prepared.neighbors))(*prepared.neighbors)
99
+ colors = (ct.c_int32 * n)(*prepared.colors)
100
+ prefix = SCHEMA.encode("ascii") + b"\0" + struct.pack("<Q", len(prepared.palette_bytes)) + prepared.palette_bytes
101
+ output_limit = caps[2] - len(prefix) if caps[2] >= 0 else -1
102
+ if caps[2] >= 0 and output_limit <= 0:
103
+ return NativeCanonicalResult(False, "output_limit", None, (), {"preparation_seconds": preparation})
104
+ remaining = max(0.0, seconds - (perf_counter() - started)) if seconds >= 0 else -1.0
105
+ context = cancel_token.borrow(library) if cancel_token is not None else nullcontext(None)
106
+ with context as token:
107
+ request = Request(1, ct.sizeof(Request), n, len(prepared.neighbors), offsets,
108
+ neighbors, colors, remaining, caps[0], caps[1], output_limit, int(max_depth), token)
109
+ handle = ct.c_void_p()
110
+ if library.synkit_canon_search(ct.byref(request), ct.byref(handle)):
111
+ raise ValueError(library.synkit_canon_error().decode("utf-8"))
112
+ try:
113
+ stat = library.synkit_canon_statistics(handle).contents
114
+ metrics = {name: getattr(stat, name) for name, _ in stat._fields_}
115
+ if hasattr(library, "synkit_canon_pruning_statistics"):
116
+ pruning = library.synkit_canon_pruning_statistics(handle).contents
117
+ metrics.update((name, getattr(pruning, name)) for name, _ in pruning._fields_)
118
+ metrics["preparation_seconds"] = preparation
119
+ metrics["packing_seconds"] = max(0.0, perf_counter() - started - preparation - stat.elapsed_seconds)
120
+ if not stat.complete:
121
+ return NativeCanonicalResult(False, REASONS[stat.reason], None, (), metrics)
122
+ size = ct.c_int64()
123
+ data = library.synkit_canon_bytes(handle, ct.byref(size))
124
+ code = prefix + ct.string_at(data, size.value)
125
+ order = library.synkit_canon_order(handle, ct.byref(size))
126
+ indices = tuple(order[i] for i in range(size.value))
127
+ if len(indices) != n or set(indices) != set(range(n)):
128
+ raise RuntimeError("Native graph core returned an invalid permutation")
129
+ elapsed = perf_counter() - started
130
+ metrics["total_seconds"] = elapsed
131
+ if cancel_token is not None and cancel_token.cancelled:
132
+ return NativeCanonicalResult(False, "cancelled", None, (), metrics)
133
+ if seconds >= 0 and elapsed >= seconds:
134
+ return NativeCanonicalResult(False, "time_limit", None, (), metrics)
135
+ return NativeCanonicalResult(True, None, code, tuple(prepared.nodes[i] for i in indices), metrics)
136
+ finally:
137
+ library.synkit_canon_free(handle)