当前位置: 首页 > news >正文

实验3 知识表示与推理

实验3 知识表示与推理

一、实验目的
(1)掌握知识和知识表示的基本概念,理解其在AI中的深刻含义与意义;
(2)熟悉AI中常用的知识表示方法的优缺点及其应用场景;
(3)掌握产生式系统知识表示的方法及其构成要素;
(4)掌握状态空间法的基本构成及其特点,能用其表示实际AI问题;
(5)深入理解图的深度、宽度搜索方法,并能应用于实际问题;
(6)根据自身情况,能选择合适的编程语言,解决实际AI问题。
二、实验内容
借助产生式系统和状态空间法,选择一种编程语言(最好为python或java),完成题目要求。
1、八数码难题
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格可用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局,找到一种移动方法,实现从初始布局到目标布局的转变。
在这里插入图片描述

1.需求分析
在一个3×3的棋盘格中,摆有1-8数字的八个棋子,剩余的空格用0表示。给出一种初始布局和目标布局,找到一种移动方法,实现从初始布局到目标布局的转变,规则是移动空格,并且空格不能移出棋盘外。

2.数据结构、功能模块设计与说明
采用广度优先搜索算法,从初始状态开始,每次进行可行操作(与0所在位置相邻数字交换),得到新的状态,并将其加入队列中,直到找到目标状态为止。

在搜索之前需要判断一下目标状态是否可达,根据八数码问题的特性,合法的移动操作只涉及两个数字的交换,空格左右移动不会改变任何两对数字之间的逆序对数量,因为整个序列的相对顺序保持不变。空格上下移动会改变两对数字之间的逆序对数量。当初始状态的空白格和目标状态的空白格在不同行时,只有通过上下移动才有可能改变逆序对的数量,从而实现初始状态到目标状态的转换。故当初始状态和结果状态逆序数奇偶性相同的时候才可达,否则不进行搜索。

当目标状态可达的时候,又因为有很多状态会重复出现,所以判断移动之后的状态是否出现过?这里用哈希表来去重,如果出现过则丢弃;否则,将它加入队列,并将它对应的步数设为前一个状态的步数+1,直到找到目标状态为止。

3.核心代码与测试结果说明

# 在 A* 算法 中的一个节点。代表了搜索空间中的一个状态
class Node:def __init__(self, state, parent=None, move=0, depth=0):self.state = stateself.parent = parentself.move = moveself.depth = depthself.cost = 0  # g(n) + h(n)def __lt__(self, other):return self.cost < other.cost# A* 算法
# 结合实际成本(g(n))和估计成本(h(n))来选择最有希望的路径
# g(n) 是从起始节点到当前节点的移动次数(或称为深度),
# 而 h(n) 是当前状态与目标状态之间的曼哈顿距离
def a_star(initial, goal):open_list = []closed_set = set()root = Node(initial)heapq.heappush(open_list, (manhattan_distance(initial, goal), root))while open_list:_, current = heapq.heappop(open_list)closed_set.add(tuple(current.state))if current.state == goal:path = []while current:path.append(current.state)current = current.parentreturn path[::-1]zero_pos = current.state.index(0)x, y = divmod(zero_pos, 3)moves = [(-1, 0), (1, 0), (0, -1), (0, 1)]for dx, dy in moves:new_x, new_y = x + dx, y + dyif 0 <= new_x < 3 and 0 <= new_y < 3:new_state = current.state[:]new_pos = new_x * 3 + new_ynew_state[zero_pos], new_state[new_pos] = new_state[new_pos], new_state[zero_pos]if tuple(new_state) not in closed_set:new_node = Node(new_state, current, move=current.move + 1, depth=current.depth + 1)new_node.cost = new_node.depth + manhattan_distance(new_state, goal)heapq.heappush(open_list, (new_node.cost, new_node))return None

结果:
在这里插入图片描述

4.存在的问题与体会
4.1 存在的问题
这种解法空间复杂度较高。使用广度优先搜索算法时,需要存储所有的状态和路径信息。通过哈希表来存储状态路径信息,可能会占用较大内存空间,特别是当搜索空间非常庞大时。所以可以考虑使用其他数据结构或优化算法,以减少空间复杂度。

