AlphaBeta剪枝算法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

AlphaBeta剪枝算法

关于AlphaBeta剪枝的文章太多,这个方法是所有其它搜索方法的基础,得多花些时间认真地理解。

先把基本概念再回顾一遍:

节点:在中国象棋中就是一个棋盘的当前局面Board,当然该轮到谁走棋也是确定的。这里的圆形节点表示终止节点,在中国象棋里就是一方被将死的情况(或者到达了搜索的最大深度),后续不会再有着法产生,游戏如果走到这里就会结束。在引擎里通常给红方一个很大的评估值,如+30000,给黑方一个很小的评估值,如-30000,来方便地判断这种结束局面。(胜利局面有稍微不同的表示法,用-30000+层数ply来表示)

连线:表示一步着法Move,通过这步着法后,局面发生变化,先后手也要交换。

层:通常的术语是ply,复数形式是plies,也有称为levels,当然与depth也是对应的。这个术语是为了与比赛里常说的回合相区分,一个回合通常包含2步,这个ply就表示某一方走了一步。根节点记为0层,以下的层数递增。

深度depth:要注意是从下到上的,还是从上到下的。(1)通常的算法书中都是从下到上递增的,即根节点为最大搜索深度,走到最底部的叶子结点为0,这种算法只要记住一个depth 值就可以了。(2)而另一种记法是根部结点为0,越向下depth增加,这时在搜索时就要传递2个参数值,depth和maxDepth,稍微有点啰嗦,应该也会影响一点效率。另外在探查置换表中的结点时,用第(1)种记法也方便一些,因为要知道从当前节点迭代的深度值,否则还要在置换表中保存depth和maxDepth两个值。

AlphaBeta剪枝方法是对Minimax方法的优化,它们产生的结果是完全相同的,只不过运行效率不一样。

这种方法的前提假设与Minimax也是一样的:

1)双方都按自己认为的最佳着法行棋。

2)对给定的盘面用一个分值来评估,这个评估值永远是从一方(搜索程序)来评价的,红方有利时给一个正数,黑方有利时给一个负数。(如果红方有利时返回正数,当轮到黑方走棋时,评估值又转换到黑方的观点,如果认为黑方有利,也返回正数,这种评估方法都不适合于常规的算法描述)

3)从我们的搜索程序(通常把它称为Max)看来,分值大的数表示对己方有利,而对于对方Min来说,它会选择分值小的着法。

但要注意:用Negamax风格来描述的AlphaBeta中的评估函数,对轮到谁走棋是敏感的。

也就是说:

在Minimax风格的AlphaBeta算法中,轮红方走棋时,评估值为100,轮黑方走棋评估值仍是100。

但在Negamax风格的AlphaBeta算法中,轮红方走棋时,评估值为100,轮黑方走棋时评估值要为-100。

贴一段伪代码:

def ABNegaMax (board, depth, maxDepth, alpha, beta)

if ( board.isGameOver() or depth == maxDepth )

return board.evaluate(), null

bestMove = null

bestScore = -INFINITY

for move in board.getMoves()

newBoard = board.makeMove(move)

score = ABNegaMax(newBoard, maxDepth, depth+1, -beta, -max(alpha, bestScore))

score = -score

if ( score > bestScore )

bestScore = score

bestMove = move

# early loop exit (pruning)

if ( bestScore >= beta ) return bestScore, bestMove

return bestScore, bestMove

用下列语句开始调用:

ABNegaMax(board, player, maxDepth, 0, -INFINITY, INFINITY)

// method call with depth 5 and minimum and maximum boundaries

// minimaxValue = alphaBeta(board, 5, -MATE, +MATE)

int alphaBeta(ChessBoard board, int depth, int alpha, int beta)

{

int value;

if( depth == 0 || board.isEnded())

{

value = evaluate(board);

return value;

}

board.getOrderedMoves();

int best = -MATE-1;

int move;

ChessBoard nextBoard;

while (board.hasMoreMoves())

{

move = board.getNextMove();

nextBoard = board.makeMove(move);

value = -alphaBeta(nextBoard, depth-1,-beta,-alpha);

if(value > best)

best = value;

if(best > alpha)

alpha = best;

if(best >= beta)

break;

}

return best;

}

下面这个PDF更清楚地说明了Negamax风格的alphabeta算法的过程:

/~anderson/cs440/index.html/lib/exe/fetch.php? media=notes:negamax2.pdf

为了更准确地理解minmax和negamax两种不同风格的搜索执行过程,画出了详细的图解,发现negamax更容易理解了,代码也确实精练了不少。

当采用了置换表算法后,还需要对PV-Nodes, Cut-Nodes和All-Nodes三种类型结点的含义以及如何变化有更准确地了解。

相关文档
最新文档