首页 > 其他分享 >1.基于搜索的路径规划:BFS、DFS、Dijkstra、A*、JPS

1.基于搜索的路径规划:BFS、DFS、Dijkstra、A*、JPS

时间:2024-03-22 16:37:25浏览次数:17  
标签:容器 队列 算法 DFS BFS Dijkstra 周围 代价 节点

1.概览

  可以对比不同算法的小动画 PathFinding.js (qiao.github.io)

  • 工作空间规划
    • 机器人有不同的形状和大小
    • 碰撞检测需要了解机器人的几何形状,耗时且难度大
  •  我们希望将机器人表示为点,只需要把工作空间转换为配置空间C-obstacle,将原始的空间膨胀,这是一次性的
    • C-space R3空间
    • C-obstacle 膨胀后的障碍空障碍
    • C-space = C-obstacle ∪ C-free

  • 图搜索算法的逻辑总是在这个框架下
    • 维护一个容器,该容器记录所有准备去访问的节点,同时一个有一个容器记录了所有已经访问的节点,避免形成环
    • 这个容器刚开始是空的,我们初始化放入起始节点
    • Loop
      • 访问一个节点:在容器里根据一种指标弹出一个节点
      • 扩展:发现该节点所有可能的邻居节点
      • 插入:将这些邻居节点插入到容器中
    • End Loop
    • 容器已经全空就达到了终止条件

2.BFS和DFS

广度优先搜索和深度优先搜索

  • 深度优先算法:总是移除容器中最深层的节点(总是把尝试一直把一条路走到底)
    • 首先S进入栈
    • S出栈,发现S的周围元素 d e p,S的周围元素 d e p 进入栈
    • d出栈,发现d的周围元素 b c e,d的周围元素 b c e 进入栈

  • 广度优先算法:总是移除容器中最浅层的节点(一层一层的搜索)
    • S 进入队列
    • S 弹出队列,发现S的周围元素 d e p,S的周围元素 d e p 进入队列
    • p 弹出队列,发现p的周围元素 q,p的周围元素 q 进入队列

  • 两种算法DFS总是一条路走到黑,所以它找到的路径不是最短路径

3.贪心算法

  • DFS或者BFS是通过先入或后入来判定从容器中拿出哪个节点
  • 贪心算法是一种启发式搜索,通过认为定义的”最短“判定从容器中弹出哪个节点(不一定有全局最优解)

4.Dijkstra算法

DFS和BFS都没有考虑边的代价问题,Dijkstra算法如果不考虑边的代价实际上就退化成广度优先算法

  • g(n):从起始节点到当前节点n累计的最佳成本
  • 更新节点n相邻节点的代价(有可能当前节点n使得它周围的节点m代价降低)
  • 保证已扩展/访问的节点开销最小

以下图为例跑一遍流程

  • S弹出队列,发现S周围节点 d e p,S的周围节点根据代价排序进入优先级队列 p d e
  • p弹出队列,发现p周围节点 q,q的周围节点 q 进入优先级队列
  • e弹出队列,发现e周围节点 h r,e的周围节点根据代价排序进入优先级队列 r h

算法伪代码逻辑

  • 维护priority queue存储所有已访问的节点
  • 将初始节点Xs加入到队列
  • 标记 g(Xs)=0,其余的节点代价为无穷大
  • Loop
    • if the queue is empty, return FALSE; break;
    • Remove the node "n" with the lowest g(n) from the priority queue
    • mark node "n" as expanded
    • if the node "n" is the goal state, return TRUE; break;
    • For all unexpanded neighbors "m" of node "n"
      • if g(m) = infinite
        • if g(m) = g(n) + COSTnm
        • push node "m" into queue
      • if g(m) > g(n) + COSTnm
        • g(m) = g(n) + COSTnm
  • End Loop

5.A*算法

  • 对Dijkstra算法进行优化,加上贪心算法的思想就可以得到A*算法
    • h(n):从当前节点n到目标状态的估计最小代价(即目标代价)
    • g(n):从起始节点到当前节点n累计的最佳成本
    • Weighted A*:f(n):g(n)+εh(n), ε>1:经过节点n,从起始节点到目标节点估计的最小代价
    • 如果代价估计大于实际代价,最终找到的路径也不一定是最优路径。ε越大越接近于贪心算法,ε=1就是A*算法,ε=0就是Dijkstra算法
  • 算法逻辑与Dijkstra完全相同,但排序将g(n)修改为f(n)
  • 以下图为例解释,每个节点的估计代价h已经给出
    • 弹出S节点,发现S周围节点a,将a加入优先队列
    • 弹出a节点,发现a周围节点b d e,通过计算当前代价和估计代价得到应该按照 d e b 加入优先队列

6.A*算法的优化

6.1 The Best Heuristic

  为了得到最优解,我们必须满足估计最小代价和实际最小代价的关系为h(n)≤h*(n),但是如果h(n)远远小于真实最小代价的话,就会导致右图所示的情况,进行很多无效的搜索,因为更小的h(n)使得算法误以为会有一条更有的路径

  但实际上这种规格化的网格只能水平走或斜45度走。所以这里不使用欧氏距离,而是使用更标准的算法会更快速的找到目标

6.2 Tie Breaker

  因为路径中大量对称的点都会有相同的F(n)值,这些值都需要不断的去遍历进行搜索,这会导致它搜索很多无效的点

  核心思想:想办法打破这种平衡,比如计算一个常数p让每个点的F(n)值不太相同

  具体做法为F(n) = g(n) + h(n)*(1+p) ,不过这种做法也可能使得h(n)>h*(n),使得我们估计最小代价大于实际最小代价,无法找到最优解

 

  也可以如果有相同的f(n),则我们选取更小的h(n)值弹出容器

  或者是我们添加一种倾向性,让他倾向于去行走一条直线,在无障碍的情况下是很好的,但是有障碍的情况下缺不太符合人的直观体会

