基于冲突搜索(CBS)的多智能体路径寻优(MAPF)

news2025/1/18 17:17:03

1 背景

1.1 问题描述

        多智能体路径寻优( Multi-Agent Path Finding,MAPF )问题由一个无向无权图G = ( V ,E )和一组k个智能体{a_{1},...,a_{k}}组成,其中智能体a_{i}有起始点s_{i} \in V和目标点g_{i} \in V。时间被离散化为时间步。在连续的时间步之间,每个智能体既可以移动到相邻的顶点,也可以在当前顶点处等待。除智能体在其目标顶点处进行最终的等待外,移动和等待动作都具有单位时间成本。a_{i}的一条路径是将ai从a_{i}引导到g_{i}的一系列移动和等待动作。元组<a_{i},a_{j},v,t>表示节点冲突,当且仅当a_{i}a_{j}在t时刻处于同一个顶点v;元组<a_{i},a_{j},u,v,t>表示边冲突,当且仅当a_{i}a_{j}在时间步t和t + 1之间沿相反方向遍历同一条边(u,v)。研究的目标是找到一组无冲突的路径,使得所有的智能体从起始点移动到目标点,同时最小化这些路径的总时间。

from typing import Tuple
import numpy as np


class Agent:

    def __init__(self, start: Tuple[int, int], goal: Tuple[int, int]):
        self.start = np.array(start)
        self.goal = np.array(goal)

    # Uniquely identify an agent with its start position
    def __hash__(self):
        return int(str(self.start[0]) + str(self.start[1]))

    def __eq__(self, other: 'Agent'):
        return np.array_equal(self.start, other.start) and \
               np.array_equal(self.goal, other.goal)

    def __str__(self):
        return str(self.start.tolist())

    def __repr__(self):
        return self.__str__()

 1.2 基于冲突的搜索(CBS)

        CBS有两个层次。下层为个体Agent寻找最优路径。如果路径发生冲突,上层通过分裂行动对冲突主体施加约束以避免这些冲突。CBS的上层是通过搜索约束树( CT )来进行的,CT是一棵二叉树,其中每个节点N包含:

 (1) 一组约束 N.constraints:约束要么是顶点约束<a_{i},v,t>用于禁止智能体a_{i}在t时刻处于顶点v,要么是边约束<a_{i},u,v,t>用于禁止智能体a_{i}在时间步t和t + 1之间从顶点u移动到顶点v;

from typing import Dict, Tuple, Set
from copy import deepcopy

from .agent import Agent

'''
Emulated dictionary of dictionaries
'''
class Constraints:

    def __init__(self):
        #                                   time,         obstacles
        self.agent_constraints: Dict[Agent: Dict[int, Set[Tuple[int, int]]]] = dict()

    '''
    Deepcopy self with additional constraints
    '''
    def fork(self, agent: Agent, obstacle: Tuple[int, int], start: int, end: int) -> 'Constraints':
        agent_constraints_copy = deepcopy(self.agent_constraints)
        for time in range(start, end):
            agent_constraints_copy.setdefault(agent, dict()).setdefault(time, set()).add(obstacle)
        new_constraints = Constraints()
        new_constraints.agent_constraints = agent_constraints_copy
        return new_constraints

    def setdefault(self, key, default):
        return self.agent_constraints.setdefault(key, default)

    def __getitem__(self, agent):
        return self.agent_constraints[agent]

    def __iter__(self):
        for key in self.agent_constraints:
            yield key

    def __str__(self):
        return str(self.agent_constraints)

(2)一个解 N.solution:由k条成本最小路径组成,其中每个智能体有一条,且都满足N.constraints;

(3)成本N.cost:即N.solution中路径的成本之和。

from typing import Dict
import numpy as np

from .agent import Agent
from .constraints import Constraints

