Skip to content

第 07 章:现实引力:分子可合成性量化与计算机辅助逆合成规划 (CASP)

“计算机可以在一微秒内画出一个在对接评分中击败所有已知药物的完美三维分子;
但如果连诺贝尔奖得主级别的全合成大师在实验室里耗费十年也无法将它合成出来,
那么它在现实世界中的价值便等于零。”


1. 引言:警惕算法世界里的“纸上科学怪人”

在早期基于自回归、变分自编码器或强化学习的分子生成研究中,研究人员经常欣喜若狂地发现:经过多轮性质优化后,模型生成了一批在 QSPR 性质预测器上“得分逆天”的神奇结构。

然而,当这些结构被打印出来递给经验丰富的药物化学家时,往往会引来无情的嘲笑:

  • 这些结构里塞满了彼此紧挨的八元扭曲桥环;
  • 结构的核心被极度拥挤的季碳立体手性中心(Quaternary Stereocenters)填死,原子轨道张力能极其巨大;
  • 甚至散布着多个相邻的过氧键(OO-O-O-)、高活性重氮基或多聚叠氮骨架(在现实中只要稍微晃动烧瓶就会剧烈爆炸!)。

这种现象被称为生成模型的“合成盲区投毒”。生成模型为了钻属性预测器的评分空子,会自发探索真实化学库中从未出现过的极端高能畸变区域。

要让逆向设计真正落地于制药与精细化工,我们必须在生成环路中建立两道严密的防线:

  1. 轻量级启发式可合成性过滤器:在毫秒级内剔除不可合成的畸变拓扑(如 SAScore, SYBA, SCScore);
  2. 重度计算机辅助逆合成规划(CASP):为筛选出的顶级候选者规划出一条从廉价市售原料出发、步步可行的全合成路线!

2. 启发式合成可达性(Synthesizability)的量化评估体系

为了在成千上万个生成候选样本中实时把关,学界建立了一系列兼顾速度与准度的可合成性量化指标。

2.1 SAScore(Synthetic Accessibility Score,Ertl 等人 2009)

由著名化学信息学家 Peter Ertl 提出的 SAScore,是目前制药界最广泛使用的工业标准:

SAScore=FragmentScoreComplexityPenalty\text{SAScore} = \text{FragmentScore} - \text{ComplexityPenalty}

  1. 片段贡献分(Fragment Score): 将分子拆解为摩根分子指纹(如半径为 2 的 Circular Fingerprints / ECFP4 片段)。在大规模公开化合物库(如包含数千万分子的 PubChem)中预先统计各个片段的出现频次 ff

    Si=log(fijfj)S_i = \log \left( \frac{f_i}{\sum_j f_j} \right)

    常见、通用的有机化学砌块(如苯环、甲基、酰胺基)赋予极高的正向分数,而罕见奇异片段赋予惩罚负分;
  2. 结构复杂度惩罚项(Complexity Penalty): 对分子的拓扑奇点施加几何惩罚:
    • 环系统复杂度(大环、扭曲桥环、螺环数量);
    • 连续立体异构手性中心数(Stereocenters);
    • 超大骨架或非生理原子比例;
  3. 分值映射:最终经线性变换映射为 1(代表极易合成的简单分子)至 10(代表结构极度繁琐的天然产物全合成噩梦)。在工业级筛选中,通常要求生成分子的 SAScore4.5\text{SAScore} \le 4.5

图 7-1:已知成药化合物库与无约束 AI 幻觉分子的合成可达性(SAScore)分布对比与阈值筛选


2.2 SCScore(Synthetic Complexity Score,Coley & Jensen 2018,Science)

麻省理工学院 Connor Coley 等人在 JCIMScience 上指出:SAScore 依赖人工专家设定的惩罚权重,且缺乏对“实际化学反应逻辑”的动态感知。

