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。

下面便是一个伪代码的流程:

[plain]  view plain copy print ?
  1. Initialize the Open list.
  2. Initialize the Closed list.
  3. Add the start node to the open list.
  4. loop util the open list is empty
  5. get the best node(cur_node) from open list.
  6. ifcur_node is the goal node
  7. end the algorithm.
  8. end if
  9. add cur_node to closed list.
  10. get the adjacent nodes(adj_node) of cur_node.
  11. if adj_node is on the closed list
  12. continue.
  13. end if
  14. if adj_node is on the open list(openlist.adjnode)
  15. if adj_node is better than openlist.adjnode
  16. replace the openlist.adjnode with adj_node.
  17. end if
  18. else
  19. add adj_node to open list.
  20. end else
  21. end
  22. 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*演示程序于此处下载下载。

[cpp]  view plain copy print ?
  1. int astart_pathsearch(constPos & posStart,const Pos & posEnd,int * map,int nWidth,int nHeight,Path & solution)
  2. {
  3. Path path,path2;
  4. path.length = 1;
  5. path.positions = newPos[path.length];
  6. path.positions[0].x = posStart.x;
  7. path.positions[0].y = posStart.y;
  8. CaculateCost(path,posEnd);
  9. //
  10. pqueue4path openlist;
  11. queue4path closelist;
  12. openlist.enQueue(path);
  13. for(int depth = 1;!openlist.isEmpty();++depth)
  14. {
  15. openlist.deQueue(path);
  16. if(!path.costtoend)//find the solution
  17. {
  18. solution.length = path.length;
  19. solution.positions = new Pos[path.length];
  20. for(int i = 0 ; i < path.length;++i)
  21. {
  22. solution.positions[i].x =path.positions[i].x;
  23. solution.positions[i].y =path.positions[i].y;
  24. }
  25. delete[]path.positions;
  26. delete[]path2.positions;
  27. returndepth;
  28. }
  29. closelist.enQueue(path);
  30. for (int i = 1 ; i < 5 ; ++i)
  31. {
  32. if(!perturbPath(path,map,nWidth,nHeight,i,path2))
  33. continue;
  34. CaculateCost(path2,posEnd);
  35. path2.cost += depth*depth;
  36. if(closelist.isOnList(path2))
  37. continue;
  38. if(openlist.isOnList(path2))
  39. {
  40. if(path2.cost< path.cost)
  41. {
  42. openlist.deletePath(path2);
  43. openlist.enQueue(path2);
  44. }
  45. }
  46. else
  47. {
  48. openlist.enQueue(path2);
  49. }
  50. }
  51. }
  52. delete[]path.positions;
  53. delete[]path2.positions;
  54. return -1;
  55. }

3.寻路效果图

AI中的几种搜索算法---A*搜索算法相关推荐

  1. AI中的几种搜索算法---Tabu搜索算法

    AI中的几种搜索算法---Tabu搜索算法 引言 Tabu相对于启发式算法家族中其他成员,要简单易懂的多.关于启发式算法的基本概念可以参见笔者的<AI中的几种搜索算法---A*搜索算法>. ...

  2. AI中的几种搜索算法---基因算法

    AI中的几种搜索算法---基因算法 引言 进化计算(Evolutionary Computation)这个涵盖的范围比较广,其中包括基因算法(Genetic Algorithm).进化式策略(Evol ...

  3. 计算机视觉在AI中的7种应用

    人类视觉类似于计算机视觉,除了人们有一个良好的开端.人类的视觉受益于一生的上下文,教它如何区分物体,它们有多远,它们是否在移动,以及图像是否不正确. 计算机视觉教计算机执行类似的任务,但使用相机,数据 ...

  4. A*搜索算法——图形搜索算法

    A* 搜索算法--图形搜索算法:从给定起点到给定终点计算出路径.其中使用了一种启发式的估算,为每个节点估算通过该节点的最佳路径,并以之为各个地点排定次序.算法以得到的次序访问这些节点.因此,A*搜索算 ...

  5. PaddleClas-图像分类中的8种数据增广方法(cutmix, autoaugment,..)

    本文主要来源于PaddleClas这个代码仓库中的数据增广文档:https://github.com/PaddlePaddle/PaddleClas/blob/master/docs/zh_CN/ad ...

  6. AI中pass架构设计优化

    AI中pass架构设计优化 Relay 和 TVM IR,包含一系列优化passes,可提高模型的性能指标,例如平均推理,内存占用,或特定设备的功耗.有一套标准优化,及特定机器学习的优化,包括常量折叠 ...

  7. 线性代数的本质及其在AI中的应用

    线性代数是 AI 专家必须掌握的知识,这已不再是个秘密.如果不掌握应用数学这个领域,你永远就只能是「门外汉」.当然,学习线性代数道阻且长.数学,尤其是线性代数常与枯燥.复杂和毫无意义的事物联系起来.不 ...

  8. AI 发展方向大争论:混合AI ?强化学习 ?将实际知识和常识整合到AI中 ?

    作者:Ben Dickson是一名软件工程师,还是探讨技术在如何解决和带来问题的TechTalks博客的创始人. 对于AI界来说意义重大,这归功于深度学习领域取得了惊人的进步,AI的这个分支因收集.存 ...

  9. java中的复合数据类型是什么_【填空题】类是Java中的一种重要的复合数据类型,是组成Java程序的基本要素。一个类的实现包括两部分:____和_____....

    [填空题]类是Java中的一种重要的复合数据类型,是组成Java程序的基本要素.一个类的实现包括两部分:____和_____. 更多相关问题 [名词解释] 观叶树木 [单选] 开花时有浓郁香气的树种是 ...

最新文章

  1. XML DOM 节点
  2. 关于找工作和选专业的思考
  3. 卸载重装得会员、偷删本地文件?网易云回应了:系造谣攻击,悬赏10万找线索...
  4. UI素材|网站404页面有什么用处
  5. Servlet/JSP-02 Servlet相关类
  6. ht1621b和单片机电平匹配_干货 | 143条 超详细整理STM32单片机学习笔记
  7. OpenDDS的学习和使用
  8. 虚幻4引擎垃圾回收原理
  9. 用友 U8 word模板修改
  10. 根据路由器MAC地址查详细地址(WIFI定位)免费接口
  11. 使用百度地图API实现地图生成、标记以及标注
  12. java获取虾米数据_json获取属性值的方式
  13. python box2d模拟平抛运动_box2d 粗略的模拟水浮力
  14. 从全拼音中得到汉字拼音
  15. Android 系统广播(大全)
  16. Joomla建站之幻灯片
  17. vscode win10笔记本 蓝屏_联想拯救者Win10蓝屏0xc000000d的解决办法
  18. KNN分类——matlab(转载)
  19. 软件工程课程作业--UON
  20. 用jmeter对抽奖接口进行抽奖概率分析测试

热门文章

  1. 《惢客创业日记》2020.11.15-17(周日)谁有谁的四十不惑?
  2. 名帖35 吴叡 隶书《离骚》
  3. Ngnix+Tomcat配置负载均衡
  4. 自制汉字字库,识别汉字(一)(数字篇)
  5. 通知短信、验证码短信、营销短信有什么不同
  6. canvas 画线条
  7. 劳动节程序员应该知道的知识——计算机
  8. 原始资料的收集方法———定性资料的收集
  9. 浙大版《Python 程序设计》题目集
  10. 第四篇:读《穷查理宝典》