# 《人工智能：线代方法》 第二部分问题求解 通过搜索进行问题求解(2)

​ 人工智能中的搜索策略大体分为两种：无信息搜索有信息搜索

• 广度优先搜索
• 代价一致搜索
• 深度优先搜索
• 深度受限搜索
• 迭代加深搜索
• 双向搜索

### 3.4.1 广度优先搜索

（一般而言，指数级别复杂度的搜索问题不能用无信息的搜索算法求解，除非是规模很小的实例）

BFS是一个简单的搜索策略，在搜索过程中会对所有状态进行遍历，因此它是完备的；

• 代码实现
"""

"""
import sys
from collections import deque
from utils import *

class Problem:
def __init__(self, initial, goal=None):
self.initial = initial
self.goal = goal
def action(self, state):
raise NotCodeError
def result(self, state, action):
raise NotCodeError
def is_goal(self, state):
if isinstance(self.goal, list):
return is_in(state, self.goal)
else:
return state == self.goal
def path_cost(self, c, state1, action, state2):
return c + 1
def value(self, state):
raise NodeCodeError

class Node:
"""搜索树中的节点"""
def __init__(self, state, parent=None, action=None, path_cost=0):
self.state = state
self.parent = parent
self.action = action
self.path_cost = path_cost
self.depth = 0
if parent:
self.depth = parent.depth + 1
def __repr__(self):
return "<Node {}>".format(self.state)
def __lt__(self.node):
return self.state < node.state
def expand(self, problem):
return [self.child_node(problem, action)
for action in problem, action]
def child_node(self, problem, action):
next_state = problem.result(self.state, action)
next_node = Node(next_state, self, action, problem.path_cost(self.path_cost, self.state, action, next_state))
def solution(self):
return [node.action for node in self.path()[1:]]

	# class Node continued
def path(self):
node, path = self, []
while node:
path_back.append(node)
node = node.parent
return list(reversed(path_back))
def __eq__(self, other):
return isinstance(other, Node) and self.state == other.state
def __hash__(self):
return hash(self.state)

"""
BFS

"""
frontier = deque([Node(problem.initial)]) # FIFO queue
while frontier:
node = frontier.popleft()
if problem.is_goal(node.state):
return node
frontier.extend(node.expand(problem))
return None


### 3.4.2 Dijkstra算法或一致代价搜索

• 1）目标检测应用于节点被选择扩展时，而不是在节点生成的时候。原因：一致代价搜索希望在替换代价更小的节点后再确认解；
• 2）如果边缘中的节点有更好的路径到达该节点，那么会引入一个测试。

,其中$$C^{*}$$是最优解的代价，每个行动的代价至少为e，所以最坏情况下，这个复杂度要比BFS的复杂度$$b^{d}$$大的多。（因为一致代价搜索在探索包含代价大的行动之前，经常会探索代价小的行动步骤所在的很大的搜索树）当所有单步耗散都相等时，复杂度变为$$b^{d+1}$$。这种情况下，由于一致代价搜索和BFS的第一个区别，一致代价搜索会在深度d上做更多无用功（因为他是在选择节点的时候才判断是不是目标达到）。

• 在BFS的基础上，一致代价搜索不在扩展深度最浅的节点，而是通过比较路径消耗$$g(n)$$，并选择当前代价最小的节点进行扩展，因此可以保证无论每一步代价是否一致，都能够找到最优解。

### 3.4.3 深度优先搜索和内存问题

DFS使用LIFO队列（最新生成的节点最早被扩展），而且要调用自己的递归函数来实现DFS算法。（有深度界限的递归深度优先搜索算法）

• DFS扩展根节点的一个后继，然后扩展它的一个后继，直到到达搜索树的最深层，那里的节点没有后继，于是DFS回溯到上一层，扩展另外一个未被扩展的节点。
• 在有限状态空间中，DFS是完备的，因为它可以把所有空间遍历一遍；而在无限空间中，DFS则有可能会进入深度无限的分支，因此是不完备的。
• DFS的时间复杂度为为$$O(bd)$$，而空间复杂度仅为$$O(d)$$，因为我们只需要保存当前分支的状态，因此空间复杂度远远好于BFS。
• 然而DFS并不能保证找到最优解。

DFS的搜索效率严重依赖于使用的是图搜索还是树搜索。

### 3.4.4 深度受限和迭代加深搜索

#### 迭代加深的深度优先算法 iterative deepening search（IDS）

IDS = DFS + BFS。

• 1）空间复杂度：O(bd) （和DFS一样）；
• 2）在分支因子有限时完备，在路径待机时节点深度的非递减函数时最优（和BFS一样）。

### 3.4.6 无信息搜索算法对比

posted @ 2023-01-29 22:20  Xu_Lin  阅读(95)  评论(0编辑  收藏  举报