HTN规划器对比与选择指南

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

系列第八篇。在前面的文章中,我们已经掌握了HTN领域的理论知识和设计方法。本篇将介绍主流的HTN规划器,帮助你选择最适合自己场景的工具。


一、开篇:规划器是HTN的"引擎"

在HTN规划中,规划器(Planner) 是执行任务分解、搜索可行解的核心引擎。

即使你的领域设计得再完美,如果没有合适的规划器,一切都只是"纸上谈兵"。

规划器做什么

输入:领域定义(Domain)+ 问题描述(Problem)
        ↓
规划器执行分解搜索
        ↓
输出:可行的任务执行序列(Plan)

本篇文章目标
- 了解主流HTN规划器的特点
- 掌握选择规划器的方法
- 学会配置和调优的基本技巧


二、主流HTN规划器介绍

2.1 SHOP2

基本信息
- 开发:University of Maryland
- 语言:Common Lisp(JSHOP2)和 Java(SHOP2)
- 特点:最经典、应用最广泛的HTN规划器

核心特点
1. 算法优先:采用任务分解顺序(Task Decomposition Order)策略
2. 支持复杂约束:内置时序约束、资源约束支持
3. 可扩展性强:可自定义推理规则
4. 工业级应用:NASA和ESA的研究项目中有应用案例

优势
- 成熟稳定,文档丰富
- 适合复杂领域(如航天器规划)
- 支持PDDL扩展

劣势
- 安装配置较复杂
- 性能在大规模问题上可能受限

适用场景:学术研究、航天器任务规划、工业级应用


2.2 PyHOP

基本信息
- 开发:Dana Nau(SHOP2作者团队)
- 语言:Python
- 特点:轻量级、教学级HTN规划器

核心特点
1. 纯Python实现:易于安装和使用
2. 代码即领域:用Python代码定义领域和动作
3. 透明可调试:可以单步跟踪规划过程
4. 适合学习:代码简单,适合理解HTN原理

优势
- 安装简单:pip install pyhop
- 调试友好
- 与Python生态系统集成

劣势
- 不支持PDDL
- 性能相对较低
- 不适合大规模复杂问题

适用场景:学习HTN原理、快速原型开发、教学演示

快速上手示例

from pyhop import hop

# 定义原子动作
def slew(state, satellite, target):
    """调整卫星指向目标"""
    if state.satellite_pointing.get(satellite) == target:
        return []  # 已经指向,无需操作
    state.satellite_pointing[satellite] = target
    return state

def take_image(state, satellite, target):
    """拍摄目标图像"""
    if state.satellite_pointing.get(satellite) == target:
        state.target_images[target] = True
        return state
    return False

# 定义方法
def observe_by_satellite(state, satellite, target):
    """观测方法:先调整指向,再拍摄"""
    return [('slew', satellite, target), ('take_image', satellite, target)]

# 注册
hop.declare_operators(slew, take_image)
hop.declare_methods('observe', observe_by_satellite)

result = hop.pyhop(state, [('observe', 'sat1', 'target1')])

2.3 SIADEX

基本信息
- 开发:Technical University of Madrid
- 语言:Java
- 特点:时序感知HTN规划器

核心特点
1. 时序规划结合:HTN + Temporal Planning
2. 支持持续性动作:Durative Actions
3. Timeline优化:适合多智能体协同场景
4. 可视化工具:提供规划过程可视化

优势
- 适合时序敏感的应用
- 支持多智能体规划
- 有友好的IDE支持

劣势
- 社区相对较小
- 文档以西班牙语为主

适用场景:多智能体协同、时序约束敏感的应用

为什么选择SIADEX而不是SHOP2?

场景 推荐 原因
需要同时处理时序约束和HTN分解 SIADEX SHOP2时序扩展不完善
多卫星协同任务 SIADEX Timeline机制天然支持多Agent
只需要HTN分解 SHOP2 社区更大,文档更全