7. Jump Point Search

  先看一下JPS算法和A*算法搜索过程的对比

  JPS算法思想1:Look Ahead Rule

  • 劣质邻居(inferior neighbors)灰色节点:到达这些节点时,没有x节点的路径更优
    • 父节点为4时,如果此时由x到1,它的消耗是4->x->1,不如x->1
    • 父节点为4时,如果此时由x到2,它的消耗是4->x->2,不如4->2
    • 父节点为4时,如果此时由x到3,它的消耗是4->x->3,和4->2->3相同,经过x的路径没有更优
  • 自然邻居(natural neighbors)白色节点:我们只需要考虑通过白色节点
  • 强制邻居(Forced Neighbors)黑色节点:墙

  JSP算法思想2:Jumping Rules

  • 直线规则:如果周围没有障碍物,就是Look Ahead Rule情况1,它只需要继续走直线
    • 当他走到y节点时,是Look Ahead Rule情况3
  • 对角线规则:如果周围没有障碍物,就是Look Ahead Rule情况2,它可以选择三条路线,优先选择水平,然后选择垂直,最后选择对角线运动。

 

 

标签:容器,队列,算法,DFS,BFS,Dijkstra,周围,代价,节点
From: https://www.cnblogs.com/stux/p/18083092

相关文章

  • 九宫幻方(DFS实现)c++
    题目描述题目分析要完成这个问题,我们需要做这几步1.用1~9的数字替换掉输入中的0,且幻方中不能出现重复元素2.替换完成后,要判断是否为幻方判断是否为幻方boolcheck()//检查是否为幻方{ intsum=a[1][1]+a[2][2]+a[3][3];//左对角线的和 if(sum!=a[1][3]+a[2][2]+a[......
  • DFS基础——迷宫
    迷宫关于dfs和bfs的区别讲解。对于上图,假设我们要找从1到5的最短路,那么我们用dfs去找,并且按照编号从大到小的顺序去找,首先找到的路径如下,从节点1出发,我们发现节点2可以走,于是我们就走向了节点2,然后又发现节点2可以走向节点4,于是走向了节点4,然后从节点4走向了节点5,......
  • DFS进阶——全排列
    通过后续的题目希望大家明白,dfs不仅仅是对图的遍历,他还有很多用法。DFS进阶1——回溯先说一下回溯的板子dfs(){for(......){标记信息dfs()撤销标记}}回溯模板——递归实现排列型枚举题目分析其实就是对1~n的数字全排列,这里就可以用dfs去做,1~n全排......
  • HDFSRPC安全认证Token篇推广
    本文主要阐述HDFSRPC安全认证相关的实现。主要介绍Token相关的实现。写在前面相关bloghttps://blog.csdn.net/hncscwc/article/details/124722784https://blog.csdn.net/hncscwc/article/details/124958357Token由来在探究完Kerberos,我一直在想一个问题,rpcConnection已经完......
  • 最优乘车+最小花费(Dijkstra写法)
    题目描述H 城是一个旅游胜地,每年都有成千上万的人前来观光。为方便游客,巴士公司在各个旅游景点及宾馆,饭店等地都设置了巴士站并开通了一些单程巴士线路。每条单程巴士线路从某个巴士站出发,依次途经若干个巴士站,最终到达终点巴士站。一名旅客最近到 H 城旅游,他很想去 S......
  • 图Graph及相关算法(Dijkstra,Kruskal)
    目录无向图有向图邻接矩阵邻接表图的bfs,dfs二部图(二分图)有向无环图(DAG)拓扑排序(TopologicalSort)AOV网迪杰斯特拉Dijkstra最小生成树克鲁斯卡尔:Kruskal普里姆:prim图是多对多关系,是顶点和边的二元组和。无向图1.依附关系:边(v1,v2)依附于顶点v1,v2。2.完全图:所有......
  • 【力扣】岛屿数量(体会一下dfs和bfs思路的实质)
    题目描述注意,需要求的是岛屿的数量,而不是岛屿的总面积,这道题很考验对dfs思路的理解,而不是简单地套用模版。可以用dfs和bfs两种方法做。深度优先搜索版本首先看代码:classSolution{private:intdir[4][2]={0,1,1,0,-1,0,0,-1};//四个方向voiddfs(ve......
  • Flume - [03] HDFS Sink
      一、概述  将事件写入Hadoop分布式文件系统(HDFS)。目前支持创建文本和序列文件。支持两种文件类型的压缩。可以根据经过的时间、数据大小或事件数周期性地滚动文件(关闭当前文件并创建文件)。根据事件起源的时间戳或机器等属性对数据进行存储/分区。HDFS目录路径可能包好......
  • 机器人路径规划:基于迪杰斯特拉算法(Dijkstra)的机器人路径规划(提供Python代码)
    迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻......
  • 《牛客》-E魔法之森的蘑菇(经典BFS变种)
    思路:由于某些固定方向的情况,我们将到达该点的粒度划分成从那个方向的到达该点,及基础bfs为每个点可以到达一次,变成没个点可以到达四次(四个方向)用一个三维数组进行标记vis[N][N][4],其余细节看下方ACcodeACcode:#include<bits/stdc++.h>usingnamespacestd;#defineendl......