通过搜索进行问题求解
本章为讨论一个智能体是如何向前搜索,找到一个动作序列来实现他的最终目的。例如较为著名的tsp问题(Traveling Salesman Problem)。
当采取的正确动作不是很明显时,智能体可能就需要提前规划,考虑一个形成通往目标状态路径的动作序列。这样的智能体被称为问题求解智能体,其所进行的这一过程被称为搜素。
本章仅考虑其中最简单的环境,即回合式的,单智能体的,完全可观测的,确定的,静态的,离散的和已知环境,并对有信息算法和无信息算法进行区分。
3.1问题求解智能体
当智能体已知目的(即目标形式化),知道如何去完成这一目的(即问题形式化),并且通过模拟并搜索,直到直到一个能到达目标的动作序列。再将其执行。这一过程就是智能体在已知环境下可执行的问题求解过程。
![](https://i-blog.csdnimg.cn/blog_migrate/8af8c2b87af521e19fb7f71af394a898.jpeg)
(图例)
并且如果智能体处于一个完全可观测的,确定的,已知的环境中,任何问题的解都是一个固定的动作序列(即上文提及求解过程)。
3.1.1搜索问题和解
搜索问题的形式化定义如下:
可能的环境状态的集合,我们称之为状态空间。
智能体启动时的初始状态。
一个或多个目标状态。(有时问题只有一个目标状态,有时存在若干个可供选择的目标状态,也有时目标是有一个适用于许多状态的属性定义的。)
智能体可以采取的行动。
转移模型用于描述每个动作所起的作用。
动作代价函数:问题求解智能体应该使用反映使用反映其自身性能指标的代价函数。(如tsp问题这个代价可能是行走的路程,也可能是所花费的时间。)
3.1.2问题形式化
我们在处理一部分问题是会将问题形式化为一个模型,一种抽象的数学概述。但是实际的问题有很多因素。但是很多因素我们都可以排除在模型之外,因为他与问题无关。
我们将剔除细节的过程称之为抽象。一个良好的问题形式化应该具有湿度的细节层次(抽象层级)。
3.2问题示例
书中举了很多例子如果有兴趣可自行购买查看。这里就以之前所提的tsp问题举例。
我们在3.1.1中已经提及搜索问题的形式化定义。而tsp问题为假设有一个旅行商人要拜访N个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。
状态:即智能体在哪个城市,或在那段路上。
初始状态:任何状态都可以被指定为初始状态。
动作:在tsp问题中我们可以定义两种动作,即行走和停止。如果我们再将行走动作细分,可以划分为:向前,向后,向左,向右行动。
转移模型:智能体在每个城市之间行走。
目标状态:智能体走完每个城市。
动作代价:可为行走的路程或时间等。
3.3搜索算法
搜索算法是利用计算机的高性能来有目的地穷举一个问题解空间的部分或所有的可能情况,从而求出问题的解的一种方法。现阶段一般有枚举算法、深度优先搜索、广度优先搜索、A*算法、回溯算法、蒙特卡洛树搜索、散列函数等算法。在大规模实验环境中,通常通过在搜索前,根据条件降低搜索规模;根据问题的约束条件进行剪枝;利用搜索过程中的中间解,避免重复计算这几种方法进行优化。
3.3.1最佳搜索算法
最佳优先搜索算法是一种启发式搜索算法(Heuristic Algorithm),其基于广度优先搜索算法,不同点是其依赖于估价函数对将要遍历的节点进行估价,选择代价小的节点进行遍历,直到找到目标点为止。BFS算法不能保证找到的路径是一条最短路径,但是其计算过程相对于Dijkstra算法会快很多。
n表示当前的点,g(n)为从起始点到点n的实际代价,h(n)为从点n到目标点的估价。
(1)BFS没有障碍物时的寻路
(2)BFS遇到障碍物时的寻路
结论:
(1)BFS算法通过估价函数,会将探测快速的导向目标点的方向,其不能够保证寻找到一条最短路径的点,但是其搜索的效率上相对于Dijestra算法会快上很多。
(2)在地图上有障碍物的情况,BFS寻找的路径一般都不是最短路径,在寻路过程中可以尝试配合其他的方法,对寻路进行修正。
3.3.2搜索数据结构
搜索算法需要一个数据结构来跟踪搜索树。树中的节点(node)由一个包含 4 个组成部分
的数据结构表示。
node.State:节点对应的状态。
node.Parent:父节点,即树中生成该节点的节点。
node.Action:父节点生成该节点时采取的动作。
node.Path-Cost:从初始状态到此节点的路径总代价。在数学公式中,一般使用 g(node)
表示 Path-Cost。
通过从一个节点返回的 Parent 指针,我们可以复原到达该节点的路径上的状态和动作。
从一个目标节点开始复原,我们就可以得到问题的解。
我们需要一个数据结构来存储边界。一个恰当的选择是某种队列(queue),因为边界上的
操作有以下几个。
Is-Empty( frontier):返回 true 当且仅当边界中没有节点。
Pop( frontier):返回边界中的第一个节点并将它从边界中删除。
Top( frontier):返回(但不删除)边界中的第一个节点。
Add(node, frontier):将节点插入队列中的适当位置。
搜索算法使用了 3 种不同类型的队列。
优先队列首先弹出根据评价函数 f 计算得到的代价最小的节点。它被用
于最佳优先搜索。
FIFO 队列,即先进先出队列,首先弹出最先添加到队列中的节点;它被用于广度优先搜索。
LIFO 队列,即后进先出队列,也称为栈,
首先弹出最近添加的节点;它被用于深度优先搜索。
已达状态可以存储为一个查找表,其中每个键是一个状态,对应的值是
该状态的节点。