期望窗口

期望窗口


  期望窗口是对迭代加深的改进。迭代加深的最简单的实现方法是这样的:

    for (depth = 1; ; depth ++) {
     val = AlphaBeta(depth, -INFINITY, INFINITY);
     if (TimedOut()) {
      break;
     }
    }
  这里调用了一个“窗口”为正负无穷大的Alpha-Beta搜索,以假定返回值可能是很大的正数或负数。
  假设下一次迭代时,搜索的值不会比上一次有太多的变动,那么就可以对以上的程序作改进,代码如下:
    #define valWINDOW 50 // 【译注:valWINDOW是窗口的半宽,在国际象棋中通常是半个兵的价值。】
    alpha = -INFINITY;
    beta = INFINITY;
    for (depth = 1; ; ) {
     val = AlphaBeta(depth, alpha, beta);
     if (TimedOut()) {
      break;
     }
     if ((val <= alpha) || (val >= beta)) {
      alpha = -INFINITY;
      beta = INFINITY;
      continue;
     }
     alpha = val - valWINDOW;
     beta = val + valWINDOW;
     depth ++;
    }
    这个代码有点烂,如果可能的话你可以把“continue”前面的部分改一下试试。这个思想是用前一次Alpha-Beta迭代的值来作用到这次的迭代中。大多数情况下你得到的返回值会在Alpha和Beta之间。如果没有,那么你可以尝试一个宽一些的窗口。
  我的重新搜索并不那么有效,但是我相信你可以做得更好。一个很明显的思想是,如果返回值大于或等于Beta,你就扩展Beta,如果返回值小于等于Alpha,你就扩展Alpha,而不是我所做的Alpha和Beta都扩展。
 
搜索不稳定性的问题
 
   这是你要小心搜索不稳定性的另一个地方。当我首次在我的国际象棋程序中加入期望窗口时,我设想如果返回值大于或等于Beta,那么重新搜索的结果就应该得到更大的值。完全错了,我的程序陷入了非常严重的故障!下面是它的代码:
    alpha = -INFINITY;
    beta = INFINITY;
    for (depth = 1; ; ) {
     val = AlphaBeta(depth, alpha, beta);
     if (TimedOut()) {
      break;
     }
     if (val <= alpha) { // 错!
      alpha = -INFINITY;
      beta = val + 1;  // 【这行没有就对了,但效率会低很多。】
      continue;
     }
     if (val >= beta) { // 错!
      beta = INFINITY;
      alpha = val - 1;
      continue;
     }
     alpha = val - valWINDOW;
     beta = val + valWINDOW;
     depth++;
    }
 
  如果你能确认重新搜索会有结果,那么上面的代码会非常有效的。但是在我这里情况却是:
  1. 搜索(Alpha, Beta)时高出边界;
  2. 重新搜索(Beta - 1, INFINITY)时低出边界;
  3. 重新搜索(-INFINITY, Alpha + 1)时高出边界;
  4. 等等,等等……
  无论如何你必须避免发生这种情况。

你可能感兴趣的:(期望窗口)