4.2 体会
虽然代码存在一些问题和可以改进的地方,但我深入理解了广度优先搜索算法,并在实践中获得了关于数据结构和代码设计的经验。

2、设有3个传教士和3个野人来到河边,打算乘一只船从右岸渡到左岸去。该船每一次只能装载2人。在任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉。请你设计一个方案怎样才能用这条船安全地把所有人都渡过河去?编程实现你的方案。
在这里插入图片描述

1.需求分析
有3个传教士和3个野人从河右岸乘一只船到左岸,且该船每次只能装载2人。必须保证在任何时候,野人人数不能超过传教士人数,否则野人就会把传教士吃掉。设计一个方案怎样才能用这条船安全地把所有人都渡过河去?并且推广到有n个传教士和n个野人,河边的船每次至多可供k个人渡河的解决方案。

2.数据结构、功能模块设计与说明
使用深度优先搜索算法,寻找所有可能的移动方案。其中,每个状态包括左岸传教士和野人的数量,以及船的位置(左岸或右岸)。通过不断尝试不同的移动方案,最终找到一种能够使所有人都安全到达右岸的方法。

3.核心代码:

# 检查一组传教士和野人的数量是否符合规则
def is_valid_state(left_missionaries, left_cannibals):if left_missionaries < 0 or left_cannibals < 0:return Falseif (3 - left_missionaries) < 0 or (3 - left_cannibals) < 0:return Falseif (left_missionaries > 0 and left_cannibals > left_missionaries) or ((3 - left_missionaries) > 0 and (3 - left_cannibals) > (3 - left_missionaries)):return False
return True# 接收一个状态state作为输入,并返回可能的下一个状态列表
def next_states(state):left_missionaries, left_cannibals, right_missionaries, right_cannibals, boat_position = statenext_states_list = []if boat_position == 'left':for i in range(3):for j in range(3):if i + j > 0 and i + j <= 2:new_left_missionaries = left_missionaries - inew_left_cannibals = left_cannibals - jnew_right_missionaries = right_missionaries + inew_right_cannibals = right_cannibals + jif is_valid_state(new_left_missionaries, new_left_cannibals):def bfs():initial_state = (3, 3, 0, 0, 'left')goal_state = (0, 0, 3, 3, 'right')visited = set()queue = deque([(initial_state, [])])while queue:state, path = queue.popleft()if state == goal_state:return path + [state]if state not in visited:visited.add(state)for next_state in next_states(state):queue.append((next_state, path + [state]))
return None

结果:
在这里插入图片描述

http://www.lryc.cn/news/542059.html

相关文章:

  • 基于Springboot银行信用卡额度管理系统【附源码】
  • 达梦数据库学习笔记@1
  • 图像处理篇---图像处理中常见参数
  • AI Agent实战:打造京东广告主的超级助手 | 京东零售技术实践
  • 50周学习go语言:第1周 环境搭建
  • 4. MySQL 逻辑架构说明
  • 《AI与NLP:开启元宇宙社交互动新纪元》
  • 面对STM32的庞大体系,如何避免迷失在细节中?
  • ragflow-RAPTOR到底是什么?请通俗的解释!
  • Linux系统移植之Uboot启动流程
  • 【Open X-Embodiment】简单数据下载与预处理
  • 【第四节】C++设计模式(创建型模式)-Builder(建造者)模式
  • 排查JVM的一些命令
  • uni-app(位置1)
  • 某手sig3-ios算法 Chomper黑盒调用
  • 登录-05.JWT令牌-介绍
  • Mac下Python版本管理,适用于pyenv不起作用的情况
  • Ubuntu 服务器Llama Factory 搭建DeepSeek-R1微调训练环境
  • 【redis】redis内存管理,过期策略与淘汰策略
  • RabbitMQ学习—day6—死信队列与延迟队列
  • seacmsv9联合注入数据以及绕过 ORDERBY
  • day58 第十一章:图论part08
  • 网络安全-openssl工具
  • Java面试第六山!《MySQL基础知识点》
  • 云计算中的API网关是什么?为什么它很重要?
  • 【WebGL】fbo双pass案例
  • Unity面板介绍_层级面板(23.1.1)
  • 详解Nginx 配置
  • 数据库系统概念
  • 51单片机学习之旅——定时器