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,118 @@
1
+ """Exact all-schedule initial stock for a fixed additive event poset.
2
+
3
+ This uses constrained maximum closure, an established minimum-cut reduction.
4
+ Species counts alone do not prove a graph match or a material-copy assignment.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass
10
+ from numbers import Integral
11
+ from typing import Hashable, Mapping
12
+
13
+ import networkx as nx
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class StockWitness:
18
+ """An enabling ideal attaining a positive initial-stock requirement."""
19
+
20
+ completed_events: frozenset[Hashable]
21
+ next_event: Hashable
22
+ demand: int
23
+ prefix_delta: int
24
+
25
+ @property
26
+ def required_stock(self) -> int:
27
+ return self.demand - self.prefix_delta
28
+
29
+
30
+ @dataclass(frozen=True)
31
+ class StockBound:
32
+ """Least nonnegative initial stock sufficient for every linear extension.
33
+
34
+ The witness proves the necessity of a positive bound by one reachable
35
+ enabling ideal. It is not a certificate for physical reaction admission.
36
+ """
37
+
38
+ initial_stock: int
39
+ witness: StockWitness | None = None
40
+
41
+
42
+ def _profile(
43
+ graph: nx.DiGraph, values: Mapping[Hashable, int], name: str
44
+ ) -> dict[Hashable, int]:
45
+ if set(values) != set(graph):
46
+ raise ValueError(f"{name} must provide exactly one count per event.")
47
+ if any(
48
+ isinstance(value, bool) or not isinstance(value, Integral) or value < 0
49
+ for value in values.values()
50
+ ):
51
+ raise ValueError(
52
+ f"{name} counts must be nonnegative integers, excluding booleans."
53
+ )
54
+ return {event: int(values[event]) for event in graph}
55
+
56
+
57
+ def _enabling_ideal(
58
+ graph: nx.DiGraph, weights: dict[Hashable, int], event: Hashable
59
+ ) -> frozenset[Hashable]:
60
+ source, sink = object(), object()
61
+ network = nx.DiGraph()
62
+ network.add_nodes_from((source, sink, *graph))
63
+ bound = 1 + sum(abs(weight) for weight in weights.values())
64
+ for node, weight in weights.items():
65
+ if weight > 0:
66
+ network.add_edge(source, node, capacity=weight)
67
+ elif weight < 0:
68
+ network.add_edge(node, sink, capacity=-weight)
69
+ for first, second in graph.edges:
70
+ network.add_edge(second, first, capacity=bound)
71
+ for node in nx.ancestors(graph, event):
72
+ network.add_edge(source, node, capacity=bound)
73
+ for node in {event} | nx.descendants(graph, event):
74
+ network.add_edge(node, sink, capacity=bound)
75
+ _, (selected, _) = nx.minimum_cut(network, source, sink)
76
+ return frozenset(set(selected) - {source, sink})
77
+
78
+
79
+ def minimum_initial_stock(
80
+ event_order: nx.DiGraph,
81
+ demands: Mapping[Hashable, int],
82
+ products: Mapping[Hashable, int],
83
+ ) -> StockBound:
84
+ """Compute exact robust initial stock for one additive resource.
85
+
86
+ At each event its demand must be available before its products are added.
87
+ The returned stock suffices for every linear extension of the supplied
88
+ poset. It need not be minimal for a particular schedule. No schedules or
89
+ ideals are enumerated; at most one minimum-cut solve is needed per event.
90
+ Conditions, graph matches and environment routing require separate checks.
91
+
92
+ :param event_order: Finite simple directed acyclic event graph.
93
+ :param demands: Nonnegative integer input count for every event.
94
+ :param products: Nonnegative integer output count for every event.
95
+ :return: Least robust stock and an attaining enabling ideal when positive.
96
+ :raises ValueError: If the graph or resource profiles violate the contract.
97
+ """
98
+ if not isinstance(event_order, nx.DiGraph) or event_order.is_multigraph():
99
+ raise ValueError("The event order must be a simple directed graph.")
100
+ graph = event_order.copy()
101
+ if not nx.is_directed_acyclic_graph(graph):
102
+ raise ValueError("The event order must be acyclic; unfold network cycles.")
103
+ inputs = _profile(graph, demands, "Demand")
104
+ outputs = _profile(graph, products, "Product")
105
+ deltas = {event: outputs[event] - inputs[event] for event in graph}
106
+ weights = {event: -deltas[event] for event in graph}
107
+ best = StockBound(0)
108
+ for event in graph:
109
+ ideal = _enabling_ideal(graph, weights, event)
110
+ witness = StockWitness(
111
+ ideal, event, inputs[event], sum(deltas[node] for node in ideal)
112
+ )
113
+ if witness.required_stock > best.initial_stock:
114
+ best = StockBound(witness.required_stock, witness)
115
+ return best
116
+
117
+
118
+ __all__ = ["StockBound", "StockWitness", "minimum_initial_stock"]
@@ -0,0 +1,447 @@
1
+ """Grounded partial-order histories for local edits on fixed atom carriers.
2
+
3
+ This profile derives semantic reads and preservation writes from unguarded,
4
+ atom-preserving source spans. It retains an admitted DPO trace and permits
5
+ shared reads without assigning a whole molecule multiple consumers.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from dataclasses import dataclass
11
+ from itertools import combinations
12
+ from typing import Any, Hashable, Iterable, Mapping
13
+
14
+ import networkx as nx
15
+
16
+ from synkit.Graph.Morphism import (
17
+ LewisLabelledGraph,
18
+ derive_electron_labeled_graph,
19
+ is_electron_schema,
20
+ )
21
+ from synkit.Rule.Apply import DPOApplication, RuleSpan, SystemBoundary, apply_dpo
22
+
23
+ Coordinate = tuple[str, Hashable, str | None]
24
+
25
+
26
+ class LocalHistoryError(ValueError):
27
+ """Raised when an event or cut is outside the grounded coordinate profile."""
28
+
29
+
30
+ @dataclass(frozen=True)
31
+ class GroundedLocalEvent:
32
+ """One rule occurrence with its explicit atom match into the fixed world."""
33
+
34
+ event_id: str
35
+ rule: RuleSpan
36
+ match: tuple[tuple[Hashable, Hashable], ...]
37
+
38
+ def __post_init__(self) -> None:
39
+ pairs = self.match.items() if isinstance(self.match, Mapping) else self.match
40
+ object.__setattr__(self, "match", tuple(sorted(pairs, key=repr)))
41
+ if not self.event_id:
42
+ raise LocalHistoryError("A local event requires a nonempty ID.")
43
+
44
+
45
+ @dataclass(frozen=True)
46
+ class LocalEventRecord:
47
+ """A retained source execution and its semantic coordinate access sets."""
48
+
49
+ event: GroundedLocalEvent
50
+ reads: frozenset[Coordinate]
51
+ writes: frozenset[Coordinate]
52
+ assignments: tuple[tuple[Coordinate, Any], ...]
53
+ application: DPOApplication
54
+
55
+
56
+ @dataclass(frozen=True)
57
+ class CoordinateCut:
58
+ """An ideal's decoded world and last-writer versions, without a schedule."""
59
+
60
+ executed_events: frozenset[str]
61
+ world: LewisLabelledGraph
62
+ versions: tuple[tuple[Coordinate, str | None], ...]
63
+
64
+
65
+ def _present(pair):
66
+ return "presence", pair, None
67
+
68
+
69
+ def _node(node, key):
70
+ return "node", node, key
71
+
72
+
73
+ def _bond(pair, key):
74
+ return "bond", pair, key
75
+
76
+
77
+ def _coordinate_state(world, pairs):
78
+ state = {
79
+ _node(node, key): world.node_labels(node, semantic=True)[key]
80
+ for node in world.node_ids
81
+ for key in world.schema.semantic_node_keys
82
+ }
83
+ for pair in pairs:
84
+ present = pair in world.edge_keys
85
+ state[_present(pair)] = present
86
+ labels = world.edge_labels(pair, semantic=True) if present else {}
87
+ for key in world.schema.semantic_edge_keys:
88
+ # Definedness is tagged independently of the raw value (including None).
89
+ state[_bond(pair, key)] = (True, labels[key]) if present else (False, None)
90
+ return state
91
+
92
+
93
+ def _decode(initial, state, pairs):
94
+ graph = initial.to_networkx()
95
+ graph.remove_edges_from(tuple(graph.edges))
96
+ for node in graph:
97
+ for key in initial.schema.semantic_node_keys:
98
+ graph.nodes[node][key] = state[_node(node, key)]
99
+ for key in initial.schema.node_derived:
100
+ graph.nodes[node].pop(key, None)
101
+ for pair in pairs:
102
+ if state[_present(pair)]:
103
+ labels = {
104
+ key: state[_bond(pair, key)][1]
105
+ for key in initial.schema.semantic_edge_keys
106
+ }
107
+ if any(
108
+ not state[_bond(pair, key)][0]
109
+ for key in initial.schema.semantic_edge_keys
110
+ ):
111
+ raise LocalHistoryError("A present bond has an absent coordinate.")
112
+ graph.add_edge(*pair, **labels)
113
+ elif any(
114
+ state[_bond(pair, key)][0] for key in initial.schema.semantic_edge_keys
115
+ ):
116
+ raise LocalHistoryError("An absent bond retains a coordinate.")
117
+ if is_electron_schema(initial.schema):
118
+ graph = derive_electron_labeled_graph(graph)
119
+ return LewisLabelledGraph.from_networkx(graph, initial.schema)
120
+
121
+
122
+ def _profile(event, initial):
123
+ rule = event.rule
124
+ if rule.left.schema != initial.schema or rule.right.schema != initial.schema:
125
+ raise LocalHistoryError("Every local rule must use the initial world's schema.")
126
+ if rule.condition is not None:
127
+ raise LocalHistoryError("Arbitrary guards have no inferred locality contract.")
128
+ if rule.boundary is SystemBoundary.OPEN:
129
+ raise LocalHistoryError(
130
+ "Open environmental resources require a separate locality contract."
131
+ )
132
+ if rule.left.partial or rule.right.partial or initial.partial:
133
+ raise LocalHistoryError("Local worlds and rule endpoints must be total.")
134
+ if set(rule.left_arm.mapping.values()) != set(rule.left.node_ids) or set(
135
+ rule.right_arm.mapping.values()
136
+ ) != set(rule.right.node_ids):
137
+ raise LocalHistoryError(
138
+ "This coordinate profile requires preservation of every rule atom."
139
+ )
140
+ match = dict(event.match)
141
+ if len(match) != len(event.match) or set(match) != set(rule.left.node_ids):
142
+ raise LocalHistoryError(
143
+ "The declared atom match must cover the left pattern exactly."
144
+ )
145
+ if len(set(match.values())) != len(match) or not set(match.values()) <= set(
146
+ initial.node_ids
147
+ ):
148
+ raise LocalHistoryError(
149
+ "The declared atom match must be injective into the fixed atom universe."
150
+ )
151
+ return match, {
152
+ rule.right_arm.mapping[interface]: match[left]
153
+ for interface, left in rule.left_arm.mapping.items()
154
+ }
155
+
156
+
157
+ def _access(event, match, right_match, all_coordinates):
158
+ rule = event.rule
159
+ schema = rule.left.schema
160
+ reads = {
161
+ _node(match[node], key)
162
+ for node in rule.left.node_ids
163
+ for key in schema.semantic_node_keys
164
+ }
165
+ if any(
166
+ endpoint.node_labels(node).get("aromatic", False)
167
+ for endpoint in (rule.left, rule.right)
168
+ for node in endpoint.node_ids
169
+ ):
170
+ # Phase-aware source matching can inspect more than the local pattern.
171
+ # A whole-world read is sufficient; no extra aromatic concurrency is inferred.
172
+ reads.update(all_coordinates)
173
+ writes = set()
174
+ for interface, left in rule.left_arm.mapping.items():
175
+ retained = rule.interface.node_labels(interface, semantic=True)
176
+ writes.update(
177
+ _node(match[left], key)
178
+ for key in schema.semantic_node_keys
179
+ if key not in retained
180
+ )
181
+ left_edges = {frozenset(match[n] for n in pair) for pair in rule.left.edge_keys}
182
+ right_edges = {
183
+ frozenset(right_match[n] for n in pair) for pair in rule.right.edge_keys
184
+ }
185
+ retained_edges = {
186
+ frozenset(match[rule.left_arm.mapping[n]] for n in pair): pair
187
+ for pair in rule.interface.edge_keys
188
+ }
189
+ for pair in left_edges:
190
+ reads.add(_present(pair))
191
+ reads.update(_bond(pair, key) for key in schema.semantic_edge_keys)
192
+ for pair in right_edges - left_edges:
193
+ # Simple-graph creation requires absence, including every new risk pair.
194
+ reads.add(_present(pair))
195
+ for pair in left_edges | right_edges:
196
+ if pair not in retained_edges:
197
+ writes.add(_present(pair))
198
+ writes.update(_bond(pair, key) for key in schema.semantic_edge_keys)
199
+ else:
200
+ labels = rule.interface.edge_labels(retained_edges[pair], semantic=True)
201
+ writes.update(
202
+ _bond(pair, key)
203
+ for key in schema.semantic_edge_keys
204
+ if key not in labels
205
+ )
206
+ return frozenset(reads), frozenset(writes)
207
+
208
+
209
+ def _conflict(first, second):
210
+ return bool(
211
+ first.writes & (second.reads | second.writes)
212
+ or second.writes & (first.reads | first.writes)
213
+ )
214
+
215
+
216
+ def _declared_precedence(events, precedence):
217
+ positions = {event.event_id: index for index, event in enumerate(events)}
218
+ try:
219
+ precedence = tuple(tuple(pair) for pair in precedence)
220
+ valid = all(
221
+ len(pair) == 2
222
+ and pair[0] in positions
223
+ and pair[1] in positions
224
+ and positions[pair[0]] < positions[pair[1]]
225
+ for pair in precedence
226
+ )
227
+ except TypeError:
228
+ valid = False
229
+ if not valid:
230
+ raise LocalHistoryError(
231
+ "Declared precedence must name known events in the supplied trace order."
232
+ )
233
+ return tuple(sorted(set(precedence), key=repr))
234
+
235
+
236
+ def _construct(initial, events, precedence=()):
237
+ if initial.partial:
238
+ raise LocalHistoryError(
239
+ "The initial world must be total, including for an empty trace."
240
+ )
241
+ if is_electron_schema(initial.schema):
242
+ initial = LewisLabelledGraph.from_networkx(
243
+ derive_electron_labeled_graph(initial.to_networkx()), initial.schema
244
+ )
245
+ if len({event.event_id for event in events}) != len(events):
246
+ raise LocalHistoryError("Local event IDs must be distinct.")
247
+ precedence = _declared_precedence(events, precedence)
248
+ plans = tuple((event, *_profile(event, initial)) for event in events)
249
+ pairs = set(initial.edge_keys)
250
+ for event, match, right_match in plans:
251
+ pairs.update(
252
+ frozenset(match[n] for n in pair) for pair in event.rule.left.edge_keys
253
+ )
254
+ pairs.update(
255
+ frozenset(right_match[n] for n in pair)
256
+ for pair in event.rule.right.edge_keys
257
+ )
258
+ pairs = frozenset(pairs)
259
+ world = initial
260
+ records = []
261
+ all_coordinates = frozenset(_coordinate_state(initial, pairs))
262
+ for event, match, right_match in plans:
263
+ reads, writes = _access(event, match, right_match, all_coordinates)
264
+ _require_raw_match(event, world)
265
+ application = apply_dpo(event.rule, world, match)
266
+ if (
267
+ not application.certificate.replay().valid
268
+ or application.result.node_ids != initial.node_ids
269
+ ):
270
+ raise LocalHistoryError(
271
+ "The retained source execution does not preserve the fixed atoms."
272
+ )
273
+ before = _coordinate_state(world, pairs)
274
+ after = _coordinate_state(application.result, pairs)
275
+ assignments = tuple(sorted(((key, after[key]) for key in writes), key=repr))
276
+ before.update(assignments)
277
+ if before != after:
278
+ raise LocalHistoryError(
279
+ "The inferred writes do not cover the source execution."
280
+ )
281
+ records.append(LocalEventRecord(event, reads, writes, assignments, application))
282
+ world = application.result
283
+ dependencies = tuple(
284
+ (first.event.event_id, second.event.event_id)
285
+ for first, second in combinations(records, 2)
286
+ if _conflict(first, second)
287
+ )
288
+ dependencies += tuple(pair for pair in precedence if pair not in dependencies)
289
+ return LocalCoordinateHistory(
290
+ initial, tuple(records), pairs, dependencies, precedence
291
+ )
292
+
293
+
294
+ def _require_raw_match(event, world):
295
+ match = dict(event.match)
296
+ if any(
297
+ event.rule.left.node_labels(node, semantic=True)
298
+ != world.node_labels(image, semantic=True)
299
+ for node, image in match.items()
300
+ ):
301
+ raise LocalHistoryError(
302
+ "The supplied event requires exact raw atom coordinates, not phase equivalence."
303
+ )
304
+ for edge in event.rule.left.edge_keys:
305
+ image = frozenset(match[node] for node in edge)
306
+ if image not in world.edge_keys or (
307
+ event.rule.left.edge_labels(edge, semantic=True)
308
+ != world.edge_labels(image, semantic=True)
309
+ ):
310
+ raise LocalHistoryError(
311
+ "The supplied event requires exact raw bond coordinates, not phase equivalence."
312
+ )
313
+
314
+
315
+ @dataclass(frozen=True)
316
+ class LocalCoordinateHistory:
317
+ """A certified trace's coordinate-dependence poset on persistent atom IDs.
318
+
319
+ This is a sufficient trace class, not all possible chemistry or a maximal
320
+ independence inference. Coordinates recreated with equal values remain
321
+ writes because the source interface did not preserve them.
322
+ """
323
+
324
+ initial: LewisLabelledGraph
325
+ records: tuple[LocalEventRecord, ...]
326
+ bond_pairs: frozenset[frozenset[Hashable]]
327
+ causal_pairs: tuple[tuple[str, str], ...]
328
+ declared_precedence: tuple[tuple[str, str], ...] = ()
329
+
330
+ @property
331
+ def causal_graph(self) -> nx.DiGraph:
332
+ """Return a fresh graph of directed semantic access dependencies."""
333
+ graph = nx.DiGraph()
334
+ graph.add_nodes_from(record.event.event_id for record in self.records)
335
+ graph.add_edges_from(self.causal_pairs)
336
+ return graph
337
+
338
+ def replay(self) -> bool:
339
+ """Reconstruct the retained trace, accesses, certificates and event order."""
340
+ try:
341
+ fresh = _construct(
342
+ self.initial,
343
+ tuple(record.event for record in self.records),
344
+ self.declared_precedence,
345
+ )
346
+ return fresh == self
347
+ except (ValueError, TypeError, KeyError):
348
+ return False
349
+
350
+ def _configuration_ids(self, completed):
351
+ completed = frozenset(completed)
352
+ graph = self.causal_graph
353
+ if not completed <= set(graph) or any(
354
+ second in completed and first not in completed
355
+ for first, second in graph.edges
356
+ ):
357
+ raise LocalHistoryError(
358
+ "A coordinate cut must name a known downward-closed event ideal."
359
+ )
360
+ return completed
361
+
362
+ def configuration(self, completed: Iterable[str]) -> CoordinateCut:
363
+ """Decode an ideal by last writers without choosing or replaying a schedule.
364
+
365
+ The retained construction is revalidated first. Its cost is separate
366
+ from the coordinate projection, which performs no schedule enumeration.
367
+
368
+ :param completed: IDs of completed events forming an order ideal.
369
+ :return: Anchored world and semantic-coordinate versions at that cut.
370
+ :raises LocalHistoryError: If history replay or ideal validation fails.
371
+ """
372
+ if not self.replay():
373
+ raise LocalHistoryError(
374
+ "The retained coordinate history is not replayable."
375
+ )
376
+ completed = self._configuration_ids(completed)
377
+ state = _coordinate_state(self.initial, self.bond_pairs)
378
+ versions = {key: None for key in state}
379
+ for record in self.records:
380
+ if record.event.event_id in completed:
381
+ state.update(record.assignments)
382
+ versions.update((key, record.event.event_id) for key in record.writes)
383
+ return CoordinateCut(
384
+ completed,
385
+ _decode(self.initial, state, self.bond_pairs),
386
+ tuple(sorted(versions.items(), key=repr)),
387
+ )
388
+
389
+ def execute(self, order: Iterable[str]) -> tuple[DPOApplication, ...]:
390
+ """Certify actual primitive source execution in a supplied full extension.
391
+
392
+ :param order: All event IDs once in a topological order.
393
+ :return: Primitive DPO applications on their actual whole-world frames.
394
+ :raises LocalHistoryError: If replay or the declared extension is invalid.
395
+ """
396
+ if not self.replay():
397
+ raise LocalHistoryError(
398
+ "The retained coordinate history is not replayable."
399
+ )
400
+ order = tuple(order)
401
+ positions = {event: index for index, event in enumerate(order)}
402
+ graph = self.causal_graph
403
+ if (
404
+ len(positions) != len(order)
405
+ or set(order) != set(graph)
406
+ or any(
407
+ positions[first] >= positions[second] for first, second in graph.edges
408
+ )
409
+ ):
410
+ raise LocalHistoryError("Execution requires a complete linear extension.")
411
+ by_id = {record.event.event_id: record.event for record in self.records}
412
+ world = self.initial
413
+ applications = []
414
+ for event_id in order:
415
+ event = by_id[event_id]
416
+ _require_raw_match(event, world)
417
+ application = apply_dpo(event.rule, world, dict(event.match))
418
+ if not application.certificate.replay().valid:
419
+ raise LocalHistoryError(
420
+ "A reordered primitive certificate failed replay."
421
+ )
422
+ applications.append(application)
423
+ world = application.result
424
+ return tuple(applications)
425
+
426
+
427
+ def build_local_coordinate_history(
428
+ initial: LewisLabelledGraph,
429
+ events: Iterable[GroundedLocalEvent],
430
+ *,
431
+ precedence: Iterable[tuple[str, str]] = (),
432
+ ) -> LocalCoordinateHistory:
433
+ """Construct a partial-order history from an admitted grounded source trace.
434
+
435
+ All rule atoms are preserved, endpoints/worlds total, guards absent, and
436
+ coordinates raw. Read-only context may be shared. Nonlocal guards, open
437
+ environment state, aromatic phase equivalence and atom allocation are not
438
+ inferred. Aromatic rules conservatively read the complete raw world. This
439
+ is a trace-specific sufficient independence construction.
440
+
441
+ :param initial: Initial total world with persistent atom identities.
442
+ :param events: One admitted sequence with explicit rule matches and IDs.
443
+ :param precedence: Additional declared ordering constraints respected by that sequence.
444
+ :return: Retained primitive certificates and their coordinate-dependence DAG.
445
+ :raises LocalHistoryError: If the declared profile is unsupported or inconsistent.
446
+ """
447
+ return _construct(initial, tuple(events), tuple(precedence))