2.4 其他规划器

规划器 语言 特点 适用场景
JSHOP Java SHOP2的Java实现 Java项目集成
PANDA系 Java 分层规划研究平台 学术研究
FF-REPLAN C HTN+经典规划混合(重规划) 混合规划研究

三、规划器对比

3.1 功能对比表

特性 SHOP2 PyHOP SIADEX
语言 Common Lisp / Java Python Java
安装难度 ⭐⭐⭐ ⭐⭐
PDDL支持 ✅ 完整 ✅ 部分
时序约束
资源约束
性能 ⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐
调试友好度 ⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐
社区活跃度 ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐
文档质量 ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐

3.2 选择决策树

需要快速原型/学习?
    │
    ├── 是 → PyHOP
    │
    └── 否 → 需要处理时序约束?
            │
            ├── 是 → SIADEX
            │
            └── 否 → 需要工业级应用?
                    │
                    ├── 是 → SHOP2
                    │
                    └── 否 → PyHOP(轻量级场景)

3.3 选择考量维度

1. 应用场景
- 学习/教学 → PyHOP
- 学术研究 → SHOP2 / PyHOP
- 工业应用 → SHOP2
- 时序敏感 → SIADEX

2. 技术栈
- Python项目 → PyHOP
- Java项目 → SHOP2 / SIADEX
- Lisp项目 → SHOP2

3. 性能需求
- 小规模问题 → PyHOP足够
- 大规模问题 → SHOP2

4. 约束复杂度
- 只需HTN分解 → 任一都行
- 需要时序约束 → SIADEX
- 需要资源约束 → SHOP2


四、规划器配置与调优

4.1 SHOP2配置指南

⚠️ 以下为概念性参数说明,实际SHOP2配置请参考官方文档。

基本配置参数

;; 搜索策略设置(概念性语法)
:plan-generator (make-nhtn-plan-generator
                 :strategy 'depth-first  ; 或 'breadth-first, 'best-first
                 :max-depth 1000
                 :time-bound 30)         ; 超时设置(秒)

;; verbose设置在调用时指定
(plan-all area 'domain 'problem :verbose 3)

调优建议
1. 搜索策略选择
- 深度优先:适合解路径较短的问题
- 广度优先:适合需要完整解空间搜索
- 最佳优先:适合有启发式评估的场景

  1. 超时设置
  2. 交互式应用:设置较短超时(5-10秒)
  3. 批处理应用:可设置较长超时

  4. 内存优化

  5. 限制搜索深度避免内存爆炸
  6. 使用迭代深化(Iterative Deepening)

4.2 PyHOP调试技巧

单步跟踪

# 启用详细输出
pyhop.pyhop(state, tasks, verbose=2)

# 观察每一步的分解过程

常见问题排查

问题 可能原因 解决方法
返回False 没有匹配的method 检查precondition
无限递归 递归method缺少终止条件 添加基础case
解不完整 method覆盖不全 检查所有情况

性能优化

# 使用状态缓存减少重复计算
from functools import lru_cache

@lru_cache(maxsize=1000)
def complex_precondition(state, arg):
    ...

4.3 SIADEX配置要点

⚠️ 以下为概念性配置示例,SIADEX的实际配置文件格式请参考其官方文档。

<!-- 概念性配置示例 -->
<configuration>
    <temporal>true</temporal>
    <duration-constraints>true</duration-constraints>
    <timeline-merge>true</timeline-merge>
</configuration>

性能调优
1. Timeline合并阈值:平衡求解质量与速度
2. 并行搜索:利用多核加速
3. 约束松弛:适当放宽约束加速求解


五、实战:从配置到运行

5.1 PyHOP完整示例

场景:卫星观测任务规划

from pyhop import hop

# 状态定义
class State:
    def __init__(self):
        self.satellite_pointing = {}  # 卫星指向
        self.satellite_energy = {}    # 卫星电量
        self.target_images = {}       # 已成像目标