他们提出了基于深度排序网络的 SCScore

  • 物理先验假定:在一场真实的有机合成反应中:

    反应物 A+B催化剂Δ 产物 C\text{反应物 } A + B \xrightarrow[\text{催化剂}]{\Delta} \text{ 产物 } C

    产物 CC 的合成复杂度在统计上几乎必然大于其前体原料 AABB
  • 基于 Reaxys 千万级反应的自监督训练: 模型无需任何人工打分标注,仅仅依靠数十万篇化学文献中记录的前向反应对 (A,C)(A, C) 进行二元成对排序(Pairwise Ranking)学习:

    LRank(θ)=log(1+exp((fθ(C)fθ(A))))\mathcal{L}_{\text{Rank}}(\theta) = \log\left( 1 + \exp\left( - (f_\theta(C) - f_\theta(A)) \right) \right)

    训练出的网络能够输出 1 到 5 之间的连续数值,准确反映从商品原料到复杂终端分子所需的潜在合成难度。

3. 计算机辅助逆合成规划(CASP)的数理本质

如果说 SAScore 是一张“体检报告”,那么**计算机辅助逆合成规划(Computer-Aided Synthesis Planning, CASP)**则是给化学家开出的“手术操作指南”。

3.1 科里(E. J. Corey)逆合成分析的断键哲学

1990 年,E. J. Corey 凭借确立**逆合成分析理论(Retrosynthetic Analysis)**荣获诺贝尔化学奖。其核心思维哲学是:

  • 从目标分子(Target Molecule)出发,在关键化学键处进行逻辑上的虚拟切断(Disconnection);
  • 将目标分子反向拆解为更小的理想化离子碎片——合成子(Synthons)
  • 寻找与合成子电荷相匹配的实际化学试剂——合成等价物(Synthetic Equivalents)
  • 周而复始迭代拆解,直至所有分支的终端全部落入货架上随时可以买到的“市售商业原料库(Building Blocks)”。

图 7-2:计算机辅助逆合成分析(CASP)与蒙特卡洛树搜索(MCTS)反应路径规划示意图


3.2 逆合成三大核心算法派系

  1. 基于反应模板的匹配法(Rule-based Template Matching): 从文献中自动抽取 SMARTS 反应规则模板(例如:羧酸与胺在缩合剂下生成酰胺键的通用模式)。优点是物理可解释性极强,缺点是无法泛化到模板库之外的全新反应;
  2. 无模板神经机器翻译法(Template-Free Neural Machine Translation): 将逆合成直接视为语言翻译任务:输入产物的 SMILES 序列,由 Transformer Seq2Seq 模型直接“翻译”出前体反应物的 SMILES 序列。优点是端到端灵活,缺点是容易偶发幻觉生成不守恒的原子;
  3. 基于蒙特卡洛树搜索的路径规划(MCTS + 3N Network,Segler et al., Nature 2018): Segler 等人将 AlphaGo 的博弈搜索框架成功迁移至化学逆合成,构建了现代 CASP 的行业基石:
    • 展开网络(Expansion Network):预测当前分子可能进行的反向断键候选动作;
    • 筛选网络(Filter Network):过滤在化学热力学上被副反应干扰的无效路径;
    • MCTS 树搜索:平衡广度探索与深度利用,在指数爆炸的反应路径树中迅速搜索出一条步数最短、总产率最高且原料最廉价的合成路线。

4. 工业级代码实战:分子复杂度与反应逆断键分析器

下面我们使用 Python 与 RDKit 构建一个轻量级的分子合成可达性分析器与单步逆合成断键推断原型

python
"""
文件名: molecular_synthesizability_analyzer.py
功能: 实现基于 RDKit 的分子合成复杂度评估器 (环张力、手性中心与杂原子比),
      并构建一个基于化学反应模板 (SMARTS) 的单步逆合成断键推断引擎。
"""

from rdkit import Chem
from rdkit.Chem import Descriptors, rdchem
from rdkit.Chem import rdChemReactions


