【问题标题】:Alpha-beta pruning in pythonpython中的Alpha-beta修剪
【发布时间】:2014-11-20 04:45:50
【问题描述】:

我正在尝试在 Connect Four 类型的游戏中实现计算机播放器。 Alpha-beta 修剪似乎是实现这一目标的最佳方法,但我似乎无法弄清楚我做错了什么。

以下是我想出的代码。它从初始根状态开始。对于每一个可能的有效移动(如果没有修剪),算法:制作状态的深层副本,更新状态(增加深度,切换转弯,添加一块,设置启发式值),并将这个新状态添加到根的继任者列表。

如果新状态不是叶子(即处于最大深度),它会递归地继续。如果它是叶子,算法检查根的值和适当的局部 alpha/beta 值并相应地更新。在检查完所有可能的有效选项后,算法会返回适当的本地 alpha/beta 值。

至少,这是我的本意。每次运行返回值 0。这里要求的是初始化代码:

class GameState:

   def __init__(self, parentState = None):

      # copy constructor
      if not(parentState == None):

         self.matrix = copy.deepcopy(parentState.matrix)
         self.successor = copy.deepcopy(parentState.successor)
         self.depth = parentState.depth
         self.turn = parentState.turn
         self.alpha = parentState.alpha
         self.beta = parentState.beta
         self.connects = copy.deepcopy(parentState.connects)
         self.value = parentState.value
         self.algo_value = parentState.value
         self.solution = parentState.solution

      # new instance 
      else:

         # empty board
         self.matrix = [[0 for y in xrange(6)] for x in xrange(7)]

         ## USED WHEN GROWING TREE
         self.successor = [] # empty list
         self.depth = 0 # start at root
         self.turn = 1 # game starts on user's turn

         ## USED WHEN SEARCHING FOR SOLUTION
         self.alpha = float("-inf")
         self.beta = float("+inf")

         self.connects = [0, 0, 0] # connects in state
         self.algo_value = float("-inf")
         self.value = 0 # alpha-beta value of connects
         self.solution = False # connect four

    def alphabeta(root):

       if root.depth < MAX_EXPANSION_DEPTH:

          # pass down alpha/beta
          alpha = root.alpha
          beta = root.beta

          # for each possible move
          for x in range(7):

             # ALPHA-BETA PRUNING

             # if root is MAXIMIZER
             if (root.turn == 2) and (root.algo_value > beta): print "beta prune"

             # if root is MINIMIZER
             elif (root.turn == 1) and (root.algo_value < alpha): print "alpha prune"

             # CANNOT prune
             else:

                # if move legal
                if (checkMove(root, x)):

                   # CREATE NEW STATE
                   root.successor.append(GameState(root))
                   working_state = root.successor[-1]

                   # update state
                   working_state.successor = []
                   working_state.depth += 1
                   working_state.turn = (working_state.turn % 2) + 1
                   cons = dropPiece(working_state, x, working_state.turn)

                   # update state values
                   # MAXIMIZER
                   if working_state.turn == 2:
                      working_state.value = ((cons[0]*TWO_VAL)+(cons[1]*THREE_VAL)+(cons[2]*FOUR_VAL)) + root.value
                      working_state.algo_value = float("-inf")
                   # MINIMIZER
                   else:
                      working_state.value = ((-1)*((cons[0]*TWO_VAL)+(cons[1]*THREE_VAL)+(cons[2]*FOUR_VAL))) + root.value
                      working_state.algo_value = float("inf")

                   # if NOT a leaf node
                   if (working_state.depth < MAX_EXPANSION_DEPTH):

                      # update alpha/beta values
                      working_state.alpha = alpha
                      working_state.beta = beta

                      ret = alphabeta(working_state)

                      # if MAXIMIZER
                      if (root.turn == 2):
                         if (ret > root.algo_value): root.algo_value = ret
                         if (ret > alpha): alpha = ret
                      # if MINIMIZER
                      else:
                         if (ret < root.algo_value): root.algo_value = ret
                         if (ret < beta): beta = ret

                   # if leaf, return value
                   else:
                      if root.turn == 2:
                         if (working_state.value > root.algo_value): root.algo_value = working_state.value
                         if working_state.value > alpha: alpha = working_state.value
                      else:
                         if (working_state.value < root.algo_value): root.algo_value = working_state.value
                         if working_state.value < beta: beta = working_state.value

          if root.turn == 2: return alpha
          else: return beta

【问题讨论】:

  • 您遇到了什么问题?
  • 返回值不正确。它应该根据根节点返回最大值或最小值,但它没有。
  • 当您检查working_state 是否为叶节点时,有时您通过修改root.algo_value“返回”一个值,但稍后您也可以通过alphabeta 来“返回”一个值。这非常很难理解。 (PS:这个函数很大而且缩进很深。这为你的 bug 提供了很大的隐藏空间,并且很难准确地发现缩进结束的位置。考虑把它分解成更容易单独测试的更小的函数。)跨度>
  • 能否包含全局根节点的初始化代码?
  • 已编辑以包含节点(又名 GameState)类

标签: python algorithm artificial-intelligence alpha-beta-pruning


【解决方案1】:

解决了这个问题。在上述算法中,我在循环移动到下一个后继(其默认 algo_values 是各自的最大值和最小值)后检查修剪。

相反,算法应该检查每个后继列表中的第一个节点,更新其 algo_value,然后检查后继列表中其余节点的修剪。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 1970-01-01
    相关资源
    最近更新 更多