极小化极大算法与负极大值算法

来源:互联网 发布:君知其难也的其意思 编辑:程序博客网 时间:2024/06/04 23:52

1.极小化极大算法(Minimax)

     Minimax算法又名极小化极大算法,是一种找出失败的最大可能性中的最小值的算法。Minimax算法常用于棋类等由两方较量的游戏和程序,这类程序由两个游戏者轮流,每次执行一个步骤。我们众所周知的五子棋、象棋等都属于这类程序,所以说Minimax算法是基于搜索的博弈算法的基础。该算法是一种零总和算法,即一方要在可选的选项中选择将其优势最大化的选择,而另一方则选择令对手优势最小化的方法。

 

     我们知道,常用的博弈算法都是基于搜索的博弈算法,所有可能的下棋步骤构成一个树的结构,以Tic-tac-toe(中文称为井字棋,即两人轮流在井字棋盘的方格内划×或〇,谁先将划过的三个方格成一直线或对角线为胜)游戏为例,下面一幅图表示了Tic-tac-toe游戏的前两步所有可能的步骤.

     上图中第0层为空棋盘,第1层是×方所有可能的步骤,第2层是〇方所有可能的步骤。在第1层,×方需要选择使其优势最大的选择,而在第2层,〇方则需要选择使×方优势最小即己方优势最大的选择。

 

     Minimax的含义就是极小化对手的最大利益,在上图中,在第2层〇方一定会选择使自己优势最大的选择,而对于×方需要做的就是选择〇方最大选择中的极小值。

 

Minimax是一种深度优先搜索,其用伪代码表示如下:

[cpp] view plain copy
  1. function minimax(node, depth)  
  2. if node is a terminal node or depth = 0  
  3.     return the heuristic value of node  
  4. if the adversary is to play at node  
  5.     let α := +∞  
  6.     foreach child of node  
  7.         α := min(α, minimax(child, depth-1))  
  8. else {we are to play at node}  
  9.     let α := -∞  
  10.     foreach child of node  
  11.         α := max(α, minimax(child, depth-1))  
  12. return α。  

 

2.负极大值算法(Negamax)

负极大值算法是极小化极大算法的一个变体,其基本原理是基于下面的公式:

                                  max (a,b) = - min ( - a, - b)

    即在几个节点中选择得分最小的节点相当于将这些节点的得分乘以-1然后取得分最大的节点。这样Negamax算法就将每一步递归过程都统一了起来,每一次递归都选取最大值。

下面是Negamax算法的伪代码:

[cpp] view plain copy
  1. function negamax(node, depth)  
  2. if node is a terminal node or depth = 0  
  3.     return the heuristic value of node  
  4.  let best := -∞  
  5.  foreach child of node  
  6.      best := max(α, -negamax(child, depth-1))  
  7. return best  

 

3.两种的区别

     我们把电脑方的价值总和叫做CpValue,对手方价值总和叫做OpValue,那么一个局面的估值Value就是电脑方和对手方的价值差。表达如下式:Value=CpValue - OpValue。这个Value也就是最终返回给搜索引擎的估值。在基本的极小极大搜索的过程里估值的取得是和上式完全契合的,即无论任何时候取估值均由固定一方的值减去另一方的值。

 

而在负极大值形式的搜索中,
1.对于电脑方走棋所形成的局面,如果该节点是叶节点,则估值是CpValue - OpValue;如果该节点有父节点,则父节点必然是对手方走棋的局面,它是取极大值极点,我们希望取OpValue - CpValue中的最大的子节点。
2.对于对手方走棋所形成的局面,如果该节点是叶节点,则估值是OpValue - CpValue;如果该节点有父节点,则必然是电脑方走棋的局面,它是取极小值节点,我们希望取CpValue - OpValue中最大的子节点。
这样我们就理解了在负极大值算法中的那个负号啦。


负极大值算法:一个局面对红方的优势为X,那么对于黑方的优势就是-X;一个局面对红方的优势为-X,对黑方的优势就是X。在负极大值搜索算法中,没有了极小点,只有极大点。需要注意的是,局面对一方的优势转化为另一方的优势时需要加负号。局面估计区间是一个关于0点对称的区间:

[-MaxValue,MaxValue].需要注意的是,为了能使负极大值搜索算法得到正确的评价,必须修改局面评估函数的返回值,原来在极大极小搜索算法中始终返回的是红方的优势,现在要改为当前走棋方的优势。

负极大值搜索算法: 

输入:搜索深度

输出:节点的最佳走法,及对应的最佳估值

函数形式:int negaMaxSearch(int depth)

 

初始化最优值best=负无穷大                //都是极大点

如果depth小于等于0

       调用评估函数,并将结果赋给value

       返回value值

 

否则

      生成当前所有合法的走法

      对于每一步走法

            执行走法

            value= -negaMaxSearch(depth-1)             //注意函数之前有负号

            撤销走法

            如果 value> best

                    best=value

                    如果  depth == Max_Depth

                            bestMove=mv

返回best                                                                 //返回某个搜索分支的最优评估值

 

 

评估函数的算法:

 

输入:棋局

输出:局面对当前走方的优势

 rValue:红方的优势总和

bValue:黑方的优势总和

分别进行评估,具体问题具体设计,获得rValue和bValue的值

 

如果当前局面是红方走棋

     return rValue-bValue;

否则

     return bValue-rValue;



两种算法估值函数的实现方法:

    如果我们把红方的价值总和叫做RedValue,黑方价值总和叫做BlackValue,那么一个局面的估值Value就是红方和黑方的价值差。表达式如下式:

               Value = RedValue-BlackValue

    这个Value也就是最终返回给搜索引擎的估值。在基本的极大极小搜索的过程里估值的取得是和上式完全契合的,即无论任何时候取估值均由固定的一方减去另一方的值。而在负极大极小值搜素中,如果被估值节点是取极小值点时取的估值RedValue-BlackValue,则被估值节点取极大值节点时取得估值应是BlcakValue-RedValue.



0 0