【MAPF】ECBS 算法:基于冲突搜索的有界次优多智能体路径规划

📢 本篇文章是博主多智能体路径规划(MAPF)领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在👉 强化学习 专栏:

【MAPF】多智能体路径规划—(3)《ECBS 算法:基于冲突搜索的有界次优多智能体路径规划》


目录


1. 算法背景:从 CBS 到有界次优搜索

1.1 回顾 CBS 的核心思想

CBS(Conflict-Based Search)是 MAPF 领域的经典最优算法,其核心可以用一句话概括:

两层搜索,冲突驱动:高层在约束树上分裂冲突,低层用 A* 求解单智能体路径。

回顾 CBS 的两个关键特点:

  • 最优性:CBS 能保证找到全局 SOC(Sum of Costs)最小的解
  • 完备性:只要有解,CBS 一定能找到

但 CBS 有一个致命缺点:计算代价高昂

1.2 CBS 的瓶颈:为什么需要"次优"?

CBS 为了追求最优性,会在约束树上展开大量节点。当智能体数量增多时,约束树的大小会呈指数级膨胀,导致计算时间不可接受。

举一个直观的例子:

10 个智能体在 20×20 的地图上:
CBS 可能需要展开数千个 CT 节点,每个节点的低层 A* 还需对单个智能体重新规划
总耗时可能达到分钟级甚至更久

然而在很多实际场景中,并不需要绝对的最优解。例如:

  • 仓储 AGV 调度:路径稍长一点但能快速算出来 > 等半天算出最短路径
  • 游戏 NPC 寻路:允许一定程度的非最优,换取实时性
  • 无人机编队:动态环境下的快速重规划比精确最优更关键

这就引出了一个问题:能不能在 CBS 的框架下,牺牲一点解的代价,换取大幅度的速度提升?

这就是 ECBS(Enhanced CBS) 要解决的核心问题。

1.3 有界次优的形式化定义

在深入 ECBS 之前,先明确"有界次优"的含义。

