HTN规划的不可判定性:理论边界与工程启示

2026-08-28 Updated 2026-08-28 29 min read 0 views

系列第五篇,深入探讨HTN规划的理论极限。如果你还没读过前面的文章,建议先从[任务规划概述]、[HTN形式化定义]、[STN与HTN的区别]、[TFD算法详解]开始。


一、开篇:从TFD到理论边界

在上一篇文章中,我们详细介绍了TFD(全序向前分解)算法——STN规划的核心方法。TFD的优势显而易见:状态确定性让数值计算变得简单,全序约束让搜索空间相对可控,清晰的算法流程让工程实现变得直接。

但如果我们把目光从STN转向更一般的HTN(分层任务网络),情况就变得复杂了。

HTN引入了状态维持约束(modal constraints / temporal constraints)——比如"在整个数据传输期间,天线必须始终指向地面站"。这种约束极大地增强了表达能力,但也带来了一个根本性的问题:

HTN规划问题是不可判定的。

这意味着什么?为什么STN可判定而HTN不可判定?这对我们的工程实践又有什么影响?本文将系统地回答这些问题。


二、什么是"不可判定性"?

在深入HTN之前,我们需要先理解"不可判定性"(Undecidability)这个概念。

2.1 可判定 vs 不可判定

在计算理论中,一个问题被称为可判定的(Decidable),如果存在一个算法,能够在有限时间内对任意输入给出"是"或"否"的答案。

相反,如果不存在这样的算法,这个问题就是不可判定的(Undecidable)。

注意:不可判定不等于"很难"。NP难问题虽然很难(需要指数时间),但至少存在算法可以解决。不可判定问题则是根本不存在这样的算法。

2.2 经典例子:停机问题

最著名的不可判定问题是停机问题(Halting Problem):

给定一个程序P和输入I,判断P在输入I上是否会停机(结束运行),还是会无限循环。

图灵在1936年证明了:不存在一个通用算法能解决所有程序的停机问题。

证明思路很巧妙:假设存在这样的算法H(P, I),我们可以构造一个程序Q:

Q(P):
    if H(P, P) == "会停机":
        无限循环
    else:
        立即停机

现在问:Q(Q)会停机吗?
- 如果H说Q(Q)会停机,那么Q就会无限循环——矛盾!
- 如果H说Q(Q)不会停机,那么Q就会立即停机——也矛盾!

所以H不可能存在。

2.3 计算复杂性层级

为了更好地理解不可判定性的位置,我们来看计算复杂性层级:

P ⊆ NP ⊆ PSPACE ⊆ EXPTIME ⊆ NEXPTIME ⊆ ... ⊆ 可判定问题 ⊆ 所有问题
                                              ↑
                                         不可判定问题在此之外
  • P:多项式时间可解
  • NP:多项式时间可验证
  • PSPACE:多项式空间可解
  • EXPTIME:指数时间可解
  • 可判定问题:存在算法(无论多慢)
  • 不可判定问题:不存在算法

HTN规划就位于这个层级的最外层——不可判定


三、HTN为什么是不可判定的?

3.1 核心原因:状态维持约束

HTN与STN的根本区别在于状态维持约束(modal constraints)。这种约束要求:

在某个任务执行期间,某个条件必须始终保持成立。

例如:
- "在数据传输期间,天线必须始终指向地面站"
- "在机动过程中,电量必须始终保持在20%以上"

这种约束引入了时间维度上的复杂性。在STN中,我们知道每个任务执行时的确切状态;但在HTN中,我们需要考虑一段时间区间内的状态变化

3.2 证明思路:归约到Post对应问题

Erol、Hendler和Nau在1996年的经典论文中证明了HTN的不可判定性。他们的证明思路是归约(reduction):

证明:如果HTN规划是可判定的,那么Post对应问题(PCP)也是可判定的。但PCP是已知的不可判定问题,所以HTN也是不可判定的。

