八数码问题

问题描述:
八数码问题也称为九宫问题。在3×3的棋盘上摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格(数字表为0),与空格相邻的棋子可以移到空格中。
需要解决的问题:给出一个初始状态和一个目标状态,求出从初始状态转变成目标状态的移动棋子的最少步数。

启发式搜索

  • 原理:启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标。这样可以省略大量无谓的搜索路径,提高了效率。在启发式搜索中,对位置的估价是十分重要的。采用了不同的估价可以有不同的效果。

  • 估价函数:
    f∗(n)=h∗(n)+g∗(n)f^*(n) = h^*(n) + g^*(n) f∗(n)=h∗(n)+g∗(n)
    其中,在任意节点nnn上定义,g∗(n)g^*(n)g∗(n)为从初始节点SSS到节点nnn的代价;h∗(n)h^*(n)h∗(n)为从节点nnn到目标节点EEE的代价;则f∗(n)f^*(n)f∗(n)定义为从初始节点S经过节点nnn到达目标节点EEE的最佳路径代价。
    定义f∗(n)f^*(n)f∗(n) 的估计函数f(n)f(n)f(n): f(n)=h(n)+g(n)f(n) = h(n) + g(n)f(n)=h(n)+g(n)
    其中,g(n)g(n)g(n)是 g∗(n)g^*(n)g∗(n)的估计函数,f(n)f(n)f(n)是f∗(n)f^*(n)f∗(n)的估计函数。这样定义的估价函数为A算A算A算法

  • 启发式AAA算法:

    1. 将初始节S点放入OPEN表,计算其f(S)f(S)f(S)。
    2. OPEN表为空搜索失败,退出。
    3. 从OPEN表中选择一个fff值最小的节点iii。如果该节点为目标节点,则搜索成功退出。
    4. 把节点iii从OPEN表中移除,放入CLOSE的已扩展节点表中。
    5. 扩展节点iii,生成所有后继节点。对于每个后继节点jjj(进行父子节点连接):
      计算f(j)f(j)f(j);如果jjj即不在OPEN也不在CLOSE中,这把节点jjj放入OPEN表中;如果jjj已在OPEN或CLOSE表中,则比较新旧节点的fff值,如果新节点的值更小,则:

      1. 以新节点替代旧节点
      2. 如果旧节点在CLOSE表中,则将其移回OPEN表中
    6. 退回第2步进行循环
  • 在AAA算法中,当所有节点对于nnn,0<=h(n)<=h∗(n)0<=h(n)<=h^*(n)0<=h(n)<=h∗(n)时(保证了算法的可采纳性),AAA算法成为A∗A^*A∗算法。

使用A*算法解决八数码问题

代码实现时,笔者用State类表示搜索状态,数位digits用长度为9的一维列表表示。g(n)g(n)g(n)为运行深度,h(n)h(n)h(n)为可变函数(可以类外更改)。A∗A^*A∗算法按照算法描述实现。(代码可进一步优化,例如找最小fff值时,笔者偷懒 采用扫描查找,可以通过后续扩展节点插入OPEN表时采用二分插入排序的方法进行优化)
代码中提供了两个可使用的h(n)h(n)h(n)函数(默认恒为0,原算法即为BFS搜索),其中第一个函数的代价定义为每一位数码与其目标位置之间的距离的总和;第二个函数的代价定义为数码错放的数量。

八数码的可解性问题,详细证明自行搜索,这里直接提供结论:把数字排列组成数列,如果初始状态和目标状态的数列的逆序数的奇偶性相同,则可由初始状态移动至目标状态,反之不可。

多说无益, 上代码

代码写的垃圾,勿喷