# 定义原子动作
def slew(state, satellite, target):
    """调整卫星指向目标"""
    if state.satellite_pointing.get(satellite) == target:
        return []  # 已经指向目标,无需操作
    state.satellite_pointing[satellite] = target
    return state

def take_image(state, satellite, target):
    """拍摄目标图像"""
    if state.satellite_pointing.get(satellite) == target:
        state.target_images[target] = True
        return state
    return False

def charge(state, satellite):
    """为卫星充电"""
    if state.satellite_energy.get(satellite, 0) >= 100:
        return []  # 电量已满,无需充电
    state.satellite_energy[satellite] = 100
    return state

# 定义方法
def observe_by_satellite(state, satellite, target):
    """基础观测方法"""
    return [('slew', satellite, target), ('take_image', satellite, target)]

def observe_with_energy(state, satellite, target):
    """带能量管理的观测方法"""
    tasks = []
    if state.satellite_energy.get(satellite, 0) < 10:
        tasks.append(('charge', satellite))
    tasks.extend([('slew', satellite, target), ('take_image', satellite, target)])
    return tasks

# 注册
hop.declare_operators(slew, take_image, charge)
hop.declare_methods('observe', observe_by_satellite, observe_with_energy)

# 执行规划
state = State()
state.satellite_pointing = {'sat1': 'target0'}
state.satellite_energy = {'sat1': 50}
state.target_images = {}

result = hop.pyhop(state, [('observe', 'sat1', 'target1')])
print(result)

💡 说明:PyHOP会自动尝试所有注册的method,选择第一个能成功返回有效计划的。这里的observe_with_energy会在电量不足时自动先充电。

5.2 SHOP2领域文件示例

;; domain file: satellite-domain.pddl
(define (domain satellite-htn)
  (:requirements :htn :typing)
  (:types satellite target mode)

  (:predicates
    (pointing ?s - satellite ?t - target)
    (calibrated ?s - satellite)
    (on-board-storage-full ?s - satellite)
  )

  ;; 原子动作
  (:action slew
    :parameters (?s - satellite ?t - target)
    :precondition (calibrated ?s)
    :effect (pointing ?s ?t)
  )

  (:action take-image
    :parameters (?s - satellite ?t - target ?m - mode)
    :precondition (and (pointing ?s ?t) (calibrated ?s))
    :effect (and (on-board-storage-full ?s) (taken-image ?s ?t ?m))
  )

  ;; HTN方法
  (:method observe-satellite
    :parameters (?s - satellite ?t - target)
    :precondition (calibrated ?s)
    :tasks ((slew ?s ?t) (take-image ?s ?t HIGH_RES))
  )
)

六、总结与展望

6.1 核心要点回顾

规划器 核心优势 最佳场景
SHOP2 功能完整、工业级 复杂领域、工业应用
PyHOP 轻量、调试友好 学习、原型开发
SIADEX 时序感知 多智能体、时序敏感

选择建议
- 入门学习 → PyHOP
- 科研论文 → SHOP2(可复现)
- 工程落地 → SHOP2 + 定制开发
- 时序约束强 → SIADEX

6.2 下一步

本系列HTN规划专栏至此已覆盖:
- ✅ 理论基础(形式化定义、TFD算法)
- ✅ 表达能力与不可判定性
- ✅ 领域设计实践
- ✅ 规划器选择与配置

后续可能的主题
- HTN与经典规划器的对比
- 前沿:HTN规划的启发式方法
- 前沿:学习增强的HTN规划


参考文献

  1. Nau, D. S., Au, T. C., Ilghami, O., Kuter, U., et al. (2003). SHOP2: An HTN planning system. JAIR, 20, 379-404.
  2. PyHOP Documentation. https://github.com
  3. SIADEX Project. Technical University of Madrid.
  4. Alford, R., Kuter, U., & Nau, D. S. (2009). Planning as homotopy of task networks. ICAPS.