Post对应问题(Post Correspondence Problem, PCP):

给定一组多米诺骨牌,每张骨牌上面有两个字符串(上串和下串):

骨牌1: [aa, a]
骨牌2: [b, ab]
骨牌3: [bba, bb]

问:是否存在一个骨牌序列(允许重复),使得上串拼接结果等于下串拼接结果?

例如上面的例子,序列[1, 3]:
- 上串:aa + bba = aabba
- 下串:a + bb = abb
不相等。

PCP被证明是不可判定的——不存在通用算法能判断任意PCP实例是否有解。

3.3 HTN如何模拟PCP

关键在于:状态维持约束让HTN能够模拟PCP的字符串拼接过程

大致思路:
1. 用状态变量表示当前的上串和下串
2. 用方法表示选择骨牌
3. 用状态维持约束确保字符串的"累积"过程
4. 用目标条件检查上串是否等于下串

简化示例(帮助理解,非严格证明):

假设有一个简化的PCP实例:

骨牌1: [a, ab]
骨牌2: [b, a]

我们可以构造对应的HTN问题:

;; 状态变量
(current-top "")      ; 当前上串
(current-bottom "")   ; 当前下串

;; 方法:选择骨牌1
(:method (select-domino)
  :precondition ()
  :tasks (!append-top "a")
          (!append-bottom "ab")
  :constraint (during task current-top保持累积))

;; 方法:选择骨牌2  
(:method (select-domino)
  :precondition ()
  :tasks (!append-top "b")
          (!append-bottom "a")
  :constraint (during task current-top保持累积))

;; 目标:上串等于下串
(:goal (equal current-top current-bottom))

这里的核心在于:constraint (during ...)——状态维持约束让HTN能够在任务执行期间"记住"并累积字符串。正是这种约束使HTN具备了模拟图灵机的能力。

由于PCP不可判定,能模拟PCP的HTN也不可判定。

:由于篇幅限制,此处为简化说明。严格的技术证明涉及将图灵机编码为HTN问题,感兴趣的读者请参考 Erol et al. (1996) 的原始论文。

3.4 关键定理

定理(Erol et al., 1996):

HTN规划问题是不可判定的,即使限制为:
- 命题逻辑(无变量)
- 有限的方法集合
- 无递归(方法不直接或间接调用自身)

这个结论非常强烈:即使做了这么多限制,HTN仍然是不可判定的。

3.5 不可判定性的具体表现

不可判定性在实际中意味着什么?

  1. 无法判断问题是否有解:不存在通用算法能判断任意HTN问题是否有解
  2. 规划器可能永远运行:对于某些输入,规划器可能既找不到解,也无法证明无解
  3. 完备性与效率的权衡:我们必须在算法完备性(找到所有解)和计算效率之间做出选择

3.5.1 什么是完备性(Completeness)?

在规划领域,完备性指的是:

如果解存在,算法一定能找到;如果不存在,算法一定能证明无解。

对于可判定问题(如STN),我们可以设计完备算法。但对于不可判定问题(如HTN),不存在完备的通用算法

3.5.2 SHOP2 为什么放弃完备性?

SHOP2 采用的是深度优先搜索,它:
- ✅ 优点:速度快,内存占用小,适合大规模问题
- ❌ 缺点:不是完备的——可能因为搜索顺序问题错过解

为什么做这种选择?

因为在实际工程应用中:
1. 时间比完备性更重要:用户通常愿意接受"大概率找到的解",而不是等待"保证找到所有解"
2. 启发式剪枝非常有效:领域知识可以指导搜索到高质量解
3. 问题本身就有约束:实际任务规划问题通常有资源、时间限制,天然限制了搜索空间

3.5.3 追求完备性需要什么?

