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,537 @@
1
+ from __future__ import annotations
2
+
3
+ from collections import Counter
4
+ from contextlib import contextmanager
5
+ import heapq
6
+ from typing import Any, Dict, Generator, List, Optional, Sequence, Tuple, Iterator
7
+
8
+ import networkx as nx
9
+
10
+ NodeSig = Counter # Counter[str, int]
11
+ EdgeSig = Counter # Counter[str, int]
12
+ DegSig = Counter # Counter[int, int]
13
+ TieTuple = Tuple[Any, ...]
14
+
15
+
16
+ class WLSel:
17
+ """WL-based selector for pairing two lists of graphs.
18
+
19
+ :param fw: Forward graphs (indices form first element of pairs).
20
+ :type fw: Sequence[nx.Graph]
21
+ :param bw: Backward graphs (indices form second element of pairs).
22
+ :type bw: Sequence[nx.Graph]
23
+ :param element_key: Node attribute name used to detect wildcard nodes. Nodes with
24
+ ``data[element_key] == "*"`` are removed from the core. If None,
25
+ no wildcard filtering is applied.
26
+ :type element_key: str or None
27
+ :param node_attrs: Node attributes used to build base labels. If provided, the base
28
+ label for a node is ``str(tuple(data[k] for k in node_attrs))``.
29
+ If empty and element_key is provided, the element value is used.
30
+ If both are empty/None, node degree is used as base label.
31
+ :type node_attrs: sequence of str or None
32
+ :param edge_attrs: Edge attributes used inside WL neighbor signatures. If multiple keys
33
+ are provided, temporary edge tuples are formed internally.
34
+ :type edge_attrs: sequence of str or None
35
+ :param wl_iters: WL refinement iterations (0 disables WL, uses base labels).
36
+ :type wl_iters: int
37
+ :param min_score: Minimum score (0..1) for pairs to be kept by default in scoring.
38
+ :type min_score: float
39
+ :param node_weight: Weight for node-overlap in final score (size-sim gets 1-node_weight).
40
+ :type node_weight: float
41
+
42
+ .. rubric:: Notes
43
+
44
+ - Use :meth:`build_signatures` then :meth:`score_pairs`.
45
+ - Results available via :attr:`pair_scores` and :attr:`pair_indices`.
46
+ """
47
+
48
+ def __init__(
49
+ self,
50
+ fw: Sequence[nx.Graph],
51
+ bw: Sequence[nx.Graph],
52
+ element_key: Optional[str] = "element",
53
+ node_attrs: Optional[Sequence[str]] = None,
54
+ edge_attrs: Optional[Sequence[str]] = None,
55
+ wl_iters: int = 1,
56
+ min_score: float = 0.8,
57
+ node_weight: float = 0.85,
58
+ ) -> None:
59
+ self._fw = list(fw)
60
+ self._bw = list(bw)
61
+
62
+ self.element_key = element_key
63
+ self.node_attrs = list(node_attrs) if node_attrs else []
64
+ self.edge_attrs = list(edge_attrs) if edge_attrs else []
65
+
66
+ self.wl_iters = max(0, int(wl_iters))
67
+ self.min_score = float(min_score)
68
+ self.node_weight = float(node_weight)
69
+
70
+ # cached per-graph signatures
71
+ self._fw_node_sigs: Dict[int, NodeSig] = {}
72
+ self._bw_node_sigs: Dict[int, NodeSig] = {}
73
+ self._fw_edge_sigs: Dict[int, EdgeSig] = {}
74
+ self._bw_edge_sigs: Dict[int, EdgeSig] = {}
75
+ self._fw_deg_sigs: Dict[int, DegSig] = {}
76
+ self._bw_deg_sigs: Dict[int, DegSig] = {}
77
+ self._fw_sizes: Dict[int, int] = {}
78
+ self._bw_sizes: Dict[int, int] = {}
79
+
80
+ self._signatures_built = False
81
+
82
+ # scored pair storage: list of (i, j, primary_score, tie_tuple)
83
+ self._pair_scores: List[Tuple[int, int, float, TieTuple]] = []
84
+ self._pairs: List[Tuple[int, int]] = []
85
+ self._pair_candidate_count = 0
86
+
87
+ # ---------------- fluent API ----------------
88
+ def build_signatures(self) -> "WLSel":
89
+ """
90
+ Build WL-based node label multisets, edge multisets and degree multisets.
91
+ Returns self for fluent usage.
92
+ """
93
+ self._fw_node_sigs.clear()
94
+ self._bw_node_sigs.clear()
95
+ self._fw_edge_sigs.clear()
96
+ self._bw_edge_sigs.clear()
97
+ self._fw_deg_sigs.clear()
98
+ self._bw_deg_sigs.clear()
99
+ self._fw_sizes.clear()
100
+ self._bw_sizes.clear()
101
+
102
+ for idx, g in enumerate(self._fw):
103
+ core = self._core_subgraph(g)
104
+ labels = self._wl_node_labels(core)
105
+ self._fw_node_sigs[idx] = Counter(labels)
106
+ self._fw_edge_sigs[idx] = self._edge_signature(core)
107
+ self._fw_deg_sigs[idx] = Counter(d for _, d in core.degree())
108
+ self._fw_sizes[idx] = core.number_of_nodes()
109
+
110
+ for idx, g in enumerate(self._bw):
111
+ core = self._core_subgraph(g)
112
+ labels = self._wl_node_labels(core)
113
+ self._bw_node_sigs[idx] = Counter(labels)
114
+ self._bw_edge_sigs[idx] = self._edge_signature(core)
115
+ self._bw_deg_sigs[idx] = Counter(d for _, d in core.degree())
116
+ self._bw_sizes[idx] = core.number_of_nodes()
117
+
118
+ self._signatures_built = True
119
+ return self
120
+
121
+ def score_pairs(
122
+ self,
123
+ top_k: Optional[int] = None,
124
+ require_label_exact: bool = False,
125
+ ) -> "WLSel":
126
+ """Score all fw–bw pairs using WL-overlap + size similarity.
127
+
128
+ :param top_k: If provided, keep only top_k pairs after sorting.
129
+ :type top_k: int or None
130
+ :param require_label_exact: If True, keep only pairs whose WL label multisets are identical.
131
+ :type require_label_exact: bool
132
+
133
+ :return: self (pairs stored in .pair_scores and .pair_indices).
134
+ :rtype: WLSel
135
+ """
136
+ if not self._signatures_built:
137
+ self.build_signatures()
138
+
139
+ scored: List[Tuple[int, int, float, TieTuple]] = []
140
+ bounded = top_k is not None
141
+ limit = 0 if top_k is None else max(0, int(top_k))
142
+ heap: list[
143
+ tuple[
144
+ tuple[Any, ...],
145
+ tuple[int, int, float, TieTuple],
146
+ ]
147
+ ] = []
148
+ candidate_count = 0
149
+ w_node = self.node_weight
150
+ min_sc = self.min_score
151
+
152
+ for i, sig1 in self._fw_node_sigs.items():
153
+ n1 = self._fw_sizes.get(i, 0)
154
+ e1 = self._fw_edge_sigs.get(i, Counter())
155
+ deg1 = self._fw_deg_sigs.get(i, Counter())
156
+ for j, sig2 in self._bw_node_sigs.items():
157
+ n2 = self._bw_sizes.get(j, 0)
158
+ e2 = self._bw_edge_sigs.get(j, Counter())
159
+ deg2 = self._bw_deg_sigs.get(j, Counter())
160
+
161
+ node_overlap = self._overlap_counters(sig1, sig2)
162
+ size_sim = self._size_similarity(n1, n2)
163
+ primary = w_node * node_overlap + (1.0 - w_node) * size_sim
164
+
165
+ if primary < min_sc:
166
+ continue
167
+
168
+ if require_label_exact and sig1 != sig2:
169
+ continue
170
+
171
+ # tie breakers (higher is better)
172
+ label_exact = 1 if sig1 == sig2 else 0
173
+ edge_overlap = (
174
+ self._overlap_counters(e1, e2) if self.edge_attrs else 0.0
175
+ )
176
+ degree_overlap = self._overlap_counters(deg1, deg2)
177
+ unique_label_overlap = self._unique_label_overlap(sig1, sig2)
178
+
179
+ tie_tuple: TieTuple = (
180
+ label_exact,
181
+ edge_overlap,
182
+ degree_overlap,
183
+ unique_label_overlap,
184
+ )
185
+
186
+ record = (i, j, primary, tie_tuple)
187
+ candidate_count += 1
188
+ if not bounded:
189
+ scored.append(record)
190
+ elif limit:
191
+ # Higher score/tie is better; lower input indices retain
192
+ # the stable ordering used by the former full sort.
193
+ rank = (primary, tie_tuple, -i, -j)
194
+ entry = (rank, record)
195
+ if len(heap) < limit:
196
+ heapq.heappush(heap, entry)
197
+ elif rank > heap[0][0]:
198
+ heapq.heapreplace(heap, entry)
199
+
200
+ # sort by primary then tie_tuple (descending)
201
+ if bounded:
202
+ scored = [record for _, record in heap]
203
+ scored.sort(key=lambda t: (t[2], t[3], -t[0], -t[1]), reverse=True)
204
+ else:
205
+ scored.sort(key=lambda t: (t[2], t[3]), reverse=True)
206
+
207
+ self._pair_candidate_count = candidate_count
208
+ self._pair_scores = scored
209
+ self._pairs = [(i, j) for (i, j, _, _) in scored]
210
+ return self
211
+
212
+ # ---------------- accessors ----------------
213
+ @property
214
+ def pair_scores(self) -> List[Tuple[int, int, float, TieTuple]]:
215
+ """Return scored pairs as (i, j, primary_score, tie_tuple)."""
216
+ return list(self._pair_scores)
217
+
218
+ @property
219
+ def pair_indices(self) -> List[Tuple[int, int]]:
220
+ """Return list of pair indices (i, j) in sorted order."""
221
+ return list(self._pairs)
222
+
223
+ @property
224
+ def pair_candidate_count(self) -> int:
225
+ """Return the number of qualifying pairs before a top-k bound."""
226
+ return self._pair_candidate_count
227
+
228
+ def candidate_pairs(
229
+ self, max_pairs: Optional[int] = None
230
+ ) -> Generator[Tuple[int, int], None, None]:
231
+ """
232
+ Yield candidate index pairs (i, j). If scoring hasn't been run, it will
233
+ be invoked with default settings.
234
+ """
235
+ if not self._pairs:
236
+ self.score_pairs()
237
+
238
+ if max_pairs is None:
239
+ for i, j in self._pairs:
240
+ yield (i, j)
241
+ else:
242
+ for i, j in self._pairs[: int(max_pairs)]:
243
+ yield (i, j)
244
+
245
+ def filter_best_pairs(
246
+ self, top_k: int = 1, min_score: Optional[float] = None
247
+ ) -> "WLSel":
248
+ """
249
+ Keep only the best `top_k` pairs (by current ordering) and optionally
250
+ enforce a minimum primary score. Returns self.
251
+ """
252
+ if not self._pair_scores:
253
+ self.score_pairs()
254
+
255
+ threshold = float(min_score) if min_score is not None else -1.0
256
+ filtered: List[Tuple[int, int, float, TieTuple]] = []
257
+ for i, j, sc, tie in self._pair_scores:
258
+ if sc >= threshold:
259
+ filtered.append((i, j, sc, tie))
260
+ if top_k > 0:
261
+ filtered = filtered[:top_k]
262
+
263
+ self._pair_scores = filtered
264
+ self._pairs = [(i, j) for (i, j, _, _) in filtered]
265
+ return self
266
+
267
+ # ---------------- internal helpers ----------------
268
+ def _core_subgraph(self, g: nx.Graph) -> nx.Graph:
269
+ """Return induced subgraph with wildcard nodes removed."""
270
+ if self.element_key is None:
271
+ return g
272
+ key = self.element_key
273
+ keep = [n for n, d in g.nodes(data=True) if d.get(key) not in ("*", ("*", "*"))]
274
+ return g.subgraph(keep)
275
+
276
+ def _base_labels(self, g: nx.Graph) -> List[str]:
277
+ """Build base labels for nodes in graph g (in g.nodes() order)."""
278
+ labels: List[str] = []
279
+
280
+ if self.node_attrs:
281
+ keys = self.node_attrs
282
+ for _, data in g.nodes(data=True):
283
+ vals = tuple(data.get(k) for k in keys)
284
+ labels.append(str(vals))
285
+ return labels
286
+
287
+ if self.element_key is not None:
288
+ key = self.element_key
289
+ for _, data in g.nodes(data=True):
290
+ labels.append(str(data.get(key, "X")))
291
+ return labels
292
+
293
+ for n in g.nodes():
294
+ labels.append(str(g.degree[n]))
295
+ return labels
296
+
297
+ # -------- WL label plumbing (refactored) --------
298
+ def _wl_node_labels(self, g: nx.Graph) -> List[str]:
299
+ """
300
+ Return WL-refined labels.
301
+
302
+ Strategy:
303
+ - If empty graph or wl_iters <= 0 -> base labels.
304
+ - Prefer networkx WL node hashes when available.
305
+ - Otherwise fall back to local deterministic WL.
306
+ """
307
+ if g.number_of_nodes() == 0 or self.wl_iters <= 0:
308
+ return self._base_labels(g)
309
+
310
+ nx_wl = self._nx_wl_hashes()
311
+ if nx_wl is None:
312
+ return self._local_wl_node_labels(g, iters=self.wl_iters)
313
+
314
+ node_attr_arg, edge_attr_arg = self._resolve_wl_attr_args()
315
+
316
+ # Combined-attribute keys are an implementation detail. Work on a
317
+ # copy so existing user attributes with the same names are neither
318
+ # overwritten nor removed, including when ``g`` is a subgraph view.
319
+ working_graph = (
320
+ g.copy()
321
+ if node_attr_arg == "__TEMP_NODE__" or edge_attr_arg == "__TEMP_EDGE__"
322
+ else g
323
+ )
324
+
325
+ with self._inject_temp_attrs(
326
+ working_graph,
327
+ node_attr_arg=node_attr_arg,
328
+ edge_attr_arg=edge_attr_arg,
329
+ ) as (node_attr_final, edge_attr_final):
330
+ node_hash_dict = nx_wl(
331
+ working_graph,
332
+ node_attr=node_attr_final,
333
+ edge_attr=edge_attr_final,
334
+ iterations=self.wl_iters,
335
+ include_initial_labels=False,
336
+ )
337
+
338
+ return self._labels_from_nx_hash_dict(working_graph, node_hash_dict)
339
+
340
+ def _nx_wl_hashes(self):
341
+ """Return networkx WL-hash function if available, else None."""
342
+ try:
343
+ from networkx.algorithms.graph_hashing import (
344
+ weisfeiler_lehman_subgraph_hashes,
345
+ )
346
+ except Exception:
347
+ return None
348
+ return weisfeiler_lehman_subgraph_hashes
349
+
350
+ def _resolve_wl_attr_args(self) -> Tuple[Optional[str], Optional[str]]:
351
+ """Decide which node_attr and edge_attr keys to use for networkx WL.
352
+
353
+ :return: These may be:
354
+ - a real attribute key,
355
+ - the special sentinel "__TEMP__" meaning "needs temp injection",
356
+ - or None.
357
+ :rtype: (node_attr_arg, edge_attr_arg)
358
+ """
359
+ node_attr_arg: Optional[str]
360
+ edge_attr_arg: Optional[str]
361
+
362
+ # Node attributes resolution
363
+ if self.node_attrs and len(self.node_attrs) > 1:
364
+ node_attr_arg = "__TEMP_NODE__"
365
+ elif self.node_attrs:
366
+ node_attr_arg = self.node_attrs[0]
367
+ elif self.element_key is not None:
368
+ node_attr_arg = self.element_key
369
+ else:
370
+ node_attr_arg = None
371
+
372
+ # Edge attributes resolution
373
+ if self.edge_attrs and len(self.edge_attrs) > 1:
374
+ edge_attr_arg = "__TEMP_EDGE__"
375
+ elif self.edge_attrs:
376
+ edge_attr_arg = self.edge_attrs[0]
377
+ else:
378
+ edge_attr_arg = None
379
+
380
+ return node_attr_arg, edge_attr_arg
381
+
382
+ @contextmanager
383
+ def _inject_temp_attrs(
384
+ self,
385
+ g: nx.Graph,
386
+ *,
387
+ node_attr_arg: Optional[str],
388
+ edge_attr_arg: Optional[str],
389
+ ) -> Iterator[Tuple[Optional[str], Optional[str]]]:
390
+ """Context manager that injects temporary combined attrs if needed.
391
+
392
+ If node_attr_arg is "__TEMP_NODE__", we create "__wl_node_temp__".
393
+ If edge_attr_arg is "__TEMP_EDGE__", we create "__wl_edge_temp__".
394
+
395
+ :yield: The actual node and edge attribute names passed to NetworkX WL.
396
+ :ytype: tuple[Optional[str], Optional[str]]
397
+ """
398
+ node_temp_key: Optional[str] = None
399
+ edge_temp_key: Optional[str] = None
400
+
401
+ node_attr_final = node_attr_arg
402
+ edge_attr_final = edge_attr_arg
403
+
404
+ try:
405
+ # Inject combined node attribute
406
+ if node_attr_arg == "__TEMP_NODE__":
407
+ node_temp_key = "__wl_node_temp__"
408
+ keys = self.node_attrs
409
+ for n, data in g.nodes(data=True):
410
+ data[node_temp_key] = str(tuple(data.get(k) for k in keys))
411
+ node_attr_final = node_temp_key
412
+
413
+ # Inject combined edge attribute
414
+ if edge_attr_arg == "__TEMP_EDGE__":
415
+ edge_temp_key = "__wl_edge_temp__"
416
+ keys = self.edge_attrs
417
+ for u, v, data in g.edges(data=True):
418
+ data[edge_temp_key] = str(tuple(data.get(k) for k in keys))
419
+ edge_attr_final = edge_temp_key
420
+
421
+ yield (node_attr_final, edge_attr_final)
422
+
423
+ finally:
424
+ # Cleanup injected attrs
425
+ if node_temp_key is not None:
426
+ for _, data in g.nodes(data=True):
427
+ data.pop(node_temp_key, None)
428
+ if edge_temp_key is not None:
429
+ for _, _, data in g.edges(data=True):
430
+ data.pop(edge_temp_key, None)
431
+
432
+ def _labels_from_nx_hash_dict(
433
+ self,
434
+ g: nx.Graph,
435
+ node_hash_dict: Dict[Any, List[str]],
436
+ ) -> List[str]:
437
+ """
438
+ Convert networkx WL hash dict to labels in g.nodes() order.
439
+ """
440
+ last_idx = max(0, self.wl_iters - 1)
441
+ labels: List[str] = []
442
+
443
+ for n in g.nodes():
444
+ hashes = node_hash_dict.get(n, [])
445
+ if not hashes:
446
+ labels.append(str(g.degree[n]))
447
+ continue
448
+
449
+ # Prefer the requested iteration index when available
450
+ if last_idx < len(hashes):
451
+ labels.append(hashes[last_idx])
452
+ else:
453
+ labels.append(hashes[-1])
454
+
455
+ return labels
456
+
457
+ # -------- Local WL remains unchanged --------
458
+ def _local_wl_node_labels(self, g: nx.Graph, iters: int = 1) -> List[str]:
459
+ """
460
+ Canonical local WL refinement (deterministic token assignment).
461
+ Returns labels in g.nodes() order.
462
+ """
463
+ base = self._base_labels(g)
464
+ curr: Dict[Any, str] = {n: base[idx] for idx, n in enumerate(g.nodes())}
465
+ num_iter = max(0, int(iters))
466
+ edge_keys = self.edge_attrs
467
+
468
+ for _ in range(num_iter):
469
+ struct: Dict[Any, str] = {}
470
+ for n in g.nodes():
471
+ neigh = []
472
+ for m in g.neighbors(n):
473
+ token = curr[m]
474
+ if edge_keys:
475
+ e_data = g.get_edge_data(n, m, default={})
476
+ e_vals = tuple(e_data.get(k) for k in edge_keys)
477
+ token = f"{token}|{e_vals}"
478
+ neigh.append(token)
479
+ neigh.sort()
480
+ struct[n] = f"{curr[n]}|{'-'.join(neigh)}"
481
+
482
+ unique = sorted(set(struct.values()))
483
+ token_map = {s: f"t{idx}" for idx, s in enumerate(unique)}
484
+ curr = {n: token_map[struct[n]] for n in g.nodes()}
485
+
486
+ return [curr[n] for n in g.nodes()]
487
+
488
+ # -------- Other helpers unchanged --------
489
+ def _edge_signature(self, g: nx.Graph) -> EdgeSig:
490
+ """Build multiset of edge labels for graph g (stringified tuples)."""
491
+ if not self.edge_attrs:
492
+ return Counter()
493
+ keys = self.edge_attrs
494
+ labels = []
495
+ for _, _, data in g.edges(data=True):
496
+ vals = tuple(data.get(k) for k in keys)
497
+ labels.append(str(vals))
498
+ return Counter(labels)
499
+
500
+ @staticmethod
501
+ def _overlap_counters(c1: Counter, c2: Counter) -> float:
502
+ """Return min-sum overlap normalized by min(total1, total2)."""
503
+ t1 = sum(c1.values())
504
+ t2 = sum(c2.values())
505
+ if t1 == 0 or t2 == 0:
506
+ return 0.0
507
+ inter = sum(min(c1.get(k, 0), c2.get(k, 0)) for k in set(c1) | set(c2))
508
+ return inter / min(t1, t2)
509
+
510
+ @staticmethod
511
+ def _size_similarity(n1: int, n2: int) -> float:
512
+ """Return size similarity in [0,1]."""
513
+ if n1 == 0 and n2 == 0:
514
+ return 1.0
515
+ if n1 == 0 or n2 == 0:
516
+ return 0.0
517
+ max_n = max(n1, n2)
518
+ return max(0.0, 1.0 - abs(n1 - n2) / max_n)
519
+
520
+ @staticmethod
521
+ def _unique_label_overlap(c1: Counter, c2: Counter) -> float:
522
+ u1 = set(c1.keys())
523
+ u2 = set(c2.keys())
524
+ if not u1 and not u2:
525
+ return 1.0
526
+ if not u1 or not u2:
527
+ return 0.0
528
+ inter = len(u1 & u2)
529
+ denom = min(len(u1), len(u2))
530
+ return inter / denom
531
+
532
+ def __repr__(self) -> str:
533
+ return (
534
+ f"<WLSel fw={len(self._fw)} bw={len(self._bw)} "
535
+ f"wl_iters={self.wl_iters} node_attrs={self.node_attrs} "
536
+ f"edge_attrs={self.edge_attrs} min_score={self.min_score:.2f}>"
537
+ )
@@ -0,0 +1,26 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ if TYPE_CHECKING:
6
+ from synkit.Graph.Mech.lwg_editor import LWGEditResult, LWGEditor, LWGStepReport
7
+
8
+ __all__ = ["LWGEditor", "LWGEditResult", "LWGStepReport"]
9
+
10
+
11
+ def __getattr__(name: str):
12
+ if name in __all__:
13
+ from synkit.Graph.Mech.lwg_editor import (
14
+ LWGEditResult,
15
+ LWGEditor,
16
+ LWGStepReport,
17
+ )
18
+
19
+ exports = {
20
+ "LWGEditor": LWGEditor,
21
+ "LWGEditResult": LWGEditResult,
22
+ "LWGStepReport": LWGStepReport,
23
+ }
24
+ return exports[name]
25
+
26
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")