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,719 @@
1
+ import networkx as nx
2
+ from typing import Tuple, Dict, Any, Optional, List, Hashable
3
+ from copy import deepcopy
4
+
5
+
6
+ class ITSConstruction:
7
+ """
8
+ Utility class for constructing an ITS graph from two input graphs.
9
+
10
+ Nodes store paired state information through the ``typesGH`` attribute.
11
+ Edges store direct paired attributes such as ``order=(g, h)`` without
12
+ an edge-level ``typesGH``.
13
+
14
+ The main public entry point is :meth:`construct`.
15
+ """
16
+
17
+ CORE_NODE_DEFAULTS: Dict[str, Any] = {
18
+ "element": "*",
19
+ "charge": 0,
20
+ "atom_map": 0,
21
+ "hcount": 0,
22
+ "aromatic": False,
23
+ "neighbors": lambda: ["", ""],
24
+ "partial_charge": 0,
25
+ "hybridization": "",
26
+ "lone_pairs": 0,
27
+ "radical": 0,
28
+ "valence_electrons": 0,
29
+ }
30
+
31
+ CORE_EDGE_DEFAULTS: Dict[str, Any] = {
32
+ "order": 0.0,
33
+ "kekule_order": 0.0,
34
+ "sigma_order": 0.0,
35
+ "pi_order": 0.0,
36
+ "ez_isomer": "",
37
+ "bond_type": "",
38
+ "conjugated": False,
39
+ "in_ring": False,
40
+ }
41
+
42
+ @staticmethod
43
+ def _resolve_defaults(
44
+ user_defaults: Optional[Dict[str, Any]], core_defaults: Dict[str, Any]
45
+ ) -> Dict[str, Any]:
46
+ """Merge user-provided defaults with built-in defaults.
47
+
48
+ :param user_defaults:
49
+ Optional mapping of user overrides.
50
+ :type user_defaults: Optional[Dict[str, Any]]
51
+ :param core_defaults:
52
+ Built-in defaults. Callable values are treated as factories.
53
+ :type core_defaults: Dict[str, Any]
54
+
55
+ :return:
56
+ Resolved defaults with fresh copies for mutable values.
57
+ :rtype: Dict[str, Any]
58
+ """
59
+ resolved: Dict[str, Any] = {}
60
+ user_defaults = user_defaults or {}
61
+
62
+ for key, core_val in core_defaults.items():
63
+ if key in user_defaults:
64
+ resolved[key] = deepcopy(user_defaults[key])
65
+ elif callable(core_val):
66
+ resolved[key] = core_val()
67
+ else:
68
+ resolved[key] = deepcopy(core_val)
69
+
70
+ return resolved
71
+
72
+ @staticmethod
73
+ def _compute_standard_order(
74
+ its: nx.Graph, ignore_aromaticity: bool = False
75
+ ) -> None:
76
+ """
77
+ Compute ``standard_order`` for each edge from ``order=(g, h)``.
78
+
79
+ :param its:
80
+ ITS graph whose edges contain an ``order`` tuple.
81
+ :type its: nx.Graph
82
+ :param ignore_aromaticity:
83
+ If ``True``, absolute differences smaller than ``1`` are set to ``0``.
84
+ :type ignore_aromaticity: bool
85
+ """
86
+ for u, v, data in its.edges(data=True):
87
+ order_tuple = data.get("order", (0.0, 0.0))
88
+ try:
89
+ o_g, o_h = order_tuple
90
+ except Exception:
91
+ o_g, o_h = 0.0, 0.0
92
+
93
+ standard_order = o_g - o_h
94
+ if ignore_aromaticity and abs(standard_order) < 1:
95
+ standard_order = 0
96
+
97
+ its[u][v]["standard_order"] = standard_order
98
+
99
+ @staticmethod
100
+ def _select_base_graph(G: nx.Graph, H: nx.Graph, balance_its: bool) -> nx.Graph:
101
+ """Select the base graph used to initialize the ITS graph.
102
+
103
+ :param G:
104
+ First input graph.
105
+ :type G: nx.Graph
106
+ :param H:
107
+ Second input graph.
108
+ :type H: nx.Graph
109
+ :param balance_its:
110
+ If ``True``, prefer the smaller graph; otherwise prefer the larger.
111
+ :type balance_its: bool
112
+
113
+ :return:
114
+ Selected base graph.
115
+ :rtype: nx.Graph
116
+ """
117
+ if (balance_its and len(G.nodes) <= len(H.nodes)) or (
118
+ not balance_its and len(G.nodes) >= len(H.nodes)
119
+ ):
120
+ return G
121
+ return H
122
+
123
+ @staticmethod
124
+ def _initialize_its(base: nx.Graph) -> nx.Graph:
125
+ """Copy the base graph and remove all edges.
126
+
127
+ :param base:
128
+ Graph chosen as ITS initialization template.
129
+ :type base: nx.Graph
130
+
131
+ :return:
132
+ Edge-free copy of the base graph.
133
+ :rtype: nx.Graph
134
+ """
135
+ its = base.copy()
136
+ its.remove_edges_from(list(its.edges()))
137
+ return its
138
+
139
+ @staticmethod
140
+ def _ensure_union_nodes(its: nx.Graph, G: nx.Graph, H: nx.Graph) -> None:
141
+ """
142
+ Ensure the ITS graph contains the union of nodes from both input graphs.
143
+
144
+ :param its:
145
+ ITS graph to update in place.
146
+ :type its: nx.Graph
147
+ :param G:
148
+ First input graph.
149
+ :type G: nx.Graph
150
+ :param H:
151
+ Second input graph.
152
+ :type H: nx.Graph
153
+ """
154
+ all_nodes = set(G.nodes()) | set(H.nodes())
155
+ for n in all_nodes:
156
+ if n in its:
157
+ continue
158
+
159
+ source_attrs: Dict[str, Any] = {}
160
+ if n in G:
161
+ source_attrs = deepcopy(G.nodes[n])
162
+ elif n in H:
163
+ source_attrs = deepcopy(H.nodes[n])
164
+
165
+ its.add_node(n, **source_attrs)
166
+
167
+ @staticmethod
168
+ def _build_node_side_tuple(
169
+ graph: nx.Graph,
170
+ node: Hashable,
171
+ attrs: List[str],
172
+ defaults: Dict[str, Any],
173
+ ) -> Tuple[Any, ...]:
174
+ """Build one side of a node tuple for ``typesGH``.
175
+
176
+ :param graph:
177
+ Source graph.
178
+ :type graph: nx.Graph
179
+ :param node:
180
+ Node identifier.
181
+ :type node: Hashable
182
+ :param attrs:
183
+ Ordered node attributes.
184
+ :type attrs: List[str]
185
+ :param defaults:
186
+ Default values for missing attributes.
187
+ :type defaults: Dict[str, Any]
188
+
189
+ :return:
190
+ Attribute tuple for the requested node.
191
+ :rtype: Tuple[Any, ...]
192
+ """
193
+ if node not in graph:
194
+ return tuple(defaults.get(attr) for attr in attrs)
195
+ return tuple(graph.nodes[node].get(attr, defaults.get(attr)) for attr in attrs)
196
+
197
+ @staticmethod
198
+ def _populate_node_attributes(
199
+ its: nx.Graph,
200
+ G: nx.Graph,
201
+ H: nx.Graph,
202
+ node_attrs: List[str],
203
+ node_defaults: Dict[str, Any],
204
+ store: bool,
205
+ ) -> None:
206
+ """
207
+ Populate node-level ``typesGH`` and per-attribute node storage.
208
+
209
+ :param its:
210
+ ITS graph to update in place.
211
+ :type its: nx.Graph
212
+ :param G:
213
+ First input graph.
214
+ :type G: nx.Graph
215
+ :param H:
216
+ Second input graph.
217
+ :type H: nx.Graph
218
+ :param node_attrs:
219
+ Ordered node attributes included in ``typesGH``.
220
+ :type node_attrs: List[str]
221
+ :param node_defaults:
222
+ Default values for missing node attributes.
223
+ :type node_defaults: Dict[str, Any]
224
+ :param store:
225
+ If ``True``, store per-attribute ``(G, H)`` tuples. Otherwise store
226
+ only the ``G``-side value.
227
+ :type store: bool
228
+ """
229
+ for n in its.nodes():
230
+ g_tuple = ITSConstruction._build_node_side_tuple(
231
+ G, n, node_attrs, node_defaults
232
+ )
233
+ h_tuple = ITSConstruction._build_node_side_tuple(
234
+ H, n, node_attrs, node_defaults
235
+ )
236
+
237
+ its.nodes[n]["typesGH"] = (g_tuple, h_tuple)
238
+ its.nodes[n]["present"] = (n in G, n in H)
239
+
240
+ for i, attr in enumerate(node_attrs):
241
+ its.nodes[n][attr] = (g_tuple[i], h_tuple[i]) if store else g_tuple[i]
242
+
243
+ @staticmethod
244
+ def _edge_keys(G: nx.Graph, H: nx.Graph) -> List[Tuple[Hashable, Hashable]]:
245
+ """Compute the union of undirected edges from ``G`` and ``H``.
246
+
247
+ :param G:
248
+ First input graph.
249
+ :type G: nx.Graph
250
+ :param H:
251
+ Second input graph.
252
+ :type H: nx.Graph
253
+
254
+ :return:
255
+ List of unique edge pairs.
256
+ :rtype: List[Tuple[Hashable, Hashable]]
257
+ """
258
+ edge_keys = {frozenset((u, v)) for u, v in G.edges()} | {
259
+ frozenset((u, v)) for u, v in H.edges()
260
+ }
261
+ return [tuple(fs) for fs in edge_keys]
262
+
263
+ @staticmethod
264
+ def _build_edge_pair_data(
265
+ G: nx.Graph,
266
+ H: nx.Graph,
267
+ u: Hashable,
268
+ v: Hashable,
269
+ edge_attrs: List[str],
270
+ edge_defaults: Dict[str, Any],
271
+ ) -> Dict[str, Any]:
272
+ """Build direct paired edge attributes for one ITS edge.
273
+
274
+ Each requested edge attribute is stored as ``(G_value, H_value)``.
275
+ The ``order`` attribute is always guaranteed to exist.
276
+
277
+ :param G:
278
+ First input graph.
279
+ :type G: nx.Graph
280
+ :param H:
281
+ Second input graph.
282
+ :type H: nx.Graph
283
+ :param u:
284
+ First edge endpoint.
285
+ :type u: Hashable
286
+ :param v:
287
+ Second edge endpoint.
288
+ :type v: Hashable
289
+ :param edge_attrs:
290
+ Edge attributes to store as paired tuples.
291
+ :type edge_attrs: List[str]
292
+ :param edge_defaults:
293
+ Default values for missing edge attributes.
294
+ :type edge_defaults: Dict[str, Any]
295
+
296
+ :return:
297
+ Edge attribute mapping for ITS storage.
298
+ :rtype: Dict[str, Any]
299
+ """
300
+ g_edge = G[u][v] if G.has_edge(u, v) else {}
301
+ h_edge = H[u][v] if H.has_edge(u, v) else {}
302
+
303
+ edge_data: Dict[str, Any] = {}
304
+ for attr in edge_attrs:
305
+ default = edge_defaults.get(attr)
306
+ g_val = g_edge.get(attr, default)
307
+ h_val = h_edge.get(attr, default)
308
+ edge_data[attr] = (g_val, h_val)
309
+
310
+ if "order" not in edge_data:
311
+ g_order = g_edge.get("order", edge_defaults.get("order", 0.0))
312
+ h_order = h_edge.get("order", edge_defaults.get("order", 0.0))
313
+ edge_data["order"] = (g_order, h_order)
314
+
315
+ if "kekule_order" in edge_data:
316
+ g_order = g_edge.get("kekule_order", edge_defaults.get("order", 0.0))
317
+ h_order = h_edge.get("kekule_order", edge_defaults.get("order", 0.0))
318
+ edge_data["kekule_order"] = (g_order, h_order)
319
+
320
+ return edge_data
321
+
322
+ @staticmethod
323
+ def _populate_edge_attributes(
324
+ its: nx.Graph,
325
+ G: nx.Graph,
326
+ H: nx.Graph,
327
+ edge_attrs: List[str],
328
+ edge_defaults: Dict[str, Any],
329
+ ) -> None:
330
+ """
331
+ Populate ITS edges with direct paired edge attributes.
332
+
333
+ :param its:
334
+ ITS graph to update in place.
335
+ :type its: nx.Graph
336
+ :param G:
337
+ First input graph.
338
+ :type G: nx.Graph
339
+ :param H:
340
+ Second input graph.
341
+ :type H: nx.Graph
342
+ :param edge_attrs:
343
+ Edge attributes to store as ``(G, H)`` tuples.
344
+ :type edge_attrs: List[str]
345
+ :param edge_defaults:
346
+ Default values for missing edge attributes.
347
+ :type edge_defaults: Dict[str, Any]
348
+ """
349
+ for u, v in ITSConstruction._edge_keys(G, H):
350
+ edge_data = ITSConstruction._build_edge_pair_data(
351
+ G, H, u, v, edge_attrs, edge_defaults
352
+ )
353
+ its.add_edge(u, v, **edge_data)
354
+
355
+ @staticmethod
356
+ def construct(
357
+ G: nx.Graph,
358
+ H: nx.Graph,
359
+ *,
360
+ ignore_aromaticity: bool = False,
361
+ balance_its: bool = True,
362
+ store: bool = True,
363
+ node_attrs: Optional[List[str]] = None,
364
+ edge_attrs: Optional[List[str]] = None,
365
+ attributes_defaults: Optional[Dict[str, Any]] = None,
366
+ stereo_reference_mappings: Optional[Dict[str, Dict[Any, Any]]] = None,
367
+ transition_graph: Optional[nx.Graph] = None,
368
+ stereo_validation: str = "preserve",
369
+ ) -> nx.Graph:
370
+ """Construct an ITS graph from two input graphs.
371
+
372
+ Nodes store ``typesGH`` as paired tuples over ``node_attrs``.
373
+ Requested edge attributes are stored directly as paired values such as
374
+ ``order=(g, h)`` and ``bond_type=(g, h)``. No edge-level ``typesGH`` is created.
375
+
376
+ :param G:
377
+ First input graph, typically the reactant-side graph.
378
+ :type G: nx.Graph
379
+ :param H:
380
+ Second input graph, typically the product-side graph.
381
+ :type H: nx.Graph
382
+ :param ignore_aromaticity:
383
+ If ``True``, bond-order differences with absolute value smaller than
384
+ ``1`` are treated as zero when computing ``standard_order``.
385
+ :type ignore_aromaticity: bool
386
+ :param balance_its:
387
+ If ``True``, initialize from the smaller graph; otherwise from the larger.
388
+ :type balance_its: bool
389
+ :param store:
390
+ Controls node attribute storage only. If ``True``, node attributes are
391
+ stored as ``(G, H)`` tuples. If ``False``, only the ``G``-side value
392
+ is stored. Edge attributes are always stored as paired tuples.
393
+ :type store: bool
394
+ :param node_attrs:
395
+ Ordered list of node attributes included in node-level ``typesGH``.
396
+ :type node_attrs: Optional[List[str]]
397
+ :param edge_attrs:
398
+ Ordered list of edge attributes stored directly as ``(G, H)`` tuples.
399
+ :type edge_attrs: Optional[List[str]]
400
+ :param attributes_defaults:
401
+ Optional overrides for node attribute defaults.
402
+ :type attributes_defaults: Optional[Dict[str, Any]]
403
+ :param stereo_reference_mappings:
404
+ Explicit leaving-to-entering ligand maps keyed by stereo target.
405
+ A unique single replacement is inferred when omitted; multiple
406
+ replacements require this mapping.
407
+ :type stereo_reference_mappings: Optional[Dict[str, Dict[Any, Any]]]
408
+ :param transition_graph:
409
+ Optional graph carrying transition-only/fleeting descriptors.
410
+ :type transition_graph: Optional[nx.Graph]
411
+ :param stereo_validation:
412
+ ``"preserve"`` keeps graph-only descriptors for compatibility.
413
+ ``"strict"`` validates endpoint/transition support before ITS
414
+ construction and rejects dangling or stale references.
415
+ :type stereo_validation: str
416
+
417
+ :return:
418
+ ITS graph with merged nodes, paired node/edge annotations, and
419
+ derived ``standard_order``.
420
+ :rtype: nx.Graph
421
+
422
+ .. rubric:: Example
423
+
424
+ .. code-block:: python
425
+
426
+ node_attrs = [
427
+ "element",
428
+ "aromatic",
429
+ "hcount",
430
+ "charge",
431
+ "neighbors",
432
+ "hybridization",
433
+ "atom_map",
434
+ "lone_pairs",
435
+ ]
436
+
437
+ edge_attrs = [
438
+ "kekule_order",
439
+ "order",
440
+ "bond_type",
441
+ "conjugated",
442
+ "in_ring",
443
+ ]
444
+
445
+ its = ITSConstruction.construct(
446
+ r_graph,
447
+ p_graph,
448
+ node_attrs=node_attrs,
449
+ edge_attrs=edge_attrs,
450
+ store=True,
451
+ )
452
+
453
+ print(its.edges[12, 30]["order"])
454
+ print(its.edges[12, 30]["bond_type"])
455
+ print(its.edges[12, 30]["standard_order"])
456
+ """
457
+ if stereo_validation not in {"preserve", "strict"}:
458
+ raise ValueError("stereo_validation must be 'preserve' or 'strict'.")
459
+ if stereo_validation == "strict":
460
+ from synkit.Graph.ITS.stereo import validate_stereo_support
461
+
462
+ validate_stereo_support(G, side="reactant")
463
+ validate_stereo_support(H, side="product")
464
+ if transition_graph is not None:
465
+ validate_stereo_support(
466
+ transition_graph,
467
+ side="transition",
468
+ )
469
+
470
+ node_attrs = node_attrs or [
471
+ "element",
472
+ "aromatic",
473
+ "hcount",
474
+ "charge",
475
+ "neighbors",
476
+ "lone_pairs",
477
+ "radical",
478
+ "valence_electrons",
479
+ ]
480
+ edge_attrs = edge_attrs or [
481
+ "order",
482
+ "kekule_order",
483
+ "sigma_order",
484
+ "pi_order",
485
+ ]
486
+
487
+ node_defaults = ITSConstruction._resolve_defaults(
488
+ attributes_defaults, ITSConstruction.CORE_NODE_DEFAULTS
489
+ )
490
+ edge_defaults = ITSConstruction._resolve_defaults(
491
+ None, ITSConstruction.CORE_EDGE_DEFAULTS
492
+ )
493
+
494
+ base = ITSConstruction._select_base_graph(G, H, balance_its)
495
+ its = ITSConstruction._initialize_its(base)
496
+
497
+ ITSConstruction._ensure_union_nodes(its, G, H)
498
+ ITSConstruction._populate_node_attributes(
499
+ its, G, H, node_attrs, node_defaults, store
500
+ )
501
+ ITSConstruction._populate_edge_attributes(its, G, H, edge_attrs, edge_defaults)
502
+ ITSConstruction._compute_standard_order(
503
+ its, ignore_aromaticity=ignore_aromaticity
504
+ )
505
+ try:
506
+ from synkit.Graph.Stereo import annotate_its_stereo
507
+
508
+ annotate_its_stereo(
509
+ its,
510
+ G,
511
+ H,
512
+ transition_graph,
513
+ reference_mappings=stereo_reference_mappings,
514
+ )
515
+ except ImportError:
516
+ pass
517
+ its.graph["stereo_validation"] = stereo_validation
518
+
519
+ return its
520
+
521
+ @staticmethod
522
+ def ITSGraph(
523
+ G: nx.Graph,
524
+ H: nx.Graph,
525
+ ignore_aromaticity: bool = False,
526
+ attributes_defaults: Optional[Dict[str, Any]] = None,
527
+ balance_its: bool = False,
528
+ store: bool = False,
529
+ stereo_reference_mappings: Optional[Dict[str, Dict[Any, Any]]] = None,
530
+ transition_graph: Optional[nx.Graph] = None,
531
+ stereo_validation: str = "preserve",
532
+ ) -> nx.Graph:
533
+ """Backward-compatible wrapper around :meth:`construct`.
534
+
535
+ :param G:
536
+ First input graph.
537
+ :type G: nx.Graph
538
+ :param H:
539
+ Second input graph.
540
+ :type H: nx.Graph
541
+ :param ignore_aromaticity:
542
+ If ``True``, small bond-order differences are ignored.
543
+ :type ignore_aromaticity: bool
544
+ :param attributes_defaults:
545
+ Optional node defaults for missing values.
546
+ :type attributes_defaults: Optional[Dict[str, Any]]
547
+ :param balance_its:
548
+ If ``True``, prefer the smaller graph as base.
549
+ :type balance_its: bool
550
+ :param store:
551
+ If ``True``, node attributes are stored as paired tuples.
552
+ :type store: bool
553
+ :param stereo_reference_mappings:
554
+ Optional target-specific endpoint reference transports.
555
+ :type stereo_reference_mappings: Optional[Dict[str, Dict[Any, Any]]]
556
+ :param transition_graph:
557
+ Optional graph carrying transition-only/fleeting descriptors.
558
+ :type transition_graph: Optional[nx.Graph]
559
+ :param stereo_validation:
560
+ ``"preserve"`` or strict support validation.
561
+ :type stereo_validation: str
562
+
563
+ :return:
564
+ Constructed ITS graph using legacy node and edge attribute defaults.
565
+ :rtype: nx.Graph
566
+ """
567
+ return ITSConstruction.construct(
568
+ G,
569
+ H,
570
+ ignore_aromaticity=ignore_aromaticity,
571
+ balance_its=balance_its,
572
+ store=store,
573
+ node_attrs=["element", "aromatic", "hcount", "charge", "neighbors"],
574
+ edge_attrs=["order"],
575
+ attributes_defaults=attributes_defaults,
576
+ stereo_reference_mappings=stereo_reference_mappings,
577
+ transition_graph=transition_graph,
578
+ stereo_validation=stereo_validation,
579
+ )
580
+
581
+ @staticmethod
582
+ def typesGH_info(
583
+ node_attrs: Optional[List[str]] = None, edge_attrs: Optional[List[str]] = None
584
+ ) -> Dict[str, Dict[str, Tuple[type, Any]]]:
585
+ """Provide expected types and defaults for node and edge attributes.
586
+
587
+ :param node_attrs:
588
+ Node attributes expected in node-level ``typesGH``.
589
+ :type node_attrs: Optional[List[str]]
590
+ :param edge_attrs:
591
+ Edge attributes expected as direct paired edge tuples.
592
+ :type edge_attrs: Optional[List[str]]
593
+
594
+ :return:
595
+ Nested mapping describing ``(type, default)`` for each selected attribute.
596
+ :rtype: Dict[str, Dict[str, Tuple[type, Any]]]
597
+ """
598
+ node_attrs = node_attrs or [
599
+ "element",
600
+ "aromatic",
601
+ "hcount",
602
+ "charge",
603
+ "neighbors",
604
+ ]
605
+ edge_attrs = edge_attrs or ["order"]
606
+
607
+ node_prop_types: Dict[str, type] = {
608
+ "element": str,
609
+ "aromatic": bool,
610
+ "hcount": int,
611
+ "charge": int,
612
+ "neighbors": list,
613
+ }
614
+ edge_prop_types: Dict[str, type] = {
615
+ "order": float,
616
+ "ez_isomer": str,
617
+ "bond_type": str,
618
+ "conjugated": bool,
619
+ "in_ring": bool,
620
+ }
621
+
622
+ node_defaults = {
623
+ attr: (
624
+ node_prop_types.get(attr, object),
625
+ (
626
+ ITSConstruction.CORE_NODE_DEFAULTS.get(attr)()
627
+ if callable(ITSConstruction.CORE_NODE_DEFAULTS.get(attr))
628
+ else ITSConstruction.CORE_NODE_DEFAULTS.get(attr)
629
+ ),
630
+ )
631
+ for attr in node_attrs
632
+ }
633
+ edge_defaults = {
634
+ attr: (
635
+ edge_prop_types.get(attr, object),
636
+ ITSConstruction.CORE_EDGE_DEFAULTS.get(attr),
637
+ )
638
+ for attr in edge_attrs
639
+ }
640
+
641
+ return {"node": node_defaults, "edge": edge_defaults}
642
+
643
+ @staticmethod
644
+ def get_node_attribute(
645
+ graph: nx.Graph, node: Hashable, attribute: str, default: Any
646
+ ) -> Any:
647
+ """Retrieve a node attribute or return a default if missing.
648
+
649
+ :param graph:
650
+ Input graph.
651
+ :type graph: nx.Graph
652
+ :param node:
653
+ Node identifier.
654
+ :type node: Hashable
655
+ :param attribute:
656
+ Attribute name.
657
+ :type attribute: str
658
+ :param default:
659
+ Fallback value.
660
+ :type default: Any
661
+
662
+ :return:
663
+ Stored node attribute or fallback default.
664
+ :rtype: Any
665
+ """
666
+ try:
667
+ return graph.nodes[node][attribute]
668
+ except KeyError:
669
+ return default
670
+
671
+ @staticmethod
672
+ def get_node_attributes_with_defaults(
673
+ graph: nx.Graph, node: Hashable, attributes_defaults: Dict[str, Any] = None
674
+ ) -> Tuple:
675
+ """Retrieve multiple node attributes using provided defaults.
676
+
677
+ :param graph:
678
+ Input graph.
679
+ :type graph: nx.Graph
680
+ :param node:
681
+ Node identifier.
682
+ :type node: Hashable
683
+ :param attributes_defaults:
684
+ Mapping from attribute names to fallback values.
685
+ :type attributes_defaults: Optional[Dict[str, Any]]
686
+
687
+ :return:
688
+ Tuple of node attributes in mapping order.
689
+ :rtype: Tuple
690
+
691
+ .. rubric:: Example
692
+
693
+ .. code-block:: python
694
+
695
+ attrs = ITSConstruction.get_node_attributes_with_defaults(
696
+ graph=G,
697
+ node=1,
698
+ attributes_defaults={
699
+ "element": "*",
700
+ "aromatic": False,
701
+ "hcount": 0,
702
+ "charge": 0,
703
+ "neighbors": ["", ""],
704
+ },
705
+ )
706
+ """
707
+ if attributes_defaults is None:
708
+ attributes_defaults = {
709
+ "element": "*",
710
+ "aromatic": False,
711
+ "hcount": 0,
712
+ "charge": 0,
713
+ "neighbors": ["", ""],
714
+ }
715
+
716
+ return tuple(
717
+ ITSConstruction.get_node_attribute(graph, node, attr, default)
718
+ for attr, default in attributes_defaults.items()
719
+ )