synkit 0.0.7__tar.gz → 0.0.9__tar.gz

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 (256) hide show
  1. {synkit-0.0.7 → synkit-0.0.9}/.gitignore +2 -1
  2. synkit-0.0.9/.readthedocs.yml +24 -0
  3. synkit-0.0.9/Data/Figure/synkit.png +0 -0
  4. {synkit-0.0.7 → synkit-0.0.9}/PKG-INFO +5 -1
  5. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Reaction/test_canon_rsmi.py +5 -1
  6. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/ITS/test_its_construction.py +4 -4
  7. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/ITS/test_its_expand.py +1 -0
  8. {synkit-0.0.7 → synkit-0.0.9}/Test/IO/test_chemical_converter.py +8 -2
  9. {synkit-0.0.7 → synkit-0.0.9}/Test/Rule/Modify/test_molecule_rule.py +1 -1
  10. {synkit-0.0.7 → synkit-0.0.9}/Test/Rule/Modify/test_rule_utils.py +2 -1
  11. synkit-0.0.9/build-doc.sh +31 -0
  12. {synkit-0.0.7 → synkit-0.0.9}/doc/api.rst +44 -9
  13. {synkit-0.0.7 → synkit-0.0.9}/doc/conf.py +14 -11
  14. {synkit-0.0.7 → synkit-0.0.9}/doc/index.rst +1 -0
  15. {synkit-0.0.7 → synkit-0.0.9}/doc/io.rst +12 -12
  16. synkit-0.0.9/doc/requirements.txt +3 -0
  17. {synkit-0.0.7 → synkit-0.0.9}/pyproject.toml +6 -2
  18. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Reaction/aam_validator.py +3 -3
  19. synkit-0.0.9/synkit/Graph/Canon/__init__.py +3 -0
  20. {synkit-0.0.7/synkit/Graph → synkit-0.0.9/synkit/Graph/Canon}/canon_graph.py +11 -2
  21. synkit-0.0.9/synkit/Graph/Canon/nauty.py +292 -0
  22. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Hyrogen/_misc.py +19 -2
  23. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Hyrogen/hcomplete.py +1 -1
  24. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/ITS/its_construction.py +105 -1
  25. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/ITS/its_expand.py +1 -2
  26. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/ITS/normalize_aam.py +0 -1
  27. synkit-0.0.9/synkit/Graph/Matcher/__init__.py +10 -0
  28. synkit-0.0.9/synkit/Graph/Matcher/mcs_matcher.py +202 -0
  29. synkit-0.0.9/synkit/Graph/Matcher/multi_turbo_iso.py +178 -0
  30. synkit-0.0.9/synkit/Graph/Matcher/partial_matcher.py +214 -0
  31. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Matcher/turbo_iso.py +8 -5
  32. synkit-0.0.9/synkit/Graph/__init__.py +16 -0
  33. synkit-0.0.9/synkit/Graph/canon_graph.py +538 -0
  34. {synkit-0.0.7 → synkit-0.0.9}/synkit/IO/chem_converter.py +65 -24
  35. synkit-0.0.9/synkit/IO/data_io.py +335 -0
  36. {synkit-0.0.7 → synkit-0.0.9}/synkit/IO/debug.py +21 -27
  37. {synkit-0.0.7 → synkit-0.0.9}/synkit/IO/gml_to_nx.py +34 -2
  38. {synkit-0.0.7 → synkit-0.0.9}/synkit/IO/graph_to_mol.py +36 -19
  39. synkit-0.0.9/synkit/IO/mol_to_graph.py +353 -0
  40. {synkit-0.0.7 → synkit-0.0.9}/synkit/IO/nx_to_gml.py +78 -73
  41. synkit-0.0.9/synkit/Synthesis/Reactor/batch_reactor.py +231 -0
  42. synkit-0.0.9/synkit/Synthesis/Reactor/rule_filter.py +201 -0
  43. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/Reactor/strategy.py +2 -0
  44. synkit-0.0.7/Data/Figure/synkit.png +0 -0
  45. synkit-0.0.7/synkit/Graph/Matcher/__init__.py +0 -10
  46. synkit-0.0.7/synkit/Graph/Matcher/mcs_matcher.py +0 -202
  47. synkit-0.0.7/synkit/Graph/__init__.py +0 -6
  48. synkit-0.0.7/synkit/IO/data_io.py +0 -356
  49. synkit-0.0.7/synkit/IO/mol_to_graph.py +0 -282
  50. synkit-0.0.7/synkit/Synthesis/Reactor/old_syn_reactor.py +0 -443
  51. {synkit-0.0.7 → synkit-0.0.9}/.github/workflows/build-doc.yml +0 -0
  52. {synkit-0.0.7 → synkit-0.0.9}/.github/workflows/publish-package.yml +0 -0
  53. {synkit-0.0.7 → synkit-0.0.9}/.github/workflows/test-and-lint.yml +0 -0
  54. {synkit-0.0.7 → synkit-0.0.9}/Data/Testcase/Compose/ComposeRule/data.txt +0 -0
  55. {synkit-0.0.7 → synkit-0.0.9}/Data/Testcase/Compose/SingleRule/R0/0.gml +0 -0
  56. {synkit-0.0.7 → synkit-0.0.9}/Data/Testcase/Compose/SingleRule/R0/1.gml +0 -0
  57. {synkit-0.0.7 → synkit-0.0.9}/Data/Testcase/Compose/SingleRule/R0/2.gml +0 -0
  58. {synkit-0.0.7 → synkit-0.0.9}/LICENSE +0 -0
  59. {synkit-0.0.7 → synkit-0.0.9}/Makefile +0 -0
  60. {synkit-0.0.7 → synkit-0.0.9}/README.md +0 -0
  61. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Fingerprint/__init__.py +0 -0
  62. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Fingerprint/test_fp_calculator.py +0 -0
  63. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Fingerprint/test_smiles_featurizer.py +0 -0
  64. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Fingerprint/test_transformation_fp.py +0 -0
  65. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Molecule/__init__.py +0 -0
  66. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Molecule/test_standardize.py +0 -0
  67. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Reaction/__init__.py +0 -0
  68. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Reaction/test_aam_utils.py +0 -0
  69. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Reaction/test_aam_validator.py +0 -0
  70. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Reaction/test_balance_checker.py +0 -0
  71. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Reaction/test_cleanning.py +0 -0
  72. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Reaction/test_deionize.py +0 -0
  73. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Reaction/test_fix_aam.py +0 -0
  74. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Reaction/test_neutralize.py +0 -0
  75. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Reaction/test_rsmi_utils.py +0 -0
  76. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Reaction/test_standardize.py +0 -0
  77. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/Reaction/test_tautomerize.py +0 -0
  78. {synkit-0.0.7 → synkit-0.0.9}/Test/Chem/__init__.py +0 -0
  79. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Context/__init__.py +0 -0
  80. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Context/test_hier_context.py +0 -0
  81. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Context/test_radius_expand.py +0 -0
  82. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Feature/__init__.py +0 -0
  83. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Feature/test_graph_descriptors.py +0 -0
  84. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Feature/test_graph_fps.py +0 -0
  85. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Feature/test_graph_signature.py +0 -0
  86. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Feature/test_hash_fps.py +0 -0
  87. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Feature/test_morgan_fps.py +0 -0
  88. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Feature/test_path_fps.py +0 -0
  89. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Hydrogen/__init__.py +0 -0
  90. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Hydrogen/test_graph_hydrogen.py +0 -0
  91. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Hydrogen/test_hcomplete.py +0 -0
  92. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Hydrogen/test_misc.py +0 -0
  93. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/ITS/__init__.py +0 -0
  94. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/ITS/test_normalize_aam.py +0 -0
  95. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/MTG/__init__.py +0 -0
  96. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/MTG/test_group_comp.py +0 -0
  97. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/MTG/test_groupoid.py +0 -0
  98. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/MTG/test_mtg.py +0 -0
  99. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Matcher/__init__.py +0 -0
  100. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Matcher/test_batch_cluster.py +0 -0
  101. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Matcher/test_graph_cluster.py +0 -0
  102. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Matcher/test_graph_matcher.py +0 -0
  103. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Matcher/test_graph_morphism.py +0 -0
  104. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/Matcher/test_subgraph_matcher.py +0 -0
  105. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/__init__.py +0 -0
  106. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/test_canon_graph.py +0 -0
  107. {synkit-0.0.7 → synkit-0.0.9}/Test/Graph/test_syn_graph.py +0 -0
  108. {synkit-0.0.7 → synkit-0.0.9}/Test/IO/__init__.py +0 -0
  109. {synkit-0.0.7 → synkit-0.0.9}/Test/IO/test_dg_to_gml.py +0 -0
  110. {synkit-0.0.7 → synkit-0.0.9}/Test/IO/test_gml_to_nx.py +0 -0
  111. {synkit-0.0.7 → synkit-0.0.9}/Test/IO/test_graph_to_mol.py +0 -0
  112. {synkit-0.0.7 → synkit-0.0.9}/Test/IO/test_mol_to_graph.py +0 -0
  113. {synkit-0.0.7 → synkit-0.0.9}/Test/IO/test_nx_to_gml.py +0 -0
  114. {synkit-0.0.7 → synkit-0.0.9}/Test/Rule/Apply/__init__.py +0 -0
  115. {synkit-0.0.7 → synkit-0.0.9}/Test/Rule/Apply/test_reactor_rule.py +0 -0
  116. {synkit-0.0.7 → synkit-0.0.9}/Test/Rule/Apply/test_retro_reactor.py +0 -0
  117. {synkit-0.0.7 → synkit-0.0.9}/Test/Rule/Apply/test_rule_rbl.py +0 -0
  118. {synkit-0.0.7 → synkit-0.0.9}/Test/Rule/Compose/__init__.py +0 -0
  119. {synkit-0.0.7 → synkit-0.0.9}/Test/Rule/Compose/test_rule_compose.py +0 -0
  120. {synkit-0.0.7 → synkit-0.0.9}/Test/Rule/Compose/test_valance_constrain.py +0 -0
  121. {synkit-0.0.7 → synkit-0.0.9}/Test/Rule/Modify/__init__.py +0 -0
  122. {synkit-0.0.7 → synkit-0.0.9}/Test/Rule/__init__.py +0 -0
  123. {synkit-0.0.7 → synkit-0.0.9}/Test/Rule/test_syn_rule.py +0 -0
  124. {synkit-0.0.7 → synkit-0.0.9}/Test/Synthesis/CRN/__init__.py +0 -0
  125. {synkit-0.0.7 → synkit-0.0.9}/Test/Synthesis/CRN/test_crn.py +0 -0
  126. {synkit-0.0.7 → synkit-0.0.9}/Test/Synthesis/CRN/test_mod_crn.py +0 -0
  127. {synkit-0.0.7 → synkit-0.0.9}/Test/Synthesis/MSR/__init__.py +0 -0
  128. {synkit-0.0.7 → synkit-0.0.9}/Test/Synthesis/MSR/test_multi_steps.py +0 -0
  129. {synkit-0.0.7 → synkit-0.0.9}/Test/Synthesis/MSR/test_path_finder.py +0 -0
  130. {synkit-0.0.7 → synkit-0.0.9}/Test/Synthesis/Reactor/__init__.py +0 -0
  131. {synkit-0.0.7 → synkit-0.0.9}/Test/Synthesis/Reactor/test_core_engine.py +0 -0
  132. {synkit-0.0.7 → synkit-0.0.9}/Test/Synthesis/Reactor/test_mod_aam.py +0 -0
  133. {synkit-0.0.7 → synkit-0.0.9}/Test/Synthesis/Reactor/test_mod_reactor.py +0 -0
  134. {synkit-0.0.7 → synkit-0.0.9}/Test/Synthesis/Reactor/test_strategy.py +0 -0
  135. {synkit-0.0.7 → synkit-0.0.9}/Test/Synthesis/__init__.py +0 -0
  136. {synkit-0.0.7 → synkit-0.0.9}/Test/Synthesis/test_reactor_utils.py +0 -0
  137. {synkit-0.0.7 → synkit-0.0.9}/Test/Vis/__init__.py +0 -0
  138. {synkit-0.0.7 → synkit-0.0.9}/Test/Vis/test_embedding.py +0 -0
  139. {synkit-0.0.7 → synkit-0.0.9}/Test/__init__.py +0 -0
  140. {synkit-0.0.7 → synkit-0.0.9}/doc/changelog.rst +0 -0
  141. {synkit-0.0.7 → synkit-0.0.9}/doc/chem.rst +0 -0
  142. {synkit-0.0.7 → synkit-0.0.9}/doc/figures/aldol.png +0 -0
  143. {synkit-0.0.7 → synkit-0.0.9}/doc/figures/aldol_its.png +0 -0
  144. {synkit-0.0.7 → synkit-0.0.9}/doc/figures/mtg.png +0 -0
  145. {synkit-0.0.7 → synkit-0.0.9}/doc/getting_started.rst +0 -0
  146. {synkit-0.0.7 → synkit-0.0.9}/doc/graph.rst +0 -0
  147. {synkit-0.0.7 → synkit-0.0.9}/doc/reference.rst +0 -0
  148. {synkit-0.0.7 → synkit-0.0.9}/doc/refs.bib +0 -0
  149. {synkit-0.0.7 → synkit-0.0.9}/doc/rule.rst +0 -0
  150. {synkit-0.0.7 → synkit-0.0.9}/doc/synthesis.rst +0 -0
  151. {synkit-0.0.7 → synkit-0.0.9}/environment.yml +0 -0
  152. {synkit-0.0.7 → synkit-0.0.9}/lint.sh +0 -0
  153. {synkit-0.0.7 → synkit-0.0.9}/make.bat +0 -0
  154. {synkit-0.0.7 → synkit-0.0.9}/pytest.sh +0 -0
  155. {synkit-0.0.7 → synkit-0.0.9}/requirements.txt +0 -0
  156. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Fingerprint/__init__.py +0 -0
  157. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Fingerprint/fp_calculator.py +0 -0
  158. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Fingerprint/smiles_featurizer.py +0 -0
  159. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Fingerprint/transformation_fp.py +0 -0
  160. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Molecule/__init__.py +0 -0
  161. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Molecule/standardize.py +0 -0
  162. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Reaction/__init__.py +0 -0
  163. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Reaction/aam_utils.py +0 -0
  164. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Reaction/balance_check.py +0 -0
  165. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Reaction/canon_rsmi.py +0 -0
  166. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Reaction/cleanning.py +0 -0
  167. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Reaction/deionize.py +0 -0
  168. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Reaction/fix_aam.py +0 -0
  169. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Reaction/neutralize.py +0 -0
  170. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Reaction/rsmi_utils.py +0 -0
  171. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Reaction/standardize.py +0 -0
  172. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/Reaction/tautomerize.py +0 -0
  173. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/__init__.py +0 -0
  174. {synkit-0.0.7 → synkit-0.0.9}/synkit/Chem/utils.py +0 -0
  175. {synkit-0.0.7/synkit/Graph → synkit-0.0.9/synkit/Graph/Canon}/canon_algs.py +0 -0
  176. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Context/__init__.py +0 -0
  177. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Context/hier_context.py +0 -0
  178. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Context/radius_expand.py +0 -0
  179. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Feature/__init__.py +0 -0
  180. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Feature/graph_descriptors.py +0 -0
  181. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Feature/graph_fps.py +0 -0
  182. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Feature/graph_signature.py +0 -0
  183. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Feature/hash_fps.py +0 -0
  184. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Feature/morgan_fps.py +0 -0
  185. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Feature/path_fps.py +0 -0
  186. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Feature/wl_hash.py +0 -0
  187. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Hyrogen/__init__.py +0 -0
  188. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Hyrogen/hextend.py +0 -0
  189. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/ITS/__init__.py +0 -0
  190. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/ITS/its_builder.py +0 -0
  191. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/ITS/its_decompose.py +0 -0
  192. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/MTG/__init__.py +0 -0
  193. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/MTG/group_comp.py +0 -0
  194. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/MTG/groupoid.py +0 -0
  195. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/MTG/mcs_matcher.py +0 -0
  196. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/MTG/mtg.py +0 -0
  197. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Matcher/batch_cluster.py +0 -0
  198. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Matcher/graph_cluster.py +0 -0
  199. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Matcher/graph_matcher.py +0 -0
  200. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Matcher/graph_morphism.py +0 -0
  201. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Matcher/sing.py +0 -0
  202. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/Matcher/subgraph_matcher.py +0 -0
  203. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/syn_graph.py +0 -0
  204. {synkit-0.0.7 → synkit-0.0.9}/synkit/Graph/utils.py +0 -0
  205. {synkit-0.0.7 → synkit-0.0.9}/synkit/IO/__init__.py +0 -0
  206. {synkit-0.0.7 → synkit-0.0.9}/synkit/IO/data_process.py +0 -0
  207. {synkit-0.0.7 → synkit-0.0.9}/synkit/IO/dg_to_gml.py +0 -0
  208. {synkit-0.0.7 → synkit-0.0.9}/synkit/IO/smiles_to_id.py +0 -0
  209. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Apply/__init__.py +0 -0
  210. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Apply/reactor_rule.py +0 -0
  211. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Apply/retro_reactor.py +0 -0
  212. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Apply/rule_rbl.py +0 -0
  213. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Compose/__init__.py +0 -0
  214. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Compose/compose_rule.py +0 -0
  215. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Compose/rule_compose.py +0 -0
  216. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Compose/rule_mapping.py +0 -0
  217. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Compose/seq_comp.py +0 -0
  218. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Compose/valence_constrain.py +0 -0
  219. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Modify/__init__.py +0 -0
  220. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Modify/implict_rule.py +0 -0
  221. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Modify/longest_path.py +0 -0
  222. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Modify/molecule_rule.py +0 -0
  223. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Modify/prune_templates.py +0 -0
  224. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Modify/rule_utils.py +0 -0
  225. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/Modify/strip_rule.py +0 -0
  226. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/__init__.py +0 -0
  227. {synkit-0.0.7 → synkit-0.0.9}/synkit/Rule/syn_rule.py +0 -0
  228. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/CRN/__init__.py +0 -0
  229. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/CRN/crn.py +0 -0
  230. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/CRN/dcrn.py +0 -0
  231. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/CRN/mod_crn.py +0 -0
  232. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/MSR/__init__.py +0 -0
  233. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/MSR/multi_steps.py +0 -0
  234. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/MSR/path_finder.py +0 -0
  235. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/Metrics/__init__.py +0 -0
  236. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/Metrics/_base.py +0 -0
  237. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/Metrics/_plot.py +0 -0
  238. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/Metrics/_ranking.py +0 -0
  239. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/Reactor/__init__.py +0 -0
  240. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/Reactor/core_engine.py +0 -0
  241. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/Reactor/mod_aam.py +0 -0
  242. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/Reactor/mod_reactor.py +0 -0
  243. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/Reactor/single_predictor.py +0 -0
  244. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/Reactor/syn_reactor.py +0 -0
  245. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/__init__.py +0 -0
  246. {synkit-0.0.7 → synkit-0.0.9}/synkit/Synthesis/reactor_utils.py +0 -0
  247. {synkit-0.0.7 → synkit-0.0.9}/synkit/Utils/__init__.py +0 -0
  248. {synkit-0.0.7 → synkit-0.0.9}/synkit/Utils/utils.py +0 -0
  249. {synkit-0.0.7 → synkit-0.0.9}/synkit/Vis/__init__.py +0 -0
  250. {synkit-0.0.7 → synkit-0.0.9}/synkit/Vis/chemical_space.py +0 -0
  251. {synkit-0.0.7 → synkit-0.0.9}/synkit/Vis/embedding.py +0 -0
  252. {synkit-0.0.7 → synkit-0.0.9}/synkit/Vis/graph_visualizer.py +0 -0
  253. {synkit-0.0.7 → synkit-0.0.9}/synkit/Vis/pdf_writer.py +0 -0
  254. {synkit-0.0.7 → synkit-0.0.9}/synkit/Vis/rule_vis.py +0 -0
  255. {synkit-0.0.7 → synkit-0.0.9}/synkit/Vis/rxn_vis.py +0 -0
  256. {synkit-0.0.7 → synkit-0.0.9}/synkit/__init__.py +0 -0
