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,299 @@
1
+ """Exact bounded decision diagram for residual assignment cost spectra.
2
+
3
+ The diagram assigns residual source rows in a fixed order. A state retains the
4
+ used product columns and the exact accumulated cost of the assigned prefix for
5
+ every remaining row/image choice. Prefixes with the same future cost table and
6
+ used-column set have identical suffix problems and can be merged safely.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import math
12
+ import time
13
+
14
+ import numpy as np
15
+
16
+ from .propagation_limits import check_deadline
17
+
18
+
19
+ class _StateLimit(Exception):
20
+ pass
21
+
22
+
23
+ class SuffixCostSpectrum:
24
+ """Build and query an exact residual CD decision diagram.
25
+
26
+ Costs are nonnegative integer quarter units. The unary matrix contains all
27
+ costs from rows assigned before this residual; pair costs within the
28
+ residual are added as rows are assigned. ``max_cost`` bounds total residual
29
+ cost and therefore caps the stored bitset. A state-cap or deadline failure
30
+ leaves no partial spectrum available to callers.
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ a,
36
+ b,
37
+ rows,
38
+ columns,
39
+ unary,
40
+ allowed,
41
+ *,
42
+ max_cost,
43
+ max_states=20_000,
44
+ max_seconds=None,
45
+ deadline=None,
46
+ ):
47
+ self.a = np.asarray(a, dtype=np.int64)
48
+ self.b = np.asarray(b, dtype=np.int64)
49
+ self.rows, self.columns = tuple(rows), tuple(columns)
50
+ self.unary = np.asarray(unary, dtype=np.int64)
51
+ self.allowed = np.asarray(allowed, dtype=bool)
52
+ self.max_cost = int(max_cost)
53
+ self.max_states = int(max_states)
54
+ self.max_seconds = max_seconds
55
+ self.deadline = deadline
56
+ self.n = len(self.rows)
57
+ self.states = 0
58
+ self.transitions = 0
59
+ self.orbits_pruned = 0
60
+ self._validated_symmetry_groups = set()
61
+ self.memo = {}
62
+ self._prepared = False
63
+ self._prepare_failed = False
64
+ self._prepare_started = None
65
+ if (
66
+ len(self.columns) != self.n
67
+ or self.unary.shape != (self.n, self.n)
68
+ or self.allowed.shape != self.unary.shape
69
+ ):
70
+ raise ValueError("residual arrays must be square and match row/column sets")
71
+ if self.max_cost < 0:
72
+ raise ValueError("max_cost must be nonnegative")
73
+ if self.max_states < 1:
74
+ raise ValueError("max_states must be positive")
75
+ if self.max_seconds is not None and (
76
+ isinstance(self.max_seconds, bool)
77
+ or not isinstance(self.max_seconds, (int, float))
78
+ or not math.isfinite(self.max_seconds)
79
+ or self.max_seconds <= 0
80
+ ):
81
+ raise ValueError("max_seconds must be finite and positive")
82
+ if np.any(self.unary < 0):
83
+ raise ValueError("suffix spectra require nonnegative unary costs")
84
+ if self.a.ndim != 2 or self.b.ndim != 2:
85
+ raise ValueError("endpoint cost matrices must be two-dimensional")
86
+ if any(i < 0 or i >= len(self.a) for i in self.rows):
87
+ raise ValueError("residual rows are outside the source matrix")
88
+ if any(j < 0 or j >= len(self.b) for j in self.columns):
89
+ raise ValueError("residual columns are outside the product matrix")
90
+
91
+ def _key(self, depth, used, future_cost):
92
+ available = tuple(j for j in range(self.n) if not used & (1 << j))
93
+ future = tuple(
94
+ int(future_cost[row, col])
95
+ for row in range(self.n - depth)
96
+ for col in available
97
+ )
98
+ return depth, used, future
99
+
100
+ def _tick(self):
101
+ self._check()
102
+ self.states += 1
103
+ if self.states > self.max_states:
104
+ raise _StateLimit
105
+
106
+ def _check(self):
107
+ check_deadline(self.deadline)
108
+ if (
109
+ self._prepare_started is not None
110
+ and self.max_seconds is not None
111
+ and time.perf_counter() - self._prepare_started > self.max_seconds
112
+ ):
113
+ raise _StateLimit
114
+
115
+ def _state(self, depth, used, future_cost):
116
+ key = self._key(depth, used, future_cost)
117
+ cached = self.memo.get(key)
118
+ if cached is not None:
119
+ return key, cached[0]
120
+ self._tick()
121
+ if depth == self.n:
122
+ self.memo[key] = (1, ())
123
+ return key, 1
124
+
125
+ support = 0
126
+ branches = []
127
+ remaining_columns = tuple(col for col in range(self.n) if not used & (1 << col))
128
+ row = self.rows[depth]
129
+ for col_pos in remaining_columns:
130
+ self._check()
131
+ if not self.allowed[depth, col_pos]:
132
+ continue
133
+ edge_cost = int(future_cost[0, col_pos])
134
+ if edge_cost > self.max_cost:
135
+ continue
136
+ child_costs = future_cost[1:, :].copy()
137
+ if depth + 1 < self.n:
138
+ image = self.columns[col_pos]
139
+ remaining_positions = tuple(
140
+ pos for pos in remaining_columns if pos != col_pos
141
+ )
142
+ for next_depth in range(depth + 1, self.n):
143
+ next_row = self.rows[next_depth]
144
+ for next_col in remaining_positions:
145
+ child_costs[next_depth - depth - 1, next_col] += abs(
146
+ int(self.a[row, next_row])
147
+ - int(self.b[image, self.columns[next_col]])
148
+ )
149
+ if remaining_positions:
150
+ used_columns = set(range(self.n)) - set(remaining_positions)
151
+ if used_columns:
152
+ child_costs[:, tuple(sorted(used_columns))] = 0
153
+ child_key, child_support = self._state(
154
+ depth + 1, used | (1 << col_pos), child_costs
155
+ )
156
+ if child_support:
157
+ branches.append((col_pos, edge_cost, child_key))
158
+ support |= child_support << edge_cost
159
+ self.transitions += 1
160
+ support &= (1 << (self.max_cost + 1)) - 1
161
+ self.memo[key] = (support, tuple(branches))
162
+ return key, support
163
+
164
+ def prepare(self):
165
+ """Build the bounded exact support, or discard it on a state-cap miss."""
166
+ if self._prepared:
167
+ return not self._prepare_failed
168
+ self._prepared = True
169
+ self._prepare_started = time.perf_counter()
170
+ try:
171
+ self.root_key, self.support = self._state(
172
+ 0,
173
+ 0,
174
+ self.unary.copy(),
175
+ )
176
+ return True
177
+ except _StateLimit:
178
+ self._prepare_failed = True
179
+ self.memo.clear()
180
+ self.support = 0
181
+ return False
182
+
183
+ @staticmethod
184
+ def _has_cost(support, cost):
185
+ return cost >= 0 and bool(support & (1 << cost))
186
+
187
+ def reachable_costs(self, lower=0, upper=None):
188
+ """Return exact reachable costs in the requested inclusive interval."""
189
+ if not self._prepared and not self.prepare():
190
+ return frozenset()
191
+ if self._prepare_failed:
192
+ return frozenset()
193
+ upper = self.max_cost if upper is None else min(int(upper), self.max_cost)
194
+ lower = max(0, int(lower))
195
+ if upper < lower:
196
+ return frozenset()
197
+ return frozenset(
198
+ cost
199
+ for cost in range(lower, upper + 1)
200
+ if self._has_cost(self.support, cost)
201
+ )
202
+
203
+ def _walk(self, key, target, mapping, symmetry_group):
204
+ check_deadline(self.deadline)
205
+ support, branches = self.memo[key]
206
+ if not self._has_cost(support, target):
207
+ return
208
+ depth = key[0]
209
+ if depth == self.n:
210
+ if target == 0:
211
+ yield tuple(mapping)
212
+ return
213
+ for col_pos, edge_cost, child_key in branches:
214
+ remainder = target - edge_cost
215
+ if remainder < 0:
216
+ continue
217
+ child_support = self.memo[child_key][0]
218
+ if not self._has_cost(child_support, remainder):
219
+ continue
220
+ image = self.columns[col_pos]
221
+ if len(symmetry_group) > 1:
222
+ orbit = {permutation[image] for permutation in symmetry_group}
223
+ if image != min(orbit):
224
+ self.orbits_pruned += 1
225
+ continue
226
+ child_group = tuple(
227
+ permutation
228
+ for permutation in symmetry_group
229
+ if permutation[image] == image
230
+ )
231
+ else:
232
+ child_group = symmetry_group
233
+ mapping[depth] = image
234
+ yield from self._walk(child_key, remainder, mapping, child_group)
235
+ mapping[depth] = -1
236
+
237
+ def _validate_symmetry_group(self, symmetry_group):
238
+ """Check that a supplied product group preserves this residual problem."""
239
+ group = tuple(tuple(permutation) for permutation in symmetry_group)
240
+ if not group:
241
+ return group
242
+ cache_key = frozenset(group)
243
+ if cache_key in self._validated_symmetry_groups:
244
+ return group
245
+ identity = tuple(range(len(self.b)))
246
+ if identity not in group:
247
+ raise ValueError("symmetry_group must contain the identity")
248
+ if len(group) == 1:
249
+ self._validated_symmetry_groups.add(cache_key)
250
+ return group
251
+ positions = {column: index for index, column in enumerate(self.columns)}
252
+ for permutation in group:
253
+ if (
254
+ len(permutation) != len(self.b)
255
+ or set(permutation) != set(range(len(self.b)))
256
+ ):
257
+ raise ValueError("symmetry_group entries must be permutations")
258
+ if any(permutation[column] not in positions for column in self.columns):
259
+ raise ValueError("symmetry_group must preserve residual columns")
260
+ image_positions = np.asarray(
261
+ [positions[permutation[column]] for column in self.columns],
262
+ dtype=int,
263
+ )
264
+ if not np.array_equal(
265
+ self.allowed, self.allowed[:, image_positions]
266
+ ) or not np.array_equal(self.unary, self.unary[:, image_positions]):
267
+ raise ValueError(
268
+ "symmetry_group must preserve residual domains and costs"
269
+ )
270
+ if not np.array_equal(
271
+ self.b[np.ix_(permutation, permutation)], self.b
272
+ ):
273
+ raise ValueError("symmetry_group must preserve product bonds")
274
+ self._validated_symmetry_groups.add(cache_key)
275
+ return group
276
+
277
+ def mappings_at(self, target, *, symmetry_group=()):
278
+ """Yield residual mappings at one cost, optionally one per orbit.
279
+
280
+ ``symmetry_group`` must be a product-index permutation group that
281
+ preserves this residual instance's allowed entries, unary costs, and
282
+ pair costs. The yielded mapping is the lexicographically least member
283
+ of its orbit in the fixed ``rows`` order.
284
+ """
285
+ if not self._prepared and not self.prepare():
286
+ return
287
+ if self._prepare_failed or not self._has_cost(self.support, int(target)):
288
+ return
289
+ group = self._validate_symmetry_group(symmetry_group)
290
+ yield from self._walk(self.root_key, int(target), [-1] * self.n, group)
291
+
292
+ def mappings_between(self, lower, upper, *, symmetry_group=()):
293
+ """Yield ``(mapping, cost)`` pairs for an inclusive cost interval."""
294
+ for cost in sorted(self.reachable_costs(lower, upper)):
295
+ for mapping in self.mappings_at(cost, symmetry_group=symmetry_group):
296
+ yield mapping, cost
297
+
298
+
299
+ __all__ = ["SuffixCostSpectrum"]
@@ -0,0 +1,55 @@
1
+ """Dispatch full-space exact mapping to Python propagation or C++ shell search.
2
+
3
+ PABS stands for Propagation and Assignment-Bounded Search. It is this package's
4
+ descriptive interface name. The Python implementation combines one-to-one
5
+ domain propagation and LAP cost bounds; the C++ implementation has a separate
6
+ integer-shell traversal. These routes do not use the reduced SLAP uncertainty
7
+ kernel or its MILP solver.
8
+ """
9
+
10
+ from dataclasses import replace
11
+
12
+ from .pabs.propagation import PropagationConfig, enumerate_synister_cp_mappings
13
+ from .pabs.multi_shell import enumerate_pabs_shells
14
+
15
+
16
+ def enumerate_pabs_mappings(lgp, *, backend="python", library_path=None, **options):
17
+ """Enumerate a minimum or selected-distance shell with an exact backend.
18
+
19
+ PABS means Propagation and Assignment-Bounded Search. ``backend='python'``
20
+ is the default and selects full-space propagation with linear-assignment
21
+ bounds. It does not run the SLAP mapper or extract its uncertainty kernel.
22
+ Explicit fixed assignments restrict the search if supplied by the caller.
23
+ Unsupported Python inputs use a recorded full-distance-search fallback.
24
+
25
+ ``cpp`` selects the optional
26
+ compiled integer shell search and requires an explicitly built library.
27
+ Both return DistanceEnumerationResult. Backend-specific unsupported options
28
+ raise errors; selecting C++ never silently executes Python search.
29
+ The C++ traversal is distinct from the Python propagation implementation.
30
+ """
31
+ if backend not in ("python", "cpp"):
32
+ raise ValueError("backend must be 'python' or 'cpp'")
33
+ if backend == "cpp":
34
+ if library_path is None:
35
+ raise ValueError(
36
+ "backend='cpp' requires library_path; build with native_build"
37
+ )
38
+ from .native.search import enumerate_cpp_mappings
39
+
40
+ return enumerate_cpp_mappings(lgp, library_path=library_path, **options)
41
+ if library_path is not None:
42
+ raise ValueError("library_path is only used by backend='cpp'")
43
+ result = enumerate_synister_cp_mappings(lgp, **options)
44
+ statistics = dict(result.backend_statistics or {})
45
+ statistics.update(
46
+ method="PABS", requested_backend="python", implementation=result.backend
47
+ )
48
+ return replace(result, backend_statistics=statistics)
49
+
50
+
51
+ __all__ = [
52
+ "PropagationConfig",
53
+ "enumerate_pabs_mappings",
54
+ "enumerate_pabs_shells",
55
+ ]
@@ -0,0 +1 @@
1
+ """Reference-free heuristics for feasible search incumbents."""
@@ -0,0 +1,104 @@
1
+ """Bounded, reference-free improvement of feasible search incumbents."""
2
+
3
+ import numpy as np
4
+
5
+
6
+ def _swap_deltas(reactant, mapped_product, left, right):
7
+ """Exact objective differences for simultaneous evaluation of pair swaps."""
8
+ a, b = reactant, mapped_product
9
+ rows = (
10
+ np.abs(a[left] - b[right])
11
+ - np.abs(a[left] - b[left])
12
+ + np.abs(a[right] - b[left])
13
+ - np.abs(a[right] - b[right])
14
+ )
15
+ columns = (
16
+ np.abs(a[:, left].T - b[:, right].T)
17
+ - np.abs(a[:, left].T - b[:, left].T)
18
+ + np.abs(a[:, right].T - b[:, left].T)
19
+ - np.abs(a[:, right].T - b[:, right].T)
20
+ )
21
+ delta = rows + columns
22
+ index = np.arange(len(left))
23
+ delta[index, left] = 0
24
+ delta[index, right] = 0
25
+ internal = (
26
+ np.abs(a[left, left] - b[right, right])
27
+ - np.abs(a[left, left] - b[left, left])
28
+ + np.abs(a[right, right] - b[left, left])
29
+ - np.abs(a[right, right] - b[right, right])
30
+ + np.abs(a[left, right] - b[right, left])
31
+ - np.abs(a[left, right] - b[left, right])
32
+ + np.abs(a[right, left] - b[left, right])
33
+ - np.abs(a[right, left] - b[right, left])
34
+ )
35
+ return 0.5 * (delta.sum(axis=1) + internal)
36
+
37
+
38
+ def improve_seed_mapping(
39
+ reactant,
40
+ product,
41
+ elements,
42
+ product_elements,
43
+ mapping,
44
+ *,
45
+ max_steps=64,
46
+ max_pool_atoms=256,
47
+ ):
48
+ """Improve a typed bijection with bounded best-improvement pair swaps.
49
+
50
+ This supplies an incumbent only: no optimum proof or domain restriction.
51
+ Pool/step limits bound work and batches have at most 256 pairs. Every
52
+ accepted swap must improve the freshly recomputed complete objective.
53
+ """
54
+ current = np.asarray(mapping, dtype=int).copy()
55
+ n = len(elements)
56
+ if sorted(current.tolist()) != list(range(n)) or any(
57
+ elements[atom] != product_elements[image] for atom, image in enumerate(current)
58
+ ):
59
+ raise ValueError("seed must be a complete element-compatible bijection")
60
+ mapped = product[np.ix_(current, current)]
61
+ cost = 0.5 * float(np.abs(reactant - mapped).sum())
62
+ pool = np.arange(n)
63
+ if n > max_pool_atoms:
64
+ mismatch = np.abs(reactant - mapped)
65
+ scores = mismatch.sum(axis=0) + mismatch.sum(axis=1)
66
+ pool = np.asarray(
67
+ sorted(pool, key=lambda atom: (-scores[atom], atom))[:max_pool_atoms]
68
+ )
69
+ pool.sort()
70
+ left, right = np.triu_indices(len(pool), 1)
71
+ left, right = pool[left], pool[right]
72
+ labels = np.asarray(elements)
73
+ compatible = labels[left] == labels[right]
74
+ left, right = left[compatible], right[compatible]
75
+ accepted = 0
76
+ evaluated = 0
77
+ for _ in range(max_steps):
78
+ best_delta, best_index = -1e-9, None
79
+ for start in range(0, len(left), 256):
80
+ deltas = _swap_deltas(
81
+ reactant, mapped, left[start : start + 256], right[start : start + 256]
82
+ )
83
+ evaluated += len(deltas)
84
+ index = int(np.argmin(deltas))
85
+ if deltas[index] < best_delta:
86
+ best_delta, best_index = float(deltas[index]), start + index
87
+ if best_index is None:
88
+ break
89
+ i, j = left[best_index], right[best_index]
90
+ current[i], current[j] = current[j], current[i]
91
+ candidate_product = product[np.ix_(current, current)]
92
+ candidate_cost = 0.5 * float(np.abs(reactant - candidate_product).sum())
93
+ if candidate_cost >= cost - 1e-9:
94
+ current[i], current[j] = current[j], current[i]
95
+ break
96
+ mapped, cost = candidate_product, candidate_cost
97
+ accepted += 1
98
+ return current.tolist(), {
99
+ "accepted_swaps": accepted,
100
+ "evaluated_swaps": evaluated,
101
+ "pool_atoms": len(pool),
102
+ "max_steps": max_steps,
103
+ "max_pool_atoms": max_pool_atoms,
104
+ }
@@ -0,0 +1,148 @@
1
+ """Bounded common-fragment anchors used only for feasible seed construction."""
2
+
3
+ import time
4
+
5
+ import numpy as np
6
+ from rdkit import Chem
7
+ from rdkit.Chem import rdFMCS
8
+
9
+ from .seed import improve_seed_mapping
10
+ from .seed_relaxation import improve_relaxed_seed_mapping
11
+
12
+ _MAX_FRAGMENT_SEARCH_SECONDS = 0.025
13
+
14
+
15
+ class _FragmentProgress(rdFMCS.MCSProgress):
16
+ def __init__(self, deadline):
17
+ super().__init__()
18
+ self.deadline = deadline
19
+ self.search_deadline = None
20
+
21
+ def __call__(self, progress, parameters):
22
+ now = time.process_time()
23
+ if self.search_deadline is None:
24
+ # MCS setup may exceed the tiny slice before any search progress.
25
+ # Keep setup inside the overall cover budget, but start the
26
+ # per-fragment search allowance at its first progress callback.
27
+ self.search_deadline = min(
28
+ self.deadline, now + _MAX_FRAGMENT_SEARCH_SECONDS
29
+ )
30
+ return now < self.search_deadline
31
+
32
+
33
+ def _molecule(matrix, elements):
34
+ molecule = Chem.RWMol()
35
+ for element in elements:
36
+ molecule.AddAtom(Chem.Atom(int(element)))
37
+ orders = {
38
+ 1: Chem.BondType.SINGLE,
39
+ 1.5: Chem.BondType.AROMATIC,
40
+ 2: Chem.BondType.DOUBLE,
41
+ 3: Chem.BondType.TRIPLE,
42
+ }
43
+ for i, j in zip(*np.triu_indices(len(elements), 1)):
44
+ if matrix[i, j]:
45
+ molecule.AddBond(int(i), int(j), orders[matrix[i, j]])
46
+ result = molecule.GetMol()
47
+ result.UpdatePropertyCache(strict=False)
48
+ Chem.GetSymmSSSR(result)
49
+ return result
50
+
51
+
52
+ def improve_fragment_seed( # noqa: C901
53
+ a, b, er, ep, mapping, *, max_fragments=16, budget_seconds=0.5
54
+ ):
55
+ """Anchor a greedy common-fragment cover, then polish a feasible bijection.
56
+
57
+ Anchors constrain only this optional heuristic. They are never passed to
58
+ exact search. The fragment finder has a shared cooperative process-CPU budget,
59
+ so scheduler descheduling does not consume its tiny search slices. The
60
+ enclosing analysis still enforces its independent wall-clock deadline, and
61
+ unsupported matrix semantics simply retain the existing seed.
62
+ """
63
+ if len(mapping) > 256 or not np.array_equal(a, a.T) or not np.array_equal(b, b.T):
64
+ return list(mapping), {"skipped": "size_or_directed_matrix"}
65
+ values = set(np.unique(a)) | set(np.unique(b))
66
+ if not values <= {0, 1, 1.5, 2, 3}:
67
+ return list(mapping), {"skipped": "unsupported_bond_orders"}
68
+ if sorted(mapping) != list(range(len(er))) or any(
69
+ er[i] != ep[p] for i, p in enumerate(mapping)
70
+ ):
71
+ raise ValueError("seed must be a complete element-compatible bijection")
72
+ fixed = {}
73
+ working = list(mapping)
74
+ orientation_evaluations = 0
75
+ sizes = []
76
+ canceled = False
77
+ deadline = time.process_time() + budget_seconds
78
+ for _ in range(max_fragments):
79
+ if time.process_time() >= deadline:
80
+ break
81
+ rows = [i for i in range(len(er)) if i not in fixed]
82
+ used = set(fixed.values())
83
+ columns = [i for i in range(len(ep)) if i not in used]
84
+ if len(rows) < 3:
85
+ break
86
+ reactant = _molecule(a[np.ix_(rows, rows)], [er[i] for i in rows])
87
+ product = _molecule(b[np.ix_(columns, columns)], [ep[i] for i in columns])
88
+ parameters = rdFMCS.MCSParameters()
89
+ parameters.Timeout = 1
90
+ parameters.BondCompareParameters.RingMatchesRingOnly = True
91
+ parameters.AtomCompareParameters.RingMatchesRingOnly = True
92
+ callback = _FragmentProgress(deadline)
93
+ parameters.ProgressCallback = callback
94
+ result = rdFMCS.FindMCS([reactant, product], parameters)
95
+ canceled |= result.canceled
96
+ if result.numAtoms < 3:
97
+ break
98
+ query = Chem.MolFromSmarts(result.smartsString)
99
+ left_matches = reactant.GetSubstructMatches(query, uniquify=False, maxMatches=8)
100
+ right_matches = product.GetSubstructMatches(
101
+ query, uniquify=False, maxMatches=32
102
+ )
103
+ best = None
104
+ for left in left_matches:
105
+ for right in right_matches:
106
+ if len(left) != len(right) or len(left) < 3:
107
+ continue
108
+ anchors = {rows[i]: columns[j] for i, j in zip(left, right)}
109
+ if any(er[i] != ep[j] for i, j in anchors.items()):
110
+ continue
111
+ trial = working.copy()
112
+ for atom, image in anchors.items():
113
+ owner = trial.index(image)
114
+ trial[atom], trial[owner] = trial[owner], trial[atom]
115
+ trial_cost = 0.5 * float(np.abs(a - b[np.ix_(trial, trial)]).sum())
116
+ orientation_evaluations += 1
117
+ if best is None or trial_cost < best[0]:
118
+ best = trial_cost, trial, anchors
119
+ if time.process_time() >= deadline:
120
+ break
121
+ if time.process_time() >= deadline:
122
+ break
123
+ if best is None:
124
+ break
125
+ _, working, anchors = best
126
+ fixed.update(anchors)
127
+ sizes.append(len(anchors))
128
+ candidate = working
129
+ if fixed:
130
+ candidate, _ = improve_relaxed_seed_mapping(
131
+ a, b, er, ep, candidate, fixed_mapping=fixed
132
+ )
133
+ candidate, _ = improve_seed_mapping(a, b, er, ep, candidate)
134
+ old_cost = 0.5 * float(np.abs(a - b[np.ix_(mapping, mapping)]).sum())
135
+ new_cost = 0.5 * float(np.abs(a - b[np.ix_(candidate, candidate)]).sum())
136
+ if new_cost >= old_cost:
137
+ candidate, new_cost = list(mapping), old_cost
138
+ return candidate, {
139
+ "fragment_sizes": sizes,
140
+ "orientation_evaluations": orientation_evaluations,
141
+ "anchored_atoms": len(fixed),
142
+ "canceled": canceled,
143
+ "cost": new_cost,
144
+ "budget_seconds": budget_seconds,
145
+ "budget_clock": "process_cpu",
146
+ "fragment_search_seconds": _MAX_FRAGMENT_SEARCH_SECONDS,
147
+ "fragment_slice_scope": "from_first_progress_callback",
148
+ }