class MolecularSynthesizabilityAnalyzer:
    """
    分子合成可达性与复杂度综合多维质检器
    """
    @staticmethod
    def analyze_complexity(mol: Chem.Mol) -> dict:
        """多维度量化分子的结构合成复杂度"""
        # 1. 基础物理指标
        mw = Descriptors.MolWt(mol)
        tpsa = Descriptors.TPSA(mol)
        logp = Descriptors.MolLogP(mol)
        rotatable_bonds = Descriptors.NumRotatableBonds(mol)

        # 2. 环系统分析 (小环与大环应变能)
        ring_info = mol.GetRingInfo()
        num_rings = ring_info.NumRings()
        ring_sizes = [len(r) for r in ring_info.AtomRings()]
        # 3元环与4元环由于角张力极大,合成通常难度剧增
        strained_small_rings = sum(1 for s in ring_sizes if s in [3, 4])
        macrocycles = sum(1 for s in ring_sizes if s >= 9)

        # 3. 立体化学复杂度 (手性中心计数)
        chiral_centers = Chem.FindMolChiralCenters(mol, includeUnassigned=True)
        num_chiral = len(chiral_centers)

        # 4. 启发式综合复杂度评分 (归一化至 1~10 标尺, 越低越易合成)
        # 基础复杂度基线
        raw_score = 1.0
        raw_score += (mw / 150.0) * 0.8
        raw_score += strained_small_rings * 1.5
        raw_score += macrocycles * 2.0
        raw_score += num_chiral * 0.75
        raw_score += (num_rings / 3.0) * 0.5

        final_sascore = min(10.0, max(1.0, raw_score))

        return {
            "molecular_weight": mw,
            "logP": logp,
            "tpsa": tpsa,
            "num_rings": num_rings,
            "strained_small_rings": strained_small_rings,
            "chiral_centers_count": num_chiral,
            "heuristic_sascore": round(final_sascore, 2),
            "is_synthetically_accessible": bool(final_sascore <= 4.5)
        }


class RetrosyntheticDisconnector:
    """
    基于 SMARTS 反应模板的单步逆合成断键引擎
    """
    def __init__(self):
        # 定义常见经典合成反应的“反向断键模板”
        # 模板 1: 酰胺键逆断键 (Amide Disconnection: R-C(=O)-NH-R' -> R-C(=O)OH + H2N-R')
        self.amide_retro = rdChemReactions.ReactionFromSmarts(
            "[C:1](=[O:2])-[N;H1,H0:3]>>[C:1](=[O:2])-[OH].[N:3]-[H]"
        )
        # 模板 2: 酯键水解逆断键 (Ester Disconnection: R-C(=O)-O-R' -> R-C(=O)OH + HO-R')
        self.ester_retro = rdChemReactions.ReactionFromSmarts(
            "[C:1](=[O:2])-[O:3]-[C:4]>>[C:1](=[O:2])-[OH].[O:3](-[H])-[C:4]"
        )

    def retro_disconnect(self, mol: Chem.Mol) -> list:
        """尝试对输入目标分子执行单步逆合成拆解"""
        disconnections = []

        # 尝试酰胺键断键
        products_amide = self.amide_retro.RunReactants((mol,))
        for prod_tuple in products_amide:
            precursor_smiles = [Chem.MolToSmiles(m) for m in prod_tuple]
            disconnections.append({
                "reaction_type": "Amide_Condensation_Retro",
                "precursors": precursor_smiles
            })

        # 尝试酯键断键
        products_ester = self.ester_retro.RunReactants((mol,))
        for prod_tuple in products_ester:
            precursor_smiles = [Chem.MolToSmiles(m) for m in prod_tuple]
            disconnections.append({
                "reaction_type": "Esterification_Retro",
                "precursors": precursor_smiles
            })

        return disconnections


