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,967 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from time import perf_counter
5
+ from typing import Any, Dict, List, Optional, Set, Tuple
6
+
7
+ import networkx as nx
8
+
9
+ from ._common import (
10
+ SymmetryConfig,
11
+ approx_automorphism_count_from_cells,
12
+ build_fast_signature,
13
+ edge_token,
14
+ graph_key_from_order,
15
+ hash_text,
16
+ node_token,
17
+ prepare_graph,
18
+ )
19
+
20
+
21
+ @dataclass(frozen=True)
22
+ class _WLState:
23
+ """
24
+ Internal cached WL state.
25
+
26
+ :param colors:
27
+ Final node colors after WL refinement.
28
+ :type colors: Dict[Any, str]
29
+
30
+ :param cells:
31
+ Final WL color cells as sorted node lists.
32
+ :type cells: List[List[Any]]
33
+
34
+ :param orbits:
35
+ Approximate node orbits induced by final WL colors.
36
+ :type orbits: List[Set[Any]]
37
+
38
+ :param color_hist:
39
+ Histogram of final colors.
40
+ :type color_hist: Dict[str, int]
41
+
42
+ :param iters_run:
43
+ Number of WL iterations actually performed.
44
+ :type iters_run: int
45
+
46
+ :param stabilized:
47
+ Whether refinement stabilized before the iteration limit.
48
+ :type stabilized: bool
49
+
50
+ :param canonical_order:
51
+ Deterministic node order induced by final WL colors.
52
+ :type canonical_order: List[Any]
53
+
54
+ :param approx_automorphism_count:
55
+ Approximate automorphism count derived from WL cells.
56
+ :type approx_automorphism_count: Optional[int]
57
+ """
58
+
59
+ colors: Dict[Any, str]
60
+ cells: List[List[Any]]
61
+ orbits: List[Set[Any]]
62
+ color_hist: Dict[str, int]
63
+ iters_run: int
64
+ stabilized: bool
65
+ canonical_order: List[Any]
66
+ approx_automorphism_count: Optional[int]
67
+
68
+
69
+ @dataclass(frozen=True)
70
+ class WLCanonicalResult:
71
+ """
72
+ Approximate canonicalization result from WL refinement.
73
+
74
+ This mirrors the exact canonicalizer style, but remains approximate.
75
+
76
+ :param canon_graph:
77
+ Graph canonically relabeled according to the WL order.
78
+ :type canon_graph: nx.DiGraph
79
+
80
+ :param graph_type:
81
+ Graph representation type, e.g. ``"bipartite"`` or ``"species"``.
82
+ :type graph_type: str
83
+
84
+ :param canonical_order:
85
+ Deterministic node order induced by the final WL partition.
86
+ :type canonical_order: List[Any]
87
+
88
+ :param canonical_key:
89
+ Canonical graph key derived from the WL order.
90
+ :type canonical_key: Any
91
+
92
+ :param automorphism_count:
93
+ Approximate automorphism count from WL cells.
94
+ :type automorphism_count: Optional[int]
95
+
96
+ :param orbits:
97
+ Approximate node orbits from the final WL cells.
98
+ :type orbits: List[Set[Any]]
99
+
100
+ :param colors:
101
+ Final WL color mapping.
102
+ :type colors: Dict[Any, str]
103
+
104
+ :param color_hist:
105
+ Histogram of final WL colors.
106
+ :type color_hist: Dict[str, int]
107
+
108
+ :param iters_run:
109
+ Number of WL iterations actually performed.
110
+ :type iters_run: int
111
+
112
+ :param stabilized:
113
+ Whether WL refinement stabilized before the maximum iteration count.
114
+ :type stabilized: bool
115
+
116
+ :param exact:
117
+ Always ``False`` for WL refinement.
118
+ :type exact: bool
119
+
120
+ :param elapsed_seconds:
121
+ Runtime in seconds for building the result object.
122
+ :type elapsed_seconds: float
123
+ """
124
+
125
+ canon_graph: nx.DiGraph
126
+ graph_type: str
127
+ canonical_order: List[Any]
128
+ canonical_key: Any
129
+ automorphism_count: Optional[int]
130
+ orbits: List[Set[Any]]
131
+ colors: Dict[Any, str]
132
+ color_hist: Dict[str, int]
133
+ iters_run: int
134
+ stabilized: bool
135
+ exact: bool
136
+ elapsed_seconds: float
137
+
138
+
139
+ class WLCanonicalizer:
140
+ """Fast approximate canonicalizer for SynKit CRN graphs using direction-aware
141
+ 1-WL refinement.
142
+
143
+ This class is designed as a lightweight companion to the exact CRN
144
+ canonicalizer. It gives:
145
+
146
+ - deterministic WL-based canonical relabeling
147
+ - approximate orbit partitions
148
+ - approximate automorphism counts from WL cells
149
+ - fast signatures for cheap prefiltering
150
+
151
+ Compared with the exact canonicalizer, this class is much faster but not
152
+ guaranteed to distinguish all non-isomorphic graphs or recover exact
153
+ automorphism groups.
154
+
155
+ :param source:
156
+ Input CRN representation. This may be a prepared
157
+ :class:`networkx.DiGraph`, an object exposing ``to_digraph()``, or any
158
+ object accepted by :func:`prepare_graph`.
159
+ :type source: Any
160
+
161
+ :param include_rule:
162
+ Whether rule nodes should be included in the prepared graph.
163
+ :type include_rule: bool
164
+
165
+ :param include_stoich:
166
+ Whether stoichiometric edge attributes should be preserved during graph
167
+ preparation.
168
+ :type include_stoich: bool
169
+
170
+ :param n_iter:
171
+ Maximum number of WL refinement iterations.
172
+ :type n_iter: int
173
+
174
+ :param digest_size:
175
+ Digest size used when hashing node and edge signatures.
176
+ :type digest_size: int
177
+
178
+ :param include_in_neighbors:
179
+ Whether incoming neighbors should contribute to refinement.
180
+ :type include_in_neighbors: bool
181
+
182
+ :param include_out_neighbors:
183
+ Whether outgoing neighbors should contribute to refinement.
184
+ :type include_out_neighbors: bool
185
+
186
+ :param estimate_automorphisms:
187
+ Whether to compute an approximate automorphism count from the final WL
188
+ cells.
189
+ :type estimate_automorphisms: bool
190
+
191
+ :param automorphism_cap:
192
+ Cap applied to approximate automorphism counts.
193
+ :type automorphism_cap: int
194
+
195
+ :param config:
196
+ Symmetry semantics configuration controlling which node and edge
197
+ attributes participate in WL coloring.
198
+ :type config: Optional[SymmetryConfig]
199
+
200
+ .. rubric:: Example
201
+
202
+ .. code-block:: python
203
+
204
+ from synkit.CRN.Sym import WLCanonicalizer, SymmetryConfig
205
+
206
+ wl = WLCanonicalizer(
207
+ syn.to_digraph(),
208
+ include_rule=True,
209
+ config=SymmetryConfig.topological(),
210
+ )
211
+
212
+ print(wl.has_nontrivial_automorphism())
213
+ print(wl.orbits())
214
+ print(wl.canonical_order())
215
+ print(wl.summary()["automorphism_count"])
216
+ """
217
+
218
+ def __init__(
219
+ self,
220
+ source: Any,
221
+ *,
222
+ include_rule: bool = True,
223
+ include_stoich: bool = True,
224
+ n_iter: int = 20,
225
+ digest_size: int = 16,
226
+ include_in_neighbors: bool = True,
227
+ include_out_neighbors: bool = True,
228
+ estimate_automorphisms: bool = True,
229
+ automorphism_cap: int = 10**18,
230
+ config: Optional[SymmetryConfig] = None,
231
+ ) -> None:
232
+ """Initialize the WL canonicalizer.
233
+
234
+ :param source:
235
+ Input CRN representation.
236
+ :type source: Any
237
+
238
+ :param include_rule:
239
+ Whether rule nodes should be included in the prepared graph.
240
+ :type include_rule: bool
241
+
242
+ :param include_stoich:
243
+ Whether stoichiometric edge attributes should be preserved.
244
+ :type include_stoich: bool
245
+
246
+ :param n_iter:
247
+ Maximum number of WL refinement rounds.
248
+ :type n_iter: int
249
+
250
+ :param digest_size:
251
+ Digest size used when hashing WL signatures.
252
+ :type digest_size: int
253
+
254
+ :param include_in_neighbors:
255
+ Whether incoming neighborhoods should be used.
256
+ :type include_in_neighbors: bool
257
+
258
+ :param include_out_neighbors:
259
+ Whether outgoing neighborhoods should be used.
260
+ :type include_out_neighbors: bool
261
+
262
+ :param estimate_automorphisms:
263
+ Whether to estimate automorphism count from final WL cells.
264
+ :type estimate_automorphisms: bool
265
+
266
+ :param automorphism_cap:
267
+ Maximum cap for approximate automorphism counting.
268
+ :type automorphism_cap: int
269
+
270
+ :param config:
271
+ Symmetry semantics configuration.
272
+ :type config: Optional[SymmetryConfig]
273
+
274
+ :return:
275
+ None.
276
+ :rtype: None
277
+
278
+ .. rubric:: Example
279
+
280
+ .. code-block:: python
281
+
282
+ wl = WLCanonicalizer(
283
+ syn.to_digraph(),
284
+ include_rule=True,
285
+ n_iter=20,
286
+ digest_size=16,
287
+ )
288
+ """
289
+ self.source = source
290
+ self.include_rule = bool(include_rule)
291
+ self.include_stoich = bool(include_stoich)
292
+ self.n_iter = int(n_iter)
293
+ self.digest_size = int(digest_size)
294
+ self.include_in_neighbors = bool(include_in_neighbors)
295
+ self.include_out_neighbors = bool(include_out_neighbors)
296
+ self.estimate_automorphisms = bool(estimate_automorphisms)
297
+ self.automorphism_cap = int(automorphism_cap)
298
+ self.config = config or SymmetryConfig.semantic()
299
+
300
+ self._G, self._graph_type = prepare_graph(
301
+ source,
302
+ include_rule=self.include_rule,
303
+ include_stoich=self.include_stoich,
304
+ )
305
+
306
+ self._state_cache: Optional[_WLState] = None
307
+ self._summary_cache: Optional[WLCanonicalResult] = None
308
+ self._fast_signature: Optional[Tuple[Any, ...]] = None
309
+ self._cache_key_last: Optional[Tuple[Any, ...]] = None
310
+
311
+ def __repr__(self) -> str:
312
+ """Return a concise representation.
313
+
314
+ :return:
315
+ String representation.
316
+ :rtype: str
317
+
318
+ .. rubric:: Example
319
+
320
+ .. code-block:: python
321
+
322
+ wl = WLCanonicalizer(syn)
323
+ print(wl)
324
+ """
325
+ return (
326
+ f"WLCanonicalizer(include_rule={self.include_rule}, "
327
+ f"graph_type={self.graph_type}, n_iter={self.n_iter}, "
328
+ f"digest_size={self.digest_size})"
329
+ )
330
+
331
+ @property
332
+ def G(self) -> nx.DiGraph:
333
+ """Return the prepared graph.
334
+
335
+ :return:
336
+ Prepared directed graph.
337
+ :rtype: nx.DiGraph
338
+
339
+ .. rubric:: Example
340
+
341
+ .. code-block:: python
342
+
343
+ wl = WLCanonicalizer(syn)
344
+ print(wl.G.number_of_nodes(), wl.G.number_of_edges())
345
+ """
346
+ return self._G
347
+
348
+ @property
349
+ def graph_type(self) -> str:
350
+ """Return the graph representation type.
351
+
352
+ :return:
353
+ Graph representation type.
354
+ :rtype: str
355
+
356
+ .. rubric:: Example
357
+
358
+ .. code-block:: python
359
+
360
+ wl = WLCanonicalizer(syn, include_rule=True)
361
+ print(wl.graph_type)
362
+ """
363
+ return self._graph_type
364
+
365
+ def _cache_key(self) -> Tuple[Any, ...]:
366
+ """Build a conservative cache key for the current graph and parameters.
367
+
368
+ :return:
369
+ Cache key tuple.
370
+ :rtype: Tuple[Any, ...]
371
+
372
+ .. rubric:: Example
373
+
374
+ .. code-block:: python
375
+
376
+ wl = WLCanonicalizer(syn)
377
+ print(wl._cache_key())
378
+ """
379
+ return (
380
+ id(self.G),
381
+ self.G.number_of_nodes(),
382
+ self.G.number_of_edges(),
383
+ self.include_rule,
384
+ self.include_stoich,
385
+ self.n_iter,
386
+ self.digest_size,
387
+ self.include_in_neighbors,
388
+ self.include_out_neighbors,
389
+ self.estimate_automorphisms,
390
+ self.automorphism_cap,
391
+ self.config,
392
+ )
393
+
394
+ def _node_seed(self, v: Any) -> str:
395
+ """Compute the initial WL color for one node.
396
+
397
+ The seed combines the semantic node token and the directed degree.
398
+
399
+ :param v:
400
+ Node identifier.
401
+ :type v: Any
402
+
403
+ :return:
404
+ Initial hashed node color.
405
+ :rtype: str
406
+ """
407
+ tok = node_token(self.G.nodes[v], self.config)
408
+ deg = (self.G.in_degree(v), self.G.out_degree(v))
409
+ return hash_text(f"N|{tok}|{deg}", digest_size=self.digest_size)
410
+
411
+ def _edge_sig(self, attrs: Dict[str, Any]) -> str:
412
+ """Compute a hashed signature for one edge attribute dictionary.
413
+
414
+ :param attrs:
415
+ Edge attributes.
416
+ :type attrs: Dict[str, Any]
417
+
418
+ :return:
419
+ Hashed edge signature.
420
+ :rtype: str
421
+ """
422
+ return hash_text(
423
+ f"E|{edge_token(attrs, self.config)}",
424
+ digest_size=self.digest_size,
425
+ )
426
+
427
+ def _edge_sig_between(self, u: Any, v: Any) -> str:
428
+ """Return a stable signature for the edge between two nodes.
429
+
430
+ For multigraphs, the minimum signature over parallel edges is used to
431
+ keep the behavior deterministic.
432
+
433
+ :param u:
434
+ Source node.
435
+ :type u: Any
436
+
437
+ :param v:
438
+ Target node.
439
+ :type v: Any
440
+
441
+ :return:
442
+ Stable edge signature.
443
+ :rtype: str
444
+ """
445
+ data = self.G.get_edge_data(u, v, default=None)
446
+ if data is None:
447
+ return self._edge_sig({})
448
+
449
+ if self.G.is_multigraph():
450
+ sigs: List[str] = []
451
+ if isinstance(data, dict):
452
+ for _, attrs in data.items():
453
+ if isinstance(attrs, dict):
454
+ sigs.append(self._edge_sig(attrs))
455
+ return min(sigs) if sigs else self._edge_sig({})
456
+
457
+ if isinstance(data, dict):
458
+ return self._edge_sig(data)
459
+
460
+ return self._edge_sig({})
461
+
462
+ def _neighbors_items(
463
+ self,
464
+ colors: Dict[Any, str],
465
+ v: Any,
466
+ *,
467
+ direction: str,
468
+ ) -> List[str]:
469
+ """Collect colored neighbor-edge descriptors for one node.
470
+
471
+ :param colors:
472
+ Current node colors.
473
+ :type colors: Dict[Any, str]
474
+
475
+ :param v:
476
+ Node identifier.
477
+ :type v: Any
478
+
479
+ :param direction:
480
+ Neighborhood direction, one of ``"in"``, ``"out"``, or ``"undir"``.
481
+ :type direction: str
482
+
483
+ :return:
484
+ Sorted color-edge descriptors.
485
+ :rtype: List[str]
486
+ """
487
+ items: List[str] = []
488
+
489
+ if direction == "in":
490
+ if not self.G.is_directed():
491
+ direction = "undir"
492
+ else:
493
+ for u in self.G.predecessors(v):
494
+ items.append(f"{colors[u]}#{self._edge_sig_between(u, v)}")
495
+
496
+ if direction == "out":
497
+ if not self.G.is_directed():
498
+ direction = "undir"
499
+ else:
500
+ for u in self.G.successors(v):
501
+ items.append(f"{colors[u]}#{self._edge_sig_between(v, u)}")
502
+
503
+ if direction == "undir":
504
+ for u in self.G.neighbors(v):
505
+ es = self._edge_sig_between(v, u) if self.G.has_edge(v, u) else ""
506
+ if not es and self.G.has_edge(u, v):
507
+ es = self._edge_sig_between(u, v)
508
+ items.append(f"{colors[u]}#{es}")
509
+
510
+ items.sort()
511
+ return items
512
+
513
+ def _refine_once(self, colors: Dict[Any, str]) -> Dict[Any, str]:
514
+ """Perform one WL refinement round.
515
+
516
+ :param colors:
517
+ Current node colors.
518
+ :type colors: Dict[Any, str]
519
+
520
+ :return:
521
+ Refined node colors.
522
+ :rtype: Dict[Any, str]
523
+ """
524
+ new_colors: Dict[Any, str] = {}
525
+
526
+ for v in self.G.nodes():
527
+ parts: List[str] = [colors[v]]
528
+
529
+ if self.include_in_neighbors:
530
+ parts.append(
531
+ "IN["
532
+ + "|".join(self._neighbors_items(colors, v, direction="in"))
533
+ + "]"
534
+ )
535
+
536
+ if self.include_out_neighbors:
537
+ parts.append(
538
+ "OUT["
539
+ + "|".join(self._neighbors_items(colors, v, direction="out"))
540
+ + "]"
541
+ )
542
+
543
+ new_colors[v] = hash_text("||".join(parts), digest_size=self.digest_size)
544
+
545
+ return new_colors
546
+
547
+ @staticmethod
548
+ def _colors_equal(a: Dict[Any, str], b: Dict[Any, str]) -> bool:
549
+ """Compare two color mappings exactly.
550
+
551
+ :param a:
552
+ First color mapping.
553
+ :type a: Dict[Any, str]
554
+
555
+ :param b:
556
+ Second color mapping.
557
+ :type b: Dict[Any, str]
558
+
559
+ :return:
560
+ ``True`` if both mappings are identical.
561
+ :rtype: bool
562
+ """
563
+ if a.keys() != b.keys():
564
+ return False
565
+ return all(a[k] == b[k] for k in a)
566
+
567
+ @staticmethod
568
+ def _buckets_from_colors(colors: Dict[Any, str]) -> Dict[str, List[Any]]:
569
+ """Group nodes by final color.
570
+
571
+ :param colors:
572
+ Node-to-color mapping.
573
+ :type colors: Dict[Any, str]
574
+
575
+ :return:
576
+ Color buckets.
577
+ :rtype: Dict[str, List[Any]]
578
+ """
579
+ buckets: Dict[str, List[Any]] = {}
580
+ for v, c in colors.items():
581
+ buckets.setdefault(c, []).append(v)
582
+ return buckets
583
+
584
+ @staticmethod
585
+ def _orbits_from_buckets(buckets: Dict[str, List[Any]]) -> List[Set[Any]]:
586
+ """Build approximate orbit sets from color buckets.
587
+
588
+ :param buckets:
589
+ Color buckets.
590
+ :type buckets: Dict[str, List[Any]]
591
+
592
+ :return:
593
+ Approximate orbit sets.
594
+ :rtype: List[Set[Any]]
595
+ """
596
+ items = sorted(buckets.items(), key=lambda kv: (kv[0], len(kv[1])))
597
+ out: List[Set[Any]] = []
598
+ for _, nodes in items:
599
+ out.append(set(sorted(nodes, key=str)))
600
+ return out
601
+
602
+ @staticmethod
603
+ def _canonical_order_from_colors(
604
+ G: nx.DiGraph,
605
+ colors: Dict[Any, str],
606
+ ) -> List[Any]:
607
+ """Build a deterministic node order from final colors.
608
+
609
+ :param G:
610
+ Input graph.
611
+ :type G: nx.DiGraph
612
+
613
+ :param colors:
614
+ Final color mapping.
615
+ :type colors: Dict[Any, str]
616
+
617
+ :return:
618
+ Deterministic canonical order.
619
+ :rtype: List[Any]
620
+ """
621
+ return sorted(G.nodes(), key=lambda v: (colors[v], str(v)))
622
+
623
+ def _run(self) -> _WLState:
624
+ """Run WL refinement once and cache the result.
625
+
626
+ :return:
627
+ Internal cached WL state.
628
+ :rtype: _WLState
629
+
630
+ .. rubric:: Example
631
+
632
+ .. code-block:: python
633
+
634
+ wl = WLCanonicalizer(syn)
635
+ state = wl._run()
636
+ print(state.iters_run, state.stabilized)
637
+ """
638
+ key = self._cache_key()
639
+ if self._state_cache is not None and self._cache_key_last == key:
640
+ return self._state_cache
641
+
642
+ colors: Dict[Any, str] = {v: self._node_seed(v) for v in self.G.nodes()}
643
+ stabilized = False
644
+ iters_run = 0
645
+
646
+ for it in range(self.n_iter):
647
+ iters_run = it + 1
648
+ new_colors = self._refine_once(colors)
649
+ if self._colors_equal(new_colors, colors):
650
+ stabilized = True
651
+ colors = new_colors
652
+ break
653
+ colors = new_colors
654
+
655
+ buckets = self._buckets_from_colors(colors)
656
+ cells = [
657
+ sorted(nodes, key=str)
658
+ for _, nodes in sorted(
659
+ buckets.items(),
660
+ key=lambda kv: (kv[0], tuple(map(str, kv[1]))),
661
+ )
662
+ ]
663
+ orbits = self._orbits_from_buckets(buckets)
664
+ color_hist = {c: len(nodes) for c, nodes in buckets.items()}
665
+ canonical_order = self._canonical_order_from_colors(self.G, colors)
666
+
667
+ approx_count: Optional[int] = None
668
+ if self.estimate_automorphisms:
669
+ approx_count = approx_automorphism_count_from_cells(
670
+ cells,
671
+ cap=self.automorphism_cap,
672
+ )
673
+
674
+ self._state_cache = _WLState(
675
+ colors=colors,
676
+ cells=cells,
677
+ orbits=orbits,
678
+ color_hist=color_hist,
679
+ iters_run=iters_run,
680
+ stabilized=stabilized,
681
+ canonical_order=canonical_order,
682
+ approx_automorphism_count=approx_count,
683
+ )
684
+ self._summary_cache = None
685
+ self._fast_signature = None
686
+ self._cache_key_last = key
687
+ return self._state_cache
688
+
689
+ def colors(self) -> Dict[Any, str]:
690
+ """Return final WL colors.
691
+
692
+ :return:
693
+ Mapping from node to final color.
694
+ :rtype: Dict[Any, str]
695
+
696
+ .. rubric:: Example
697
+
698
+ .. code-block:: python
699
+
700
+ wl = WLCanonicalizer(syn)
701
+ print(wl.colors())
702
+ """
703
+ return dict(self._run().colors)
704
+
705
+ def color_of(self, v: Any) -> str:
706
+ """Return the final WL color of one node.
707
+
708
+ :param v:
709
+ Node identifier.
710
+ :type v: Any
711
+
712
+ :return:
713
+ Final WL color.
714
+ :rtype: str
715
+
716
+ .. rubric:: Example
717
+
718
+ .. code-block:: python
719
+
720
+ wl = WLCanonicalizer(syn)
721
+ print(wl.color_of(1))
722
+ """
723
+ return self._run().colors[v]
724
+
725
+ def orbits(self) -> List[Set[Any]]:
726
+ """Return approximate WL orbit sets.
727
+
728
+ :return:
729
+ Approximate orbits induced by final WL colors.
730
+ :rtype: List[Set[Any]]
731
+
732
+ .. rubric:: Example
733
+
734
+ .. code-block:: python
735
+
736
+ wl = WLCanonicalizer(syn)
737
+ print(wl.orbits())
738
+ """
739
+ return [set(x) for x in self._run().orbits]
740
+
741
+ def wl_orbits(self) -> List[Set[Any]]:
742
+ """Alias for :meth:`orbits`.
743
+
744
+ :return:
745
+ Approximate WL orbit sets.
746
+ :rtype: List[Set[Any]]
747
+ """
748
+ return self.orbits()
749
+
750
+ def has_nontrivial_automorphism(self) -> bool:
751
+ """Heuristically detect whether symmetry may be present.
752
+
753
+ This is approximate and simply checks whether any WL color cell has size
754
+ greater than one.
755
+
756
+ :return:
757
+ ``True`` if WL detects a non-singleton cell, else ``False``.
758
+ :rtype: bool
759
+
760
+ .. rubric:: Example
761
+
762
+ .. code-block:: python
763
+
764
+ wl = WLCanonicalizer(syn)
765
+ print(wl.has_nontrivial_automorphism())
766
+ """
767
+ return any(len(cell) > 1 for cell in self._run().cells)
768
+
769
+ def canonical_order(self) -> List[Any]:
770
+ """Return the deterministic WL node order.
771
+
772
+ :return:
773
+ WL-based canonical node order.
774
+ :rtype: List[Any]
775
+
776
+ .. rubric:: Example
777
+
778
+ .. code-block:: python
779
+
780
+ wl = WLCanonicalizer(syn)
781
+ print(wl.canonical_order())
782
+ """
783
+ return list(self._run().canonical_order)
784
+
785
+ def canonical_key(self) -> Any:
786
+ """Return the canonical key induced by the WL order.
787
+
788
+ :return:
789
+ WL canonical key.
790
+ :rtype: Any
791
+
792
+ .. rubric:: Example
793
+
794
+ .. code-block:: python
795
+
796
+ wl = WLCanonicalizer(syn)
797
+ print(wl.canonical_key())
798
+ """
799
+ return graph_key_from_order(self.G, self.canonical_order(), self.config)
800
+
801
+ def canonical_graph(self) -> nx.DiGraph:
802
+ """Return the canonically relabeled graph using the WL order.
803
+
804
+ :return:
805
+ WL-canonically relabeled graph.
806
+ :rtype: nx.DiGraph
807
+
808
+ .. rubric:: Example
809
+
810
+ .. code-block:: python
811
+
812
+ wl = WLCanonicalizer(syn)
813
+ G_can = wl.canonical_graph()
814
+ print(sorted(G_can.nodes()))
815
+ """
816
+ order = self.canonical_order()
817
+ mapping = {v: i + 1 for i, v in enumerate(order)}
818
+ return nx.relabel_nodes(self.G, mapping, copy=True)
819
+
820
+ def graph(self) -> nx.DiGraph:
821
+ """Alias for :meth:`canonical_graph`, matching the older canon style.
822
+
823
+ :return:
824
+ WL-canonically relabeled graph.
825
+ :rtype: nx.DiGraph
826
+
827
+ .. rubric:: Example
828
+
829
+ .. code-block:: python
830
+
831
+ wl = WLCanonicalizer(syn)
832
+ G_can = wl.graph()
833
+ """
834
+ return self.canonical_graph()
835
+
836
+ def canonical_result(self) -> WLCanonicalResult:
837
+ """Build an approximate canonicalization result in a CRN-canon-like format.
838
+
839
+ :return:
840
+ Approximate canonicalization result.
841
+ :rtype: WLCanonicalResult
842
+
843
+ .. rubric:: Example
844
+
845
+ .. code-block:: python
846
+
847
+ wl = WLCanonicalizer(syn)
848
+ result = wl.canonical_result()
849
+ print(result.canonical_order)
850
+ print(result.automorphism_count)
851
+ """
852
+ if self._summary_cache is not None:
853
+ return self._summary_cache
854
+
855
+ start = perf_counter()
856
+ state = self._run()
857
+ can_graph = self.canonical_graph()
858
+ can_key = graph_key_from_order(self.G, state.canonical_order, self.config)
859
+
860
+ self._summary_cache = WLCanonicalResult(
861
+ canon_graph=can_graph,
862
+ graph_type=self.graph_type,
863
+ canonical_order=list(state.canonical_order),
864
+ canonical_key=can_key,
865
+ automorphism_count=state.approx_automorphism_count,
866
+ orbits=[set(x) for x in state.orbits],
867
+ colors=dict(state.colors),
868
+ color_hist=dict(state.color_hist),
869
+ iters_run=state.iters_run,
870
+ stabilized=state.stabilized,
871
+ exact=False,
872
+ elapsed_seconds=perf_counter() - start,
873
+ )
874
+ return self._summary_cache
875
+
876
+ def summary(self) -> Dict[str, Any]:
877
+ """Return a dictionary summary in a format close to the exact canonicalizer.
878
+
879
+ The reported automorphism count and orbit sets are WL-based
880
+ approximations.
881
+
882
+ :return:
883
+ Summary dictionary.
884
+ :rtype: Dict[str, Any]
885
+
886
+ .. rubric:: Example
887
+
888
+ .. code-block:: python
889
+
890
+ wl = WLCanonicalizer(syn)
891
+ info = wl.summary()
892
+ print(info["automorphism_count"])
893
+ print(info["orbits"])
894
+ """
895
+ res = self.canonical_result()
896
+ return {
897
+ "canon_graph": res.canon_graph,
898
+ "graph_type": res.graph_type,
899
+ "automorphism_count": res.automorphism_count,
900
+ "orbits": res.orbits,
901
+ "canonical_perm": res.canonical_order,
902
+ "canonical_key": res.canonical_key,
903
+ "colors": res.colors,
904
+ "color_hist": res.color_hist,
905
+ "iters_run": res.iters_run,
906
+ "stabilized": res.stabilized,
907
+ "exact": res.exact,
908
+ "elapsed_seconds": res.elapsed_seconds,
909
+ }
910
+
911
+ def fast_signature(self) -> Tuple[Any, ...]:
912
+ """Return a fast graph signature using graph statistics and WL color
913
+ histogram.
914
+
915
+ This is useful as a cheap prefilter before exact graph isomorphism or
916
+ exact canonicalization.
917
+
918
+ :return:
919
+ Fast graph signature.
920
+ :rtype: Tuple[Any, ...]
921
+
922
+ .. rubric:: Example
923
+
924
+ .. code-block:: python
925
+
926
+ wl = WLCanonicalizer(syn)
927
+ print(wl.fast_signature())
928
+ """
929
+ if self._fast_signature is None:
930
+ state = self._run()
931
+ self._fast_signature = build_fast_signature(
932
+ self.G,
933
+ self.graph_type,
934
+ self.config,
935
+ wl_color_hist=state.color_hist,
936
+ )
937
+ return self._fast_signature
938
+
939
+
940
+ def wl_canonical(source: Any, **kwargs: Any) -> nx.DiGraph:
941
+ """Convenience function returning the WL-canonically relabeled graph.
942
+
943
+ :param source:
944
+ Input CRN representation.
945
+ :type source: Any
946
+
947
+ :param kwargs:
948
+ Additional keyword arguments forwarded to :class:`WLCanonicalizer`.
949
+ :type kwargs: Any
950
+
951
+ :return:
952
+ WL-canonically relabeled graph.
953
+ :rtype: nx.DiGraph
954
+
955
+ .. rubric:: Example
956
+
957
+ .. code-block:: python
958
+
959
+ from synkit.CRN.Sym import SymmetryConfig, wl_canonical
960
+
961
+ G_can = wl_canonical(
962
+ syn.to_digraph(),
963
+ include_rule=True,
964
+ config=SymmetryConfig.topological(),
965
+ )
966
+ """
967
+ return WLCanonicalizer(source, **kwargs).canonical_graph()