AI中的几种搜索算法---A*搜索算法
AI中的几种搜索算法---A*搜索算法
引言
A*搜索算法作为一种典型的启发式搜索(Informed Search)算法,这种算法与一般的算法相比,便是其在搜索过程中,会利用一些引导机制,来引导整个搜索。相比于盲目的搜索,其性能是不言而喻的。
而运用A*最广泛的地方便是游戏中的路径搜索(Path Finding)。这篇文章主要会基本地介绍A*算法,并会介绍一个游戏路径搜索的例子。
这里套着AI这个帽子,我会先介绍一些基本的搜索算法;随后我会写几篇文章介绍AI中几个经典概念:Machine Learning、基因算法等。
一、A*搜索算法的基本介绍
1.启发式搜索
启发式搜索,简单地说,便是在搜索下一个结点的时候,利用启发函数,能够找到搜索代价最小的结点,进行搜索。
比较有名的启发式搜索:BFS(Best First Search)、A * Search、SA、TABU search等等。
我这里只介绍A*,因为这个算法是其中名气最大的,也是比较典型的。其中BFS和A*很类似,所以不会单独写一篇文章进行介绍,不过我会在之后几种搜索算法综合比较的时候对其进行简单介绍;SA算法是我下篇讨论的对象。
2.核心等式
我将这个等式称为消耗公式,意思是说搜索的结点需要耗费的“资源”。
首先简单介绍一下这个等式:f(n) = g(n) + h(n)(公式1)。
其中g(n)表示消耗(cost),也可以这么理解g:从出发到现在的消耗,该值是从搜索空间中计算得到。
其中h表示引导函数(heuristic function),可以这么理解h:从现在到目标的距离,注意这里的距离是一个抽象概念,该值是一个预测值。
3.两个列表
然后介绍一下算法当中需要用到的两个列表:open list和closed list。
Open list是一个优先队列,为每一次搜索提供最好的结点。该队列以结点的f为升序,该队列是A*算法更有效率地找到从开始到目标最短的路径。
Closed list是一个普通队列,保存了已访问过的结点,避免一个结点的重复访问。
4.A*算法的流程
大致描述一下这个流程:
1. 首先便是初始化工作,初始化上面提到的两个列表(Open list和Closed list),并获取一个开始结点放入Open list中。
2. 然后进行具体的搜索,从优先队列中取出最好的搜索结点(记为cur_node),这里最好的搜索结点便是根据公式1计算出来的,拥有最小f的结点。由于open list是一个优先队列,所以能够很方便地取出最优结点。
3. 如果取出的cur_node就是目标,就是我们要的结果,那么就结束算法。
4. 将cur_node保存在closed list中。表示我们已经访问这个结点。
5. 展开cur_node所有的邻接结点,并进行遍历(adj_node)。
6. 如果adj_node 已存在于closed list。表示我们已经访问过adj_node。取下一个邻接结点,继续步骤6。
7. 如果结点已存在于open list中,并且cur_node比open list上的那个结点好,也就是所cur_node的g小于那个结点,那么计算一下cur_node的f,并进行替换。
8. 如果cur_node不存在于open list中,那么计算cur_node的f并插入open list。
下面便是一个伪代码的流程:
- Initialize the Open list.
- Initialize the Closed list.
- Add the start node to the open list.
- loop util the open list is empty
- get the best node(cur_node) from open list.
- ifcur_node is the goal node
- end the algorithm.
- end if
- add cur_node to closed list.
- get the adjacent nodes(adj_node) of cur_node.
- if adj_node is on the closed list
- continue.
- end if
- if adj_node is on the open list(openlist.adjnode)
- if adj_node is better than openlist.adjnode
- replace the openlist.adjnode with adj_node.
- end if
- else
- add adj_node to open list.
- end else
- end
- end loop
这个流程可以简单的理解:搜索的时候不停地往两个list中插数据,open list保证每次访问的结点是其中最好的结点,而closed list则保证要访问的结点在之前没有被访问过的。
二、游戏中的路径搜索
这里举一个2D 迷宫寻出路的例子。
1.消耗公式
我们来简要的分析一下。我们就利用公式1来进行切入,首先我们要计算出h。
当前距离目标的“距离”,这个距离可以是当前位置与目标位置之间具体的物理距离()。也可以是一个抽象距离:比如说当前位置要去目标位置的消耗,你明白去两个地方的消耗,不光要考虑要距离,还更要考虑路况的。
当然为了讨论和实现的简单,我们只需考虑物理距离就行了。
既然我们已经得出h,那么接下来就考虑g,于h相类似,g的计算简单多了,已走路线的长度就行了。
这样整个具体的消耗公式便是:
(公式2)
2.代码
上面说了这么多,这里就放一段核心的代码,其中pqueue4path和queue4path这两个是我自己专门为这个例子写的,其中pqueue4path便是那个优先队列。
至于其中的CaculateCost,是计算结点的消耗,包括g、h和f。
PerturbPath这个函数,主要充当获得邻接结点的作用。
如果要看整个项目代码请于A*演示程序于此处下载下载。
- int astart_pathsearch(constPos & posStart,const Pos & posEnd,int * map,int nWidth,int nHeight,Path & solution)
- {
- Path path,path2;
- path.length = 1;
- path.positions = newPos[path.length];
- path.positions[0].x = posStart.x;
- path.positions[0].y = posStart.y;
- CaculateCost(path,posEnd);
- //
- pqueue4path openlist;
- queue4path closelist;
- openlist.enQueue(path);
- for(int depth = 1;!openlist.isEmpty();++depth)
- {
- openlist.deQueue(path);
- if(!path.costtoend)//find the solution
- {
- solution.length = path.length;
- solution.positions = new Pos[path.length];
- for(int i = 0 ; i < path.length;++i)
- {
- solution.positions[i].x =path.positions[i].x;
- solution.positions[i].y =path.positions[i].y;
- }
- delete[]path.positions;
- delete[]path2.positions;
- returndepth;
- }
- closelist.enQueue(path);
- for (int i = 1 ; i < 5 ; ++i)
- {
- if(!perturbPath(path,map,nWidth,nHeight,i,path2))
- continue;
- CaculateCost(path2,posEnd);
- path2.cost += depth*depth;
- if(closelist.isOnList(path2))
- continue;
- if(openlist.isOnList(path2))
- {
- if(path2.cost< path.cost)
- {
- openlist.deletePath(path2);
- openlist.enQueue(path2);
- }
- }
- else
- {
- openlist.enQueue(path2);
- }
- }
- }
- delete[]path.positions;
- delete[]path2.positions;
- return -1;
- }
3.寻路效果图
AI中的几种搜索算法---A*搜索算法相关推荐
- AI中的几种搜索算法---Tabu搜索算法
AI中的几种搜索算法---Tabu搜索算法 引言 Tabu相对于启发式算法家族中其他成员,要简单易懂的多.关于启发式算法的基本概念可以参见笔者的<AI中的几种搜索算法---A*搜索算法>. ...
- AI中的几种搜索算法---基因算法
AI中的几种搜索算法---基因算法 引言 进化计算(Evolutionary Computation)这个涵盖的范围比较广,其中包括基因算法(Genetic Algorithm).进化式策略(Evol ...
- 计算机视觉在AI中的7种应用
人类视觉类似于计算机视觉,除了人们有一个良好的开端.人类的视觉受益于一生的上下文,教它如何区分物体,它们有多远,它们是否在移动,以及图像是否不正确. 计算机视觉教计算机执行类似的任务,但使用相机,数据 ...
- A*搜索算法——图形搜索算法
A* 搜索算法--图形搜索算法:从给定起点到给定终点计算出路径.其中使用了一种启发式的估算,为每个节点估算通过该节点的最佳路径,并以之为各个地点排定次序.算法以得到的次序访问这些节点.因此,A*搜索算 ...
- PaddleClas-图像分类中的8种数据增广方法(cutmix, autoaugment,..)
本文主要来源于PaddleClas这个代码仓库中的数据增广文档:https://github.com/PaddlePaddle/PaddleClas/blob/master/docs/zh_CN/ad ...
- AI中pass架构设计优化
AI中pass架构设计优化 Relay 和 TVM IR,包含一系列优化passes,可提高模型的性能指标,例如平均推理,内存占用,或特定设备的功耗.有一套标准优化,及特定机器学习的优化,包括常量折叠 ...
- 线性代数的本质及其在AI中的应用
线性代数是 AI 专家必须掌握的知识,这已不再是个秘密.如果不掌握应用数学这个领域,你永远就只能是「门外汉」.当然,学习线性代数道阻且长.数学,尤其是线性代数常与枯燥.复杂和毫无意义的事物联系起来.不 ...
- AI 发展方向大争论:混合AI ?强化学习 ?将实际知识和常识整合到AI中 ?
作者:Ben Dickson是一名软件工程师,还是探讨技术在如何解决和带来问题的TechTalks博客的创始人. 对于AI界来说意义重大,这归功于深度学习领域取得了惊人的进步,AI的这个分支因收集.存 ...
- java中的复合数据类型是什么_【填空题】类是Java中的一种重要的复合数据类型,是组成Java程序的基本要素。一个类的实现包括两部分:____和_____....
[填空题]类是Java中的一种重要的复合数据类型,是组成Java程序的基本要素.一个类的实现包括两部分:____和_____. 更多相关问题 [名词解释] 观叶树木 [单选] 开花时有浓郁香气的树种是 ...
最新文章
- XML DOM 节点
- 关于找工作和选专业的思考
- 卸载重装得会员、偷删本地文件?网易云回应了:系造谣攻击,悬赏10万找线索...
- UI素材|网站404页面有什么用处
- Servlet/JSP-02 Servlet相关类
- ht1621b和单片机电平匹配_干货 | 143条 超详细整理STM32单片机学习笔记
- OpenDDS的学习和使用
- 虚幻4引擎垃圾回收原理
- 用友 U8 word模板修改
- 根据路由器MAC地址查详细地址(WIFI定位)免费接口
- 使用百度地图API实现地图生成、标记以及标注
- java获取虾米数据_json获取属性值的方式
- python box2d模拟平抛运动_box2d 粗略的模拟水浮力
- 从全拼音中得到汉字拼音
- Android 系统广播(大全)
- Joomla建站之幻灯片
- vscode win10笔记本 蓝屏_联想拯救者Win10蓝屏0xc000000d的解决办法
- KNN分类——matlab(转载)
- 软件工程课程作业--UON
- 用jmeter对抽奖接口进行抽奖概率分析测试