@@ -19,4 +19,5 @@ Data/Benchmark/*
19
19
  # *.png
20
20
  *.json.gz
21
21
  run.sh
22
- docs/*
22
+ docs/*
23
+ run_rdcanon.py
@@ -0,0 +1,24 @@
1
+ # Read the Docs configuration file
2
+ # https://docs.readthedocs.io/en/stable/config-file/v2.html
3
+
4
+ # 1) Tell RTD this is v2 of the schema
5
+ version: 2
6
+
7
+ # 2) Pick your build image and interpreter
8
+ build:
9
+ os: ubuntu-22.04
10
+ tools:
11
+ python: "3.11"
12
+
13
+ # 3) Install your package + any doc-only extras
14
+ python:
15
+ install:
16
+ - method: pip
17
+ path: .
18
+ extra_requirements:
19
+ - docs
20
+
21
+ # 4) Point Sphinx at your conf.py and choose HTML
22
+ sphinx:
23
+ configuration: doc/conf.py
24
+ builder: html
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synkit
3
- Version: 0.0.7
3
+ Version: 0.0.9
4
4
  Summary: Utility for reaction modeling using graph grammar
5
5
  Project-URL: homepage, https://github.com/TieuLongPhan/SynKit
6
6
  Project-URL: source, https://github.com/TieuLongPhan/SynKit
@@ -22,6 +22,10 @@ Requires-Dist: seaborn>=0.13.2
22
22
  Provides-Extra: all
23
23
  Requires-Dist: numpy>=2.2.0; extra == 'all'
24
24
  Requires-Dist: torch>=2.2.0; extra == 'all'
25
+ Provides-Extra: docs
26
+ Requires-Dist: sphinx-rtd-theme; extra == 'docs'
27
+ Requires-Dist: sphinx>=6.0; extra == 'docs'
28
+ Requires-Dist: sphinxcontrib-bibtex; extra == 'docs'
25
29
  Description-Content-Type: text/markdown
26
30
 
27
31
  # SynKit
@@ -7,7 +7,11 @@ from synkit.IO.chem_converter import rsmi_to_graph
7
7
  class TestCanonRSMI(unittest.TestCase):
8
8
  def setUp(self):
9
9
  # Use generic backend for deterministic behavior
10
- self.canon = CanonRSMI(backend="wl", wl_iterations=5)
10
+ self.canon = CanonRSMI(
11
+ backend="wl",
12
+ wl_iterations=5,
13
+ node_attrs=["element", "aromatic", "charge", "hcount", "neighbors"],
14
+ )
11
15
  # Example reaction SMILES with atom-map labels
12
16
  self.input_rsmi = "[CH3:3][CH2:5][OH:10]>>[CH2:3]=[CH2:5].[OH2:10]"
13
17
  # After expand_aam and canonicalisation, since backend is generic,
@@ -21,21 +21,21 @@ class TestITSConstruction(unittest.TestCase):
21
21
  self.H.add_edge(1, 2, order=1) # Different order
22
22
 
23
23
  def test_ITSGraph(self):
24
- ITS = ITSConstruction.ITSGraph(self.G, self.H)
24
+ ITS = ITSConstruction().ITSGraph(self.G, self.H)
25
25
  self.assertTrue(isinstance(ITS, nx.Graph))
26
26
  self.assertEqual(len(ITS.nodes()), 2)
27
27
  self.assertEqual(len(ITS.edges()), 1)
28
28
  self.assertEqual(ITS[1][2]["order"], (2, 1))
29
29
 
30
30
  def test_get_node_attributes_with_defaults(self):
31
- attributes = ITSConstruction.get_node_attributes_with_defaults(self.G, 1)
31
+ attributes = ITSConstruction().get_node_attributes_with_defaults(self.G, 1)
32
32
  self.assertEqual(attributes, ("C", False, 2, 0, ["", ""]))
33
33
 
34
34
  def test_add_edges_to_ITS(self):
35
35
  ITS = nx.Graph()
36
36
  ITS.add_node(1, element="C", aromatic=False, hcount=3, charge=0)
37
37
  ITS.add_node(2, element="C", aromatic=False, hcount=3, charge=0)
38
- new_ITS = ITSConstruction.add_edges_to_ITS(ITS, self.G, self.H)
38
+ new_ITS = ITSConstruction().add_edges_to_ITS(ITS, self.G, self.H)
39
39
  self.assertTrue(isinstance(new_ITS, nx.Graph))
40
40
  self.assertEqual(len(new_ITS.edges()), 1)
41
41
  self.assertEqual(new_ITS[1][2]["order"], (2, 1))
@@ -43,7 +43,7 @@ class TestITSConstruction(unittest.TestCase):
43
43
  def test_add_standard_order_attribute(self):
44
44
  graph = nx.Graph()
45
45
  graph.add_edge(1, 2, order=(1, 2))
46
- updated_graph = ITSConstruction.add_standard_order_attribute(graph)
46
+ updated_graph = ITSConstruction().add_standard_order_attribute(graph)
47
47
  self.assertEqual(updated_graph[1][2]["standard_order"], -1)
48
48
 
49
49
 
@@ -12,6 +12,7 @@ class TestPartialExpand(unittest.TestCase):
12
12
  "[CH3:1][CH2:2][CH2:3][Cl:4].[NH2:5][H:6]"
13
13
  + ">>[CH3:1][CH2:2][CH2:3][NH2:5].[Cl:4][H:6]"
14
14
  )
15
+ print(output_rsmi)
15
16
  self.assertTrue(AAMValidator.smiles_check(output_rsmi, expected_rsmi, "ITS"))
16
17
 
17
18
 
@@ -86,7 +86,10 @@ class TestChemicalConversions(unittest.TestCase):
86
86
  def test_smiles_to_graph_valid(self):
87
87
  # Test converting a valid SMILES to a graph
88
88
  result = smiles_to_graph(
89
- "[CH3:1][CH2:2][OH:3]", False, True, True, use_index_as_atom_map=True
89
+ "[CH3:1][CH2:2][OH:3]",
90
+ False,
91
+ True,
92
+ True,
90
93
  )
91
94
  self.assertIsInstance(result, nx.Graph)
92
95
  self.assertEqual(result.number_of_nodes(), 3)
@@ -94,7 +97,10 @@ class TestChemicalConversions(unittest.TestCase):
94
97
  def test_smiles_to_graph_invalid(self):
95
98
  # Test converting an invalid SMILES string to a graph
96
99
  result = smiles_to_graph(
97
- "invalid_smiles", True, False, False, use_index_as_atom_map=True
100
+ "invalid_smiles",
101
+ True,
102
+ False,
103
+ False,
98
104
  )
99
105
  self.assertIsNone(result)
100
106
 
@@ -1,6 +1,6 @@
1
1
  import unittest
2
2
  from synkit.Rule.Modify.molecule_rule import MoleculeRule
3
- from synkit.Graph.Matcher import GraphMatcherEngine
3
+ from synkit.Graph.Matcher.graph_matcher import GraphMatcherEngine
4
4
  import importlib
5
5
 
6
6
  MOD_AVAILABLE = importlib.util.find_spec("mod") is not None
@@ -7,7 +7,8 @@ from synkit.Rule.Modify.rule_utils import (
7
7
  strip_context,
8
8
  _increment_gml_ids,
9
9
  )
10
- from synkit.Graph.Matcher import GraphMatcherEngine, SubgraphMatch
10
+ from synkit.Graph.Matcher.graph_matcher import GraphMatcherEngine
11
+ from synkit.Graph.Matcher.subgraph_matcher import SubgraphMatch
11
12
  import importlib
12
13
 
13
14
  MOD_AVAILABLE = importlib.util.find_spec("mod") is not None
@@ -0,0 +1,31 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ echo "Checking and installing documentation dependencies..."
6
+
7
+ # Function to check and install a Python package if missing
8
+ install_if_missing() {
9
+ PACKAGE=$1
10
+ python -c "import $PACKAGE" 2>/dev/null || {
11
+ echo "Installing $PACKAGE..."
12
+ pip install "$PACKAGE"
13
+ }
14
+ }
15
+
16
+ # Check and install main Sphinx packages
17
+ install_if_missing sphinx
18
+ install_if_missing sphinx_rtd_theme
19
+
20
+ # sphinxcontrib-bibtex can have a dash in its import, so:
21
+ pip show sphinxcontrib-bibtex >/dev/null 2>&1 || {
22
+ echo "Installing sphinxcontrib-bibtex..."
23
+ pip install sphinxcontrib-bibtex
24
+ }
25
+
26
+ echo "Building Sphinx documentation..."
27
+
28
+ # Build the docs (adjust source/build dirs as needed)
29
+ python3 -m sphinx -b html ./doc ./docs
30
+
31
+ echo "Documentation built in ./docs"
@@ -2,15 +2,6 @@
2
2
  API
3
3
  ====
4
4
 
5
- IO Module
6
- =========
7
- The `IO` module provides tools for handling input and output operations related to the chemical converter. It allows seamless interaction with various chemical data formats.
8
-
9
- .. automodule:: synkit.IO.chem_converter
10
- :members:
11
- :undoc-members:
12
- :show-inheritance:
13
-
14
5
  Chem Module
15
6
  ===========
16
7
  The `Chem` module provides tools for handling input and output operations related to the chemical converter. It allows seamless interaction with various chemical data formats.
@@ -198,3 +189,47 @@ The ``synkit.Vis`` package offers a suite of **visualization utilities** for bot
198
189
  :members:
199
190
  :undoc-members:
200
191
  :show-inheritance:
192
+
193
+ IO Module
194
+ =========
195
+ The `IO` module provides tools for handling input and output operations related to the chemical converter. It allows seamless interaction with various chemical data formats.
196
+
197
+ Chemical Conversion
198
+ -------------------
199
+ .. automodule:: synkit.IO.chem_converter
200
+ :members:
201
+ :undoc-members:
202
+ :show-inheritance:
203
+
204
+ .. automodule:: synkit.IO.mol_to_graph
205
+ :members:
206
+ :undoc-members:
207
+ :show-inheritance:
208
+
209
+ .. automodule:: synkit.IO.graph_to_mol
210
+ :members:
211
+ :undoc-members:
212
+ :show-inheritance:
213
+
214
+ .. automodule:: synkit.IO.nx_to_gml
215
+ :members:
216
+ :undoc-members:
217
+ :show-inheritance:
218
+
219
+ .. automodule:: synkit.IO.gml_to_nx
220
+ :members:
221
+ :undoc-members:
222
+ :show-inheritance:
223
+
224
+ IO Functions
225
+ ------------
226
+
227
+ .. automodule:: synkit.IO.data_io
228
+ :members:
229
+ :undoc-members:
230
+ :show-inheritance:
231
+
232
+ .. automodule:: synkit.IO.data_io
233
+ :members:
234
+ :undoc-members:
235
+ :show-inheritance:
@@ -1,31 +1,34 @@
1
- # Configuration file for the Sphinx documentation builder.
2
- #
3
- # For the full list of built-in configuration values, see the documentation:
4
- # https://www.sphinx-doc.org/en/master/usage/configuration.html
1
+ import os
2
+ import sys
5
3
 
6
- # -- Project information -----------------------------------------------------
7
- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
4
+ sys.path.insert(0, os.path.abspath(".."))
8
5
 
6
+ # -- Project information -----------------------------------------------------
9
7
  project = "synkit"
10
- copyright = "2025, Tieu-Long Phan"
11
8
  author = "Tieu-Long Phan"
9
+ release = "0.0.8"
10
+ version = release
12
11
 
13
12
  # -- General configuration ---------------------------------------------------
14
- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
15
-
16
13
  extensions = [
17
14
  "sphinx.ext.autodoc",
18
15
  "sphinx.ext.autosectionlabel",
19
16
  "sphinx.ext.githubpages",
20
17
  "sphinxcontrib.bibtex",
18
+ # "sphinx.ext.napoleon", # un-comment if using Google/NumPy docstrings
21
19
  ]
20
+
22
21
  bibtex_bibfiles = ["refs.bib"]
23
22
  templates_path = ["_templates"]
24
23
  exclude_patterns = []
25
24
  autosectionlabel_prefix_document = True
26
25
 
27
- # -- Options for HTML output -------------------------------------------------
28
- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
26
+ autodoc_default_options = {
27
+ "members": True,
28
+ "undoc-members": True,
29
+ "show-inheritance": True,
30
+ }
29
31
 
32
+ # -- Options for HTML output -------------------------------------------------
30
33
  html_theme = "sphinx_rtd_theme"
31
34
  html_static_path = ["_static"]
@@ -1,5 +1,6 @@
1
1
  Welcome to synkit documentation!
2
2
  ================================
3
+ This is documentation for synkit version |version| (release |release|).
3
4
 
4
5
  .. toctree::
5
6
  :caption: Contents
@@ -102,31 +102,31 @@ Set ``core=True`` to include only the **reaction center**, and ``useSmile=True``
102
102
  :linenos:
103
103
 
104
104
  from synkit.IO import (
105
- rsmi_to_its,
106
- smart_to_gml,
107
- its_to_gml,
108
- save_text_as_gml,
109
- load_gml_as_text,
105
+ rsmi_to_its,
106
+ smart_to_gml,
107
+ its_to_gml,
108
+ save_text_as_gml,
109
+ load_gml_as_text,
110
110
  )
111
111
 
112
112
  # Define the aldol reaction template
113
113
  reaction = (
114
- '[CH3:1][CH:2]=[O:3].'
115
- '[CH:4]([H:7])([H:8])[CH:5]=[O:6]'
116
- '>>'
117
- '[CH3:1][CH:2]=[CH:4][CH:5]=[O:6].'
118
- '[O:3]([H:7])([H:8])'
114
+ '[CH3:1][CH:2]=[O:3].'
115
+ '[CH:4]([H:7])([H:8])[CH:5]=[O:6]'
116
+ '>>'
117
+ '[CH3:1][CH:2]=[CH:4][CH:5]=[O:6].'
118
+ '[O:3]([H:7])([H:8])'
119
119
  )
120
120
 
121
121
  # Option 1: Direct SMARTS → GML
122
- gml_rule_1 = smart_to_gml(reaction, core=True, useSmile=False)
122
+ gml_rule_1 = smart_to_gml(reaction, core=True, useSmiles=False)
123
123
 
124
124
  # Option 2: SMILES → ITS → GML
125
125
  its_graph = rsmi_to_its(reaction, core=True)
126
126
  gml_rule_2 = its_to_gml(its_graph, core=True)
127
127
 
128
128
  # Save to disk
129
- save_text_as_gml("aldol_rule.gml", gml_rule_2)
129
+ save_text_as_gml(gml_text=gml_rule_2, file_path="aldol_rule.gml")
130
130
 
131
131
  # Load back into text
132
132
  loaded_rule = load_gml_as_text("aldol_rule.gml")
@@ -0,0 +1,3 @@
1
+ sphinx
2
+ sphinx-rtd-theme
3
+ sphinxcontrib-bibtex
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "synkit"
7
- version = "0.0.7"
7
+ version = "0.0.9"
8
8
  authors = [
9
9
  {name="Tieu Long Phan", email="tieu@bioinf.uni-leipzig.de"}
10
10
  ]
@@ -30,7 +30,11 @@ dependencies = [
30
30
 
31
31
  [project.optional-dependencies]
32
32
  all = ["numpy>=2.2.0", "torch>=2.2.0"]
33
-
33
+ docs = [
34
+ "sphinx>=6.0",
35
+ "sphinx-rtd-theme",
36
+ "sphinxcontrib-bibtex",
37
+ ]
34
38
  [project.urls]
35
39
  homepage = "https://github.com/TieuLongPhan/SynKit"
36
40
  source = "https://github.com/TieuLongPhan/SynKit"
@@ -85,10 +85,10 @@ class AAMValidator:
85
85
  its_graphs, rc_graphs = [], []
86
86
  try:
87
87
  for rsmi in (mapped_smile, ground_truth):
88
- G, H = rsmi_to_graph(
89
- rsmi=rsmi, sanitize=True, drop_non_aam=True, light_weight=True
88
+ G, H = rsmi_to_graph(rsmi=rsmi, sanitize=True, drop_non_aam=True)
89
+ its = ITSConstruction().ITSGraph(
90
+ G, H, ignore_aromaticity=ignore_aromaticity
90
91
  )
91
- its = ITSConstruction.ITSGraph(G, H, ignore_aromaticity)
92
92
  its_graphs.append(its)
93
93
  rc_graphs.append(get_rc(its))
94
94
 
@@ -0,0 +1,3 @@
1
+ from .canon_graph import GraphCanonicaliser, CanonicalGraph
2
+
3
+ __all__ = ["GraphCanonicaliser", "CanonicalGraph"]
@@ -63,6 +63,7 @@ from networkx.algorithms.graph_hashing import (
63
63
  weisfeiler_lehman_subgraph_hashes as _wl_hashes,
64
64
  )
65
65
  from .canon_algs import canon_morgan
66
+ from .nauty import NautyCanonicalizer
66
67
 
67
68
  __all__: list[str] = ["CanonicalGraph", "GraphCanonicaliser", "CanonicalRule"]
68
69
 
@@ -145,14 +146,14 @@ class GraphCanonicaliser:
145
146
  def __init__(
146
147
  self,
147
148
  *,
148
- backend: Literal["generic", "wl", "morgan"] = "generic",
149
+ backend: Literal["generic", "wl", "morgan", "nauty"] = "generic",
149
150
  wl_iterations: int = 3,
150
151
  morgan_radius: int = 3,
151
152
  node_attrs: List[str] = ["element", "aromatic", "charge", "hcount"],
152
153
  node_sort_key: T_NodeSortKey = _default_node_key,
153
154
  edge_sort_key: T_EdgeSortKey = _default_edge_key,
154
155
  ) -> None:
155
- if backend not in {"generic", "wl", "morgan"}:
156
+ if backend not in {"generic", "wl", "morgan", "nauty"}:
156
157
  raise ValueError("backend must be 'generic' or 'wl' or 'morgan' ")
157
158
  self.backend: Literal["generic", "wl", "morgan"] = backend
158
159
  self._wl_k: int = wl_iterations
@@ -161,6 +162,8 @@ class GraphCanonicaliser:
161
162
  self._edge_key: T_EdgeSortKey = edge_sort_key
162
163
  self._wl_node_attrs: Tuple[str, ...] = tuple(node_attrs)
163
164
  self._mg_node_attrs: List[str] = node_attrs
165
+ if self.backend == "nauty":
166
+ self.nauty = NautyCanonicalizer(node_attrs=node_attrs, edge_attrs=["order"])
164
167
 
165
168
  # ------------------------------------------------------------------ #
166
169
  # High‑level helpers #
@@ -220,6 +223,8 @@ class GraphCanonicaliser:
220
223
  return self._canon_generic(g)
221
224
  elif self.backend == "wl":
222
225
  return self._canon_wl(g)
226
+ elif self.backend == "nauty":
227
+ return self._canon_nauty(g)
223
228
  else:
224
229
  return canon_morgan(
225
230
  g, morgan_radius=self._mg_k, node_attributes=self._mg_node_attrs
@@ -228,6 +233,9 @@ class GraphCanonicaliser:
228
233
  # self._canon_generic(g) if self.backend == "generic" else self._canon_wl(g)
229
234
  # )
230
235
 
236
+ def _canon_nauty(self, g: nx.Graph) -> nx.Graph:
237
+ return self.nauty.canonical_form(g)
238
+
231
239
  def _canon_generic(self, g: nx.Graph) -> nx.Graph:
232
240
  """Pure attribute‑sort strategy – O(|V| log |V| + |E| log |E|)."""
233
241
  nodes_sorted = sorted(g.nodes(data=True), key=lambda x: self._node_key(*x))
@@ -274,6 +282,7 @@ class GraphCanonicaliser:
274
282
  wl_hash = _wl_hashes(
275
283
  g2,
276
284
  node_attr=node_attr,
285
+ edge_attr="order",
277
286
  iterations=self._wl_k,
278
287
  )
279
288