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,395 @@
1
+ """
2
+ Automorphism orbits of a labeled graph (thin wrapper over synkit).
3
+
4
+ Two atoms are *symmetry-equivalent* when some automorphism of the molecular graph
5
+ maps one to the other; the set of atoms reachable from a given atom under the
6
+ automorphism group is its *orbit*. Branching the exact search over one
7
+ representative per orbit (orbital branching, :mod:`mapper.exact.branching`) avoids
8
+ exploring assignments that are equivalent by symmetry, and orbits also drive
9
+ symmetry-distinct optimum enumeration (:mod:`mapper.exact.enumerate`).
10
+
11
+ This module converts a :class:`~mapper.graph.labeled_graph.LabeledGraph` into a
12
+ ``networkx`` graph (node attribute ``element`` = atomic number, edge attribute
13
+ ``order`` = bond order) and asks
14
+ :class:`synkit.Graph.Matcher.automorphism.Automorphism` for the orbits over the
15
+ *whole* graph (all connected components). If automorphism analysis fails,
16
+ :func:`node_orbits` falls back to the discrete partition, which simply disables
17
+ symmetry pruning without affecting correctness.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import hashlib
23
+ import time
24
+
25
+ import networkx as nx
26
+ import numpy as np
27
+ from typing import Dict, List, FrozenSet
28
+
29
+ from synkit.Graph.Canon import ExactCanonicalResult, ExactColoredGraphCanonicalizer
30
+ from synkit.Graph.Matcher.automorphism import Automorphism
31
+
32
+ from .synkit_adapter import graph_to_nx
33
+
34
+ _MAX_ORBIT_NODES = 48
35
+
36
+
37
+ def _atomic_numbers(lg):
38
+ nums = lg.props.get("atomic numbers")
39
+ if nums is None:
40
+ nums = list(lg.labels)
41
+ return list(nums)
42
+
43
+
44
+ def _objective_graph_data(lg, binary=False, node_properties=()):
45
+ """Return the exact matrix/element data used by chemical distance."""
46
+ n = len(lg.labels)
47
+ matrix = []
48
+ for source in range(n):
49
+ neighbours = lg.graph.get(source, {})
50
+ row = []
51
+ for target in range(n):
52
+ if source == target or target not in neighbours:
53
+ row.append(0.0)
54
+ else:
55
+ row.append(1.0 if binary else float(neighbours[target]))
56
+ matrix.append(tuple(row))
57
+ colors = []
58
+ atomic_numbers = _atomic_numbers(lg)
59
+ for index, atomic_number in enumerate(atomic_numbers):
60
+ extras = []
61
+ for name in node_properties:
62
+ values = lg.props.get(name)
63
+ if values is None or len(values) != n:
64
+ raise ValueError(
65
+ f"symmetry node property {name!r} requires one value per atom"
66
+ )
67
+ extras.append(values[index])
68
+ colors.append((atomic_number, *extras) if extras else atomic_number)
69
+ return tuple(matrix), tuple(colors)
70
+
71
+
72
+ def _objective_graph_digest(lg, binary=False, node_properties=()) -> str:
73
+ matrix, elements = _objective_graph_data(lg, binary, node_properties)
74
+ payload = repr(
75
+ (
76
+ tuple((type(value).__module__, type(value).__qualname__, repr(value)) for value in elements),
77
+ matrix,
78
+ )
79
+ ).encode("utf-8", "surrogatepass")
80
+ return hashlib.sha256(payload).hexdigest()
81
+
82
+
83
+ def _is_exact_automorphism(permutation, matrix, elements) -> bool:
84
+ """Check a permutation against the exact chemical-distance input."""
85
+ n = len(elements)
86
+ if len(permutation) != n or sorted(permutation) != list(range(n)):
87
+ return False
88
+ if any(elements[index] != elements[permutation[index]] for index in range(n)):
89
+ return False
90
+ array = np.asarray(matrix)
91
+ return bool(np.array_equal(array, array[np.ix_(permutation, permutation)]))
92
+
93
+
94
+ def to_nx(lg, binary=False, node_properties=()):
95
+ """Build a ``networkx.Graph`` from a labeled graph for automorphism analysis.
96
+
97
+ Nodes carry ``element`` (atomic number); edges carry ``order`` (bond order,
98
+ or ``1`` when ``binary``).
99
+ """
100
+ g = graph_to_nx(lg, binary=binary, include_label=False)
101
+ _, elements = _objective_graph_data(lg, binary, node_properties)
102
+ for i in range(len(lg.labels)):
103
+ g.nodes[i]["element"] = elements[i] if i < len(elements) else 0
104
+ return g
105
+
106
+
107
+ def _discrete_orbits(n: int) -> List[FrozenSet[int]]:
108
+ return [frozenset({i}) for i in range(n)]
109
+
110
+
111
+ def node_orbits(lg, binary=False) -> List[FrozenSet[int]]:
112
+ """Automorphism orbits of a labeled graph's atoms.
113
+
114
+ :param lg:
115
+ :type lg: LabeledGraph
116
+ :param binary: Whether bond orders are binarised.
117
+ :type binary: bool, optional
118
+
119
+ :return: The orbits (a partition of the atom indices). Without synkit, the
120
+ discrete partition (one atom per orbit) is returned.
121
+ :rtype: list[frozenset[int]]
122
+ """
123
+ n = len(lg.labels)
124
+ if n > _MAX_ORBIT_NODES:
125
+ return _discrete_orbits(n)
126
+ try:
127
+ g = to_nx(lg, binary=binary)
128
+ auto = Automorphism(
129
+ g,
130
+ node_attr_keys=["element"],
131
+ edge_attr_keys=["order"],
132
+ anchor_largest_component=False,
133
+ )
134
+ orbits = [frozenset(o) for o in auto.orbits]
135
+ except Exception:
136
+ return _discrete_orbits(n)
137
+ seen = set().union(*orbits) if orbits else set()
138
+ # Isolated atoms may be omitted by the backend; add them as singletons.
139
+ for i in range(n):
140
+ if i not in seen:
141
+ orbits.append(frozenset({i}))
142
+ return orbits
143
+
144
+
145
+ def orbit_id_map(orbits) -> Dict[int, int]:
146
+ """Map each atom index to an integer orbit id."""
147
+ out = {}
148
+ for oid, orb in enumerate(orbits):
149
+ for i in orb:
150
+ out[i] = oid
151
+ return out
152
+
153
+
154
+ def n_automorphisms(lg, binary=False) -> int:
155
+ """Size of the automorphism group."""
156
+ try:
157
+ g = to_nx(lg, binary=binary)
158
+ auto = Automorphism(
159
+ g,
160
+ node_attr_keys=["element"],
161
+ edge_attr_keys=["order"],
162
+ anchor_largest_component=False,
163
+ )
164
+ return int(auto.n_automorphisms)
165
+ except Exception:
166
+ return 1
167
+
168
+
169
+ def _verified_twin_permutations(matrix, elements, limit):
170
+ """Recover a bounded subgroup from equal incoming and outgoing rows.
171
+
172
+ Adjacent transpositions within each nonadjacent-twin class generate its
173
+ full symmetric group. Check each witness against the complete objective.
174
+ """
175
+ n = len(elements)
176
+ identity = tuple(range(n))
177
+ classes = {}
178
+ for atom in range(n):
179
+ signature = (matrix[atom], tuple(row[atom] for row in matrix))
180
+ classes.setdefault(signature, []).append(atom)
181
+ permutations = [identity]
182
+ for atoms in classes.values():
183
+ # Colors may be comparable but not hashable.
184
+ color_classes = []
185
+ for atom in atoms:
186
+ for group in color_classes:
187
+ if elements[atom] == elements[group[0]]:
188
+ group.append(atom)
189
+ break
190
+ else:
191
+ color_classes.append([atom])
192
+ for group in color_classes:
193
+ for first, second in zip(group, group[1:]):
194
+ permutation = list(identity)
195
+ permutation[first], permutation[second] = second, first
196
+ permutation = tuple(permutation)
197
+ if _is_exact_automorphism(permutation, matrix, elements):
198
+ permutations.append(permutation)
199
+ if len(permutations) >= limit:
200
+ return tuple(sorted(permutations))
201
+ return tuple(sorted(permutations))
202
+
203
+
204
+ def _component_automorphism_permutations( # noqa: C901
205
+ graph, matrix, elements, limit, timeout_seconds, max_search_nodes
206
+ ):
207
+ """Find component generators and equal-component swaps under shared budgets.
208
+
209
+ Equal canonical codes propose transports; full matrix verification is the
210
+ authority for every lifted witness. Retain compact generators instead of
211
+ expanding their often enormous direct-product group.
212
+ """
213
+ components = sorted(
214
+ (tuple(sorted(c)) for c in nx.connected_components(graph)),
215
+ key=lambda c: (len(c), c),
216
+ )
217
+ if len(components) <= 1:
218
+ return None
219
+ started = time.perf_counter()
220
+ identity = tuple(range(len(elements)))
221
+ permutations = {identity}
222
+ verification_matrix = np.asarray(matrix)
223
+ matches = {}
224
+ remaining_nodes = max_search_nodes
225
+ complete = True
226
+
227
+ def accept(permutation):
228
+ nonlocal complete
229
+ permutation = tuple(permutation)
230
+ if permutation in permutations:
231
+ return
232
+ if len(permutations) >= limit:
233
+ complete = False
234
+ return
235
+ if _is_exact_automorphism(permutation, verification_matrix, elements):
236
+ permutations.add(permutation)
237
+ else:
238
+ complete = False
239
+
240
+ for atoms in components:
241
+ remaining = timeout_seconds - (time.perf_counter() - started)
242
+ if remaining <= 0 or remaining_nodes <= 0 or len(permutations) >= limit:
243
+ complete = False
244
+ break
245
+ try:
246
+ result = ExactColoredGraphCanonicalizer(
247
+ graph.subgraph(atoms).copy(),
248
+ node_color="element",
249
+ edge_color="order",
250
+ prune_automorphisms=True,
251
+ enumerate_automorphism_group=False,
252
+ ).search(timeout_seconds=remaining, max_search_nodes=remaining_nodes)
253
+ except Exception:
254
+ complete = False
255
+ break
256
+ remaining_nodes -= result.statistics.visited_nodes
257
+ for witness in result.automorphisms:
258
+ permutation = list(identity)
259
+ for source, target in witness.as_dict().items():
260
+ permutation[source] = target
261
+ accept(permutation)
262
+ if not isinstance(result, ExactCanonicalResult):
263
+ complete = False
264
+ continue
265
+ previous = matches.get(result.canonical_code)
266
+ if previous is not None:
267
+ permutation = list(identity)
268
+ for first, second in zip(previous, result.canonical_order):
269
+ permutation[first], permutation[second] = second, first
270
+ accept(permutation)
271
+ # Adjacent component swaps generate all permutations of equal components.
272
+ matches[result.canonical_code] = result.canonical_order
273
+ if not complete:
274
+ for permutation in _verified_twin_permutations(matrix, elements, limit):
275
+ accept(permutation)
276
+ return tuple(sorted(permutations)), complete
277
+
278
+
279
+ def bounded_automorphism_permutations( # noqa: C901
280
+ lg,
281
+ binary=False,
282
+ *,
283
+ limit=256,
284
+ timeout_seconds=0.25,
285
+ max_search_nodes=10000,
286
+ node_properties=(),
287
+ ):
288
+ """Return bounded, exactly verified product-graph symmetries.
289
+
290
+ Disconnected graphs use component canonicalization under shared time/node
291
+ budgets, retaining compact internal generators and equal-component swaps.
292
+ Connected graphs use SynKit's bounded exact canonicalizer and a bounded
293
+ expansion of its generators. If a canonical search does not complete,
294
+ verified nonadjacent-twin transpositions recover a safe subgroup; absent
295
+ such witnesses the identity disables pruning. Every returned permutation
296
+ is a concrete automorphism; group completeness is not required for safety.
297
+
298
+ :param lg: Mapper labeled graph.
299
+ :param binary: Whether edge orders are binarized.
300
+ :param limit: Maximum number of returned permutations.
301
+ :param timeout_seconds: Canonical-search wall-time budget.
302
+ :param max_search_nodes: Canonical-search node budget.
303
+ :return: ``(permutations, canonical_search_complete)``.
304
+ """
305
+ if isinstance(limit, bool) or not isinstance(limit, int) or limit < 1:
306
+ raise ValueError("limit must be a positive integer")
307
+ node_properties = tuple(str(name) for name in node_properties)
308
+ n = len(lg.labels)
309
+ identity = tuple(range(n))
310
+ if n <= 1 or limit == 1:
311
+ return (identity,), n <= 1
312
+
313
+ cache_key = (
314
+ _objective_graph_digest(lg, binary, node_properties),
315
+ bool(binary),
316
+ node_properties,
317
+ int(limit),
318
+ float(timeout_seconds),
319
+ int(max_search_nodes),
320
+ )
321
+ cache = lg.props.setdefault("_bounded_automorphism_permutations", {})
322
+ if cache_key in cache:
323
+ return cache[cache_key]
324
+
325
+ graph = to_nx(lg, binary=binary, node_properties=node_properties)
326
+ matrix, elements = _objective_graph_data(lg, binary, node_properties)
327
+
328
+ def fallback():
329
+ outcome = (_verified_twin_permutations(matrix, elements, limit), False)
330
+ cache[cache_key] = outcome
331
+ return outcome
332
+
333
+ component_outcome = _component_automorphism_permutations(
334
+ graph, matrix, elements, limit, timeout_seconds, max_search_nodes
335
+ )
336
+ if component_outcome is not None:
337
+ cache[cache_key] = component_outcome
338
+ return component_outcome
339
+
340
+ try:
341
+ canonicalizer = ExactColoredGraphCanonicalizer(
342
+ graph,
343
+ node_color="element",
344
+ edge_color="order",
345
+ prune_automorphisms=True,
346
+ enumerate_automorphism_group=False,
347
+ )
348
+ result = canonicalizer.search(
349
+ timeout_seconds=timeout_seconds,
350
+ max_search_nodes=max_search_nodes,
351
+ )
352
+ except Exception:
353
+ return fallback()
354
+ if not isinstance(result, ExactCanonicalResult):
355
+ partial = set(_verified_twin_permutations(matrix, elements, limit))
356
+ for witness in result.automorphisms:
357
+ permutation = tuple(witness.as_dict()[index] for index in range(n))
358
+ if len(partial) >= limit:
359
+ break
360
+ if _is_exact_automorphism(permutation, matrix, elements):
361
+ partial.add(permutation)
362
+ outcome = (tuple(sorted(partial)), False)
363
+ cache[cache_key] = outcome
364
+ return outcome
365
+
366
+ generators = {
367
+ tuple(witness.as_dict()[index] for index in range(n))
368
+ for witness in result.automorphisms
369
+ }
370
+ generators.add(identity)
371
+ generators = {
372
+ permutation
373
+ for permutation in generators
374
+ if _is_exact_automorphism(permutation, matrix, elements)
375
+ }
376
+ permutations = set(generators)
377
+ frontier = list(sorted(generators))
378
+ while frontier and len(permutations) < limit:
379
+ right = frontier.pop(0)
380
+ for left in tuple(sorted(permutations)):
381
+ for composed in (
382
+ tuple(left[right[index]] for index in range(n)),
383
+ tuple(right[left[index]] for index in range(n)),
384
+ ):
385
+ if composed in permutations:
386
+ continue
387
+ permutations.add(composed)
388
+ frontier.append(composed)
389
+ if len(permutations) >= limit:
390
+ break
391
+ if len(permutations) >= limit:
392
+ break
393
+ outcome = (tuple(sorted(permutations)[:limit]), True)
394
+ cache[cache_key] = outcome
395
+ return outcome
@@ -0,0 +1,98 @@
1
+ """
2
+ Block-cut-tree decomposition of a labeled graph.
3
+
4
+ A connected graph decomposes into *biconnected components* (blocks) joined at
5
+ *articulation points* (cut vertices). Contracting each block to a node and
6
+ linking it to its cut vertices yields the *block-cut tree*. Removing an
7
+ articulation point disconnects the graph, so any matching/automorphism question
8
+ factorises over this tree: the pieces interact only through the shared cut
9
+ vertices.
10
+
11
+ This module exposes the decomposition (:func:`block_cut_tree`) and a helper to
12
+ locate which block(s) each atom belongs to (:func:`node_block_map`). The exact
13
+ kernel solver uses them to split an uncertainty region that spans several
14
+ independent blocks into per-block sub-problems, turning one ``O(k!)`` search into
15
+ a sum of much smaller ones (see ``solve_kernel_blockwise`` in
16
+ :mod:`mapper.exact.branching`).
17
+
18
+ Built on :func:`networkx.biconnected_components` /
19
+ :func:`networkx.articulation_points`.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ from dataclasses import dataclass
25
+ from typing import Dict, FrozenSet, List, Set
26
+
27
+ try:
28
+ import networkx as nx
29
+
30
+ HAS_NX = True
31
+ except Exception: # pragma: no cover
32
+ HAS_NX = False
33
+
34
+
35
+ def _to_nx(graph, n):
36
+ g = nx.Graph()
37
+ g.add_nodes_from(range(n))
38
+ for i, nbrs in graph.items():
39
+ for j in nbrs:
40
+ if i != j:
41
+ g.add_edge(i, j)
42
+ return g
43
+
44
+
45
+ @dataclass
46
+ class BlockCutTree:
47
+ """Block-cut-tree decomposition.
48
+
49
+ :ivar blocks: Biconnected components (node sets). A bridge edge is a block of size 2.
50
+ :vartype blocks: list[frozenset[int]]
51
+ :ivar articulation_points: Cut vertices shared between blocks.
52
+ :vartype articulation_points: set[int]
53
+ :ivar tree: Bipartite block-cut tree with nodes ``("B", block_index)`` and
54
+ ``("C", cut_vertex)``.
55
+ :vartype tree: networkx.Graph
56
+ """
57
+
58
+ blocks: List[FrozenSet[int]]
59
+ articulation_points: Set[int]
60
+ tree: "nx.Graph"
61
+
62
+
63
+ def block_cut_tree(graph, n):
64
+ """Compute the block-cut-tree decomposition of a labeled-graph adjacency dict.
65
+
66
+ :param graph: Adjacency (edge weights ignored).
67
+ :type graph: dict[int, dict[int, number]]
68
+ :param n: Number of nodes.
69
+ :type n: int
70
+
71
+ :rtype: BlockCutTree
72
+ """
73
+ if not HAS_NX:
74
+ raise ImportError("networkx is required for block-cut-tree decomposition")
75
+ g = _to_nx(graph, n)
76
+ blocks = [frozenset(b) for b in nx.biconnected_components(g)]
77
+ arts = set(nx.articulation_points(g))
78
+
79
+ tree = nx.Graph()
80
+ for bi, block in enumerate(blocks):
81
+ tree.add_node(("B", bi))
82
+ for v in block:
83
+ if v in arts:
84
+ tree.add_node(("C", v))
85
+ tree.add_edge(("B", bi), ("C", v))
86
+ return BlockCutTree(blocks=blocks, articulation_points=arts, tree=tree)
87
+
88
+
89
+ def node_block_map(bct) -> Dict[int, List[int]]:
90
+ """Map each atom index to the list of block indices containing it.
91
+
92
+ Articulation points belong to several blocks; ordinary atoms to exactly one.
93
+ """
94
+ out: Dict[int, List[int]] = {}
95
+ for bi, block in enumerate(bct.blocks):
96
+ for v in block:
97
+ out.setdefault(v, []).append(bi)
98
+ return out
@@ -0,0 +1,104 @@
1
+ from __future__ import annotations
2
+
3
+ from collections import defaultdict
4
+
5
+ from .synkit_adapter import stable_int_token, synkit_wl_node_labels
6
+
7
+
8
+ class LabeledGraph:
9
+ """Indexed graph with labels and metadata."""
10
+
11
+ SYNKIT_WL_NODE_LIMIT = 256
12
+
13
+ def __init__(self, graph, labels):
14
+ self.graph = self._normalise_graph(graph, len(labels))
15
+ self.labels = list(labels)
16
+ self.label2idxs = defaultdict(list)
17
+ self.props = {}
18
+ self.reindex_labels()
19
+
20
+ self._ini_labels = list(self.labels)
21
+ self._ini_wl_labels = None
22
+ self._irred_labels = {}
23
+
24
+ @staticmethod
25
+ def _normalise_graph(graph, n_nodes):
26
+ normalised = {idx: dict(graph.get(idx, {})) for idx in range(n_nodes)}
27
+ for src, nbrs in graph.items():
28
+ normalised.setdefault(src, {}).update(nbrs)
29
+ return normalised
30
+
31
+ def reindex_labels(self):
32
+ """Rebuild label -> indices."""
33
+ label_index = defaultdict(list)
34
+ for idx, label in enumerate(self.labels):
35
+ label_index[label].append(idx)
36
+ self.label2idxs = label_index
37
+
38
+ def build_label2idxs(self):
39
+ """Alias for reindex_labels."""
40
+ self.reindex_labels()
41
+
42
+ def copy(self):
43
+ """Copy graph state."""
44
+ clone = type(self).__new__(type(self))
45
+ clone.graph = {idx: dict(nbrs) for idx, nbrs in self.graph.items()}
46
+ clone.labels = list(self.labels)
47
+ clone.label2idxs = defaultdict(
48
+ list,
49
+ {label: list(idxs) for label, idxs in self.label2idxs.items()},
50
+ )
51
+ clone.props = self.props
52
+ clone._ini_labels = self._ini_labels
53
+ clone._ini_wl_labels = self._ini_wl_labels
54
+ clone._irred_labels = dict(self._irred_labels)
55
+ return clone
56
+
57
+ def set_prop(self, name, prop):
58
+ """Set metadata."""
59
+ self.props[name] = prop
60
+
61
+ def binarize_graph(self):
62
+ """Set all edge weights to 1."""
63
+ for nbrs in self.graph.values():
64
+ for nbr in list(nbrs):
65
+ nbrs[nbr] = 1
66
+
67
+ def neighborhood_signature(self, idx, labels=None, binary=False):
68
+ """WL neighborhood signature."""
69
+ labels = self.labels if labels is None else labels
70
+ grouped = defaultdict(list)
71
+ for nbr, weight in self.graph.get(idx, {}).items():
72
+ grouped[labels[nbr]].append(1 if binary else weight)
73
+ return (
74
+ labels[idx],
75
+ tuple(
76
+ sorted(
77
+ (label, tuple(sorted(weights, reverse=True)))
78
+ for label, weights in grouped.items()
79
+ )
80
+ ),
81
+ )
82
+
83
+ def one_wl_round(self, labels=None, binary=False):
84
+ """One deterministic WL round."""
85
+ labels = self.labels if labels is None else labels
86
+ return [
87
+ stable_int_token(self.neighborhood_signature(idx, labels, binary))
88
+ for idx in range(len(labels))
89
+ ]
90
+
91
+ def get_WL_labels(self):
92
+ """Stabilized WL colors."""
93
+ if len(self.labels) <= self.SYNKIT_WL_NODE_LIMIT:
94
+ synkit_labels = synkit_wl_node_labels(self)
95
+ if synkit_labels is not None:
96
+ return synkit_labels
97
+
98
+ colors = list(self.labels)
99
+ for _ in range(max(1, 2 * len(colors))):
100
+ refined = self.one_wl_round(colors)
101
+ if len(set(refined)) == len(set(colors)):
102
+ return colors
103
+ colors = refined
104
+ return colors