1、人工智能导论实验一 A*算法 Python 实现实验环境:Python(英语发音:/pan/), 是一种面向对象、解释型计算机程序设计语言,由Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年。Python 语法简洁而清晰,具有丰富和强大的类库。它常被昵称为胶水语言,它能够把用其他语言制作的各种模块(尤其是 C/C+)很轻松地联结在一起。常见的一种应用情形是,使用 Python 快速生成程序的原型(有时甚至是程序的最终界面) ,然后对其中有特别要求的部分,用更合适的语言改写,比如 3D 游戏中的图形渲染模块,性能要求特别高,就可以用 C+重写。实验目
2、的:了解和掌握 Python 语言的使用方法,并能利用它解决实际应用中所遇到的问题;同时实现经典的 A*算法,加深对它的印象,并巩固对人工智能领域中最重要的方面“搜索”的理解。实验内容:利用 python 语言实现经典的 A*算法,其中 A*(A-Star) 算法是一种静态路网中求解最短路最有效的直接搜索方法。估价值与实际值越接近,估价函数取得就越好。它的原理在于 A*1 (A-Star)算法是一种静态路网中求解最短路最有效的直接搜索方法。注意是最有效的直接搜索算法。之后涌现了很多预处理算法(ALT,CH ,HL 等等) ,在线查询效率是 A*算法的数千甚至上万倍。公式表示为: f(n)=g(
3、n)+h(n),其中 f(n) 是从初始点经由节点 n 到目标点的估价函数,g(n) 是在状态空间中从初始节点到 n 节点的实际代价,h(n) 是从 n 到目标节点最佳路径的估计代价。保证找到最短路径(最优解的)条件,关键在于估价函数 h(n)的选取:估价值 h(n)实际值 ,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。实验步骤:1算法的基本描述采用数组的方式来进行 A*查找首先定义 Map 类,作为障碍迷宫的地图,里头会根据地图的大小,生成四个跟地图大小一致的列表:self._nodeparentx = 节点的父节点 X 信息self._nodeparenty = 节点的父节点
4、Y 信息self._nodegcost = 节点的权值 gself._nodehcost = 节点的估算开销 h而地图本身则是一个一维列表即 self._maze = 于是,python 自身对小整数的优化,就导致我们的算法的优化本算法采用起点,终点同时搜索的办法:起点使用 A*搜索;终点采用波纹扩散搜索 ,也就是说随便找一个点,只要不在 close 列表,就扩展其相邻节点,直到无路可寻或找到起点搜索过来的节点为止;一旦起点终点的搜索路径相遇,表示实际上已经有一条不是最优的路径了,直接返回该路径,对于一般的大面积零星障碍地图,A*肯定比终点算法快;如果从终点的搜索更快,说明该地图障碍密集,因此
5、,这里不考虑再去用 A*搜索剩余路径了,返回起点路径 + 终点路径的集合在 本代码中,就是写了个例子,其障碍图几乎就是一个从上到下,又从下到上,仅余一个格子让其通过的这么一个极度疏密的迷宫2.算法的实现# -*- coding: utf-8 -*-from time import time# A*地图可达数据管理接口。class AMap:def _init_(self, width, height, maze):self._width = widthself._height = heightself._mask = -1self._maze = maze # 直接指向内存结构self._no
6、deparentx = self._nodeparenty = self._nodegcost = self._nodehcost = self._size = width * heightfor i in range(self._size):self._nodeparentx.append(-1)self._nodeparenty.append(-1)self._nodegcost.append(0)self._nodehcost.append(0)self.reset = Trueself._left = 0self._top = 0self._right = 0self._bottom
7、= 0self.setRectAll()# reset 重置地图def resetMap(self):if self.reset = True:return #已经重置过self.reset = Truefor i in range(self._size):self._nodeparentxi = -1self._nodeparentyi = -1self._nodegcosti = 0self._nodehcosti = 0if self._mazei != self._mask:self._mazei = 0#/# 搜索参数设置。每次寻路前初始化。# 获取可达逻辑判断掩码def getMa
8、sk(self):return self._mask# 设置搜索范围,范围之外被看成不可达。# (left, top)为 Rect 左上角坐标,(right, bottom)为 Rect 右下角坐标。单位是格子def setRect(self,left, top, right, bottom):self._left = left self._top = top self._right = right self._bottom = bottom# 搜索范围为整个地图。def setRectAll(self):self._left = 0self._top = 0self._right = sel
9、f._widthself._bottom = self._heightdef left(self):return self._leftdef top(self):return self._topdef right(self):return self._rightdef bottom(self):return self._bottomdef width(self):return self._widthdef height(self):return self._heightdef walkable(self, x, y):# in rect. 搜索范围限制if (x = self._right o
10、r y = self._bottom):return Falsereturn self._mazex + y * self._width != self._mask# A*类class AStar:def _init_(self,amap):self.amap = amapself.openList = self.openListEnd = # 从终点开始搜的开放列表self.parent = Noneself.target = Noneself.parentend = Noneself.targetend = Noneself.onOpenList = 1 # 记录,节点是否是开放的标志。s
11、elf.onClosedList = 2 # 记录,节点是否是关闭的标志。self.onOpenListEnd = 4 # 记录,节点是否是从终点开始搜索的开放的标志。self.onClosedListEnd = 8 # 记录,节点是否是从终点开始搜索的关闭的标志。self.width = self.amap._widthself.height = self.amap._heightdef ACORNER_END(self, cx, cy, cost, cx0, cy0, cx1, cy1):#tx,ty = self.targetendpx,py = self.parentendx = px
12、 + cx y = py + cy if amap.walkable(x, y) and amap.walkable(px + cx0, py + cy0) and amap.walkable(px + cx1, py + cy1):index = x + y * self.widthchild = self.amap._mazeindex if (child s = time()for i in range(size):mapdata.append(0)for i in range(size):mapdata1.append(0)for i in range(size):mapdata2.a
13、ppend(0)p = Noneamap = AMap(w,h,mapdata)mask = amap.getMask()endpoint = w-2,h-2endpointrounds = endpointrounds.append(endpoint0 +1,endpoint1 +0)endpointrounds.append(endpoint0 -1,endpoint1 +0)endpointrounds.append(endpoint0 +0,endpoint1 +1)endpointrounds.append(endpoint0 +0,endpoint1 -1)endpointroun
14、ds.append(endpoint0 +1,endpoint1 +1)endpointrounds.append(endpoint0 +1,endpoint1 -1)endpointrounds.append(endpoint0 -1,endpoint1 +1)endpointrounds.append(endpoint0 -1,endpoint1 -1)test = “for i in range(0,h):x = (int)(w / 2 + 2 / 2)e = i*w + xmapdatae = mask“tick = 20for u in range(5, 955, tick):for
15、 i in range(0,h-1):x = (int)(u)e = i*w + xmapdatae = maskfor i in range(1,h):x = (int)(u + tick / 2)e = i*w + xmapdatae = masktest = “ for ep in endpointrounds:e = (ep1*w)+ep0mapdatae = maske = time() “ a = AFinder()a.setAMap(amap)s = time()p = a.find(0,0,w-2,h-2)e = time()if not p:print “No path fo
16、und! %d nodes and %f seconds.“ % (-1,(e-s)else:print “Found path in %d moves and %d nodes and %f seconds.“ % (-1,-1,(e-s)output = open(output.txt, w)count = 0for xy in p:count += 1s = “(%d,%d)“ % xyoutput.write(s)output.close( )print count:%d % count以上代码中的障碍地图,是 1000*1000,从上刷到下,留一格,又从下刷到上,留一格,中间间隔 10 个格子,也就是说,差不多有 100 道极度曲折的障碍。实验结果:Found path in -1 moves and -1 nodes and 8.730000 seconds.count:98934