class CTNode:

    def __init__(self, constraints: Constraints,
                       solution: Dict[Agent, np.ndarray]):

        self.constraints = constraints
        self.solution = solution
        self.cost = self.sic(solution)

    # Sum-of-Individual-Costs heuristics
    @staticmethod
    def sic(solution):
        return sum(len(sol) for sol in solution.items())

    def __lt__(self, other):
        return self.cost < other.cost

    def __str__(self):
        return str(self.constraints.agent_constraints)

        当CBS选择一个CT节点N进行扩展时,它检查N.solution中的冲突。如果没有,CBS终止并返回N.solution。否则,CBS选择其中一个冲突(默认情况下,任意),通过将N拆分为两个子CT节点来解决,CT树子节点继承父节点的约束。在每个子CT节点中,来自冲突的一个智能体通过增加约束的方式被禁止使用冲突的节点或边,该智能体的路径不再满足CT树子节点的约束,必须通过低层搜索(例如,时空A *搜索[1])重新规划,其他智能体的所有路径保持不变。如果低层搜索无法找到满足约束条件的路径,则该子CT节点没有解,因此进行剪枝。每个冲突有两个子CT节点,CBS通过探索解决每个冲突的两种方式来保证最优性。

时空A*搜索的第三方库:

pip3 install space-time-astar

导入:

from stastar.planner import Planner

1.3 改进CBS

        CBS任意选择冲突进行拆分,然而,不好的选择将大幅增加CT的结点数,从而增加运行时间。

1.3.1 ICBS[2]

        2015年,Boyarski提出ICBS,通过对每个CT节点处的冲突进行优先级排序来解决这个问题。他将冲突节点分为3种类型:

(1) cardinal 冲突 :对于CT节点N,一个冲突C =〈a1,a2,v,t〉,如果在N中添加由C (〈a1 , v , t〉,〈a2 , v , t〉)导出的两个约束中的任意一个,并调用约束Agent上的低层,其路径成本相对于N中的成本增加,则称之为cardinal冲突。

(2) semi-cardinal 冲突: 如果添加由C导出的两个约束中的一个增加了N . cost,而其他叶子N . cost不变,则冲突C是semi-cardinal 冲突。

(3) non-cardinal 冲突:  如果由C导出的约束都不增加N . cost,则冲突是non-cardinal 冲突。

        当选择具有路径成本c节点N进行CBS扩展时,首先检查它的所有冲突。如果遇到cardinal冲突,则立即进行拆分动作。这会产生两个成本> c的子节点。在这种情况下,如果OPEN中的另一个节点N′具有成本c,那么可以立即选择N′进行下一步的扩展,而不需要进一步开发N以下的节点。如果不存在cardinal冲突,下一个偏好是选择semi-cardinal冲突。在这里,我们知道至少一个子节点的成本会立刻增加。如果只存在non-cardinal冲突,则任意选择一个。       

 1.3.2 CBSH

        CBS的上层总是选择具有最小N.cost的节点来扩展CT节点。CBSH通过增加一个可接受的启发式来加速上层搜索,具体思路如下:

        如果N.solution包含一个cardinal冲突,那么令h值为1是允许的,因为它的任何一个具有无冲突解的后代CT节点的cost至少为N.cost+1,如果N.solution包含多个基数冲突,则CBSH构建一个冲突图,其顶点为多智能体,边表示N.solution中的cardinal冲突,每个cardinal冲突至少有一个智能体的路径成本至少增加1,于是,冲突图的最小顶点覆盖(minimun vertex cover, MVC)的大小是节点N的容许h值,这种启发式也称之为CG启发式。

文献参考

[1] Silver, D., 2021. Cooperative Pathfinding. Proc. AAAI Conf. Artif. Intell. Interact. Digit. Entertain. 1, 117–122. https://doi.org/10.1609/aiide.v1i1.18726

[2] Boyarski, E., n.d. ICBS: The Improved Conflict-based Search algorithm for Multi-Agent Pathfinding: Extended Abstract.

代码参考

[Preview] README.md - Multi-Agent-Path-Finding [GitHub] - Visual Studio Code - GitHub

[Preview] README.md - mapf [GitHub] - Visual Studio Code - GitHub

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/155529.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kafka生产者——消息发送流程,同步、异步发送API