理论上,如果要设计一个完备的HTN规划器,需要:
- 广度优先搜索:保证找到最短解,但内存爆炸
- 无限时间和空间:对于不可判定问题,完备算法可能永不停止
- 严格的深度限制:人为限制搜索深度,但这又牺牲了完备性

所以在实践中,所有HTN规划器都在完备性和实用性之间做出了权衡


四、STN为什么是可判定的?

4.1 核心区别:没有状态维持约束

STN(Simple Task Network)之所以可判定,是因为它不支持状态维持约束。STN只支持:
- 顺序约束(任务A在任务B之前)
- 变量绑定约束

这看似是一个很大的限制,但实际上让问题变得可处理。

4.2 可判定性来源

第一,可以转换为经典规划问题

STN问题可以转换为经典STRIPS规划问题:
- 每个任务对应一个操作
- 方法的分解对应于操作序列的展开
- 由于是全序的,可以预先展开所有可能的分解树

第二,TFD算法可以穷尽搜索

TFD算法的搜索空间虽然是指数级的,但是有限的
- 每个复合任务只有有限个分解方法
- 每次分解都会增加任务数量
- 由于无递归(假设方法不循环调用),分解深度是有限的

所以TFD可以在有限时间内穷尽所有可能性,从而判定问题是否有解。

4.3 复杂度分析

虽然STN是可判定的,但它的复杂度仍然很高:

  • 最坏情况下是EXPTIME-complete:搜索空间随任务数量指数增长
  • 实际中通常是PSPACE-complete或更低:对于特定领域可以设计更高效算法

但至少,我们知道算法一定会停机——要么找到解,要么证明无解。


五、HTN vs STN 对比总结

特性 HTN STN
状态维持约束 ✅ 支持 ❌ 不支持
可判定性 ❌ 不可判定 ✅ 可判定
表达能力 更强(可表达时序约束) 受限(仅顺序约束)
算法完备性 无法保证 可以保证
搜索空间 可能无限 有限(给定有限分解)
工程应用 需要启发式/近似 可精确求解

5.1 表达能力对比

HTN能表达STN不能表达的场景:

# HTN可以表达:在数据传输期间保持指向
[task: 传输数据]
constraint: during(task, pointing == ground_station)

# STN的表达局限:
# 只能分解为两个顺序任务,但无法保证"传输期间"始终指向
# 如果传输过程中姿态被其他任务改变,STN无法检测这种违规
[task1: 指向地面站]
[task2: 传输数据]
order: task1 < task2
# ❌ 没有机制确保 task2 执行期间 pointing 保持为 ground_station

4.4 复杂度对比表

特性 STN HTN
可判定性 ✅ 可判定 ❌ 不可判定
最坏时间复杂度 EXPTIME-complete 不可判定(无上限)
实际常用算法 TFD(完备) SHOP2(启发式,不完备)
状态维持约束 ❌ 不支持 ✅ 支持
搜索空间 有限(可穷尽) 可能无限
完备性保证
实际适用场景 航天器任务规划(顺序为主) 复杂时序约束场景

关键洞察
- STN 牺牲表达能力换取可判定性和完备性
- HTN 保留表达能力但接受不可判定性和启发式求解


5.2 实际影响

在航天任务规划中,这种差异非常重要:
- 如果需要"姿态始终稳定"、"电量始终充足"这类约束,必须用HTN
- 如果只是"先做这个,再做那个",STN就够了


六、这对工程实践意味着什么?

6.1 理论不可判定 ≠ 工程不可用

这是最重要的一点。不可判定性是一个理论结果,不意味着HTN在工程中不能用

事实上,SHOP、SHOP2、SIADEX等HTN规划器在航天、应急管理等实际应用中表现很好。

6.2 实际应对策略

工程实践中,我们常用以下策略应对不可判定性:

策略1:限制方法深度(Bounded Depth)

设置最大分解深度,超过就停止搜索。这保证了算法会停机,但可能错过深层解。

