第三章搜索
基本概念
无需重新安排OPEN表的搜索叫做无信息搜索(盲目搜索)
OPEN表(开节点表,也叫作边缘frontier):在任一给定时间,所有待扩展的叶节点的集合
CLOSE表(探索集):记录每个已经扩展过的节点
树搜索:
图搜索
树搜索:重复状态增大时间开销,甚至导致死循环
图搜索:避免重复状态,空间开销大
盲目搜索
宽度优先搜索:
宽度优先搜索 (BFS)
基于节点深度的非递减函数,宽搜最优
扩展的是未扩展节点中深度最浅的节点
目标检测应用于被选择拓展时
S是起始节点
**
def breadthFirstSearch(problem):
"""Search the shallowest nodes in the search tree first."""
"*** YOUR CODE HERE ***"
queue = util.Queue()
search_already = []
now_node = problem.getStartState()
queue.push((now_node,[]))
while not queue.isEmpty():
now_node,actions = queue.pop()
if problem.isGoalState(now_node):
return actions
if not now_node in search_already:
search_already.append(now_node)
successor = problem.getSuccessors(now_node)
for next in successor:
next_state = next[0]
direction = next[1]
if not next_state in search_already:
queue.push((next_state,actions+[direction]))
util.raiseNotDefined()
一致代价搜索
参考
一致代价搜索总是扩展路径消耗最小的节点N。N点的路径消耗等于前一节点N-1的路径消耗加上N-1到N节点的路径消耗
图的一致性代价搜索使用了优先级队列并在边缘中的状态发现更小代价的路径时引入的额外的检查。边缘的数据结构需要支持有效的成员校测,这样它就结合了优先级队列和哈希表的能力。
**
一致代价搜索使用优先级队列,而优先级队列本质上是一个二叉堆
二叉堆
def uniformCostSearch(problem):
"""Search the node of least total cost first."""
"*** YOUR CODE HERE ***"
start = problem.getStartState()
search_already = []
pqueue = util.PriorityQueue()
pqueue.push((start,[]),0)
while not pqueue.isEmpty():
state,action = pqueue.pop()
if problem.isGoalState(state):
return action
if state not in search_already:
successor = problem.getSuccessors(state)
for next in successor:
next_state = next[0]
next_action = next[1]
if next_state not in search_already:
pqueue.push((next_state,action+[next_action]),problem.getCostOfActions(action+[next_action]))
search_already.append(state)
util.raiseNotDefined()
python pacman.py -l mediumMaze -p SearchAgent -a fn=ucs
深度优先搜索
def depthFirstSearch(problem):
"""
Search the deepest nodes in the search tree first.
Your search algorithm needs to return a list of actions that reaches the
goal. Make sure to implement a graph search algorithm.
To get started, you might want to try some of these simple commands to
understand the search problem that is being passed in:
print "Start:", problem.getStartState()
print "Is the start a goal?", problem.isGoalState(problem.getStartState())
print "Start's successors:", problem.getSuccessors(problem.getStartState())
"""
"*** YOUR CODE HERE ***"
#return a list of triples, (successor,action, stepCost), successor that is the next state of next node
start = problem.getStartState()
search_already = []
stack = util.Stack()
stack.push((start,[]))
while not stack.isEmpty():
now_node,action = stack.pop()
if problem.isGoalState(now_node):
return action
if not now_node in search_already:
search_already.append(now_node)
successor = problem.getSuccessors(now_node)
for next in successor:
next_state = next[0]
direction = next[1]
if not next_state in search_already:
stack.push((next_state,action+[direction]))
util.raiseNotDefined()
BFS/UCS/DFS对比
深度受限搜索
迭代加深深度优先搜索
迭代加深的深度有限搜索也设定一个最大深度dmax,开始我们把dmax设为1,然后进行深度受限搜索,如果么有找到答案,则让dmax加一,并再次进行深度有限搜索,以此类推直到找到目标。这样既可以避免陷入深度无限的分支,同时还可以找到深度最浅的目标解,从而在每一步代价一致的时候找到最优解,再加上其优越的空间复杂度,因此常常作为首选的无信息搜索策略
双向搜索
分别从源头和目标搜索