当前位置: 首页 > 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 = state
        self.parent = parent
        self.move = move
        self.depth = depth
        self.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.parent
            return 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 + dy
            if 0 <= new_x < 3 and 0 <= new_y < 3:
                new_state = current.state[:]
                new_pos = new_x * 3 + new_y
                new_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 False
    if (3 - left_missionaries) < 0 or (3 - left_cannibals) < 0:
        return False
    if (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 = state
    next_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 - i
                    new_left_cannibals = left_cannibals - j
                    new_right_missionaries = right_missionaries + i
                    new_right_cannibals = right_cannibals + j
                    if 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

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

相关文章:

  • LabVIEW电能质量分析软件
  • 【学习笔记】Google的Lyra项目:基于神经网络的超低比特率语音编解码技术
  • MFC笔记:本专栏课件
  • 详解Tomcat下载安装以及IDEA配置Tomcat(2023最新)
  • 【NLP 24、实践 ⑤ 计算Bert模型中的参数数量】
  • stack,queue,priority_queue学习知识点
  • 《深度剖析Linux 系统 Shell 核心用法与原理_666》
  • 解决升级flutter 3.29.0 Gradle8.7后报错 Exception has occurred. MissingPluginException
  • 网络安全之Web后端PHP
  • 【GESP】C++二级模拟 luogu-b3995, [GESP 二级模拟] 小洛的田字矩阵
  • 【DBeaver】Oracle数据库连接报错:驱动程序 ‘Oracle‘ 的配置错误的解决办法
  • mysql基础知识
  • MFC学习笔记-1
  • 利用开源小智AI制作桌宠机器狗
  • Word(2010)排版技巧
  • 人工智能之不同数据类型及其特点梳理
  • Kafka面试题----Kafka是如何保证顺序消费的
  • WordPress ABF Freight Edition sql注入漏洞复现(CVE-2024-13485)(附脚本)
  • JMeter 中实现 100 个用户在 3 秒内并发登录
  • vue3学习4-pinia+组件通信
  • 商务部回应稀土出口管制问题
  • 远洋集团:今年前4个月销售80.9亿元,同比增加13.62%
  • 普京确定俄乌谈判俄方代表团名单
  • 陕西一村民被冒名贷款40余万续:名下已无贷款,将继续追责
  • 大外交|巴西总统卢拉第六次访华签署20项协议,“双方都视对方为机遇”
  • 中国-拉共体论坛第四届部长级会议北京宣言