# 状态类
class State:# h(n) 将付出的代价h = lambda self: 0def __init__(self, digits, depth, pa):# 数位self.digits = digits# 父状态self.pa = pa# 深度 g(n)已付出的代价self.depth = depth# 估价函数self.f = self.__f()# 交换zero位和next位的数def get_digits(self, zero, next):digits = list(self.digits)digits[zero] = digits[next]digits[next] = 0return digits# 获取可移动的下一个digitsdef next_digits(self):zero = [i for i, v in enumerate(self.digits) if v == 0][0]if int(zero / 3) != 0:yield self.get_digits(zero, zero-3)if int(zero / 3) != 2:yield self.get_digits(zero, zero+3)if zero % 3 != 0:yield self.get_digits(zero, zero-1)if zero % 3 != 2:yield self.get_digits(zero, zero+1)# 获取下一个可转换状态(父状态不在内)def next_state(self):for d in self.next_digits():if not self.pa or d != self.pa.digits:yield State(d, self.depth + 1, self)# 计算估价函数f(n) = g(n) + h(n)def __f(self):return self.depth + State.h(self) * 2# 更换h(x)@staticmethoddef change_h(h):State.h = hpassdef __eq__(self, other):return self.digits == other.digitsdef __str__(self):res = 'depth = %d, f(x) = %d\n' % (self.depth, self.f)for i in range(3):res += str(self.digits[i*3: (i+1)*3]) + '\n'return resclass EightDigits:def __init__(self, s, e = [1, 2, 3, 8, 0, 4, 7, 6, 5]):# 初始状态self.s = State(s, 0, None)# 目标状态self.e = eself.open = []self.close = []self.open.append(self.s)# 判断奇偶排列def isOdd(self, digits):num = 0for i in range(9):if digits[i] == 0:continuefor j in range(i + 1, 9):if digits[j] == 0:continueif digits[i] > digits[j]:num += 1return num % 2 == 1# A*算法def A(self):# 判断可不可解if self.isOdd(self.s.digits) != self.isOdd(self.e):return Nonenum = 0while self.open:front = min(self.open, key=lambda x: x.f)self.open.remove(front)num += 1print(front)if front.digits == self.e:# 搜索次数print("-" * 10 + str(num) + "-" * 10 + '\n')return frontself.close.append(front)for next in front.next_state():if next in self.open:for i, o in enumerate(self.open):if next == o:if next.f < o.f:self.open[i] = nextbreakelif next in self.close:for c in self.close:if next == c:if next.f < c.f:self.close.remove(c)self.open.append(next)breakelse:self.open.append(next)return None@staticmethoddef show(state):if state.pa:EightDigits.show(state.pa)print(state)# h函数1 代价为所有数恢复原有状态所移动距离的代价总和
def p(s):e = [1, 2, 3, 8, 0, 4, 7, 6, 5]digits = s.digitsres = 0for i in range(9):for j, v in enumerate(digits):if v == e[i]:t = abs(i - j)res += int(t / 3) + t % 3breakreturn res# h函数2 代价为不在正确位置的数的数量
def w(s):e = [1, 2, 3, 8, 0, 4, 7, 6, 5]digits = s.digitsreturn len([i for i in range(9) if e[i] != digits[i]])if __name__ == '__main__':State.change_h(p) # 采用h函数1eight_digits = EightDigits([2, 1, 3, 0, 8, 7, 4, 6, 5])state = eight_digits.A()if not state:print('初始状态无法移动至目标状态')else:EightDigits.show(state)