生产者消息发送流程 发送原理 Kafka的Producer发送消息采用的是异步发送的方式。 在消息发送的过程中&#xff0c;涉及到了两个线程:main线程和Sender线程&#xff0c;以及一个线程共享变量:RecordAccumulator。 ①main线程中创建了一个双端队列RecordAccumulator&#xff0c…

Spring Boot 创建和使用

Spring Boot 创建和使用一、什么是 Spring Boot二、Spring Boot 优点三、Spring Boot 项目创建3.1 使用 Idea 创建验证3.2 网页版创建四、项目目录介绍五、约定大于配置 (重要)5.1 启动类5.2 自定义类在目录中的位置一、什么是 Spring Boot Spring 的诞⽣是为了简化 Java 程序…

《架构300讲》学习笔记(51-100)

前言 内容来自B站IT老齐架构300讲内容。 053动静分离 静态数据&#xff1a;无个性化的数据&#xff0c;静态文件&#xff0c;低频变动的数据。 动态数据&#xff1a;个性化推荐&#xff0c;高频写。 有效的区分页面中的动静数据是优化的关键前提。 页面伪静态化技术&#x…

【Leetcode】308. 二维区域和检索 - 可变

一、题目 1、题目描述 给你一个 2D 矩阵 matrix&#xff0c;请计算出从左上角 (row1, col1) 到右下角 (row2, col2) 组成的矩形中所有元素的和。 实现 NumMatrix 类&#xff1a; NumMatrix(int[][] matrix) 用整数矩阵 matrix 初始化对象。void update(int row, int col, i…

OpenCv相机标定——圆形标定板标定

提取角点时与黑白棋盘格差别主要在于寻找角点的函数&#xff0c;只需将第一章内第二段代码 ret, corners1 cv.findChessboardCorners(img_gray, (w, h)) # 寻找内角点改为 ret, corners1 cv.findCirclesGrid(img_gray, (w, h)) # 寻找内角点&#xff0c;更详细的内容参考第一…

盘点| 能够实现小程序开发提效的框架/工具有这些

近年来&#xff0c;为了研发效率的提升&#xff0c;技术高频革新&#xff0c;开发者们纷纷表示&#xff1a;“好是好&#xff0c;就是快学不动了&#xff01;”。开发者们在不断学习新语言、框架、工具等内容的同时&#xff0c;也在担心所学是否真正有用。而小程序其实能够帮助…

9、Javaweb_http响应概念Response+验证码案例ServletContext+文件下载

HTTP协议&#xff1a; 1. 请求消息&#xff1a;客户端发送给服务器端的数据 * 数据格式&#xff1a; 1. 请求行 2. 请求头 3. 请求空行 4. 请求体 2. 响应消息&#xff1a;服务器端发送给客户端的数据 * 数据格式&#xff1a; …

Nginx 常用配置、操作详解

学习每个技术都要有目标&#xff0c;比如说要源码精通gRPC实现原理&#xff0c;要熟练应用Prometheus、Gin&#xff0c;以及Nginx&#xff0c;Nginx个人定位目标是不需要深入了解技术原理、更不要阅读源码&#xff0c;只需要在自己使用的时候能通过本文章快速检索就够了。 在看…

Graphing calculator PRO

Graphing calculator PRO计算器是一个专业的计算器&#xff0c;它也是编译的&#xff0c;也是学生和学生需要的工具。该程序旨在取代大型和昂贵的图形计算。此外&#xff0c;它在手机或广告牌显示屏上以更高的质量显示计算&#xff0c;这使其更易于理解。Mathlab提供的计算器是…

【云原生进阶之容器】第三章List-Watch机制3.1节-- List-Watch机制剖析

1 list-watch机制 1.1 list-watch介绍 Kubernetes 是通过 List-Watch 的机制进行每个组件的协作,保持数据同步的,每个组件之间的设计实现了解耦。 用户是通过 kubectl 根据配置文件,向 APIServer 发送命令,在 Node 节点上面建立 Pod 和 Container。 APIServer 经过 API 调…

回收租赁商城系统功能拆解06讲-商品评价

