题目链接http://ai.berkeley.edu/search.html
由于能力有限,并没有做到满分。最终成绩为23/25
先更前四个题目,后四个题目陆续更新。
Q1: Depth First Search
第一个问题是需要实现深度优先搜索算法,选择利用util.py文件中已经定义好的Stack结构实现。Stack结构实现了一个后进先出的栈结构,则通过对该栈结构的使用,构造深度优先搜索树。
# 修改search.py 中的depthFirstSearch函数
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 ***"
#获得当前pacman的初始状态
startNode = problem.getStartState()
#检测初始状态是否正好为目标状态
if problem.isGoalState(startNode):
return []
#构造搜索树
myStack = util.Stack()
visitedNode = []
#搜索树的节点结构为(当前状态,[actions]从初始状态到达当前状态经过的动作集合)
myStack.push((startNode, []))
#对搜索树进行遍历,如果遍历结束仍未找到解即返回无解
while not myStack.isEmpty():
currentNode, action = myStack.pop()
if not (currentNode in visitedNode):
visitedNode.append(currentNode)
if problem.isGoalState(currentNode):
return action
#扩展搜索树
for nextNode, nextAction, cost in problem.getSuccessors(currentNode):
newAction = action + [nextAction]
myStack.push((nextNode, newAction))
util.raiseNotDefined()
Q2: Breadth First Search
第二个问题是需要实现宽度有限搜索,其与Q1的深度有限搜索唯一的区别是,使用util.py中的Queue结构构造搜索树。(由于与之前的宽度有限搜索的区别较小,则不再详细说明)
#修改search.py中的breadthFirstSearch函数
def breadthFirstSearch(problem):
"""Search the shallowest nodes in the search tree first."""
"*** YOUR CODE HERE ***"
startNode = problem.getStartState()
if problem.isGoalState(startNode):
return []
myStack = util.Queue()
visitedNode = []
myStack.push((startNode, []))
while not myStack.isEmpty():
currentNode, action = myStack.pop()
if not (currentNode in visitedNode):
visitedNode.append(currentNode)
if problem.isGoalState(currentNode):
return action
for nextNode, nextAction, cost in problem.getSuccessors(currentNode):
newAction = action + [nextAction]
myStack.push((nextNode, newAction))
util.raiseNotDefined()
Q3: Uniform Cost Search
代价一致搜索算法即首先搜索动作代价最小的节点,则使用util.py中的PriorityQueue结构构造搜索树,为搜索树的每个节点增加一个priority参数记录其代价。
def uniformCostSearch(problem):
"""Search the node of least total cost first."""
"*** YOUR CODE HERE ***"
startNode = problem.getStartState()
if problem.isGoalState(startNode):
return []
myCostQueue = util.PriorityQueue()
visitedNode = []
myCostQueue.push((startNode, []), 0)
while not myCostQueue.isEmpty():
currentNode, action = myCostQueue.pop()
if not (currentNode in visitedNode):
visitedNode.append(currentNode)
if problem.isGoalState(currentNode):
return action
for nextNode, nextAction, cost in problem.getSuccessors(currentNode):
newAction = action + [nextAction]
#计算由初始状态到达该节点所需的代价
newCost = problem.getCostOfActions(newAction)
myCostQueue.push((nextNode, newAction), newCost)
util.raiseNotDefined()
Q4: A* Search
A*搜索与代价一致搜索的区别就是,其搜索树节点中的priority参数不仅记录到达此状态已经花费的代价,还需要加上使用启发式函数计算得到的从该状态到目标节点可能花费的代价。
def aStarSearch(problem, heuristic=nullHeuristic):
"""Search the node that has the lowest combined cost and heuristic first."""
"*** YOUR CODE HERE ***"
startNode = problem.getStartState()
startPriority = heuristic(startNode, problem) + 0
if problem.isGoalState(startNode):
return []
myQueue = util.PriorityQueue()
visitedNode = []
myQueue.push((startNode, [], 0), startPriority)
while not myQueue.isEmpty():
currentNode, action, preCost = myQueue.pop()
if not (currentNode in visitedNode):
visitedNode.append(currentNode)
if problem.isGoalState(currentNode):
return action
for nextNode, nextAction, nextCost in problem.getSuccessors(currentNode):
newAction = action + [nextAction]
newCost = problem.getCostOfActions(newAction)
#其中的newCost即为到达此节点已经花费的代价
#heuristic即是用来计算该节点到目标节点可能花费的代价的启发式函数
newPriority = newCost + heuristic(nextNode, problem)
myQueue.push((nextNode, newAction, newCost), newPriority)
util.raiseNotDefined()
测试结果
Question q1
===========
*** PASS: test_cases\q1\graph_backtrack.test
*** solution: ['1:A->C', '0:C->G']
*** expanded_states: ['A', 'D', 'C']
*** PASS: test_cases\q1\graph_bfs_vs_dfs.test
*** solution: ['2:A->D', '0:D->G']
*** expanded_states: ['A', 'D']
*** PASS: test_cases\q1\graph_infinite.test
*** solution: ['0:A->B', '1:B->C', '1:C->G']
*** expanded_states: ['A', 'B', 'C']
*** PASS: test_cases\q1\graph_manypaths.test
*** solution: ['2:A->B2', '0:B2->C', '0:C->D', '2:D->E2', '0:E2->F', '0:F->G']
*** expanded_states: ['A', 'B2', 'C', 'D', 'E2', 'F']
*** PASS: test_cases\q1\pacman_1.test
*** pacman layout: mediumMaze
*** solution length: 130
*** nodes expanded: 146
### Question q1: 3/3 ###
Question q2
===========
*** PASS: test_cases\q2\graph_backtrack.test
*** solution: ['1:A->C', '0:C->G']
*** expanded_states: ['A', 'B', 'C', 'D']
*** PASS: test_cases\q2\graph_bfs_vs_dfs.test
*** solution: ['1:A->G']
*** expanded_states: ['A', 'B']
*** PASS: test_cases\q2\graph_infinite.test
*** solution: ['0:A->B', '1:B->C', '1:C->G']
*** expanded_states: ['A', 'B', 'C']
*** PASS: test_cases\q2\graph_manypaths.test
*** solution: ['1:A->C', '0:C->D', '1:D->F', '0:F->G']
*** expanded_states: ['A', 'B1', 'C', 'B2', 'D', 'E1', 'F', 'E2']
*** PASS: test_cases\q2\pacman_1.test
*** pacman layout: mediumMaze
*** solution length: 68
*** nodes expanded: 269
### Question q2: 3/3 ###
Question q3
===========
*** PASS: test_cases\q3\graph_backtrack.test
*** solution: ['1:A->C', '0:C->G']
*** expanded_states: ['A', 'B', 'C', 'D']
*** PASS: test_cases\q3\graph_bfs_vs_dfs.test
*** solution: ['1:A->G']
*** expanded_states: ['A', 'B']
*** PASS: test_cases\q3\graph_infinite.test
*** solution: ['0:A->B', '1:B->C', '1:C->G']
*** expanded_states: ['A', 'B', 'C']
*** PASS: test_cases\q3\graph_manypaths.test
*** solution: ['1:A->C', '0:C->D', '1:D->F', '0:F->G']
*** expanded_states: ['A', 'B1', 'C', 'B2', 'D', 'E1', 'F', 'E2']
*** PASS: test_cases\q3\ucs_0_graph.test
*** solution: ['Right', 'Down', 'Down']
*** expanded_states: ['A', 'B', 'D', 'C', 'G']
*** PASS: test_cases\q3\ucs_1_problemC.test
*** pacman layout: mediumMaze
*** solution length: 68
*** nodes expanded: 269
*** PASS: test_cases\q3\ucs_2_problemE.test
*** pacman layout: mediumMaze
*** solution length: 74
*** nodes expanded: 260
*** PASS: test_cases\q3\ucs_3_problemW.test
*** pacman layout: mediumMaze
*** solution length: 152
*** nodes expanded: 173
*** PASS: test_cases\q3\ucs_4_testSearch.test
*** pacman layout: testSearch
*** solution length: 7
*** nodes expanded: 14
*** PASS: test_cases\q3\ucs_5_goalAtDequeue.test
*** solution: ['1:A->B', '0:B->C', '0:C->G']
*** expanded_states: ['A', 'B', 'C']
### Question q3: 3/3 ###
Question q4
===========
*** PASS: test_cases\q4\astar_0.test
*** solution: ['Right', 'Down', 'Down']
*** expanded_states: ['A', 'B', 'D', 'C', 'G']
*** PASS: test_cases\q4\astar_1_graph_heuristic.test
*** solution: ['0', '0', '2']
*** expanded_states: ['S', 'A', 'D', 'C']
*** PASS: test_cases\q4\astar_2_manhattan.test
*** pacman layout: mediumMaze
*** solution length: 68
*** nodes expanded: 221
*** PASS: test_cases\q4\astar_3_goalAtDequeue.test
*** solution: ['1:A->B', '0:B->C', '0:C->G']
*** expanded_states: ['A', 'B', 'C']
*** PASS: test_cases\q4\graph_backtrack.test
*** solution: ['1:A->C', '0:C->G']
*** expanded_states: ['A', 'B', 'C', 'D']
*** PASS: test_cases\q4\graph_manypaths.test
*** solution: ['1:A->C', '0:C->D', '1:D->F', '0:F->G']
*** expanded_states: ['A', 'B1', 'C', 'B2', 'D', 'E1', 'F', 'E2']
### Question q4: 3/3 ###