设:

  • C ∗ C^* C = 问题的最优解代价(最优 SOC)
  • C C C = 算法找到的解的代价
  • w w w = 次优性上界因子( w ≥ 1 w \geq 1 w1

则有界次优保证:

C ≤ w ⋅ C ∗ C \leq w \cdot C^* CwC

也就是说:

算法找到的解的代价,不会超过最优解的 w w w 倍。

这就像是给算法"松了绑":允许在最优解的 w w w 倍范围内自由搜索,从而大幅减少搜索空间。

ECBS 之于 CBS,正如 A ϵ ∗ A^*_\epsilon Aϵ 之于 A ∗ A^* A——都是有界次优搜索在 MAPF 上下文中的应用。


2. ECBS 算法核心思想

2.1 从 A* 到 A*ε 的启示

经典 A* 用 f ( n ) = g ( n ) + h ( n ) f(n) = g(n) + h(n) f(n)=g(n)+h(n) 评估节点,在 OPEN 中选 f f f 最小的来扩展。

A ϵ ∗ A^*_\epsilon Aϵ(epsilon-A*)则引入了一个放松因子 ϵ ≥ 1 \epsilon \geq 1 ϵ1,用加权启发式:

f ϵ ( n ) = g ( n ) + ϵ ⋅ h ( n ) f_\epsilon(n) = g(n) + \epsilon \cdot h(n) fϵ(n)=g(n)+ϵh(n)

核心思想:膨胀启发式函数,让算法更"激进"地向目标方向搜索,减少扩展的节点数。

但是 A ϵ ∗ A^*_\epsilon Aϵ 本身不是有界次优的——它需要一个 FOCAL 列表来保证次优界。

Focal Search 正是弥补这一点的机制。

2.2 Focal Search:在候选集中用辅助标准选择

Focal Search 维护两个列表:

列表 含义 排序标准
OPEN 所有待扩展节点 f m i n f_{min} fmin(或 f 1 f_1 f1)排序——主标准
FOCAL OPEN 的子集: f 1 ( n ) ≤ w ⋅ f 1 m i n f_1(n) \leq w \cdot f_{1}^{min} f1(n)wf1min 的那些节点 按辅助标准 f 2 f_2 f2 排序——辅助标准

其中:

  • f 1 ( n ) f_1(n) f1(n) = 主代价评估函数(通常是 f f f
  • f 1 m i n f_{1}^{min} f1min = OPEN 中当前最小的 f 1 f_1 f1
  • w w w = 次优性权重( w ≥ 1 w \geq 1 w1
  • f 2 ( n ) f_2(n) f2(n) = 辅助评估函数(用于在 FOCAL 里挑"好"节点)

FOCAL 的核心直觉

OPEN 里的节点按 f 排序,选最小的最"便宜"
FOCAL 在 f 不太大(≤ w·f_min)的那些便宜节点里,
用另一个标准(比如冲突数、剩余步估算等)挑一个"更聪明"的

这样一来,虽然不选全局最便宜的节点,但也保证所选节点不贵得太离谱(不超过 w w w 倍),从而确保有界次优。

2.3 双层 Focal Search 的整体架构

ECBS 在 CBS 的两层次上都应用了 Focal Search:

高层(约束树搜索):
  OPEN_CT 按代价排序 → FOCAL_CT 按冲突数选节点
  
低层(单智能体路径搜索):
  OPEN_agent 按 f 排序 → FOCAL_agent 按 h 选节点

ECBS 的独特之处在于:低层不仅返回路径代价,还会返回一个 下界值 L B ( a g e n t ) LB(agent) LB(agent) ,这个下界会传递到高层,帮助高层更精确地计算整体下界,从而收紧次优性边界。

整体流程示意:

每个智能体的局部观测 + 约束
        ↓
   低层 Focal Search(A*_ε 变体)
   返回:路径代价 + 下界 LB(agent)
        ↓
   高层约束树搜索(FOCAL)
   利用 LB 累加计算全局下界
        ↓
   冲突检测 & 分裂子节点
        ↓
   输出:有界次优解

在这里插入图片描述


3. 从 GCBS → BCBS → ECBS:演进路线

ECBS 的论文原题为《Suboptimal Variants of the Conflict-Based Search Algorithm for the Multi-Agent Pathfinding Problem》,实际上是一条逐步演进的路线。理清这条路线,才能理解 ECBS 的设计动机。

在这里插入图片描述

3.1 GCBS(Greedy-CBS):顶层与底层的双重松弛

GCBS 的目标是 最快找到解,不保证任何次优界

顶层松弛:高层不再按代价选节点,而是按 冲突数 h c h_c hc 选。冲突越少的节点越先扩展。

几个常用的冲突启发式:

启发式 含义
h 1 h_1 h1 全局冲突总数
h 2 h_2 h2 有冲突的智能体数量
h 3 h_3 h3 有冲突的智能体对数(pairs)
h 4 h_4 h4 顶点覆盖数(Vertex Cover)
h 5 h_5 h5 可变启发式(动态选择)

底层松弛:低层用加权 A* 而不是精确 A*,追求快而不是最优。

GCBS 不是最优,但是完备的。速度极快,但解的代价没有上界保证。

3.2 BCBS(Bounded-CBS):固定权重下的有界次优

BCBS 在 GCBS 的基础上引入了 FOCAL 列表,从而提供次优性上界保证。

关键参数:一个固定的权重 w w w

高层 FOCAL:从 OPEN_CT 中选出 c o s t ≤ w ⋅ c o s t m i n cost \leq w \cdot cost_{min} costwcostmin 的节点构成 FOCAL_CT,在其中选冲突最少的扩展。

低层 FOCAL:从 OPEN_agent 中选出 f ≤ w ⋅ f m i n f \leq w \cdot f_{min} fwfmin 的节点构成 FOCAL_agent,在其中选启发式值 h h h 最小的扩展。

BCBS 保证了: c o s t ( s o l u t i o n ) ≤ w ⋅ c o s t ( o p t i m a l ) cost(solution) \leq w \cdot cost(optimal) cost(solution)wcost(optimal)

BCBS 的问题:参数 w w w 的选择很敏感。

  • w = 1 w = 1 w=1 时退化为 CBS(最优但慢)
  • w w w 太大时解质量差
  • w w w 的"最佳值"依赖于具体问题实例

而且,BCBS 的高层和底层共享同一个 w w w,缺乏灵活性。

3.3 ECBS:动态下界传递的巧妙设计

ECBS 解决了 BCBS 的两个问题:

问题一:共享 w w w 不灵活

ECBS 将权重拆分为两个:

  • w s o w_{so} wso:控制全局次优性上界
  • w f o c a l w_{focal} wfocal:控制 FOCAL 列表的松弛程度

这两个参数有清晰的物理含义,调参更直观。

问题二:没有利用低层的下界信息

ECBS 最巧妙的设计是:低层在返回路径的同时,还会返回一个下界 L B LB LB

具体的:

低层 Focal Search 运行结束后,会返回:

  • c o s t i cost_i costi:智能体 i i i 的路径代价
  • f m i n ( i ) f_{min}(i) fmin(i):智能体 i i i 的最优下界(即 OPEN_agent 中未被扩展的节点的最小 f f f 值)

利用这些下界,高层可以计算出整体下界:

L B ( s o l u t i o n ) = ∑ i = 1 n f m i n ( i ) LB(solution) = \sum_{i=1}^{n} f_{min}(i) LB(solution)=i=1nfmin(i)

然后,高层 FOCAL 的入选条件变为一个 动态下界约束

c o s t ( n o d e ) ≤ w s o ⋅ L B ( n o d e ) cost(node) \leq w_{so} \cdot LB(node) cost(node)wsoLB(node)

由于 L B LB LB 总是实际下界且随搜索推进越来越紧,这个设计比 BCBS 的固定权重更加精确和高效。

一句话总结演进

CBS(最优)→ GCBS(松弛,最快)→ BCBS(有界,固定 w)
→ ECBS(有界,动态 LB + 拆分参数)

4. ECBS 高层搜索:带 FOCAL 的约束树扩展

4.1 高层 OPEN 与 FOCAL 双列表结构

ECBS 的高层维护两个列表:

列表 内容 排序依据
OPEN 所有未被扩展的 CT 节点 按 cost(SOC)升序
FOCAL OPEN 的子集: c o s t ( n o d e ) ≤ w s o ⋅ L B ( n o d e ) cost(node) \leq w_{so} \cdot LB(node) cost(node)wsoLB(node) 按冲突数量升序

其中 L B ( n o d e ) LB(node) LB(node) 是该节点对应的 解下界

L B ( n o d e ) = ∑ i = 1 n f m i n ( i ) LB(node) = \sum_{i=1}^{n} f_{min}(i) LB(node)=i=1nfmin(i)

f m i n ( i ) f_{min}(i) fmin(i) 来自低层搜索的最优下界。

在这里插入图片描述

4.2 高层节点选择策略:优先最少冲突

每次迭代,ECBS 高层从 FOCAL 中选一个节点扩展——不直接从 OPEN 中选。

选择标准:冲突数最少的那个节点。

这相当于在"代价不太贵的那些节点"里,优先解决"最干净的"。

这种策略的直觉:

场景:两个 CT 节点
- 节点 A:cost=50,冲突=3
- 节点 B:cost=52,冲突=1

CBS 会选 A(cost 最低)
ECBS 会选 B(冲突最少,且 cost 在 FOCAL 范围内)

因为冲突少的节点"离无冲突解更近",优先扩展可能更快找到解

4.3 下界 LB 的来源与利用

L B ( n o d e ) LB(node) LB(node) 的值 = 低层搜索返回的各智能体 f m i n ( i ) f_{min}(i) fmin(i) 之和。

f m i n ( i ) f_{min}(i) fmin(i) 的物理含义:

给定当前约束条件,智能体 i i i 的单智能体路径代价的严格下界。

注意这个下界有两个来源:

  1. 初始根节点:每个智能体跑低层 Focal Search 时获得
  2. 子节点:只有被加约束的那个智能体需要重新跑低层,其他智能体的 f m i n f_{min} fmin 沿用父节点

L B LB LB 的关键作用是动态收紧 FOCAL 的入选门槛:

高层每次从 OPEN 中选 cost_min 时:
FOCAL = { n ∈ OPEN | cost(n) ≤ w_so × LB(n) }

如果某个解的下界很大(比如 LB=100),
即使它的 cost 较小(cost=95),
FOCAL 入选条件 cost ≤ 1.5 × 100 = 150 也会让它入选。

如果 LB 很小(比如 LB=10),
cost=95 > 1.5 × 10 = 15,它就不会入选。

这比 BCBS 的 c o s t ( n ) ≤ w ⋅ c o s t m i n cost(n) \leq w \cdot cost_{min} cost(n)wcostmin 更精准,因为 L B LB LB 考虑了每个智能体的实际约束情况。


5. ECBS 低层搜索:加权 A* + Focal Search

5.1 低层 OPEN 与 FOCAL 双列表

单个智能体 i i i 的低层搜索也维护两个列表:

列表 内容 排序依据
OPEN 所有待扩展的搜索状态 f ( n ) = g ( n ) + h ( n ) f(n) = g(n) + h(n) f(n)=g(n)+h(n)
FOCAL OPEN 的子集: f ( n ) ≤ w f o c a l ⋅ f m i n f(n) \leq w_{focal} \cdot f_{min} f(n)wfocalfmin h ( n ) h(n) h(n)(启发式值)升序

选择策略:从 FOCAL 中选 h h h 最小的节点扩展。

为什么用 h h h 作为辅助标准?因为 h h h 小的节点"离目标更近"——在代价可接受的范围内,优先向目标逼近,加速搜索。

5.2 f_min 的获取与"下界路径"概念

低层搜索结束(找到路径到达目标)后,OPEN 中剩余的节点的最小 f f f 值就是 f m i n f_{min} fmin

f m i n ( i ) = min ⁡ n ∈ O P E N f ( n ) f_{min}(i) = \min_{n \in OPEN} f(n) fmin(i)=nOPENminf(n)

这个 f m i n f_{min} fmin 就是该智能体在满足当前约束条件下的 单智能体最优路径代价下界

为什么叫"下界"?因为:

如果继续搜索,找到的更优路径的代价不会低于 f m i n f_{min} fmin

在标准 A* 中,OPEN 中最小的 f f f 值就是最优代价的下界(因为 A* 的 f f f 值是单调非递减的)。

5.3 低层为什么返回"两条路径"

ECBS 低层搜索实际上包含两层含义:

  1. 实际路径 p a t h i path_i pathi f f f 在 FOCAL 范围内找到的路径(可能非最优)
  2. 下界路径 L B i LB_i LBi f m i n ( i ) f_{min}(i) fmin(i) 是对单智能体最优代价的估计

这两者配合,使高层能够:

  • 用实际路径检测冲突(进行约束分裂)
  • 用下界之和评估解的"潜在最优性",控制 FOCAL 范围

6. ECBS 完整算法流程与伪代码

ECBS 主流程

ECBS(G, starts, goals, w_so, w_focal):
    
    // 1. 初始化根节点
    root.constraints = ∅
    for each agent i:
        (root.paths[i], root.f_min[i]) = LowLevelSearch(G, starts[i], goals[i], 
                                                         root.constraints, i, w_focal)
    root.cost = sum(cost(root.paths[i]))
    root.LB = sum(root.f_min[i])
    
    // 2. 初始化 OPEN 和 FOCAL
    OPEN = {root}  // 按 cost 排序
    updateFOCAL(OPEN, w_so)  // FOCAL = {n ∈ OPEN | cost(n) ≤ w_so × LB(n)}
    
    while FOCAL not empty:
        
        // 3. 从 FOCAL 中选择冲突最少的节点
        P = argmin_{n ∈ FOCAL} num_conflicts(n)
        
        // 4. 冲突检测
        conflict = first_conflict(P.paths)
        if conflict is None:
            return P.paths  // 找到解!
        
        // 5. 冲突分裂:为每个冲突智能体创建子节点
        (i, j, type, details) = conflict
        
        for agent k in {i, j}:
            child = copy(P)
            
            // 加约束
            child.constraints += generate_constraint(agent=k, conflict)
            
            // 只对 k 重新跑低层搜索
            (child.paths[k], child.f_min[k]) = LowLevelSearch(
                G, starts[k], goals[k], child.constraints, k, w_focal
            )
            
            if child.paths[k] is not None:
                child.cost = sum(cost(child.paths[m]))
                child.LB = sum(child.f_min[m])
                OPEN.add(child)
        
        // 6. 更新 FOCAL
        updateFOCAL(OPEN, w_so)
    
    return failure  // 无解

低层 Focal Search

LowLevelSearch(G, start, goal, constraints, agent_id, w_focal):
    
    OPEN = {start_state}  // 按 f(n) = g(n) + h(n) 排序
    CLOSED = {}
    FOCAL = {start_state}  // OPEN 中满足 f(n) ≤ w_focal × f_min 的节点
    
    while FOCAL not empty:
        
        // 从 FOCAL 选 h 最小的节点
        S = argmin_{n ∈ FOCAL} h(n)
        
        if is_goal(S, goal):
            // 记录 f_min 作为下界
            f_min = OPEN 中最小 f 值(如果 OPEN 非空)
            return (reconstruct_path(S), f_min)
        
        CLOSED.add(S)
        
        // 生成后继
        for each action in {上, 下, 左, 右, 等待}:
            S' = apply_action(S, action)
            
            if violates_constraints(S', constraints, agent_id):
                continue
            
            if S' ∈ CLOSED:
                continue
            
            g' = g(S) + 1
            f' = g' + h(S')
            
            if S' ∉ OPEN or g' < g(S'):
                OPEN.add(S', key=f')
                update FOCAL: {n ∈ OPEN | f(n) ≤ w_focal × f_min}
    
    return (None, ∞)  // 无可行路径

7. 理论保证:次优性上界与完备性

7.1 ECBS 的次优界证明(直观理解)

定理:ECBS 找到的解满足 c o s t ( s o l u t i o n ) ≤ w s o ⋅ c o s t ( o p t i m a l ) cost(solution) \leq w_{so} \cdot cost(optimal) cost(solution)wsocost(optimal)

直观证明思路

  1. 第一个被扩展的 CT 节点代价为 C 1 C_1 C1
  2. 由于 FOCAL 约束, C 1 ≤ w s o ⋅ L B ( r o o t ) C_1 \leq w_{so} \cdot LB(root) C1wsoLB(root)
  3. L B ( r o o t ) ≤ c o s t ( o p t i m a l ) LB(root) \leq cost(optimal) LB(root)cost(optimal)(下界不会超过最优解)
  4. 所以 C 1 ≤ w s o ⋅ c o s t ( o p t i m a l ) C_1 \leq w_{so} \cdot cost(optimal) C1wsocost(optimal)

关键点: L B LB LB 的单调性保证了高层扩展过程中,FOCAL 的第一个解一定满足上界。

7.2 完备性分析

ECBS 继承了 CBS 的完备性:

只要问题有解,ECBS 就一定能找到解(或返回无解)。

完备性来源于:

  • 约束树上的搜索是完备的(穷举约束组合)
  • 低层 Focal Search 在有可行路径时总能找到(至少在与精确 A* 相同的条件下)
  • 冲突分裂不会丢失解(每个冲突都会产生两个互补约束分支,保证不漏解)

8. [Python] 一个可运行的 ECBS 实例

🔥 项目可参考的代码已放入 GitCode 里面,可以通过下面链接跳转:

【MAPF】— ECBS 算法

后续相关 MAPF 算法也会不断在 【MAPF】 项目里更新,如果该项目对你有所帮助,请帮我点一个星星 ✨✨✨✨✨,鼓励分享,十分感谢 !!!

若是下面代码复现困难或者有问题,也欢迎评论区留言

8.1 核心代码结构

ecbs/
├── main.py             # 主入口:构建场景、运行 ECBS、可视化
├── ecbs.py             # ECBS 核心类:约束树搜索 + FOCAL 管理
├── ct_node.py          # CT 节点数据结构
├── focal_search.py     # 低层 Focal Search(加权 A* + FOCAL)
├── a_star.py           # 标准 A*(作为对比 baseline)
├── entity.py           # 数据结构:智能体、约束、冲突、路径
├── map_utils.py        # 地图工具:障碍物生成、可视化
└── requirements.txt    # 依赖

ECBS 核心类骨架

"""增强的基于冲突搜索(ECBS)算法"""

from focal_search import FocalSearch
from entity import *
from ct_node import CTNode
from copy import deepcopy
import heapq


class ECBS:
    def __init__(self, agents, size, obstacles, w_so=1.5, w_focal=1.2):
        self.agents = agents
        self.size = size
        self.obstacles = obstacles
        self.w_so = w_so          # 全局次优界因子
        self.w_focal = w_focal    # FOCAL 松弛因子
        self.open_list = []       # OPEN_CT(按 cost 排序)
        self.focal_list = []      # FOCAL_CT(按冲突数排序)
        self.focal_search = FocalSearch(size, obstacles, w_focal)

    def check_problem(self):
        """检查问题合理性(起点/终点冲突、边界检查等)"""
        # TODO: 实现
        pass

    def search_first_conflict(self, solution):
        """冲突检测:返回第一个发现的冲突(顶点冲突/边冲突)"""
        # TODO: 实现
        pass

    def update_focal(self):
        """根据 w_so 更新 FOCAL_CT 列表"""
        self.focal_list.clear()
        if not self.open_list:
            return
        cost_min = self.open_list[0][0]  # OPEN 中最小 cost
        
        for cost, node in self.open_list:
            # FOCAL 入选条件:cost ≤ w_so × LB
            if cost <= self.w_so * node.LB:
                # FOCAL 按冲突数排序(冲突数作为 heap key)
                conflicts = self.count_conflicts(node.paths)
                heapq.heappush(self.focal_list, (conflicts, cost, node))

    def solve(self):
        """ECBS 主求解流程"""
        # TODO: 实现完整的 ECBS 流程
        pass

低层 Focal Search 类骨架

"""低层 Focal Search:加权 A* + FOCAL 列表"""

import heapq


class FocalSearch:
    def __init__(self, size, obstacles, w_focal=1.2):
        self.size = size
        self.obstacles = obstacles
        self.w_focal = w_focal

    def heuristic(self, pos, goal):
        """曼哈顿距离启发式"""
        return abs(pos[0] - goal[0]) + abs(pos[1] - goal[1])

    def search(self, start, goal, constraints):
        """
        低层 Focal Search
        返回: (path, f_min)
          - path: 路径列表 [(x1,y1), (x2,y2), ...] 或 None
          - f_min: 最优下界
        """
        open_list = []    # 按 f = g + h 排序
        focal_list = []   # OPEN 中 f ≤ w_focal × f_min 的节点,按 h 排序
        
        # TODO: 实现 Focal Search 核心逻辑
        
        return (path, f_min)

8.2 [Results] 运行结果

========================================
ECBS 多智能体路径规划
========================================
地图大小: 20 × 20
智能体数量: 8
障碍物数量: 30
w_so = 1.5, w_focal = 1.2
========================================

初始化根节点...
  智能体 0: path_cost=12, f_min=10
  智能体 1: path_cost=8, f_min=7
  智能体 2: path_cost=15, f_min=13
  ...
  根节点 SOC = 85, LB = 72

开始约束树搜索...
  迭代  1: FOCAL 大小=1, 冲突=3, 扩展子节点...
  迭代  2: FOCAL 大小=2, 冲突=1, 扩展子节点...
  迭代  3: FOCAL 大小=1, 冲突=0 ✓ 找到解!

========================================
求解成功!
ECBS 总代价 (SOC): 93
最优下界 (LB):   72
次优比:           93/72 = 1.29 ≤ w_so(1.5) ✓
CT 扩展节点数:    5
总耗时:           0.87s
========================================

路径可视化

  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19
0  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
1  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
2  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
3  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
4  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
   ...(完整的路径轨迹动画)...

8.3 与 CBS 的运行对比

在这里插入图片描述

指标 CBS ECBS (w=1.5) 提升
SOC 85 (最优) 93 +9.4%
CT 节点数 127 5 -96.1%
耗时 12.4s 0.87s -93.0%
最优性保证 最优 ≤ 1.5×最优

9. 复杂度、优缺点与适用场景

9.1 时间复杂度分析

ECBS 的时间复杂度受两个因素主导:

高层

  • 约束树最坏情况下仍可能指数级膨胀( O ( b d ) O(b^d) O(bd),其中 b b b 是分支因子, d d d 是约束深度)
  • 但 FOCAL 策略大幅减少了实际扩展的节点数

低层

  • 每次 Focal Search: O ( ∣ V ∣ log ⁡ ∣ V ∣ ) O(|V| \log |V|) O(VlogV),类似于加权 A*
  • 只在加约束后重跑被影响的智能体

整体上,ECBS 的实际运行时间远小于 CBS,尤其在智能体数量较多时。

9.2 ECBS vs CBS vs GCBS vs BCBS 横向对比

特性 CBS GCBS BCBS ECBS
最优性保证 ✓ 最优 ✗ 无界 ✓ w 界 ✓ w_so 界
完备性
高层策略 cost 最小 冲突最少 FOCAL+cost FOCAL+LB
低层策略 A* 最优 加权 A* FOCAL+A* FOCAL+LB 返回
参数 w(可选) w(固定) w_so, w_focal
速度 最快 中等 较快
调参难度
论文年份 2012 2014 2014 2014

9.3 适用场景选择建议

场景 推荐算法 原因
学术研究/基准测试 CBS 需要最优解作为 ground truth
大规模仓储 AGV(50+台) ECBS 速度远快于 CBS,代价可控
实时游戏 NPC 寻路 GCBS 或 ECBS 需要快速响应
无人机编队(动态重规划) ECBS 兼顾速度与质量
高精度协作任务 CBS 每一步都不能多走

10. 总结

ECBS 是 MAPF 领域将"有界次优"思想应用于双层搜索的一次优雅尝试。它的核心贡献可以归纳为三点:

  1. 双层 Focal Search:在 CBS 的高层和低层都引入 FOCAL 机制,用辅助标准(冲突数、启发式值)引导搜索,大幅减少扩展节点数。

  2. 动态下界传递:低层不仅返回路径,还返回 f m i n f_{min} fmin 下界,高层利用这些下界计算动态的入选阈值,比固定权重方案(BCBS)更精确。

  3. 参数解耦:将次优性控制拆分为 w s o w_{so} wso(全局上界)和 w f o c a l w_{focal} wfocal(搜索激进程度),两个参数物理含义清晰,调参更直观。

一句话记住 ECBS

ECBS = CBS 框架 + 双层 Focal Search + 动态下界传递 = 有界次优的快速 MAPF 求解器

对于实际的 MAPF 工程应用,ECBS 往往是用起来最"舒服"的选择——它在速度和质量之间找到了一个很好的平衡点。


参考资料

  1. Barer M, Sharon G, Stern R, et al. Suboptimal Variants of the Conflict-Based Search Algorithm for the Multi-Agent Pathfinding Problem. Proceedings of the Seventh Annual Symposium on Combinatorial Search (SoCS 2014). DOI

  2. Sharon G, Stern R, Felner A, et al. Conflict-Based Search for Optimal Multi-Agent Pathfinding. Artificial Intelligence, 2015.

  3. 博主往期相关文章:

  4. GitCode 项目仓库:MAPF 算法合集(CBS / ECBS / …)


✨ 如果本文对你理解 ECBS 有帮助,欢迎点赞、收藏、关注,你的支持是我持续分享的最大动力!

📬 交流学习请在博客主页左下方添加微信,一起探讨 MAPF、强化学习与路径规划的前沿问题!

更多推荐