chython 2.19__cp313-cp313-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 (175) hide show
  1. chython/__init__.py +35 -0
  2. chython/_functions.py +95 -0
  3. chython/_java.py +57 -0
  4. chython/algorithms/__init__.py +18 -0
  5. chython/algorithms/_isomorphism.cp313-win_amd64.pyd +0 -0
  6. chython/algorithms/_isomorphism.pyx +189 -0
  7. chython/algorithms/_rings.cp313-win_amd64.pyd +0 -0
  8. chython/algorithms/_rings.pyx +478 -0
  9. chython/algorithms/aromatics/__init__.py +27 -0
  10. chython/algorithms/aromatics/_rules.py +124 -0
  11. chython/algorithms/aromatics/kekule.py +532 -0
  12. chython/algorithms/aromatics/test/__init__.py +18 -0
  13. chython/algorithms/aromatics/test/test_kekule.py +160 -0
  14. chython/algorithms/aromatics/test/test_thiele.py +263 -0
  15. chython/algorithms/aromatics/thiele.py +222 -0
  16. chython/algorithms/calculate2d/__init__.py +23 -0
  17. chython/algorithms/calculate2d/clean2d.js +1 -0
  18. chython/algorithms/calculate2d/molecule.py +191 -0
  19. chython/algorithms/calculate2d/reaction.py +75 -0
  20. chython/algorithms/conformers.py +106 -0
  21. chython/algorithms/depict.py +596 -0
  22. chython/algorithms/fingerprints/__init__.py +43 -0
  23. chython/algorithms/fingerprints/linear.py +202 -0
  24. chython/algorithms/fingerprints/morgan.py +132 -0
  25. chython/algorithms/fingerprints/test/__init__.py +18 -0
  26. chython/algorithms/fingerprints/test/test_linear.py +127 -0
  27. chython/algorithms/fingerprints/test/test_morgan.py +79 -0
  28. chython/algorithms/groups/__init__.py +212 -0
  29. chython/algorithms/groups/_functional.py +290 -0
  30. chython/algorithms/groups/_oxidations.py +70 -0
  31. chython/algorithms/groups/_protective.py +964 -0
  32. chython/algorithms/groups/_reactions.py +809 -0
  33. chython/algorithms/groups/_reductions.py +88 -0
  34. chython/algorithms/groups/_transformations.py +278 -0
  35. chython/algorithms/groups/test/__init__.py +18 -0
  36. chython/algorithms/groups/test/test_deprotection.py +108 -0
  37. chython/algorithms/groups/test/test_reactions.py +377 -0
  38. chython/algorithms/isomorphism.py +664 -0
  39. chython/algorithms/mapping/__init__.py +188 -0
  40. chython/algorithms/mapping/_groups.py +94 -0
  41. chython/algorithms/mapping/_reactions.py +72 -0
  42. chython/algorithms/mapping/attention.py +266 -0
  43. chython/algorithms/mapping/reconstruct.py +346 -0
  44. chython/algorithms/mcs.py +201 -0
  45. chython/algorithms/morgan.py +77 -0
  46. chython/algorithms/rings.py +178 -0
  47. chython/algorithms/smiles.py +597 -0
  48. chython/algorithms/standardize/__init__.py +30 -0
  49. chython/algorithms/standardize/_groups.py +958 -0
  50. chython/algorithms/standardize/_isomers.py +330 -0
  51. chython/algorithms/standardize/_metal_organics.py +189 -0
  52. chython/algorithms/standardize/_reagents.py +44 -0
  53. chython/algorithms/standardize/_salts.py +68 -0
  54. chython/algorithms/standardize/molecule.py +475 -0
  55. chython/algorithms/standardize/reaction.py +384 -0
  56. chython/algorithms/standardize/resonance.py +191 -0
  57. chython/algorithms/standardize/salts.py +128 -0
  58. chython/algorithms/standardize/saturation.py +373 -0
  59. chython/algorithms/standardize/test/__init__.py +18 -0
  60. chython/algorithms/standardize/test/test_canonicalize.py +66 -0
  61. chython/algorithms/standardize/test/test_groups.py +146 -0
  62. chython/algorithms/standardize/test/test_isomers.py +198 -0
  63. chython/algorithms/stereo.py +1215 -0
  64. chython/algorithms/tautomers/__init__.py +167 -0
  65. chython/algorithms/tautomers/_acid.py +59 -0
  66. chython/algorithms/tautomers/_base.py +116 -0
  67. chython/algorithms/tautomers/_keto_enol.py +107 -0
  68. chython/algorithms/tautomers/acid_base.py +208 -0
  69. chython/algorithms/tautomers/heteroarenes.py +103 -0
  70. chython/algorithms/tautomers/keto_enol.py +143 -0
  71. chython/algorithms/tautomers/test/__init__.py +18 -0
  72. chython/algorithms/tautomers/test/test_tautomers.py +80 -0
  73. chython/algorithms/test/__init__.py +18 -0
  74. chython/algorithms/test/test_isomorphism.py +58 -0
  75. chython/algorithms/test/test_smiles.py +76 -0
  76. chython/algorithms/x3dom.py +350 -0
  77. chython/containers/__init__.py +48 -0
  78. chython/containers/_pack_v2.cp313-win_amd64.pyd +0 -0
  79. chython/containers/_pack_v2.pyx +271 -0
  80. chython/containers/_unpack_v0v2.cp313-win_amd64.pyd +0 -0
  81. chython/containers/_unpack_v0v2.pyx +302 -0
  82. chython/containers/bonds.py +255 -0
  83. chython/containers/cgr.py +115 -0
  84. chython/containers/chimera.py +63 -0
  85. chython/containers/graph.py +199 -0
  86. chython/containers/molecule.py +817 -0
  87. chython/containers/query.py +71 -0
  88. chython/containers/rdkit.py +183 -0
  89. chython/containers/reaction.py +324 -0
  90. chython/containers/test/__init__.py +18 -0
  91. chython/containers/test/test_molecule.py +117 -0
  92. chython/containers/test/test_pack.py +60 -0
  93. chython/containers/test/test_rdkit.py +70 -0
  94. chython/containers/test/test_reaction.py +40 -0
  95. chython/exceptions.py +114 -0
  96. chython/files/MRVrw.py +532 -0
  97. chython/files/PDBrw.py +255 -0
  98. chython/files/RDFrw.py +309 -0
  99. chython/files/SDFrw.py +221 -0
  100. chython/files/__init__.py +30 -0
  101. chython/files/_convert.py +207 -0
  102. chython/files/_mapping.py +117 -0
  103. chython/files/_xyz.cp313-win_amd64.pyd +0 -0
  104. chython/files/_xyz.pyx +74 -0
  105. chython/files/daylight/__init__.py +24 -0
  106. chython/files/daylight/parser.py +157 -0
  107. chython/files/daylight/smarts.py +107 -0
  108. chython/files/daylight/smiles.py +260 -0
  109. chython/files/daylight/test/__init__.py +18 -0
  110. chython/files/daylight/test/test_daylight_smarts.py +289 -0
  111. chython/files/daylight/test/test_daylight_smiles.py +101 -0
  112. chython/files/daylight/test/test_parser.py +118 -0
  113. chython/files/daylight/test/test_tokenize.py +77 -0
  114. chython/files/daylight/tokenize.py +376 -0
  115. chython/files/libinchi/__init__.py +22 -0
  116. chython/files/libinchi/libinchi.dll +0 -0
  117. chython/files/libinchi/wrapper.py +554 -0
  118. chython/files/mdl/__init__.py +25 -0
  119. chython/files/mdl/emol.py +251 -0
  120. chython/files/mdl/erxn.py +67 -0
  121. chython/files/mdl/mol.py +186 -0
  122. chython/files/mdl/read.py +223 -0
  123. chython/files/mdl/rxn.py +67 -0
  124. chython/files/mdl/stereo.py +63 -0
  125. chython/files/mdl/write.py +201 -0
  126. chython/files/opsin.py +35 -0
  127. chython/files/test/__init__.py +0 -0
  128. chython/files/test/test_inchi.py +27 -0
  129. chython/files/test/test_mrv.py +47 -0
  130. chython/files/test/test_sdf_rdf.py +64 -0
  131. chython/files/test/test_xyz.py +20 -0
  132. chython/files/xyz.py +78 -0
  133. chython/periodictable/__init__.py +69 -0
  134. chython/periodictable/base/__init__.py +25 -0
  135. chython/periodictable/base/dynamic.py +149 -0
  136. chython/periodictable/base/element.py +451 -0
  137. chython/periodictable/base/groups.py +90 -0
  138. chython/periodictable/base/periods.py +46 -0
  139. chython/periodictable/base/query.py +473 -0
  140. chython/periodictable/base/vector.py +119 -0
  141. chython/periodictable/groupI.py +252 -0
  142. chython/periodictable/groupII.py +223 -0
  143. chython/periodictable/groupIII.py +1154 -0
  144. chython/periodictable/groupIV.py +210 -0
  145. chython/periodictable/groupIX.py +196 -0
  146. chython/periodictable/groupV.py +192 -0
  147. chython/periodictable/groupVI.py +183 -0
  148. chython/periodictable/groupVII.py +162 -0
  149. chython/periodictable/groupVIII.py +161 -0
  150. chython/periodictable/groupX.py +166 -0
  151. chython/periodictable/groupXI.py +164 -0
  152. chython/periodictable/groupXII.py +158 -0
  153. chython/periodictable/groupXIII.py +239 -0
  154. chython/periodictable/groupXIV.py +262 -0
  155. chython/periodictable/groupXV.py +276 -0
  156. chython/periodictable/groupXVI.py +457 -0
  157. chython/periodictable/groupXVII.py +324 -0
  158. chython/periodictable/groupXVIII.py +260 -0
  159. chython/periodictable/test/__init__.py +0 -0
  160. chython/periodictable/test/test_element.py +100 -0
  161. chython/reactor/__init__.py +24 -0
  162. chython/reactor/base.py +222 -0
  163. chython/reactor/reactor.py +177 -0
  164. chython/reactor/test/__init__.py +18 -0
  165. chython/reactor/test/test_reactor.py +40 -0
  166. chython/reactor/test/test_transformer.py +78 -0
  167. chython/reactor/transformer.py +72 -0
  168. chython/utils/__init__.py +50 -0
  169. chython/utils/free_wilson.py +114 -0
  170. chython/utils/grid.py +130 -0
  171. chython/utils/retro.py +139 -0
  172. chython-2.19.dist-info/METADATA +105 -0
  173. chython-2.19.dist-info/RECORD +175 -0
  174. chython-2.19.dist-info/WHEEL +4 -0
  175. chython-2.19.dist-info/licenses/LICENSE +165 -0
