2.2.1 设计思想:把一张图读成一行字
2.1 节解决了“分子在内存里长什么样”,本节解决“怎么把它写出来”。交换、入库、喂给序列模型,都要一维文本。SMILES(simplified molecular input line entry system)(Weininger, 1988)的回答直截了当:在分子图上挑一个原子起步,沿一条键走到下一个原子,再沿键继续;走不动了就回头换路,遇到岔口就先把旁支走完。把沿途的原子与键依次记成符号,就得到一行字符串。这是一次深度优先遍历(depth-first traversal):主干连成主链,旁支写进括号,走到已访问过的原子时说明碰上了环。二维图压成一维串,靠的不是压缩技巧,而是遍历——不妨称之为“图的语言化”。
遍历与图论的对应可以用生成树说清。对连通分子图 G=(V, E) 做深度优先遍历,首次到达每个新原子所经的 |V|−1 条边构成一棵生成树(spanning tree);其余的边都是回边——轮到它们时两端都已访问,无法再“前进”。SMILES 的处理是把每条回边断开:在第一次到达的原子旁记一个数字,行进到另一端时再记同一个数字,这对数字即环号(ring-closure digit),解析时照号连边。要断开的回边数由图本身决定:
由此看清 SMILES 的定位:它是描述语言,不是编号。同一分子有许多合法写法——起点任选、次序任选、断口任选;合法性不带来唯一性。这与 InChI 的定位互补:InChI 是 IUPAC 主持制定的标识符,算法写进标准,各实现应给出同一串(Heller et al., 2015)——不过它定义的“同一”自带标准化策略:移动氢与互变异构的归一、金属键的默认断开等,拿它对账之前要先确认这套身份定义与手头的化学问题匹配。SMILES 内部的唯一性靠各工具自己的规范化算法解决(Weininger et al., 1989);跨工具的一致性,至今仍要借助 InChI 或以 InChI 为中介的“通用 SMILES”方案(O'Boyle, 2012)。分工由此清楚:描述与输入用 SMILES;跨工具的对账与去重,在明确身份定义的前提下交给 InChI。
还需确立一个观念:读 SMILES 与写 SMILES 是同一趟遍历的两个方向。读串时,遇到原子符号就建一个节点,遇到键符号或紧邻关系就连一条边;左括号把当前原子压栈,右括号弹栈回位;数字找到同号的未闭合者即连边。写串规则与读串规则严格互逆——“语言”的含义正在于此:一套语法对读写双方同时生效。
2.2.2 原子与键:能省则省,必须明示处明示
原子的写法分两档。第一档是裸写:有机子集(organic subset)的十种元素——B、C、N、O、P、S、F、Cl、Br、I——直接写元素符号,氢从不出现,个数由价规则从连接关系推出(2.1.3 的隐式氢;允许价见表 2.1-1)。乙醇写作 CCO,三个符号、两条隐式单键,氢由读者补齐。第二档是方括号:有机子集之外的元素([Na+])、带形式电荷([NH4+])、标同位素([13C])、显式给氢计数或手性的原子,必须连同全部属性写进方括号,属性次序固定:同位素–元素–手性–氢计数–电荷;末尾还可缀一个可选的原子类别号 :n(atom class,供工具自定义标记,本节不涉及)。方括号是“退出默认价态”的显式声明。吡咯的芳香氮带氢,超出隐式推断的范围,必须写作 [nH],整个分子 c1cc[nH]c1。
键符号有六种:-(单键)、=(双键)、#(三键)、:(芳香键)、以及方向键 / 与 \(2.2.4 专述);OpenSMILES 文法另纳入四键 $,用于四重键等罕见结构,日常分子用不到。省略约定:相邻两个原子符号之间不写键符号时,解释为“单键或芳香键中合法的那一个”;= 与 # 永远不能省略,方向键也不在省略之列。点号 . 表示两个片段不相连,用于盐与混合物,如 [Na+].[Cl-]。显式的 - 几乎总是冗余:C-C-O 与 CCO 解析出同一张图。
省略键的推断规则。省略的键解释为“单键或芳香键中化学上合法的那一个”(Daylight Theory Manual)——注意这不是“看两端是否都小写”的局部判定。规则只有一条方向是硬的:芳香键必须连接两个芳香原子;反过来不成立——两个芳香原子之间的键未必是芳香键。联苯 c1ccccc1-c2ccccc2 中,连接两个苯环的键两头都是芳香碳,却是普通单键;各自环内的六条键才是芳香键。一条键最终是单键还是芳香键,由清洗阶段的芳香性感知对整个环系判定(2.1.4),随后价态检查裁决,推断结果使任一端超价即整体失败。另一面:C#N 的 # 省略不得——省了就成单键,串 CN 指向另一个分子(甲胺对氰化氢)。省略的前提是不产生歧义:只有“省掉不改变分子”的键才可以省,规则只放行无信息损失的情形。
2.2.3 分支、环号与芳香表示
分支。遍历到一个原子的第二个及以后的邻居时,旁支整体写进括号:左括号记住当前原子,括号内的字符串自成一次完整遍历(可以嵌套),右括号回到分岔原子继续主干。CC(=O)O 中的 (=O) 就是一次绕行——从羰基碳出发访问氧再返回。括号的语义是“绕行—返回”,跨度始终局部:进出括号之间就是一次小规模的遍历往返。
环号。写环时任选一条边作断口:起点原子缀数字开号,行进到断口另一端再缀同一数字闭号,解析时补连这条边。单字符环号共十个(数字 0–9,0 合法但少用),可复用,闭合即释放;同时张开的环号超过十个时启用两位记法 %10、%11(% 配两位数字,至 %99);回边的键级可缀在数字上,环己烯可写 C=1CCCCC1。断口选哪条边是自由的——这是“一物多写”的又一来源。图 2.2-1 把阿司匹林的字符串逐段对照到分子片段;图 2.2-2 把整条串回放成图,环号配对与分支绕行一目了然。
芳香表示。芳香原子小写:c、n、o、s 等。苯的 c1ccccc1 与凯库勒式 C1=CC=CC=C1 描述同一分子——2.1.4 已说明两种写法经 sanitize 收敛到同一内部态:凯库勒化验证交替单双键可以指派,芳构化感知再把环系折叠回芳香标记。小写约定让环上六条边在数据上保持等价,省去“双键画在哪”的无谓区分;代价是解析器必须自己完成凯库勒化验证。小写声明的真正约束,是存在一个能保持隐含 sp² 杂化、隐含氢数与形式电荷的凯库勒式指派,而不是“最终必须被判为芳香环系”:Daylight 官方举例,c1ccc1 与 c1ccccccc1 都是合法输入,分别生成反芳香结构的环丁二烯 C1=CC=C1 与环辛四烯;真正失败的是 c1cccc1 这类指派不出合法凯库勒式的写法——五元环上交替双键布不满,总有原子被迫离开 sp²。孤立于环系之外的小写原子同样失败:芳香描述的是环系的离域,CcC 中间的 c 无环可属,清洗直接报错(Daylight Theory Manual)。
习题 2.2-1
对乙酰氨基酚(扑热息痛)是苯环对位分别接乙酰氨基与羟基的化合物。(1) 写出它的 SMILES,标出环号在哪两个原子之间配对;(2) 解释乙酰氨基与羟基的对位关系如何在字符串中体现;(3) 再给出一条“换起点”的合法写法,说明两条串为何解析出同一个分子。
参考解答(1) CC(=O)Nc1ccc(O)cc1。主链 C–C(=O)–N 进入苯环:接 N 的环原子缀 1 开号,沿环走三个 c,第四个环原子以 (O) 分出酚羟基,再两个 c 缀 1 闭号;环号 1 配对的是首末两个环原子,这对原子在环上相邻。(2) N 挂在开环原子上,O 挂在从开环原子数起的第四个环原子上,沿环相隔三条边,恰为 1,4-位即对位;开环与闭环原子相邻这一事实,把“环走了一圈”编码进了两枚数字。(3) 例如 Oc1ccc(NC(C)=O)cc1,从酚羟基起步反向进入。两条串的遍历次序不同,但逐字符回放得到的边集相同,解析后的 Mol 对象相同——写法不唯一,分子唯一;两条串经 MolToSmiles 会收敛到同一规范串(2.2.5)。
2.2.4 立体化学:视角与方向
平面语法到此已经够写任何连通的分子图,但分子是三维的。SMILES 的立体编码覆盖多种情形,本节介绍最常用的两类:四面体手性中心与双键构型。完整文法还定义了丙二烯型、四方平面、三角双锥、八面体等手性类别(记号 @AL、@SP、@TB、@OH,见 OpenSMILES 规范),RDKit 已支持其中一部分,本节不展开。两者的共同设计取向是不记录绝对坐标,只记录相对关系,而且参照系由遍历次序决定。
手性标记 @ 与 @@。方括号原子内的 @ 与 @@ 指定四面体构型,语义是“观察视角”:观察者站在前一原子——串中紧挨在手性中心之前出现的原子——的位置看向中心,其余配体按它们在串中的出现次序排列;逆时针记 @,顺时针记 @@。L-丙氨酸 N[C@@H](C)C(=O)O:站在 N 的方向看,H→CH₃→COOH 顺时针,故记 @@。同一分子换起点或换次序重写,视角随之改变,@ 与 @@ 可能互换——手性标记不是分子的绝对属性,是“分子加遍历”的联合属性。图 2.2-3 左侧给出该例的视角标注。“站在前一原子”默认了手性原子不在串首;手性原子恰为串首、隐式氢与环号配对邻居的先后次序另有专门规则(Daylight Theory Manual / OpenSMILES),本节不展开。
方向键 / 与 \。双键构型靠方向键表达:/ 记录左低右高的倾斜,\ 记录左高右低,斜向沿 SMILES 书写方向而言。方向键写在双键两侧的单键上,指明所连的取代基位于双键的哪一侧。二氟乙烯的两个构型:F/C=C/F 中两个 F 分落双键两侧,是反式(E);F/C=C\F 中两个 F 同在一侧,是顺式(Z)。
二氟乙烯这种两端对称的分子,看两个 F 的同侧异侧就够了。一般情形要交给 E、Z 记号:比较双键两端各自优先级较高的取代基,异侧记 E,同侧记 Z。优先级由 CIP 规则排定,最常用的一条是比较直接相连原子的原子序数,大者优先——氟(9)高于氢(1)。方向键只负责记录各取代基在哪一侧;取代基再复杂,也是先由方向键读出位置,再按优先级选出参与比较的两个基团。
方向键必须成对出现在双键两侧才有意义,且不可省略——省略即丢弃构型信息,双键退化为“不指定构型”。
2.2.5 一物多写与 canonical SMILES
起点、次序、断口、分支嵌套都自由,写法数量随之爆炸,但不同拓扑的自由度差别很大,两个极端情形正好对照。n 个原子排成链的路径图受 DFS 约束最紧:必须把一条臂走到底才能回溯换臂,从链端出发只有一种原子次序,从链中某原子出发也只有两种——左臂或右臂谁先写完——合计 2(n−1) 种,链状图的写法只随规模线性增长。星形图相反:一个中心接 n−1 个分支,从中心出发时各分支互不干扰,书写次序任意排列,共 (n−1)! 种。n=20 的星形图仅分支次序就有约 1017 量级的合法写法。写法爆炸的来源是分支而非链;真实分子两者兼有,分支主导写法数目。合法写法是天文数字,“哪条串代表这个分子”必须有确定答案,否则字符串无法当键使用。
规范 SMILES(canonical SMILES)。同一分子的全部合法写法中,由一个确定性算法选出的唯一代表串。要点有二:其一,唯一性是算法内部的——同一算法对同一分子(同一内部图)给出同一串,与输入写法无关;其二,确定性指不依赖随机性。规范 SMILES 不是全局标准:不同工具、甚至同一工具的不同版本,都可能给出不同的规范串。
Weininger 的规范化算法 CANGEN 分两步走(Weininger et al., 1989)。
CANGEN:先分等价类,再定全序。第一步,为每个原子计算初始不变量(invariant)——1989 年论文取一组从图上直接读出的量:连接数、非氢键数、原子序数、电荷的符号与绝对值、连接氢数(质量数与立体信息属于 isomeric SMILES 的扩展,另行追加)——并据此给出原子的初始等价类划分。第二步,迭代细化:每个原子的类别由“自身不变量+邻居的当前类别”重新计算,重复到划分不再变化(Morgan 式的逐层传播,与 2.5 节的指纹同源);仍并列的原子由确定性的规则排出先后,得到原子的全序。最后按全序做深度优先遍历,输出唯一的串。等价类同时标记了对称性:完全等价的原子互换不产生新写法,这正是把组合爆炸折叠掉的机制。
算法内部一致不等于跨工具一致。初始不变量选哪些属性、细化到什么程度、并列怎么打破,各家实现各有选择,最终串随之不同——原论文公开的算法在高度对称体系上的并列处理,后来也被指出留有歧义,现代工具都按自己的方式补齐了这一环。规范 SMILES 解决“本工具内的唯一性”,解决不了“跨工具的一致性”。
规范串不是对账钥匙。用规范 SMILES 跨数据库去重是常见事故源:两边工具不同或版本不同,同一分子得到两个规范串,去重静默失效,没有任何报错。稳妥做法:跨工具的一致性交给 InChI 与 InChIKey——算法由标准固定,各实现给出同一串(Heller et al., 2015);或以 InChI 为中介生成“通用 SMILES”(O'Boyle, 2012)。注意 InChI 的“同一”自带标准化约定(互变异构与移动氢的归一、金属键的默认断开等),跨库对账前先确认这套身份定义与自己的化学问题匹配。库内主键可以用本工具的规范串,但应记录生成工具与版本,升级后须全量重算。
下面用 RDKit 印证“多条写法收敛到同一规范串”:同一阿司匹林,一条从甲基起步,一条从羧酸起步,规范化后字面全同。
from rdkit import Chem
w1 = Chem.MolFromSmiles("CC(=O)Oc1ccccc1C(=O)O") # 阿司匹林:从甲基起步
w2 = Chem.MolFromSmiles("OC(=O)c1ccccc1OC(C)=O") # 同一分子:从羧酸起步的另一遍历
print(Chem.MolToSmiles(w1) == Chem.MolToSmiles(w2)) # True —— 规范化收敛
print(Chem.MolToSmiles(w1)) # CC(=O)Oc1ccccc1C(=O)O
习题 2.2-2
(1) 论证:不使用任何环号,能否写出环丙烷?(2) 给出环丙烷的三种合法 SMILES,并逐一验证三者解析出的边集相同。(3) 以 C1CC1 为基式,“任选起点(3 种)× 任选断口(3 种)”共 9 种组合,最终只产生三个不同字符串——恰为 (2) 列出的三条。组合数为何坍缩?坍缩发生在哪一层?
参考解答(1) 不能。无环号的写法只有主链与分支,两者都是树;环丙烷有三条边、三个原子,μ = 3 − 3 + 1 = 1(式 2.2-1),那条回边必须靠一对环号补记,缺了环号就只剩两条边。(2) C1CC1:主链 0–1–2,环号闭合 2–0;C(C1)C1:分支 0–1、主链 0–2、环号闭合 1–2;C1(CC1):分支 0–1、分支内主链 1–2、环号闭合 2–0。三者边集同为 {01, 02, 12},解析出同一个三元环。(3) 坍缩发生在起点这一层:三个碳同种、同价态,完全等价,换起点只是给同一结构重新命名,不产生新串;断口的选择则真正影响写法——它决定哪条边由环号补上、哪两条边留在树里,三种断口各对应一个字符串。于是 9 = 3(起点)× 3(断口)种组合坍缩为 3 串,每个字符串恰好由三种组合共享。规范 SMILES 算法中的等价类划分正是这一现象的算法化:完全等价的原子互换不产生新串。
2.2.6 合法性:不是每个字符串都是分子
SMILES 是形式语言:语法对字符串给出强约束。随机字符序列几乎必然非法——括号不配对、环号找不到配对、元素符号不存在、方括号属性排列有误。语法之上还有化学层:价态、凯库勒化与芳构化检查(2.1.4)。两层失败的表现都是“解析拿到 None”,但原因不同:语法失败发生在解析器,价态失败发生在 sanitize;排查数据问题时先分层,再谈修复。
这对生成模型有直接含义。把分子生成当作“学一门语言”:模型逐字符采样,语法约束并不会自动生效——采样出的串可能括号不配、环号不闭、价态不通,成为废句。自由采样的 SMILES 语言模型确有可观比例的无效输出(具体数值随模型与数据集差异很大),这既是算力与样本的浪费,也是分布偏差:废句集中在模型掌握不牢的结构区域,静默剔除会让训练分布与评测分布悄悄分叉。对策有三类:语法约束解码、把语法编进模型结构,或者换掉表示本身——4.2 节的图生成模型逐个原子、逐条键地搭建分子,动作空间天然受限,“非法字符串”这一失败模式从根上消失。字符串范式与图范式的取舍,到第 4 章展开。
下面一段代码印证语法层的拦截:三条废句都在解析入口返回 None,根本走不到价态检查。
for s in ["c1ccccc", "C1CC", "C(C(C(C1"]: # 环号未闭 / 环号未闭 / 括号不配对
m = Chem.MolFromSmiles(s)
print(s, "解析结果:", m) # 三者皆 None:语法层即告失败
# 语法检查先于价态检查;无效串在入口被拦截,不会进入任何下游计算
习题 2.2-3
判断下列字符串能否解析为分子,指出失败发生在语法层还是化学层:① c1ccccc;② C1CC;③ C(C(C(C1;④ CC(=O)Oc1ccccc1C(=O)O;⑤ O=C(C)(C)(C)C。并回答:若这些串来自某个生成模型的输出,评测程序应当如何处置?
参考解答① 环号 1 未闭合,语法层失败——六个小写 c 本身并无不妥,错在数字有开无闭。② 环号 1 未闭合,语法层失败。③ 三个左括号无一闭合,且环号 1 未闭,语法层失败。④ 阿司匹林,合法,通过价态与芳构化。⑤ 羰基碳带双键氧与四个碳取代基,价数 6,语法层通过、价态层失败。评测程序必须先解析、剔除返回 None 的输出,并统计无效比例作为模型指标之一;直接把废句计入样本量或性质均值,会同时污染效率指标与化学指标(2.1.4 的早失败原则)。
2.2.7 长程依赖:环号的隐性代价
回到图 2.2-2 的回放。第二枚“1”必须与第一枚“1”配对,中间隔着四个原子、十几个字符;环号把串中相距很远的两个位置强行绑定,配对错一个位置,要么非法,要么变成另一个分子。价态约束同样非局部:分支括号要求栈式记忆,氢计数依赖此前出现过的全部键。串的下一个字符是否合法,取决于远处的历史——这就是长程依赖(long-range dependency)。
长程依赖是 SMILES 对语言模型的隐性难度。循环网络要维护“未闭合环号”的寄存器状态,跨长距离保留信息正是其弱项;Transformer 用注意力直接连接远端位置,缓解了记忆问题,代价是数据需求。依赖的规模随环系增长:环号对数等于 μ(式 2.2-1),一个四环甾体骨架至少要四对环号先后或同时张开,多环并合时两位环号 %10 也会登场。图模型没有这道坎——边是一等公民,环就是一个环,无须拆成两枚数字再记住配对。生成范式从字符串迁往图(4.2 节),语法有效性与长程依赖是两条方法论理由;但字符串的简洁、成熟的工具链与海量存量数据仍在,两条路线的实证比较留给第 4 章。
收束本节。SMILES 用极小的字符集达成对分子图的完整覆盖:原子两档写法、六种键符号、括号与数字两个结构记号,加上立体语义,一行文本即可交换任意有机分子。它的两个固有代价——写法不唯一与序列上的长程依赖——分别由规范化算法与图表示回应。下一节把同一套语法从“写一个分子”扩展到“写一类分子”:SMARTS 与子结构匹配。
关键术语
- SMILES (simplified molecular input line entry system)
- 把分子图沿深度优先遍历写成一行的描述语言;合法写法不唯一。
- 深度优先遍历 (depth-first traversal)
- 沿一条路径走到头再回溯换路的图遍历策略,SMILES 主链与分支的来源。
- 生成树 (spanning tree)
- 连通图的 |V|−1 条边构成的覆盖全部节点的树;深度优先遍历的主干。
- 独立环数 (cyclomatic number)
- μ = |E| − |V| + 1,等于需要断开的回边数即环号对数。
- 有机子集 (organic subset)
- 可裸写元素符号且氢隐含的十种元素:B、C、N、O、P、S、F、Cl、Br、I。
- 环号 (ring-closure digit)
- 断开环边时在两端原子缀记的配对数字,解析时照号连边。
- 手性标记 (@ / @@)
- 相对前一原子视角的配体排列方向编码,随遍历次序改变符号。
- 方向键 (/ 和 \)
- 记录双键两端单键倾斜的符号,成对使用,指明两端取代基在双键的同侧还是异侧。
- 规范 SMILES (canonical SMILES)
- 由确定性算法从全部合法写法中选出的唯一代表串,唯一性仅限算法内部。
- 规范化 (canonicalization)
- 生成规范串的过程:初始不变量划分、迭代细化、择优定序三步。
- InChI (IUPAC International Chemical Identifier)
- 算法由标准固定的化学标识符,跨工具一致,弥补规范 SMILES 的分歧。
- 长程依赖 (long-range dependency)
- 序列中远距离位置相互约束的现象;环号配对是其典型来源。
参考文献与延伸阅读
- Weininger D. 1988. SMILES, a chemical language and information system. 1. Introduction to methodology and encoding rules. Journal of Chemical Information and Computer Sciences 28:31–36.
- Weininger D, Weininger A, Weininger JL. 1989. SMILES. 2. Algorithm for generation of unique SMILES notation. Journal of Chemical Information and Computer Sciences 29:97–101.
- O'Boyle NM. 2012. Towards a universal SMILES representation — a standard method to generate canonical SMILES based on the InChI. Journal of Cheminformatics 4:22.
- Heller SR, McNaught A, Pletnev I, Stein S, Tchekhovskoi D. 2015. InChI, the IUPAC International Chemical Identifier. Journal of Cheminformatics 7:23.
- Daylight Chemical Information Systems. SMILES — A Simplified Chemical Language. Daylight Theory Manual.
- James CA, et al. 2016. OpenSMILES Specification (version 1.0). opensmiles.org——键符号、环号与扩展手性类别的形式文法。
- Landrum G, et al. 2026. RDKit: Open-Source Cheminformatics. RDKit 官方文档(Getting Started · RDKit Book),2026.03 系列.