启发式搜索--八数码问题相关推荐

  1. 人工智能作业 八数码启发式搜索与bfs比较

    问题描述 3×3九宫棋盘,放置数码为1 -8的8个棋牌,剩下一个空格,只能通过棋牌向空格的移动来改变棋盘的布局. 要求:根据给定初始布局(即初始状态)和目标布局(即目标状态),如何移动棋牌才能从初始布 ...

  2. 人工智能----八数码问题(启发式搜索)

    启发式搜索 一. 实验目的 理解人工智能系统中搜索策略的含义. 熟悉盲目搜索和启发式搜索算法的实际应用. 结合八数码问题的建模.求解及编程语言的应用,掌握启发式搜索算法的应用. 二. 实验原理 启发式 ...

  3. 【八数码问题】基于状态空间法的知识表示与状态搜索:无信息搜索(BFS/DFS) 启发式搜索(A*)

    前言 一.问题引入 二.状态空间法 1. 知识及其表示 2. 状态空间法定义 3. 问题求解 三.基于状态空间搜索法解决八数码问题 1. 八数码问题的知识表示 2. 状态空间图搜索 1. 无信息搜索 ...

  4. A*算法解决八数码问题 人工智能原理实验报告 启发式搜索 python

    目录 一.实验主要步骤 ①.设计界面输入规则 ②.判断是否有解 ③.求解 二.实验结果展示 三.附录 完整实验程序代码: 一.实验主要步骤 ①.设计界面输入规则 有且仅有9位数字代表数码和空格,从左到 ...

  5. 八数码问题及A*算法

    一.八数码问题 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个空格,与空格相邻的棋子可以移到空格中.要求解决的问题是: ...

  6. Eight HDU - 1043(八数码+搜索)

    题意: 就是还原八数码.输出操作. 题目: The 15-puzzle has been around for over 100 years; even if you don't know it by ...

  7. 【codevs1225】八数码难题,如何精确地搜索

    1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道 ...

  8. 《人工智能》实验二——搜索技术(八数码问题)

    必须记住下一步还可以走哪些点--OPEN表(记录还没有扩展的点) 必须记住哪些点走过了--CLOSED表(记录已经扩展的点 广度优先搜索 在应用BFS算法进行八数码问题搜索时需要open和closed ...

  9. 八数码 || 九宫重排(A*搜索代码)

    八数码 || 九宫重排 废话: 这道题如果我们用bfs确实可以跑,但是大概率会炸掉,这道题是可以双向bfs,但今天我要展示的是用A*搜索的代码 策略分析: 1,标记: 既然是搜索,那我们就肯定就要加标 ...

  10. 全局择优搜索、A*算法、宽度优先算法解决八数码问题

    1问题描述 使用盲目搜索中的宽度优先搜索算法或者使用启发式搜索中的全局择优搜索或A算法,对任意的八数码问题给出求解结果.例如:对于如下具体的八数码问题: 通过设计启发函数,编程实现求解过程,如果问题有 ...

最新文章

  1. 特朗普“模仿”奥巴马?进阶版换脸技术DeepFakes来了
  2. linux hadoop etc目录,题目Linux平台下Hadoop的安装配置
  3. ftp搭建后为什么登录不了??_为什么防爆胎就是普及不了?知道真相后,你也许会心凉一大截...
  4. PAT(Basic Level)--个位数统计
  5. ubuntu18.04环境系安装指定版本gitlab-ce
  6. JSF----事件处理----实时事件
  7. 前端实现在线预览pdf、word、xls、ppt等文件
  8. 中南大学毕业设计(论文)LaTeX模板
  9. 《Java 核心技术 卷 Ⅱ:高级特性》(原书第8版) 已经上市了
  10. Flask 项目打包 线上部署
  11. SQL server 还原数据库遇到正在使用的解决方法:
  12. #网络流24# 餐巾计划问题
  13. 怎样用计算机表白我爱你,怎样用简单有“内涵”的话向喜欢的人表白 我爱你!...
  14. python语音控制地图导航_基于python语音控制大疆创新EP机器人并进行对话——第一步学会录音...
  15. 国培计算机音乐教学设计作业,2017国培计划教学设计
  16. flutter 相机加入mask(遮罩层)
  17. (转)实用Word使用技巧大全
  18. 图解LVS的工作原理
  19. Coremail论客全球安全生态合作伙伴召集令正式启动
  20. PMOS防浪涌抑制电路

热门文章

  1. 计算机三级网络技术-----DHCP报文分析
  2. esp8266使用安信可IDE编译、烧录
  3. tftp目录linux目录,tftp命令指定下载目录,2步完成tftp命令传输文件
  4. 图形化编程Mixly——RFID智能门禁
  5. 燕无锡计算机学校,第二十七届中国儿童青少年计算机表演赛无锡赛区决赛成绩-无锡少年宫.doc...
  6. matlab for 数组,Matlab数组
  7. 数字音频接口时序简介
  8. 白盒测试的逻辑覆盖辨析(语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、条件组合覆盖)
  9. 平面坐标转大地坐标(经纬度)
  10. 今日分享:js制作一个简单的新年倒计时