@@ -0,0 +1,809 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright 2026 Ramil Nugmanov <nougmanoff@protonmail.com>
4
+ # This file is part of chython.
5
+ #
6
+ # chython is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU Lesser General Public License as published by
8
+ # the Free Software Foundation; either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License
17
+ # along with this program; if not, see <https://www.gnu.org/licenses/>.
18
+ #
19
+ from lazy_object_proxy import Proxy
20
+
21
+
22
+ def _make_reactor(rxn_name, reactants, product_smarts):
23
+ from ._functional import rules
24
+ from ...reactor import Reactor
25
+ from ... import smarts
26
+
27
+ queries = []
28
+ fg_names = []
29
+ for fg_name, remap in reactants:
30
+ q = rules[fg_name]
31
+ if remap:
32
+ q = q.copy()
33
+ q.remap(remap)
34
+ queries.append(q)
35
+ fg_names.append(fg_name)
36
+
37
+ product = smarts(product_smarts)
38
+ return rxn_name, fg_names, Reactor(tuple(queries), (product,),
39
+ delete_atoms=True, one_shot=True, ignore_pyrrole_hydrogen=True)
40
+
41
+
42
+ def _rules():
43
+ rules = []
44
+
45
+ # amidation: RCOX + R'NH2 -> RC(=O)NHR'
46
+ for acyl in ('carboxylic_acid', 'acyl_chloride'):
47
+ for amine in ('primary_amine', 'primary_aniline'):
48
+ rules.append(_make_reactor('amidation',
49
+ [(acyl, None),
50
+ (amine, {1: 3, 2: 4})],
51
+ '[A:1](=[A:2])-[A:3]-[A:4]'))
52
+ for amine in ('secondary_amine', 'secondary_aniline'):
53
+ rules.append(_make_reactor('amidation',
54
+ [(acyl, None),
55
+ (amine, {1: 3, 2: 4, 3: 5})],
56
+ '[A:1](=[A:2])-[A:3](-[A:4])-[A:5]'))
57
+
58
+ # carbamoylation: ROC(=O)X + amine -> ROC(=O)NR'R'' (carbamate from chloroformate)
59
+ for formate in ('chloroformate', 'fluoroformate'):
60
+ for amine in ('primary_amine', 'primary_aniline'):
61
+ rules.append(_make_reactor('carbamoylation',
62
+ [(formate, None),
63
+ (amine, {1: 4, 2: 5})],
64
+ '[A:3]-[A:1](=[A:2])-[A:4]-[A:5]'))
65
+ for amine in ('secondary_amine', 'secondary_aniline'):
66
+ rules.append(_make_reactor('carbamoylation',
67
+ [(formate, None),
68
+ (amine, {1: 4, 2: 5, 3: 6})],
69
+ '[A:3]-[A:1](=[A:2])-[A:4](-[A:5])-[A:6]'))
70
+ rules.append(_make_reactor('carbamoylation',
71
+ [(formate, None),
72
+ ('pyrrole', {1: 4})],
73
+ '[A:3]-[A:1](=[A:2])-[A:4]'))
74
+ rules.append(_make_reactor('carbamoylation',
75
+ [(formate, None),
76
+ ('imidazole', {1: 4, 2: 5, 3: 6})],
77
+ '[A:3]-[A:1](=[A:2])-[A:6]:[A:5]:[A:4]'))
78
+
79
+ # urea from carbamoyl chloride: R2NC(=O)X + amine -> R2NC(=O)NR'R''
80
+ for carbamoyl in ('carbamoyl_chloride', 'carbamoyl_fluoride'):
81
+ for amine in ('primary_amine', 'primary_aniline'):
82
+ rules.append(_make_reactor('urea_from_carbamoyl',
83
+ [(carbamoyl, None),
84
+ (amine, {1: 4, 2: 5})],
85
+ '[A:3]-[A:1](=[A:2])-[A:4]-[A:5]'))
86
+ for amine in ('secondary_amine', 'secondary_aniline'):
87
+ rules.append(_make_reactor('urea_from_carbamoyl',
88
+ [(carbamoyl, None),
89
+ (amine, {1: 4, 2: 5, 3: 6})],
90
+ '[A:3]-[A:1](=[A:2])-[A:4](-[A:5])-[A:6]'))
91
+
92
+ # suzuki
93
+ # aryl: ArX + ArB(OH)2 -> Ar-Ar
94
+ # alkenyl: ArX + alkenyl_boronic -> Ar-CH=CH-R
95
+ # alkyl: ArX + alkyl_boronic -> Ar-R
96
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate'):
97
+ for boron in ('aryl_boronic_acid', 'aryl_boronic_ester', 'aryl_molander_salt'):
98
+ rules.append(_make_reactor('suzuki',
99
+ [(halide, {100: 200, 101: 201, 102: 202, 103: 203,
100
+ 104: 204, 105: 205, 106: 206, 107: 207}),
101
+ (boron, {1: 2})],
102
+ '[A:1]-[A:2]'))
103
+
104
+ for boron in ('alkenyl_boronic_acid', 'alkenyl_boronic_ester', 'alkenyl_molander_salt'):
105
+ rules.append(_make_reactor('suzuki',
106
+ [(halide, {100: 200, 101: 201, 102: 202, 103: 203,
107
+ 104: 204, 105: 205, 106: 206, 107: 207}),
108
+ (boron, {1: 2, 2: 3})],
109
+ '[A:1]-[A:2]=[A:3]'))
110
+
111
+ for boron in ('alkyl_boronic_acid', 'alkyl_boronic_ester', 'alkyl_molander_salt'):
112
+ rules.append(_make_reactor('suzuki',
113
+ [(halide, {100: 200, 101: 201, 102: 202, 103: 203,
114
+ 104: 204, 105: 205, 106: 206, 107: 207}),
115
+ (boron, {1: 2})],
116
+ '[A:1]-[A:2]'))
117
+
118
+ # buchwald-hartwig: ArX + R'NH2 -> ArNHR'
119
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate', 'aryl_mesylate'):
120
+ for amine in ('primary_amine', 'primary_aniline', 'primary_amidine_amine'):
121
+ rules.append(_make_reactor('buchwald_hartwig',
122
+ [(halide, None),
123
+ (amine, {1: 3, 2: 4})],
124
+ '[A:1]-[A:3]-[A:4]'))
125
+ for amine in ('secondary_amine', 'secondary_aniline'):
126
+ rules.append(_make_reactor('buchwald_hartwig',
127
+ [(halide, None),
128
+ (amine, {1: 3, 2: 4, 3: 5})],
129
+ '[A:1]-[A:3](-[A:4])-[A:5]'))
130
+
131
+ # buchwald-hartwig: ArX + amide-NH -> Ar-N-C(=O) (N-arylation of amides/lactams)
132
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate', 'aryl_mesylate'):
133
+ for amide in ('primary_amide', 'secondary_amide'):
134
+ rules.append(_make_reactor('buchwald_hartwig',
135
+ [(halide, None),
136
+ (amide, {1: 3, 2: 4, 3: 5})],
137
+ '[A:1]-[A:3]-[A:4]=[A:5]'))
138
+
139
+ # buchwald-hartwig: lactam halides + amines
140
+ for _x in ('fluoride', 'chloride', 'bromide', 'iodide'):
141
+ for _n in ('1', '2', '3', '4', '5', '6'):
142
+ lactam = f'lactam_{_n}_{_x}'
143
+ for amine in ('primary_amine', 'primary_aniline'):
144
+ rules.append(_make_reactor('buchwald_hartwig',
145
+ [(lactam, None),
146
+ (amine, {1: 3, 2: 4})],
147
+ '[A:1]-[A:3]-[A:4]'))
148
+ for amine in ('secondary_amine', 'secondary_aniline'):
149
+ rules.append(_make_reactor('buchwald_hartwig',
150
+ [(lactam, None),
151
+ (amine, {1: 3, 2: 4, 3: 5})],
152
+ '[A:1]-[A:3](-[A:4])-[A:5]'))
153
+
154
+ # ugi 3CR: RCHO + R'NH2 + R''NC -> R'NH-CH(R)-C(=O)NHR''
155
+ rules.append(_make_reactor('ugi_3cr',
156
+ [('aldehyde', None),
157
+ ('primary_amine', {1: 3, 2: 4}),
158
+ ('isocyano', {1: 5, 2: 6})],
159
+ '[A:1](-[A:3](-[A:4]))-[A:6](=[O:20])-[A:5]'))
160
+
161
+ # mitsunobu ether: ROH + ArOH -> R-O-Ar; ester: ROH + RCOOH -> R-OC(=O)R'
162
+ for alcohol in ('primary_alcohol', 'secondary_alcohol'):
163
+ rules.append(_make_reactor('mitsunobu',
164
+ [(alcohol, None),
165
+ ('phenol', {1: 3, 2: 4})],
166
+ '[A:2]-[A:3]-[A:4]'))
167
+ rules.append(_make_reactor('mitsunobu',
168
+ [(alcohol, None),
169
+ ('carboxylic_acid', {1: 3, 2: 4})],
170
+ '[A:2]-[A:100]-[A:3](=[A:4])'))
171
+
172
+ # deoxygenative coupling: ROH + ArX -> R-Ar
173
+ for alcohol in ('primary_alcohol', 'secondary_alcohol'):
174
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate'):
175
+ rules.append(_make_reactor('deoxygenative_coupling',
176
+ [(alcohol, None),
177
+ (halide, {1: 3})],
178
+ '[A:2]-[A:3]'))
179
+
180
+ # decarboxylative coupling: R-COOH + ArX -> R-Ar
181
+ for acid in ('alkyl_carboxylic_acid', 'aryl_carboxylic_acid'):
182
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate'):
183
+ rules.append(_make_reactor('decarboxylative_coupling',
184
+ [(acid, None),
185
+ (halide, {100: 200, 1: 4})],
186
+ '[A:3]-[A:4]'))
187
+
188
+ # XEC (cross-electrophile coupling): ArX + R'X -> Ar-R'
189
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate'):
190
+ for alkyl_halide in ('alkyl_chloride', 'alkyl_bromide', 'alkyl_iodide'):
191
+ rules.append(_make_reactor('xec',
192
+ [(halide, None),
193
+ (alkyl_halide, {100: 200, 1: 2})],
194
+ '[A:1]-[A:2]'))
195
+
196
+ # reductive amination: RCHO/R2CO + amine -> amine
197
+ for carbonyl in ('aldehyde', 'ketone'):
198
+ for amine in ('primary_amine', 'primary_aniline'):
199
+ rules.append(_make_reactor('reductive_amination',
200
+ [(carbonyl, None),
201
+ (amine, {1: 3, 2: 4})],
202
+ '[A:1]-[A:3]-[A:4]'))
203
+ for amine in ('secondary_amine', 'secondary_aniline'):
204
+ rules.append(_make_reactor('reductive_amination',
205
+ [(carbonyl, None),
206
+ (amine, {1: 3, 2: 4, 3: 5})],
207
+ '[A:1]-[A:3](-[A:4])-[A:5]'))
208
+
209
+ # ullmann phenol: ArX + ArOH -> Ar-O-Ar
210
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate'):
211
+ rules.append(_make_reactor('ullmann_phenol',
212
+ [(halide, None),
213
+ ('phenol', {1: 3, 2: 4})],
214
+ '[A:1]-[A:3]-[A:4]'))
215
+
216
+ # ullmann alcohol: ArX + ROH -> Ar-O-R (SNAr/Cu-mediated with aliphatic alcohols)
217
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_fluoride', 'aryl_triflate', 'aryl_mesylate'):
218
+ for alcohol in ('primary_alcohol', 'secondary_alcohol'):
219
+ rules.append(_make_reactor('snar',
220
+ [(halide, None),
221
+ (alcohol, {1: 3, 2: 4})],
222
+ '[A:1]-[A:3]-[A:4]'))
223
+
224
+ # ullmann pyrrole: ArX + pyrrole-NH -> Ar-N(pyrrole)
225
+ for halide in ('aryl_fluoride', 'aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate'):
226
+ rules.append(_make_reactor('ullmann_pyrrole',
227
+ [(halide, None),
228
+ ('pyrrole', {1: 3})],
229
+ '[A:1]-[A:3]'))
230
+ rules.append(_make_reactor('ullmann_pyrrole',
231
+ [(halide, None),
232
+ ('pyrazole', {1: 3, 2: 4})],
233
+ '[A:1]-[A:4]:[A:3]'))
234
+ rules.append(_make_reactor('ullmann_pyrrole',
235
+ [(halide, None),
236
+ ('imidazole', {1: 3, 2: 4, 3: 5})],
237
+ '[A:1]-[A:5]:[A:4]:[A:3]'))
238
+
239
+ # ullmann pyrrole: lactam halides + N-heterocycles
240
+ for _x in ('fluoride', 'chloride', 'bromide', 'iodide'):
241
+ for _n in ('1', '2', '3', '4', '5', '6'):
242
+ lactam = f'lactam_{_n}_{_x}'
243
+ rules.append(_make_reactor('ullmann_pyrrole',
244
+ [(lactam, None),
245
+ ('pyrrole', {1: 3})],
246
+ '[A:1]-[A:3]'))
247
+ rules.append(_make_reactor('ullmann_pyrrole',
248
+ [(lactam, None),
249
+ ('pyrazole', {1: 3, 2: 4})],
250
+ '[A:1]-[A:4]:[A:3]'))
251
+ rules.append(_make_reactor('ullmann_pyrrole',
252
+ [(lactam, None),
253
+ ('imidazole', {1: 3, 2: 4, 3: 5})],
254
+ '[A:1]-[A:5]:[A:4]:[A:3]'))
255
+
256
+ # chan-lam: ArB(OH)2 + amine/phenol -> Ar-N/Ar-O
257
+ for boron in ('aryl_boronic_acid', 'aryl_boronic_ester'):
258
+ for amine in ('primary_amine', 'primary_aniline'):
259
+ rules.append(_make_reactor('chan_lam',
260
+ [(boron, None),
261
+ (amine, {1: 3, 2: 4})],
262
+ '[A:1]-[A:3]-[A:4]'))
263
+ for amine in ('secondary_amine', 'secondary_aniline'):
264
+ rules.append(_make_reactor('chan_lam',
265
+ [(boron, None),
266
+ (amine, {1: 3, 2: 4, 3: 5})],
267
+ '[A:1]-[A:3](-[A:4])-[A:5]'))
268
+ rules.append(_make_reactor('chan_lam',
269
+ [(boron, None),
270
+ ('phenol', {1: 3, 2: 4})],
271
+ '[A:1]-[A:3]-[A:4]'))
272
+
273
+ # sulfonylation: RSO2X + alcohol/phenol -> sulfonate ester
274
+ for sulfonyl in ('sulfonyl_chloride', 'sulfonyl_fluoride'):
275
+ for alcohol in ('primary_alcohol', 'secondary_alcohol'):
276
+ rules.append(_make_reactor('sulfonylation',
277
+ [(sulfonyl, None),
278
+ (alcohol, {1: 4, 2: 5})],
279
+ '[A:1](=[A:2])(=[A:3])-[A:4]-[A:5]'))
280
+ rules.append(_make_reactor('sulfonylation',
281
+ [(sulfonyl, None),
282
+ ('phenol', {1: 4, 2: 5})],
283
+ '[A:1](=[A:2])(=[A:3])-[A:4]-[A:5]'))
284
+
285
+ # sulfonamide: RSO2X + amine -> sulfonamide
286
+ for sulfonyl in ('sulfonyl_chloride', 'sulfonyl_fluoride'):
287
+ for amine in ('primary_amine', 'primary_aniline'):
288
+ rules.append(_make_reactor('sulfonamide_formation',
289
+ [(sulfonyl, None),
290
+ (amine, {1: 4, 2: 5})],
291
+ '[A:1](=[A:2])(=[A:3])-[A:4]-[A:5]'))
292
+ for amine in ('secondary_amine', 'secondary_aniline'):
293
+ rules.append(_make_reactor('sulfonamide_formation',
294
+ [(sulfonyl, None),
295
+ (amine, {1: 4, 2: 5, 3: 6})],
296
+ '[A:1](=[A:2])(=[A:3])-[A:4](-[A:5])-[A:6]'))
297
+
298
+ # sulfonamide from amide N-H: RSO2X + R'C(=O)NHR" -> R'C(=O)N(SO2R)R"
299
+ for sulfonyl in ('sulfonyl_chloride', 'sulfonyl_fluoride'):
300
+ for amide in ('primary_amide', 'secondary_amide'):
301
+ rules.append(_make_reactor('sulfonamide_formation',
302
+ [(sulfonyl, None),
303
+ (amide, {1: 4, 2: 5, 3: 6})],
304
+ '[A:1](=[A:2])(=[A:3])-[A:4]-[A:5]=[A:6]'))
305
+
306
+ # aminolysis: ester + amine -> amide
307
+ for amine in ('primary_amine', 'primary_aniline'):
308
+ rules.append(_make_reactor('aminolysis',
309
+ [('ester', None),
310
+ (amine, {1: 3, 2: 4})],
311
+ '[A:1](=[A:2])-[A:3]-[A:4]'))
312
+ for amine in ('secondary_amine', 'secondary_aniline'):
313
+ rules.append(_make_reactor('aminolysis',
314
+ [('ester', None),
315
+ (amine, {1: 3, 2: 4, 3: 5})],
316
+ '[A:1](=[A:2])-[A:3](-[A:4])-[A:5]'))
317
+
318
+ # grignard: RMgX + RCHO/R2CO -> alcohol
319
+ for grignard in ('alkyl_grignard', 'aryl_grignard'):
320
+ for carbonyl in ('aldehyde', 'ketone'):
321
+ rules.append(_make_reactor('grignard',
322
+ [(grignard, None),
323
+ (carbonyl, {1: 3, 2: 4})],
324
+ '[A:1]-[A:3]-[A:4]'))
325
+ for carbonyl in ('aldehyde', 'ketone'):
326
+ rules.append(_make_reactor('grignard',
327
+ [('alkenyl_grignard', None),
328
+ (carbonyl, {1: 3, 2: 4})],
329
+ '[A:1]=[A:2]-[A:3]-[A:4]'))
330
+ # grignard from halide surrogates
331
+ for alkyl_halide in ('alkyl_chloride', 'alkyl_bromide', 'alkyl_iodide'):
332
+ for carbonyl in ('aldehyde', 'ketone'):
333
+ rules.append(_make_reactor('grignard',
334
+ [(alkyl_halide, None),
335
+ (carbonyl, {1: 2, 2: 3})],
336
+ '[A:1]-[A:2]-[A:3]'))
337
+ for aryl_halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide'):
338
+ for carbonyl in ('aldehyde', 'ketone'):
339
+ rules.append(_make_reactor('grignard',
340
+ [(aryl_halide, None),
341
+ (carbonyl, {1: 2, 2: 3})],
342
+ '[A:1]-[A:2]-[A:3]'))
343
+
344
+ # sonogashira: ArX + terminal alkyne -> Ar-C≡C-R
345
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate'):
346
+ rules.append(_make_reactor('sonogashira',
347
+ [(halide, None),
348
+ ('terminal_alkyne', {1: 2, 2: 3})],
349
+ '[A:1]-[A:2]#[A:3]'))
350
+
351
+ # urea synthesis: R-N=C=O + amine -> R-NH-C(=O)-NH-R'
352
+ for amine in ('primary_amine', 'primary_aniline'):
353
+ rules.append(_make_reactor('urea_synthesis',
354
+ [('isocyanate', None),
355
+ (amine, {1: 4, 2: 5})],
356
+ '[A:1]-[A:2](=[A:3])-[A:4]-[A:5]'))
357
+ for amine in ('secondary_amine', 'secondary_aniline'):
358
+ rules.append(_make_reactor('urea_synthesis',
359
+ [('isocyanate', None),
360
+ (amine, {1: 4, 2: 5, 3: 6})],
361
+ '[A:1]-[A:2](=[A:3])-[A:4](-[A:5])-[A:6]'))
362
+
363
+ # CuAAC: azide + terminal alkyne -> 1,2,3-triazole
364
+ rules.append(_make_reactor('cuaac',
365
+ [('azide', None),
366
+ ('terminal_alkyne', {1: 4, 2: 5})],
367
+ '[A:1]:1:[A:2]:[A:3]:[A:5]:[A:4]:1'))
368
+
369
+ # SNAr: ArF + amine -> Ar-NR2 (nucleophilic aromatic substitution)
370
+ for amine in ('primary_amine', 'primary_aniline'):
371
+ rules.append(_make_reactor('snar',
372
+ [('aryl_fluoride', None),
373
+ (amine, {1: 3, 2: 4})],
374
+ '[A:1]-[A:3]-[A:4]'))
375
+ for amine in ('secondary_amine', 'secondary_aniline'):
376
+ rules.append(_make_reactor('snar',
377
+ [('aryl_fluoride', None),
378
+ (amine, {1: 3, 2: 4, 3: 5})],
379
+ '[A:1]-[A:3](-[A:4])-[A:5]'))
380
+
381
+ # SNAr: ArF + amide-NH -> Ar-N-C(=O)
382
+ for amide in ('primary_amide', 'secondary_amide'):
383
+ rules.append(_make_reactor('snar',
384
+ [('aryl_fluoride', None),
385
+ (amide, {1: 3, 2: 4, 3: 5})],
386
+ '[A:1]-[A:3]-[A:4]=[A:5]'))
387
+
388
+ # SNAr: ArF + phenol -> Ar-O-Ar
389
+ rules.append(_make_reactor('snar',
390
+ [('aryl_fluoride', None),
391
+ ('phenol', {1: 3, 2: 4})],
392
+ '[A:1]-[A:3]-[A:4]'))
393
+
394
+ # SNAr: ArF + thiol -> Ar-S-R
395
+ rules.append(_make_reactor('snar',
396
+ [('aryl_fluoride', None),
397
+ ('thiol', {1: 3, 2: 4})],
398
+ '[A:1]-[A:3]-[A:4]'))
399
+
400
+ # Williamson ether:
401
+ # alkyl_halide + phenol -> R-O-Ar
402
+ # alkyl_halide + primary_alcohol -> R-O-R'
403
+ for halide in ('alkyl_chloride', 'alkyl_bromide', 'alkyl_iodide'):
404
+ rules.append(_make_reactor('williamson',
405
+ [(halide, None),
406
+ ('phenol', {1: 3, 2: 4})],
407
+ '[A:1]-[A:3]-[A:4]'))
408
+
409
+ for alcohol in ('primary_alcohol', 'secondary_alcohol', 'tertiary_alcohol'):
410
+ rules.append(_make_reactor('williamson',
411
+ [(halide, None),
412
+ (alcohol, {1: 3, 2: 4})],
413
+ '[A:1]-[A:3]-[A:4]'))
414
+
415
+ # Williamson ether with pseudohalides:
416
+ for pseudohalide in ('alkyl_triflate', 'alkyl_mesylate', 'alkyl_tosylate'):
417
+ rules.append(_make_reactor('williamson',
418
+ [(pseudohalide, None),
419
+ ('phenol', {1: 3, 2: 4})],
420
+ '[A:1]-[A:3]-[A:4]'))
421
+ for alcohol in ('primary_alcohol', 'secondary_alcohol', 'tertiary_alcohol'):
422
+ rules.append(_make_reactor('williamson',
423
+ [(pseudohalide, None),
424
+ (alcohol, {1: 3, 2: 4})],
425
+ '[A:1]-[A:3]-[A:4]'))
426
+
427
+ # acylation (ester): acyl_chloride + alcohol -> ester
428
+ for alcohol in ('primary_alcohol', 'secondary_alcohol'):
429
+ rules.append(_make_reactor('acylation',
430
+ [('acyl_chloride', None),
431
+ (alcohol, {1: 3, 2: 4})],
432
+ '[A:1](=[A:2])-[A:3]-[A:4]'))
433
+ rules.append(_make_reactor('acylation',
434
+ [('acyl_chloride', None),
435
+ ('phenol', {1: 3, 2: 4})],
436
+ '[A:1](=[A:2])-[A:3]-[A:4]'))
437
+
438
+ # thioether: thiol + alkyl_halide/pseudohalide -> R-S-R'
439
+ for halide in ('alkyl_chloride', 'alkyl_bromide', 'alkyl_iodide', 'alkyl_triflate', 'alkyl_mesylate', 'alkyl_tosylate'):
440
+ rules.append(_make_reactor('thioether',
441
+ [('thiol', None),
442
+ (halide, {100: 200, 1: 3})],
443
+ '[A:1](-[A:2])-[A:3]'))
444
+
445
+ # carbamate: isocyanate + alcohol -> R-NH-C(=O)-OR'
446
+ for alcohol in ('primary_alcohol', 'secondary_alcohol'):
447
+ rules.append(_make_reactor('carbamate',
448
+ [('isocyanate', None),
449
+ (alcohol, {1: 4, 2: 5})],
450
+ '[A:1]-[A:2](=[A:3])-[A:4]-[A:5]'))
451
+ rules.append(_make_reactor('carbamate',
452
+ [('isocyanate', None),
453
+ ('phenol', {1: 4, 2: 5})],
454
+ '[A:1]-[A:2](=[A:3])-[A:4]-[A:5]'))
455
+
456
+ # tetrazole: azide + nitrile -> 2,5-disubstituted tetrazole (ring formation)
457
+ rules.append(_make_reactor('tetrazole',
458
+ [('azide', None),
459
+ ('nitrile', {1: 4, 2: 5})],
460
+ '[A:1]:1:[A:2]:[A:3]:[A:4]:[A:5]:1'))
461
+
462
+ # wittig: phosphonium_ylide + aldehyde/ketone -> alkene
463
+ for carbonyl in ('aldehyde', 'ketone'):
464
+ rules.append(_make_reactor('wittig',
465
+ [('phosphonium_ylide', None),
466
+ (carbonyl, {1: 2, 2: 3})],
467
+ '[A:1]=[A:2]'))
468
+
469
+ # hwe: phosphonate + aldehyde/ketone -> alkene (E-selective)
470
+ for carbonyl in ('aldehyde', 'ketone'):
471
+ rules.append(_make_reactor('hwe',
472
+ [('phosphonate', None),
473
+ (carbonyl, {1: 2, 2: 3})],
474
+ '[A:1]=[A:2]'))
475
+
476
+ # weinreb: weinreb_amide + grignard -> ketone
477
+ for grignard in ('alkyl_grignard', 'aryl_grignard'):
478
+ rules.append(_make_reactor('weinreb',
479
+ [('weinreb_amide', None),
480
+ (grignard, {100: 200, 101: 201, 1: 3})],
481
+ '[A:2]=[A:1]-[A:3]'))
482
+ # weinreb from ester surrogate: ester + grignard -> ketone
483
+ for grignard in ('alkyl_grignard', 'aryl_grignard'):
484
+ rules.append(_make_reactor('weinreb',
485
+ [('ester', None),
486
+ (grignard, {100: 200, 101: 201, 1: 3})],
487
+ '[A:2]=[A:1]-[A:3]'))
488
+ # weinreb from acyl_chloride surrogate: acyl_chloride + grignard -> ketone
489
+ for grignard in ('alkyl_grignard', 'aryl_grignard'):
490
+ rules.append(_make_reactor('weinreb',
491
+ [('acyl_chloride', None),
492
+ (grignard, {100: 200, 101: 201, 1: 3})],
493
+ '[A:2]=[A:1]-[A:3]'))
494
+
495
+ # friedel-crafts acylation: acyl_chloride + arene -> Ar-COR
496
+ rules.append(_make_reactor('friedel_crafts',
497
+ [('acyl_chloride', None),
498
+ ('arene_ch', {1: 3})],
499
+ '[A:1](=[A:2])-[A:3]'))
500
+
501
+ # heck: ArX + alkene -> Ar-CH=CH-R
502
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate'):
503
+ for alkene in ('terminal_alkene', 'alkene'):
504
+ rules.append(_make_reactor('heck',
505
+ [(halide, None),
506
+ (alkene, {1: 2, 2: 3})],
507
+ '[A:1]-[A:2]=[A:3]'))
508
+
509
+ # cross metathesis: terminal_alkene + terminal_alkene -> internal alkene
510
+ rules.append(_make_reactor('cross_metathesis',
511
+ [('terminal_alkene', None),
512
+ ('terminal_alkene', {1: 3, 2: 4})],
513
+ '[A:2]=[A:4]'))
514
+
515
+ # kumada: ArX + RMgX -> Ar-R
516
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate'):
517
+ for grignard in ('alkyl_grignard', 'aryl_grignard'):
518
+ rules.append(_make_reactor('kumada',
519
+ [(halide, None),
520
+ (grignard, {100: 200, 101: 201, 1: 2})],
521
+ '[A:1]-[A:2]'))
522
+ rules.append(_make_reactor('kumada',
523
+ [(halide, None),
524
+ ('alkenyl_grignard', {100: 200, 101: 201, 1: 2, 2: 3})],
525
+ '[A:1]-[A:2]=[A:3]'))
526
+
527
+ # negishi: ArX + RZnX -> Ar-R
528
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate'):
529
+ for zinc in ('alkyl_zinc', 'aryl_zinc'):
530
+ rules.append(_make_reactor('negishi',
531
+ [(halide, None),
532
+ (zinc, {100: 200, 101: 201, 1: 2})],
533
+ '[A:1]-[A:2]'))
534
+ rules.append(_make_reactor('negishi',
535
+ [(halide, None),
536
+ ('alkenyl_zinc', {100: 200, 101: 201, 1: 2, 2: 3})],
537
+ '[A:1]-[A:2]=[A:3]'))
538
+
539
+ # stille: ArX + R-SnR3 -> Ar-R
540
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate'):
541
+ rules.append(_make_reactor('stille',
542
+ [(halide, None),
543
+ ('aryl_stannane', {100: 200, 1: 2})],
544
+ '[A:1]-[A:2]'))
545
+ rules.append(_make_reactor('stille',
546
+ [(halide, None),
547
+ ('alkenyl_stannane', {100: 200, 1: 2, 2: 3})],
548
+ '[A:1]-[A:2]=[A:3]'))
549
+ rules.append(_make_reactor('stille',
550
+ [(halide, None),
551
+ ('alkyl_stannane', {100: 200, 1: 2})],
552
+ '[A:1]-[A:2]'))
553
+
554
+ # hiyama: ArX + R-SiR3 -> Ar-R
555
+ for halide in ('aryl_chloride', 'aryl_bromide', 'aryl_iodide', 'aryl_triflate'):
556
+ rules.append(_make_reactor('hiyama',
557
+ [(halide, None),
558
+ ('aryl_silane', {100: 200, 1: 2})],
559
+ '[A:1]-[A:2]'))
560
+ rules.append(_make_reactor('hiyama',
561
+ [(halide, None),
562
+ ('alkenyl_silane', {100: 200, 1: 2, 2: 3})],
563
+ '[A:1]-[A:2]=[A:3]'))
564
+
565
+ # hantzsch thiazole: alpha_haloketone + thioamide -> thiazole
566
+ rules.append(_make_reactor('hantzsch_thiazole',
567
+ [('alpha_haloketone', None),
568
+ ('thioamide', {1: 4, 2: 5, 3: 6})],
569
+ '[A:5]:1:[A:4]:[A:6]:[A:1]:[A:3]:1'))
570
+
571
+ # knorr pyrazole: 1,3-diketone + alkyl_hydrazine -> pyrazole
572
+ rules.append(_make_reactor('knorr_pyrazole',
573
+ [('1_3_diketone', None),
574
+ ('alkyl_hydrazine', {1: 6, 2: 7, 3: 8})],
575
+ '[A:6](:1:[A:7]:[A:1]:[A:5]:[A:3]:1)-[A:8]'))
576
+
577
+ # paal_knorr pyrrole: 1,4-diketone + primary_amine -> pyrrole
578
+ for amine in ('primary_amine', 'primary_aniline'):
579
+ rules.append(_make_reactor('paal_knorr',
580
+ [('1_4_diketone', None),
581
+ (amine, {1: 7, 2: 8})],
582
+ '[A:7](:1:[A:1]:[A:5]:[A:6]:[A:3]:1)-[A:8]'))
583
+
584
+ # fischer indole: aryl_hydrazine + alpha_ketone -> indole
585
+ rules.append(_make_reactor('fischer_indole',
586
+ [('aryl_hydrazine', None),
587
+ ('alpha_ketone', {1: 5, 2: 6, 3: 7})],
588
+ '[A:1]:1:[A:3]:[A:4]:[A:7]:[A:5]:1'))
589
+
590
+ # benzimidazole: o_diaminoarene + aldehyde/acid -> benzimidazole
591
+ for carbonyl in ('aldehyde', 'carboxylic_acid'):
592
+ rules.append(_make_reactor('benzimidazole',
593
+ [('o_diaminoarene', None),
594
+ (carbonyl, {1: 5, 2: 6})],
595
+ '[A:1]:1:[A:3]:[A:4]:[A:2]:[A:5]:1'))
596
+
597
+ # benzoxazole: o_aminophenol + aldehyde/acid -> benzoxazole
598
+ for carbonyl in ('aldehyde', 'carboxylic_acid'):
599
+ rules.append(_make_reactor('benzoxazole',
600
+ [('o_aminophenol', None),
601
+ (carbonyl, {1: 5, 2: 6})],
602
+ '[A:1]:1:[A:3]:[A:4]:[A:2]:[A:5]:1'))
603
+
604
+ # benzothiazole: o_aminothiophenol + aldehyde/acid -> benzothiazole
605
+ for carbonyl in ('aldehyde', 'carboxylic_acid'):
606
+ rules.append(_make_reactor('benzothiazole',
607
+ [('o_aminothiophenol', None),
608
+ (carbonyl, {1: 5, 2: 6})],
609
+ '[A:1]:1:[A:3]:[A:4]:[A:2]:[A:5]:1'))
610
+
611
+ # quinoxaline: o_diaminoarene + 1,2-diketone -> quinoxaline
612
+ rules.append(_make_reactor('quinoxaline',
613
+ [('o_diaminoarene', None),
614
+ ('1_2_diketone', {1: 5, 2: 6, 3: 7, 4: 8})],
615
+ '[A:1]:1:[A:3]:[A:4]:[A:2]:[A:7]:[A:5]:1'))
616
+
617
+ # friedlander quinoline: o_aminobenzaldehyde + alpha_ketone -> quinoline
618
+ rules.append(_make_reactor('friedlander',
619
+ [('o_aminobenzaldehyde', None),
620
+ ('alpha_ketone', {1: 7, 2: 8, 3: 9})],
621
+ '[A:1]:1:[A:3]:[A:4]:[A:5]:[A:9]:[A:7]:1'))
622
+
623
+ # pictet_spengler: beta_arylethylamine + aldehyde -> THIQ
624
+ rules.append(_make_reactor('pictet_spengler',
625
+ [('beta_arylethylamine', None),
626
+ ('aldehyde', {1: 6, 2: 7})],
627
+ '[A:1]1-[A:2]-[A:3]-[A:4]:[A:5]-[A:6]-1'))
628
+
629
+ # 1,2,4-oxadiazole: amidoxime + acyl source -> 1,2,4-oxadiazole
630
+ for acyl in ('acyl_chloride', 'acyl_fluoride', 'carboxylic_acid'):
631
+ rules.append(_make_reactor('oxadiazole_124',
632
+ [('amidoxime', None),
633
+ (acyl, {1: 5, 2: 6, 100: 200})],
634
+ '[A:4]:1:[A:1]:[A:3]:[A:5]:[A:2]:1'))
635
+
636
+ # pyrimidine: 1,3-diketone + amidine -> pyrimidine
637
+ rules.append(_make_reactor('pyrimidine',
638
+ [('1_3_diketone', None),
639
+ ('amidine', {1: 6, 2: 7, 3: 8})],
640
+ '[A:7]:1:[A:6]:[A:8]:[A:1]:[A:5]:[A:3]:1'))
641
+
642
+ # van_leusen oxazole: alpha_isocyano + aldehyde -> oxazole
643
+ rules.append(_make_reactor('van_leusen_oxazole',
644
+ [('tosyl_isocyanide', None),
645
+ ('aldehyde', {1: 4, 2: 5})],
646
+ '[A:1]:1:[A:2]:[A:3]:[A:5]:[A:4]:1'))
647
+
648
+ # imidazo[1,2-a]pyridine: aminopyridine + alpha_haloketone
649
+ rules.append(_make_reactor('imidazopyridine',
650
+ [('aminopyridine', None),
651
+ ('alpha_haloketone', {1: 4, 2: 5, 3: 6, 100: 200})],
652
+ '[A:3]:1:[A:6]:[A:4]:[A:1]:[A:2]:1'))
653
+ # imidazo[1,2-a]pyridine: aminopyridine + alpha_haloester (ester O masked, carbonyl O deleted)
654
+ rules.append(_make_reactor('imidazopyridine',
655
+ [('aminopyridine', None),
656
+ ('alpha_haloester', {1: 4, 2: 5, 3: 6, 100: 200})],
657
+ '[A:3]:1:[A:6]:[A:4]:[A:1]:[A:2]:1'))
658
+
659
+ # biginelli: aldehyde + beta_ketoester + urea/thiourea -> DHPM (3-component)
660
+ for urea_fg in ('urea', 'thiourea'):
661
+ rules.append(_make_reactor('biginelli',
662
+ [('aldehyde', None),
663
+ ('beta_ketoester', {1: 3, 2: 4, 3: 5, 4: 6, 5: 7, 100: 200}),
664
+ (urea_fg, {1: 8, 2: 9, 3: 10, 4: 11})],
665
+ '[A:8]1-[A:9](=[A:10])-[A:11]-[A:3]=[A:7]-[A:1]-1'))
666
+
667
+ # niementowski quinazoline: anthranilic_acid + primary_amide -> 4-oxoquinazoline
668
+ rules.append(_make_reactor('niementowski',
669
+ [('anthranilic_acid', None),
670
+ ('primary_amide', {1: 7, 2: 8, 3: 9})],
671
+ '[A:1]:1:[A:3]:[A:4]:[A:5](-[A:6]):[A:7]:[A:8]:1'))
672
+
673
+ # ugi 4CR: RCHO + R'NH2 + R"COOH + R"'NC -> R"C(=O)N(R')CH(R)C(=O)NHR"'
674
+ rules.append(_make_reactor('ugi_4cr',
675
+ [('aldehyde', None),
676
+ ('primary_amine', {1: 3, 2: 4}),
677
+ ('carboxylic_acid', {100: 200, 1: 7, 2: 8}),
678
+ ('isocyano', {1: 5, 2: 6})],
679
+ '[A:7](=[A:8])-[A:3](-[A:4])-[A:1]-[A:6](=[O:20])-[A:5]'))
680
+
681
+ # liebeskind-srogl: R-C(=O)-SR' + ArB(OH)2 -> R-C(=O)-Ar (ketone synthesis)
682
+ for boron in ('aryl_boronic_acid', 'aryl_boronic_ester'):
683
+ rules.append(_make_reactor('liebeskind_srogl',
684
+ [('thioester', None),
685
+ (boron, {100: 200, 101: 201, 102: 202, 1: 3})],
686
+ '[A:1](=[A:2])-[A:3]'))
687
+
688
+ # knoevenagel: active_methylene + aldehyde -> alkene (condensation)
689
+ rules.append(_make_reactor('knoevenagel',
690
+ [('active_methylene', None),
691
+ ('aldehyde', {1: 4, 2: 5})],
692
+ '[A:4]=[A:1](-[A:2])-[A:3]'))
693
+
694
+ # aldol: alpha_ketone + aldehyde -> beta-hydroxy carbonyl
695
+ rules.append(_make_reactor('aldol',
696
+ [('alpha_ketone', None),
697
+ ('aldehyde', {1: 4, 2: 5})],
698
+ '[A:1](=[A:2])-[A:3]-[A:4]-[A:5]'))
699
+
700
+ # larock indole: o_haloaniline + alkyne -> indole
701
+ rules.append(_make_reactor('larock_indole',
702
+ [('o_haloaniline', None),
703
+ ('alkyne', {1: 4, 2: 5})],
704
+ '[A:1]:1:[A:2]:[A:3]:[A:5]:[A:4]:1'))
705
+
706
+ # doebner-miller: aniline_ortho_ch + enal -> quinoline
707
+ rules.append(_make_reactor('doebner_miller',
708
+ [('aniline_ortho_ch', None),
709
+ ('enal', {1: 4, 2: 5, 3: 6, 4: 7})],
710
+ '[A:1]:1:[A:2]:[A:3]:[A:7]:[A:6]:[A:4]:1'))
711
+
712
+ # hantzsch pyridine: aldehyde + 2x beta_ketoester -> pyridine (NH3 implicit)
713
+ rules.append(_make_reactor('hantzsch_pyridine',
714
+ [('aldehyde', {1: 11, 2: 12}),
715
+ ('beta_ketoester', None),
716
+ ('beta_ketoester', {1: 6, 2: 7, 3: 8, 4: 9, 5: 10, 100: 200})],
717
+ '[N:20]:1:[A:1]:[A:5](-[A:3](=[A:4])-[A:100]):[A:11]:[A:10](-[A:8](=[A:9])-[A:200]):[A:6]:1'))
718
+
719
+ # nitrile_grignard: R-C≡N + RMgX → ketone (via imine hydrolysis)
720
+ for grignard in ('alkyl_grignard', 'aryl_grignard'):
721
+ rules.append(_make_reactor('nitrile_grignard',
722
+ [('nitrile', None),
723
+ (grignard, {100: 200, 101: 201, 1: 3})],
724
+ '[A:1](=[O:20])-[A:3]'))
725
+
726
+ # N-alkylation: alkyl_halide/triflate/tosylate/mesylate + pyrrole/pyrazole/imidazole/pyridol
727
+ for halide in ('alkyl_chloride', 'alkyl_bromide', 'alkyl_iodide', 'alkyl_triflate', 'alkyl_tosylate', 'alkyl_mesylate'):
728
+ rules.append(_make_reactor('n_alkylation',
729
+ [(halide, None),
730
+ ('pyrrole', {1: 3})],
731
+ '[A:1]-[A:3]'))
732
+ rules.append(_make_reactor('n_alkylation',
733
+ [(halide, None),
734
+ ('pyrazole', {1: 3, 2: 4})],
735
+ '[A:1]-[A:4]:[A:3]'))
736
+ rules.append(_make_reactor('n_alkylation',
737
+ [(halide, None),
738
+ ('imidazole', {1: 3, 2: 4, 3: 5})],
739
+ '[A:1]-[A:5]:[A:4]:[A:3]'))
740
+
741
+ # N-alkylation: alkyl_halide/triflate/tosylate/mesylate + primary/secondary amine
742
+ for halide in ('alkyl_chloride', 'alkyl_bromide', 'alkyl_iodide', 'alkyl_triflate', 'alkyl_tosylate', 'alkyl_mesylate',
743
+ 'boronate_alkyl_chloride', 'boronate_alkyl_bromide', 'boronate_alkyl_iodide'):
744
+ for amine in ('primary_amine', 'primary_aniline'):
745
+ rules.append(_make_reactor('n_alkylation',
746
+ [(halide, None),
747
+ (amine, {1: 3, 2: 4})],
748
+ '[A:1]-[A:3]-[A:4]'))
749
+ for amine in ('secondary_amine', 'secondary_aniline'):
750
+ rules.append(_make_reactor('n_alkylation',
751
+ [(halide, None),
752
+ (amine, {1: 3, 2: 4, 3: 5})],
753
+ '[A:1]-[A:3](-[A:4])-[A:5]'))
754
+
755
+ # N-alkylation: alkyl_halide/triflate/tosylate/mesylate + primary/secondary amide (lactam NH)
756
+ for halide in ('alkyl_chloride', 'alkyl_bromide', 'alkyl_iodide', 'alkyl_triflate', 'alkyl_tosylate', 'alkyl_mesylate'):
757
+ for amide in ('primary_amide', 'secondary_amide'):
758
+ rules.append(_make_reactor('n_alkylation',
759
+ [(halide, None),
760
+ (amide, {1: 3, 2: 4, 3: 5})],
761
+ '[A:1]-[A:3]-[A:4]=[A:5]'))
762
+
763
+ # urea from 2 amines (CDI/phosgene implicit)
764
+ for amine1 in ('primary_amine', 'primary_aniline'):
765
+ for amine2 in ('primary_amine', 'primary_aniline'):
766
+ rules.append(_make_reactor('urea_from_amines',
767
+ [(amine1, None),
768
+ (amine2, {1: 3, 2: 4})],
769
+ '[A:1](-[A:2])-[C:20](=[O:21])-[A:3]-[A:4]'))
770
+
771
+ # oxazoline: amino_alcohol + carboxylic_acid → 2-oxazoline ring
772
+ rules.append(_make_reactor('oxazoline',
773
+ [('amino_alcohol', None),
774
+ ('carboxylic_acid', {100: 200, 1: 5, 2: 6})],
775
+ '[A:5]1=[A:1]-[A:2]-[A:3]-[A:4]-1'))
776
+
777
+ # oxime O-alkylation: oxime + alkyl_halide/pseudohalide → oxime ether
778
+ for halide in ('alkyl_chloride', 'alkyl_bromide', 'alkyl_iodide', 'alkyl_triflate', 'alkyl_mesylate', 'alkyl_tosylate'):
779
+ rules.append(_make_reactor('oxime_alkylation',
780
+ [('oxime', None),
781
+ (halide, {100: 200, 1: 4})],
782
+ '[A:1](-[A:4])-[A:2]=[A:3]'))
783
+
784
+ # oxime ether formation: O-alkylhydroxylamine + aldehyde → R-O-N=CH-R'
785
+ rules.append(_make_reactor('oxime_ether',
786
+ [('O_alkylhydroxylamine', None),
787
+ ('aldehyde', {1: 4, 2: 5})],
788
+ '[A:3]-[A:2]-[A:1]=[A:4]'))
789
+
790
+ # aldol with ketone (extension): alpha_ketone + ketone
791
+ rules.append(_make_reactor('aldol',
792
+ [('alpha_ketone', None),
793
+ ('ketone', {1: 4, 2: 5})],
794
+ '[A:1](=[A:2])-[A:3]-[A:4]-[A:5]'))
795
+
796
+ # hydrazone formation: aldehyde/ketone + aryl_hydrazine -> C=N-NH-Ar
797
+ for carbonyl in ('aldehyde', 'ketone'):
798
+ rules.append(_make_reactor('hydrazone',
799
+ [(carbonyl, None),
800
+ ('aryl_hydrazine', {1: 3, 2: 4, 3: 5, 4: 6})],
801
+ '[A:1]=[A:4]-[A:3]-[A:5]:[A:6]'))
802
+
803
+ return rules
804
+
805
+
806
+ rules = Proxy(_rules)
807
+
808
+
809
+ __all__ = ['rules']