master
huangjielun 2 years ago
parent 566a42c81f
commit 4d56ebbbc2

3
.idea/.gitignore vendored

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 2.7" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
</module>

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 2.7" project-jdk-type="Python SDK" />
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Pacman.iml" filepath="$PROJECT_DIR$/.idea/Pacman.iml" />
</modules>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

@ -0,0 +1,541 @@
# Pacman 实验1
## 一.实验目的
1.加深对经典的DFSBFS一致代价搜索A*搜索的理解,并掌握其初步的使用方法
## 二.实验原理
### 1.宽度优先搜索
**宽度优先搜索**bread-first search)是简单搜索策略,先扩展根节点,接着扩展根节点的所有后继,然后再扩展它们的后继,以此类推。其伪代码如下![image-20221021212311445](D:\AI\Subject\Pacman\doc\image-20221021212311445.png)
下图显示了一个简单二叉树的搜索过程
![image-20221021212559638](D:\AI\Subject\Pacman\doc\image-20221021212559638.png)
### 2.深度优先搜索
**深度优先搜索**(depth-first search)总是扩展搜索树的当前边缘结点集中最深的节点。搜索很快推进到搜索树的最深层,那里的结点没有后继。当那些结点扩展完之后,就从边缘结点集中去掉,然后搜索算法回溯到下一个还有未扩展后继的深度稍浅的结点。其伪代码如下![image-20221021212636227](D:\AI\Subject\Pacman\doc\image-20221021212636227.png)
下图显示了一个简单的二叉树搜索过程
![image-20221021212936449](D:\AI\Subject\Pacman\doc\image-20221021212936449.png)
### 3.一致代价搜索
**一致代价搜索**总是扩展路径消耗最小的节点N。N点的路径消耗等于前一节点N-1的路径消耗加上N-1到N节点的路径消耗。其伪代码如下
![image-20221021213229986](D:\AI\Subject\Pacman\doc\image-20221021213229986.png)
下图举了一个简单的例子说明一致代价搜索
![image-20221021213316266](D:\AI\Subject\Pacman\doc\image-20221021213316266.png)
### 4.A*搜索
**A*搜索**对结点的评估结合了g(n),即到达此结点已经花费的代价,和A(n),从该结点到目标结点所花代价:
`f(n)=g(n)+h(n)`
由于g(n)是从开始结点到结点n的路径代价,而A(n)是从结点n到目标结点的最小代价路径的估计值,因此
` f(n)= 经过结点n的最小代价解的估计代价`
这样,如果我们想要找到最小代价的解,首先扩展g(n)+ A(n)值最小的结点是合理的.可以发现这个策略不仅仅合理:假设启发式函数H(n)满足特定的条件,A*搜索既是完备的也是最优的.算法与一致代价搜索类似,除了A*使用g+h而不是g.
下图举了一个简单的例子说明A*搜索的过程
![image-20221021213939136](D:\AI\Subject\Pacman\doc\image-20221021213939136.png)
## 三.实验内容
1.完成search文件夹中search.py中的depthFirstSearchbreadFirstSearchuniformCostSearchaStarSearch四个函数。
在编写完代码后可在终端中的search目录下执行`python2 .\autograder.py` 命令,即可查看是否通过!
## 四.实验结果
搜索算法中四个函数的具体实现如下
### 1.depthFirstSearch
```python
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 ***"
visited_node = []
myStack= util.Stack()
actions = []
s = problem.getStartState()
if problem.isGoalState(s):
return actions
myStack.push((s, actions))
while not myStack.isEmpty():
state = myStack.pop()
if state[0] in visited_node:
continue
visited_node.append(state[0])
actions = state[1]
if (problem.isGoalState(state[0])):
return actions
for successor in problem.getSuccessors(state[0]):
child_state = successor[0]
action = successor[1]
sub_action = list(actions)
if not child_state in visited_node:
sub_action.append(action)
myStack.push((child_state, sub_action))
return actions
util.raiseNotDefined()
```
### 2.breadFirstSearch
```python
def breadthFirstSearch(problem):
"""Search the shallowest nodes in the search tree first."""
"*** YOUR CODE HERE ***"
visited_node = []
myQueue = util.Queue()
actions = []
s = problem.getStartState()
if problem.isGoalState(s):
return actions
myQueue.push((s, actions))
while not myQueue.isEmpty():
state = myQueue.pop()
if state[0] in visited_node:
continue
visited_node.append(state[0])
actions = state[1]
if (problem.isGoalState(state[0])):
return actions
for successor in problem.getSuccessors(state[0]):
child_state = successor[0]
action = successor[1]
sub_action = list(actions)
if not child_state in visited_node:
sub_action.append(action)
myQueue.push((child_state, sub_action))
return actions
util.raiseNotDefined()
```
### 3.uniformCostSearch
```python
def uniformCostSearch(problem):
"""Search the node of least total cost first."""
"*** YOUR CODE HERE ***"
visited_node = []
mypriorityQueue = util.PriorityQueue()
actions = []
s = problem.getStartState()
if problem.isGoalState(s):
return actions
mypriorityQueue.push((s, actions), 0)
while not mypriorityQueue.isEmpty():
state = mypriorityQueue.pop()
if state[0] in visited_node:
continue
visited_node.append(state[0])
actions = state[1]
if (problem.isGoalState(state[0])):
return actions
for successor in problem.getSuccessors(state[0]):
child_state = successor[0]
action = successor[1]
sub_action = list(actions)
if not child_state in visited_node:
sub_action.append(action)
mypriorityQueue.push((child_state, sub_action), problem.getCostOfActions(sub_action))
return actions
util.raiseNotDefined()
```
### 4.aStarSearch
```python
def aStarSearch(problem, heuristic=nullHeuristic):
"""Search the node that has the lowest combined cost and heuristic first."""
"*** YOUR CODE HERE ***"
visited_node = []
mypriorityQueue = util.PriorityQueue()
actions = []
s = problem.getStartState()
if problem.isGoalState(s):
return actions
mypriorityQueue.push((s, actions), 0)
while not mypriorityQueue.isEmpty():
state = mypriorityQueue.pop()
if state[0] in visited_node:
continue
visited_node.append(state[0])
actions = state[1]
if (problem.isGoalState(state[0])):
return actions
for successor in problem.getSuccessors(state[0]):
child_state = successor[0]
action = successor[1]
sub_action = list(actions)
if not child_state in visited_node:
sub_action.append(action)
mypriorityQueue.push((child_state, sub_action),heuristic(child_state, problem)
+ problem.getCostOfActions(sub_action))
return actions
util.raiseNotDefined()
```
在写完这四个函数后,在终端中输入 `python2 .\autograder.py`
![image-20221022153157435](D:\AI\Subject\Pacman\doc\image-20221022153157435.png)
等到一段时间后,可以得到测试结果
![image-20221022153238236](D:\AI\Subject\Pacman\doc\image-20221022153238236.png)
测试通过!
## 五.附加实验
在完成了search实验的四个搜索算法的基础上进一步完成附加实验包括[Corners Problem: Representation](http://ai.berkeley.edu/search.html#Q5)[Corners Problem: Heuristic](http://ai.berkeley.edu/search.html#Q6)[Eating All The Dots: Heuristic](http://ai.berkeley.edu/search.html#Q7)[Suboptimal Search](http://ai.berkeley.edu/search.html#Q8).
### 1.Corner Problem
本关主要是实现一个找到所有角落的启发式函数,实现思路为先获取地图的大小,然后记录每个后继的坐标,然后通过比较判断是否为地图角落,实现代码如下
```python
def __init__(self, startingGameState):
"""
Stores the walls, pacman's starting position and corners.
"""
self.walls = startingGameState.getWalls()
self.startingPosition = startingGameState.getPacmanPosition()
top, right = self.walls.height-2, self.walls.width-2
self.corners = ((1,1), (1,top), (right, 1), (right, top))
for corner in self.corners:
if not startingGameState.hasFood(*corner):
print 'Warning: no food in corner ' + str(corner)
self._expanded = 0 # DO NOT CHANGE; Number of search nodes expanded
# Please add any code here which you would like to use
# in initializing the problem
"*** YOUR CODE HERE ***"
self.top = top
self.right = right
```
```python
def getStartState(self):
"""
Returns the start state (in your state space, not the full Pacman state
space)
"""
"*** YOUR CODE HERE ***"
startState = (self.startingPosition,[])
return startState
util.raiseNotDefined()
```
```python
def isGoalState(self, state):
"""
Returns whether this search state is a goal state of the problem.
"""
"*** YOUR CODE HERE ***"
result = state[1]
if state[0] in self.corners:
if state[0] not in result:
result.append(state[0])
if (len(result) == 4):
return True
else:
return False
util.raiseNotDefined()
```
```python
def getSuccessors(self, state):
"""
Returns successor states, the actions they require, and a cost of 1.
As noted in search.py:
For a given state, this should return a list of triples, (successor,
action, stepCost), where 'successor' is a successor to the current
state, 'action' is the action required to get there, and 'stepCost'
is the incremental cost of expanding to that successor
"""
successors = []
for action in [Directions.NORTH, Directions.SOUTH, Directions.EAST, Directions.WEST]:
# Add a successor state to the successor list if the action is legal
# Here's a code snippet for figuring out whether a new position hits a wall:
# x,y = currentPosition
# dx, dy = Actions.directionToVector(action)
# nextx, nexty = int(x + dx), int(y + dy)
# hitsWall = self.walls[nextx][nexty]
"*** YOUR CODE HERE ***"
x, y = state[0]
dx, dy = Actions.directionToVector(action)
nextx, nexty = int(x + dx), int(y + dy)
visited = list(state[1])
if not self.walls[nextx][nexty]:
nextState = (nextx, nexty)
cost = 1
if nextState in self.corners and nextState not in visited:
visited.append(nextState)
successors.append(((nextState, visited), action, cost))
self._expanded += 1 # DO NOT CHANGE
return successors
```
### 2.Corners Heuristic
本关实现一个走到所有角落的最短路径的启发式函数为之后的搜索作准备实现思路为通过last记录四个角落然后依次计算所有后继至四个角落的曼哈顿距离求和之后取最小值该后继作为下一步实现代码如下
```python
def cornersHeuristic(state, problem):
"""
A heuristic for the CornersProblem that you defined.
state: The current search state
(a data structure you chose in your search problem)
problem: The CornersProblem instance for this layout.
This function should always return a number that is a lower bound on the
shortest path from the state to a goal of the problem; i.e. it should be
admissible (as well as consistent).
"""
corners = problem.corners # These are the corner coordinates
walls = problem.walls # These are the walls of the maze, as a Grid (game.py)
"*** YOUR CODE HERE ***"
visited = state[1]
now_state = state[0]
Heuristic = 0
last = []
if (problem.isGoalState(state)):
return 0
for i in corners:
if i not in visited:
last.append(i)
pos = now_state
cost = 999999
while len(last) != 0:
for i in last:
if cost > (abs(pos[0] - i[0]) + abs(pos[1] - i[1])):
min_con = i
cost = (abs(pos[0] - i[0]) + abs(pos[1] - i[1]))
Heuristic += cost
pos = min_con
cost = 999999
last.remove(min_con)
return Heuristic
```
### 3.Food Heuristic
本关实现一个新的搜索食物的启发式函数,使找到所有食物的路径最小。实现思路为先找到代价最大的食物,然后根据当前位置与最大代价的食物的相对位置,计算出已经吃掉的食物数量,先将代价小的食物都吃掉,最后再吃代价大的食物,即为最短路径。实现代码如下,
```python
def foodHeuristic(state, problem):
"""
Your heuristic for the FoodSearchProblem goes here.
This heuristic must be consistent to ensure correctness. First, try to come
up with an admissible heuristic; almost all admissible heuristics will be
consistent as well.
If using A* ever finds a solution that is worse uniform cost search finds,
your heuristic is *not* consistent, and probably not admissible! On the
other hand, inadmissible or inconsistent heuristics may find optimal
solutions, so be careful.
The state is a tuple ( pacmanPosition, foodGrid ) where foodGrid is a Grid
(see game.py) of either True or False. You can call foodGrid.asList() to get
a list of food coordinates instead.
If you want access to info like walls, capsules, etc., you can query the
problem. For example, problem.walls gives you a Grid of where the walls
are.
If you want to *store* information to be reused in other calls to the
heuristic, there is a dictionary called problem.heuristicInfo that you can
use. For example, if you only want to count the walls once and store that
value, try: problem.heuristicInfo['wallCount'] = problem.walls.count()
Subsequent calls to this heuristic can access
problem.heuristicInfo['wallCount']
"""
position, foodGrid = state
"*** YOUR CODE HERE ***"
lsFoodGrid = foodGrid.asList()
last = list(lsFoodGrid)
Heuristic = 0
cost = 0
max_con = position
for i in last:
if cost < (abs(position[0] - i[0]) + abs(position[1] - i[1])):
max_con = i
cost = (abs(position[0] - i[0]) + abs(position[1] - i[1]))
Heuristic = cost
diff = position[0] - max_con[0]
count = 0
for i in last:
if diff > 0:
if position[0] < i[0]:
count += 1
if diff < 0:
if position[0] > i[0]:
count += 1
if diff == 0:
if position[0] != i[0]:
count += 1
return Heuristic + count
```
### 4.Suboptimal Search
本关实现一个次优搜索在保证吃掉所有食物的条件下在较短的时间内找到一个比较好的路径。实现思路为使用优先队列和AnyFoodSearchProblem类中实现的函数完成本关实现代码如下
```python
class ClosestDotSearchAgent(SearchAgent):
"Search for all food using a sequence of searches"
def registerInitialState(self, state):
self.actions = []
currentState = state
while(currentState.getFood().count() > 0):
nextPathSegment = self.findPathToClosestDot(currentState) # The missing piece
self.actions += nextPathSegment
for action in nextPathSegment:
legal = currentState.getLegalActions()
if action not in legal:
t = (str(action), str(currentState))
raise Exception, 'findPathToClosestDot returned an illegal move: %s!\n%s' % t
currentState = currentState.generateSuccessor(0, action)
self.actionIndex = 0
print 'Path found with cost %d.' % len(self.actions)
def findPathToClosestDot(self, gameState):
"""
Returns a path (a list of actions) to the closest dot, starting from
gameState.
"""
# Here are some useful elements of the startState
startPosition = gameState.getPacmanPosition()
food = gameState.getFood()
walls = gameState.getWalls()
problem = AnyFoodSearchProblem(gameState)
"*** YOUR CODE HERE ***"
Result = []
Visited = []
Queue = util.PriorityQueue()
startState = (problem.getStartState(),[],0)
Queue.push(startState,startState[2])
while not Queue.isEmpty():
(state,path,cost) = Queue.pop()
if problem.isGoalState(state):
Result = path
break
if state not in Visited:
Visited.append(state)
for currentState,currentPath,currentCost in problem.getSuccessors(state):
newPath = path + [currentPath]
newCost = cost + currentCost
newState = (currentState,newPath,newCost)
Queue.push(newState,newCost)
return Result
util.raiseNotDefined()
class AnyFoodSearchProblem(PositionSearchProblem):
"""
A search problem for finding a path to any food.
This search problem is just like the PositionSearchProblem, but has a
different goal test, which you need to fill in below. The state space and
successor function do not need to be changed.
The class definition above, AnyFoodSearchProblem(PositionSearchProblem),
inherits the methods of the PositionSearchProblem.
You can use this search problem to help you fill in the findPathToClosestDot
method.
"""
def __init__(self, gameState):
"Stores information from the gameState. You don't need to change this."
# Store the food for later reference
self.food = gameState.getFood()
# Store info for the PositionSearchProblem (no need to change this)
self.walls = gameState.getWalls()
self.startState = gameState.getPacmanPosition()
self.costFn = lambda x: 1
self._visited, self._visitedlist, self._expanded = {}, [], 0 # DO NOT CHANGE
def isGoalState(self, state):
"""
The state is Pacman's position. Fill this in with a goal test that will
complete the problem definition.
"""
x,y = state
"*** YOUR CODE HERE ***"
foodGrid = self.food
if foodGrid[x][y] == True or foodGrid.count() == 0:
return True
else:
return False
util.raiseNotDefined()
def mazeDistance(point1, point2, gameState):
"""
Returns the maze distance between any two points, using the search functions
you have already built. The gameState can be any game state -- Pacman's
position in that state is ignored.
Example usage: mazeDistance( (2,4), (5,6), gameState)
This might be a useful helper function for your ApproximateSearchAgent.
"""
x1, y1 = point1
x2, y2 = point2
walls = gameState.getWalls()
assert not walls[x1][y1], 'point1 is a wall: ' + str(point1)
assert not walls[x2][y2], 'point2 is a wall: ' + str(point2)
prob = PositionSearchProblem(gameState, start=point1, goal=point2, warn=False, visualize=False)
return len(search.bfs(prob))
```
## 六.实验总结
学会了四个经典的搜索算法的用法在前期的算法课中虽然学习过DFSBFSaStar等搜索算法但是之前的考试都考背诵代码都没有真正的理解这些算法的过程。Pacman实验将算法的过程通过吃豆人的移动与路径的选择表现出来让人眼前一亮也让人更加深刻的理解这些算法。

@ -0,0 +1,257 @@
# Pacman 实验2
## 一.实验目的
1.通过实验理解零和游戏的博弈过程,学会简单的评估函数的设计
2.掌握极小极大法和alpha-beta剪枝
## 二.实验原理
### 1.极小极大法
在零和博弈中玩家均会在可选的选项中选择将其N步后优势最大化或者令对手优势最小化的选择。将双方决策过程视作一颗决策树若决策树某一层均为己方决策依据状态即接下来是己方进行动作则己方必定会选择使得己方收益最大化的路径将该层称为MAX层。若决策树某一层均为对手决策依据状态即接下来是对手进行动作则对手必定会选择使得己方收益最小化的路径将该层成为MIN层。由此一个极小极大决策树将包含max节点MAX层中的节点、min节点MIN层中的节点和终止节点博弈终止状态节点或N步时的状态节点。每个节点对应的预期收益成为该节点的minimax值。
对于终止结点, minimax值等于直接对局面的估值。对于max结点由于max节点所选择的动作将会由己方给定因此选择minimax值最大的子结点的值作为max结点的值。对于min结点则选择minimax值最小的子结点的值作为min结点的值。
极小极大算法过程可描述如下:
构建决策树;
1.将评估函数应用于叶子结点;
2.自底向上计算每个结点的minimax值
3.从根结点选择minimax值最大的分支作为行动策略。
minimax计算流程如下
1.如果节点是终止节点:应用估值函数求值;
2.如果节点是max节点找到每个子节点的值将其中最大的子节点值作为该节点的值
3.如果节点时min节点找到每个子节点的值将其中最小的子节点值作为该节点的值。
其伪代码如下,
![image-20221021214532214](D:\AI\Subject\Pacman\doc\image-20221021214532214.png)
### 2.alpah-beta剪枝
举个简单的例子说明**alpha-beta剪枝**的过程
![image-20221021214643168](D:\AI\Subject\Pacman\doc\image-20221021214643168.png)
其伪代码如下,
![image-20221021214709128](D:\AI\Subject\Pacman\doc\image-20221021214709128.png)
## 三.实验内容
1.完成multiagent文件夹中的evaluationFunctionMinimaxAgentAlphaBetaAgent函数。
在编写完代码后可在终端中的multiagent目录下执行`python2 .\autograder.py` 命令,即可查看是否通过!
## 四.实验结果
博弈算法中的三个函数(类)的具体实现如下
### 1.evaluationFunction
```python
def evaluationFunction(self, currentGameState, action):
"""
Design a better evaluation function here.
The evaluation function takes in the current and proposed successor
GameStates (pacman.py) and returns a number, where higher numbers are better.
The code below extracts some useful information from the state, like the
remaining food (newFood) and Pacman position after moving (newPos).
newScaredTimes holds the number of moves that each ghost will remain
scared because of Pacman having eaten a power pellet.
Print out these variables to see what you're getting, then combine them
to create a masterful evaluation function.
"""
# Useful information you can extract from a GameState (pacman.py)
successorGameState = currentGameState.generatePacmanSuccessor(action)
newPos = successorGameState.getPacmanPosition()
newFood = successorGameState.getFood()
newGhostStates = successorGameState.getGhostStates()
newScaredTimes = [ghostState.scaredTimer for ghostState in newGhostStates]
#many ghosts
"*** YOUR CODE HERE ***"
GhostPos = successorGameState.getGhostPositions()
x_pacman,y_pacman = newPos
failedDist = min([(abs(each[0]- x_pacman) + abs(each[1]-y_pacman)) for each in GhostPos])
if failedDist != 0 and failedDist < 4:
ghostScore = -11 / failedDist
else :
ghostScore = 0
nearestFood = float('inf')
width = newFood.width
height = newFood.height
if failedDist >= 2:
dx = [1,0,-1,0]
dy = [0,1,0,-1]
List = []
d = {}
List.append(newPos)
d.update({(x_pacman,y_pacman) : 1})
while List:
tempPos = List[0]
List.pop(0)
temp_x,temp_y = tempPos
if newFood[temp_x][temp_y]:
nearestFood = min(nearestFood,(abs(temp_x - x_pacman) + abs(temp_y - y_pacman)))
break
for i in range(len(dx)):
x = temp_x + dx[i]
y = temp_y + dy[i]
if 0 <= x < width and 0 <= y < height:
tempPos =(x,y)
if tempPos not in d:
d[tempPos] = 1
List.append(tempPos)
if nearestFood != float('inf'):
foodScore = 10 / nearestFood
else :
foodScore = 0
return successorGameState.getScore() + foodScore + ghostScore
```
### 2.MinimaxAgent
```python
class MinimaxAgent(MultiAgentSearchAgent):
"""
Your minimax agent (question 2)
"""
def getAction(self, gameState):
"""
Returns the minimax action from the current gameState using self.depth
and self.evaluationFunction.
Here are some method calls that might be useful when implementing minimax.
gameState.getLegalActions(agentIndex):
Returns a list of legal actions for an agent
agentIndex=0 means Pacman, ghosts are >= 1
gameState.generateSuccessor(agentIndex, action):
Returns the successor game state after an agent takes an action
gameState.getNumAgents():
Returns the total number of agents in the game
gameState.isWin():
Returns whether or not the game state is a winning state
gameState.isLose():
Returns whether or not the game state is a losing state
"""
"*** YOUR CODE HERE ***"
def gameOver(gameState):
return gameState.isWin() or gameState.isLose()
#Be different with me
def min_value(gameState, depth, ghost):
value = float('inf')
if gameOver(gameState):
return self.evaluationFunction(gameState)
for action in gameState.getLegalActions(ghost):
if ghost == gameState.getNumAgents() - 1:
value = min(value, max_value(gameState.generateSuccessor(ghost, action), depth))
else:
value = min(value, min_value(gameState.generateSuccessor(ghost, action), depth,
ghost + 1))
return value
def max_value(gameState, depth):
value = float('-inf')
depth = depth + 1
#Be different with me
if depth == self.depth or gameOver(gameState):
return self.evaluationFunction(gameState)
for action in gameState.getLegalActions(0):
value = max(value, min_value(gameState.generateSuccessor(0, action), depth, 1))
return value
nextAction = gameState.getLegalActions(0)
Max = float('-inf')
Result = None
for action in nextAction:
if (action != "stop"):
depth = 0
value = min_value(gameState.generateSuccessor(0, action), depth, 1)
if (value > Max):
Max = value
Result = action
return Result
util.raiseNotDefined()
```
### 3.AlphaBetaAgent
```python
class AlphaBetaAgent(MultiAgentSearchAgent):
"""
Your minimax agent with alpha-beta pruning (question 3)
"""
def getAction(self, gameState):
"""
Returns the minimax action using self.depth and self.evaluationFunction
"""
"*** YOUR CODE HERE ***"
ghostIndex = [i for i in range(1,gameState.getNumAgents())]
def gameOver(state,depth):
return state.isWin() or state.isLose() or depth == self.depth
def min_value(state,depth,ghost,alpha,beta):
if gameOver(state,depth):
return self.evaluationFunction(state)
value = float('inf')
for action in state.getLegalActions(ghost):
if ghost == ghostIndex[-1]:
value = min(value,max_value(state.generateSuccessor(ghost,action),depth+1,alpha,beta))
else:
value = min(value,min_value(state.generateSuccessor(ghost,action),depth,ghost+1,alpha,beta))
if value < alpha:
return value
beta = min(beta,value)
return value
def max_value(state,depth,alpha,beta):
if gameOver(state,depth):
return self.evaluationFunction(state)
value = float('-inf')
for action in state.getLegalActions(0):
if action == 'stop':
continue
value = max(value,min_value(state.generateSuccessor(0,action),depth,1,alpha,beta))
if value > beta:
return value
alpha = max(value,alpha)
return value
def function(state):
value = float('-inf')
actions = None
alpha = float('-inf')
beta = float('inf')
for action in state.getLegalActions(0):
if action == 'stop':
continue
tmpValue = min_value(state.generateSuccessor(0,action),0,1,alpha,beta)
if value < tmpValue:
value = tmpValue
actions = action
alpha = max(value,alpha)
return actions
return function(gameState)
util.raiseNotDefined()
```
测试过程与结果如下
![image-20221022153803006](D:\AI\Subject\Pacman\doc\image-20221022153803006.png)
![image-20221022153822732](D:\AI\Subject\Pacman\doc\image-20221022153822732.png)
## 五.实验总结
博弈算法在AI课程中第一次接触虽然博弈过程是一个十分玄妙的过程但是计算机人用其大智慧将这个过程转化为一个可以用数学公式描述的过程而这种抽象化的思维能力是一个及其重要的能力。通过Pacman的实验加深了我对alpha-beta剪枝的原理与过程。

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save