更新2:在使用笔和纸检查测试用例并将其与自动评分器的测试进行比较,以及测试代码的其他部分以确保修剪正在发生之后,我相当确定自动评分器正在出问题,这代码实际上是 alpha-beta 修剪的一个正常工作的示例,这也许也是为什么尽管有近 30 次浏览却没有人发布答案的原因。不确定我现在要做什么,我想把它全部拆掉并构建一个全新的解决方案,并希望自动平地机这次让它滑行。我会保留这个,因为我很想知道自动评分器专门出于我自己的好奇心而叽叽喳喳地说了什么,或者万一我错了并且这段代码在某种程度上是不正确的。
更新:在对此进行了更多的困惑之后,我认为问题可能是我在检查 minVal() 和 maxVal() 函数之前生成了下一组状态,并且也许自动评分器将其读取为过多的状态生成。我修复了这个问题,如下所示:
def minVal(self, state, depth, agentIndex, alpha, beta):
v = float('inf')
#Keeping track of agents and depth.
newAgent = agentIndex + 1
if newAgent == state.getNumAgents():
newAgent = 0
newDepth = depth
if newAgent == 0:
newDepth = depth - 1
#Generating new states
for action in state.getLegalActions(agentIndex):
v = min(v,self.minimax(state.generateSuccessor(agentIndex,action), newDepth, newAgent,alpha, beta))
if v < alpha:
return v
beta = min(beta,v)
return v
def maxVal(self, state, depth, agentIndex, alpha, beta):
v = float('-inf')
#Generating new states.
for action in state.getLegalActions(agentIndex):
v = max(v, self.minimax(state.generateSuccessor(agentIndex,action), depth, agentIndex+1, alpha, beta))
if v > beta:
return v
alpha = max(alpha,v)
return v
不幸的是,这没有导致任何改变,我仍然遇到同样的错误。
我正在尝试完成伯克利吃豆人项目的第二个吃豆人项目。第二个项目是在极小极大上。我的极小极大解决方案工作完美,并被自动评分器接受,但它声称我的 alpha-beta 剪枝算法扩展了太多节点,在对其进行了一番思考并对照在线资源进行检查后,我完全不知道为什么,对我来说这似乎是该算法的正确实现。
我的实现:
class AlphaBetaAgent(MultiAgentSearchAgent):
"""
Your minimax agent with alpha-beta pruning (question 3)
"""
def minimax(self, state, depth, agentIndex, alpha, beta):
if depth == 0 or state.isWin() or state.isLose():
return self.evaluationFunction(state)
if agentIndex == 0:
return self.maxVal(state, depth, agentIndex,alpha, beta)
else:
return self.minVal(state, depth, agentIndex, alpha, beta)
def minVal(self, state, depth, agentIndex, alpha, beta):
v = float('inf')
#Keeping track of agents and depth.
newAgent = agentIndex + 1
if newAgent == state.getNumAgents():
newAgent = 0
newDepth = depth
if newAgent == 0:
newDepth = depth - 1
#Generating new states
newStates = []
for action in state.getLegalActions(agentIndex):
newStates.append(state.generateSuccessor(agentIndex,action))
#Iterating over new states
for newState in newStates:
v = min(v,self.minimax(newState, newDepth, newAgent,alpha, beta))
if v < alpha:
return v
beta = min(beta,v)
return v
def maxVal(self, state, depth, agentIndex, alpha, beta):
v = float('-inf')
#Generating new states.
newStates = []
for action in state.getLegalActions(agentIndex):
newStates.append(state.generateSuccessor(agentIndex,action))
#Iterating over new states.
for newState in newStates:
v = max(v, self.minimax(newState, depth, agentIndex+1, alpha, beta))
if v > beta:
return v
alpha = max(alpha,v)
return v
def getAction(self, gameState):
"""
Returns the minimax action using self.depth and self.evaluationFunction
"""
"*** YOUR CODE HERE ***"
alpha = float('-inf')
beta = float('inf')
legalActions = []
for action in gameState.getLegalActions(0):
legalActions.append(action)
valuedStates = []
for action in legalActions:
valuedStates.append(self.minimax(gameState.generateSuccessor(0,action),self.depth,1,alpha,beta))
ind = valuedStates.index(self.minimax(gameState,self.depth,0,alpha,beta))
return legalActions[ind]
根据我所看到的情况,我认为这是一种有点不寻常的方法,特别是 getAction() 中的部分,我实际上是第二次调用 minimax 以检索操作本身。然而,这是有效的,因为自动评分器接受了我对上一个关于极小极大问题的解决方案。对第二个问题所做的唯一更改是那些直接与 alpha-beta 修剪相关的更改,在这里我完全遵循了该算法。
我在这里无计可施,不知道为什么这会扩大太多的州。我尝试过的一些事情:
我想知道这里是否有人能够看到这个问题,我也向我的教授展示了代码,但他在查看代码时无法注意到任何问题,并说他需要更多时间来检查它。我真的很想了解为什么这不起作用,而不是我希望修复它。
经过一天的工作,我解决了自己的问题,我想为其他参与这些项目的学生回答我自己的问题,他们可能会找到此页面。
问题最终出在 getAction() 中第二次运行 minimax 并使用值索引来找到最佳操作的部分。原因是因为自动评分器出于某种原因对于代码调用generateSuccessor()的次数极其敏感。如果你这样做,它会指责你生成了太多状态。然而,由于两个原因,这个投诉变得更加令人困惑:
无论如何,修复方法是重新设计代码,以便调用generateSuccessor()的次数永远不会超过绝对最低必要次数。为此,我重新设计了最大化器,以便它也返回操作。这需要稍微重新设计所有函数,但最相关的两个是 getAction( ) 和最大化器,我将其称为 maxVal( )。这是重新设计的 getAction( ):
def getAction(self, gameState):
"""
Returns the minimax action using self.depth and self.evaluationFunction
"""
"*** YOUR CODE HERE ***"
alpha = float('-inf')
beta = float('inf')
return self.minimax(gameState,0,0,alpha,beta)
这里是 maxVal( ):
def maxVal(self, state, depth, agentIndex, alpha, beta):
v = float('-inf')
#Generating new states.
returnAct = Directions.STOP
highestVal = float('-inf')
for action in state.getLegalActions(agentIndex):
v = self.minimax(state.generateSuccessor(agentIndex,action), depth, agentIndex+1, alpha, beta)
if v > highestVal:
highestVal = v
returnAct = action
if highestVal > beta:
return highestVal
alpha = max(alpha,v)
if depth == 0:
return returnAct
else:
return highestVal
我还对辅助函数(不是必需的,但我喜欢它)和最小化器做了一些小的更改。不过,发布这些内容会堵塞已经很长的帖子。
我希望这可以帮助将来遇到类似问题的人。