def plan_htn(state, task_network, max_depth=10):
    if max_depth <= 0:
        return None  # 达到深度限制,放弃
    # ... 正常规划逻辑

策略2:使用启发式搜索(Heuristic Search)

用启发式函数指导搜索,优先探索更有希望的路径。这不保证找到最优解,但通常能找到满意解。

策略3:领域特定的约束检查

在问题定义阶段就加入领域知识,剪枝不可能的搜索分支。

策略4:超时机制(Timeout)

设置时间上限,超时则返回当前找到的最佳解(或报告失败)。

import time

def plan_with_timeout(state, task_network, timeout=60):
    start = time.time()
    while time.time() - start < timeout:
        solution = search_one_solution(state, task_network)
        if solution:
            return solution
    return None  # 超时,未找到解

6.3 SHOP/SHOP2的实践智慧

SHOP和SHOP2是HTN规划的经典实现,它们的作者Nau等人对不可判定性有深刻的理解:

"我们接受规划器的不完备性,以换取实用性。"

SHOP2的设计原则:
- 使用深度优先搜索(可能错过最优解,但速度快)
- 支持外部函数调用(用领域知识剪枝)
- 允许用户定义启发式函数

这些设计都是在"理论不可判定"的限制下,追求"工程可用"的折中。

6.4 选择HTN还是STN?

实际项目中如何选择?

选择STN,如果:
- 任务之间有明确的先后顺序,没有复杂的时序约束
- 需要算法的完备性保证
- 问题规模较小,可以接受指数级搜索

选择HTN,如果:
- 需要表达"期间维持"、"并行约束"等复杂时序关系
- 问题规模较大,需要启发式剪枝
- 可以接受不完备性,换取表达能力


七、总结

7.1 核心要点

  1. HTN规划是不可判定的:不存在通用算法能判断任意HTN问题是否有解
  2. 根本原因是状态维持约束:这种约束让HTN能模拟图灵机,从而具有计算完备性
  3. STN是可判定的:因为没有状态维持约束,搜索空间有限
  4. 理论不限制工程应用:通过限制深度、超时机制、启发式搜索等策略,HTN在实践中完全可用

7.2 与前面文章的关系

[任务规划概述] → [HTN形式化定义] → [STN与HTN区别] → [TFD算法] → [本文: 不可判定性]
                                                    ↓
                                           理解了为什么需要更复杂的算法

前面我们学了STN的TFD算法——简单、高效、可判定。本文解释了为什么要发明更复杂的HTN算法:因为STN的表达能力不够,而HTN虽然不可判定,但工程上可以通过各种策略来应对。

7.3 工程启示

理解HTN的不可判定性,对工程实践有几个重要启示:

  1. 不要追求理论完备性:在实际应用中,"足够好"的解往往比"最优"的解更有价值
  2. 充分利用领域知识:启发式函数、约束检查等都可以显著提高规划效率
  3. 设置合理的终止条件:超时、深度限制等都是必要的工程手段
  4. 选择合适的工具:不是所有问题都需要HTN的表达能力,有时候STN就够了

参考文献

  1. Erol, K., Hendler, J., & Nau, D. S. (1996). Complexity results for HTN planning. Annals of Mathematics and Artificial Intelligence, 18(1), 69-93.
  2. Erol, K., Hendler, J., & Nau, D. S. (1994). HTN Planning: Complexity and Expressivity. Proceedings of the 12th National Conference on Artificial Intelligence (AAAI-94), 1123-1128.
  3. Post, E. L. (1946). A variant of a recursively unsolvable problem. Bulletin of the American Mathematical Society, 52(4), 264-268.
  4. Nau, D. S., et al. (2003). SHOP2: An HTN planning system. Journal of Artificial Intelligence Research, 20, 379-404.
  5. Ghallab, M., Nau, D., & Traverso, P. (2004). Automated Planning: Theory and Practice. Morgan Kaufmann. (Chapter 11)