回收租赁系统适用于物品回收、物品租赁、二手买卖交易等三大场景。 可以快速帮助企业搭建类似闲鱼回收/爱回收/爱租机/人人租等回收租赁商城。 回收租赁系统支持智能评估回收价格&#xff0c;后台调整最终回收价&#xff0c;用户同意回收后系统即刻放款&#xff0c;用户微信零…

Ubuntu20.04 (ROS noetic) 运行 Vins-Fusion

参考博客&#xff1a;Ubuntu20.04 运行 Vins-Fusion&#xff0c;问题没有完全解决&#xff0c;所以自己写了一篇Vins-Fusion 开源地址&#xff1a;https://github.com/HKUST-Aerial-Robotics/VINS-Fusion由于仅支持ROS kinetic 和 melodic&#xff0c;所以在Ubuntu20.04对应的R…

【Nginx】Nginx的安装

1. 基于apt源安装 1.1 安装1.2 测试安装是否成功1.3 卸载 1. 停止nginx服务2. 删除nginx&#xff0c;-purge包括配置文件3. 移除全部不使用的软件包4. 罗列出与nginx相关的软件并删除5. 查看nginx正在运行的进程&#xff0c;如果有就kill掉 2. 通过源码包编译安装 1. 安装各种…

Java 开源开发平台 O2OA V7.3 发布,新增带权限的全文检索等重要功能

O2OA 自产品发布以来&#xff0c;我们收到了很多伙伴对产品的宝贵建议和意见&#xff0c;在 2022 年的最后一个版本里&#xff0c;我们为伙伴们又提供了新的能力&#xff0c;v7.3 版本正式发布&#xff0c;对平台做了更多的优化。一、平台架构新增带权限的全文检索协同办公领域…

MATLAB-拉格朗日插值运算

在结点上给出结点基函数&#xff0c;接着做该基函数的线性组合&#xff0c;组合的系数为结点的函数值,这种插值多项式称为拉格朗日插值公式。通俗地说&#xff0c;就是通过平面上的两个点确定一条直线。该插值方法是一种较为基础的方法&#xff0c;同时该方法也较容易理解与实现…

Go语言结构

Go语言结构 知识主要参考菜鸟教程。 简单实例 Go语言的基础组成有以下几个部分&#xff1a; 包声明引入包函数变量语句 & 发表达式注释 package mainimport "fmt"func main() {/*这是一行注释*/fmt.Println("hello,world") }上述程序各个部分组成&am…

北大硕士LeetCode算法专题课-字符串相关问题

算法面试相关专题&#xff1a; 北大硕士LeetCode算法专题课-数组相关问题_骨灰级收藏家的博客-CSDN博客 北大硕士LeetCode算法专题课---算法复杂度介绍_骨灰级收藏家的博客-CSDN博客 北大硕士LeetCode算法专题课-基础算法之排序_骨灰级收藏家的博客-CSDN博客 反转字符串(Lee…

springcloud3 Nacos的服务搭建和生产消费案例

一 nacos 1.1 nacos概念 Nacos是服务注册发现中心配置中心的组合。比eurka实现的功能更加强大。 nacos默认均有负载均衡的功能&#xff0c;集成了netflix的ribbon代码包。 1.2 nacos与其他进行对别 1.3 nacos的配置 1.4 namespace和group和dataid之间的关系 二 nacos的安…

2023年网络工程师必备10大软件,最新安装包分享

常听人说&#xff1a;拳头再硬&#xff0c;也比不上锤子&#xff01;同样的&#xff0c;作为一个网络工程师只有满腹的技术而不会使用对应的软件工具&#xff0c;是完全不行的。那作为一个2023年的网络工程师必备的软件有哪些呢&#xff1f;以下10大网工必备软件都已整理好安装…

smsalarm怎么读取intouch系统平台的点

有两种方式&#xff0c;分别是DDE和OPC方式 DDE方式 在SMC里面添加SIDIR驱动&#xff0c;连接到1200PLC 在IDE中创建对象DT01并绑定到驱动上 可看到已经可以读取到值了 打开smsalarm 8.26 创建一个DDE连接 创建一个DDE逻辑组 创建一个tag. 名称可以填任意字符串&#xff0c;…