# =====================================================================
# 单元验证模块: 对比“高可合成性药物”与“荒谬纸上怪兽”的质检差异
# =====================================================================
if __name__ == "__main__":
    print(">>> [STEP 1] 评估真实商品药物分子 (对乙酰氨基酚 Paracetamol)...")
    smiles_good = "CC(=O)Nc1ccc(O)cc1"  # 对乙酰氨基酚
    mol_good = Chem.MolFromSmiles(smiles_good)
    res_good = MolecularSynthesizabilityAnalyzer.analyze_complexity(mol_good)

    print(f"    对乙酰氨基酚分析结果:")
    print(f"    - 分子量: {res_good['molecular_weight']:.1f}, 环数: {res_good['num_rings']}")
    print(f"    - 手性中心数: {res_good['chiral_centers_count']}, 启发式 SAScore: {res_good['heuristic_sascore']}")
    print(f"    - 是否具备高可合成性: {res_good['is_synthetically_accessible']}")

    print("\n>>> [STEP 2] 评估算法盲目拟合产生的‘化学怪物分子’ (高度扭曲与多手性中心)...")
    # 一个包含了三元高张力环、连续手性中心与繁琐桥环的构型
    smiles_bad = "CC12CC3(CC1)C(C2)C34C5C(C4)C5"
    mol_bad = Chem.MolFromSmiles(smiles_bad)
    res_bad = MolecularSynthesizabilityAnalyzer.analyze_complexity(mol_bad)

    print(f"    怪物分子分析结果:")
    print(f"    - 分子量: {res_bad['molecular_weight']:.1f}, 环数: {res_bad['num_rings']}")
    print(f"    - 强张力小环数: {res_bad['strained_small_rings']}, 启发式 SAScore: {res_bad['heuristic_sascore']}")
    print(f"    - 是否具备高可合成性: {res_bad['is_synthetically_accessible']}")

    assert res_good['heuristic_sascore'] < res_bad['heuristic_sascore'], "合成复杂度打分逻辑颠倒!"

    print("\n>>> [STEP 3] 执行对乙酰氨基酚的自动化单步逆合成断键推导...")
    retro_engine = RetrosyntheticDisconnector()
    disconnections = retro_engine.retro_disconnect(mol_good)

    print(f"    成功匹配到 {len(disconnections)} 条经典逆断键反应途径:")
    for i, d in enumerate(disconnections, 1):
        print(f"    途径 {i} [{d['reaction_type']}]:")
        print(f"      前体 1: {d['precursors'][0]} (乙酸/乙酰试剂)")
        print(f"      前体 2: {d['precursors'][1]} (对氨基苯酚市售原料)")

    assert len(disconnections) > 0, "未能识别出对乙酰氨基酚的酰胺逆断键路线!"
    print("\n>>> [SUCCESS] 分子合成可达性质检与逆合成断键模块单元测试全部通过!")

5. 本章小结

本章为有机小分子与功能聚合物的逆向设计构筑了抵御“纸上空谈”的防线:

  1. 揭露了算法盲区投毒本质:分析了为什么性质预测器的高分区域往往是合成化学的“死区”;
  2. 构建了轻量级可合成性过滤器:解析了 SAScore 常见片段统计频次、环张力复杂度惩罚与 SCScore 反应步长深度排序的数学逻辑;
  3. 溯源了科里逆合成分析的断键哲学:系统梳理了反应模板匹配与 MCTS 树搜索在自动化路线规划中的应用;
  4. 交付了可测试的逆合成原型:编写并验证了从分子复杂度量化到单步逆合成断键的完整 Python 引擎。

现在,我们已经在数字世界中完成了生成设计、流形优化、凸包检验与合成规划。但这依然停留在虚拟磁盘中。

如何推开机房大门,让算法直接调遣机械臂、马弗炉与高通量 XRD,迈向人类历史上最壮阔的实体智能发现闭环?

请进入 第 08 章:自驱动无人自主实验室(从生成算法到物理闭环)

《原子智能》· 纸质出版预备版 · PolyAI Team 著