zoukankan
html css js c++ java
AlphaBeta搜索
《对弈程序基本技术》专题
Alpha-Beta
搜索
Bruce Moreland /
文
最小
-
最大的问题
Alpha-Beta
同“
最小
-
最大
”非常相似,事实上只多了一条额外的语句。最小最大运行时要检查整个博弈树,然后尽可能选择最好的线路。这是非常好理解的,但效率非常低。每次搜索更深一层时,树的大小就呈指数式增长。
通常一个国际象棋局面都有
35
个左右的合理着法,所以用最小
-
最大搜索来搜索一层深度,就有
35
个局面要检查,如果用这个函数来搜索两层,就有
35
2
个局面要搜索。这就已经上千了,看上去还不怎样,但是数字增长得非常迅速,例如六层的搜索就接近是二十亿,而十层的搜索就超过两千万亿了。
要想通过检查搜索树的前面几层,并且在叶子结点上用启发式的评价,那么做尽可能深的搜索是很重要的。最小
-
最大搜索无法做到很深的搜索,因为有效的分枝因子实在太大了。
口袋的例子
幸运的是我们有办法来减小分枝因子,这个办法非常可靠,实际上这样做绝对没有坏处,纯粹是个有益的办法。这个方法是建立在一个思想上的,如果你已经有一个不太坏的选择了,那么当你要作别的选择并知道它不会更好时,你没有必要确切地知道它有多坏。有了最好的选择,任何不比它更好的选择就是足够坏的,因此你可以撇开它而不需要完全了解它。只要你能证明它不比最好的选择更好,你就可以完全抛弃它。
你可能仍旧不明白,那么我就举个例子。比如你的死敌面前有很多口袋,他和你打赌赌输了,因此他必须从中给你一样东西,而挑选规则却非常奇怪:
每个口袋里有几件物品,你能取其中的一件,你来挑这件物品所在的口袋,而他来挑这个口袋里的物品。你要赶紧挑出口袋并离开,因为你不愿意一直做在那里翻口袋而让你的死敌盯着你。
假设你一次只能找一只口袋,在找口袋时一次只能从里面摸出一样东西。
很显然,当你挑出口袋时,你的死敌会把口袋里最糟糕的物品给你,因此你的目标是挑出“诸多最糟的物品当中是最好的”那个口袋。
你很容易把最小
-
最大原理运用到这个问题上。你是最大一方棋手,你将挑出最好的口袋。而你的死敌是最小一方棋手,他将挑出最好的口袋里尽可能差的物品。运用最小
-
最大原理,你需要做的就是挑一个有“最好的最差的”物品的口袋。
假设你可以估计口袋里每个物品的准确价值的话,最小
-
最大原理可以让你作出正确的选择。我们讨论的话题中,准确评价并不重要,因为它同最小
-
最大或
Alpha-Beta
的工作原理没有关系。现在我们假设你可以正确地评价物品。
最小
-
最大原理刚才讨论过,它的问题是效率太低。你必须看每个口袋里的每件物品,这就需要花很多时间。
那么怎样才能做得比最小
-
最大更高效呢?
我们从第一个口袋开始,看每一件物品,并对口袋作出评价。比方说口袋里有一只花生黄油三明治和一辆新汽车的钥匙。你知道三明治更糟,因此如果你挑了这只口袋就会得到三明治。事实上只要我们假设对手也会跟我们一样正确评价物品,那么口袋里的汽车钥匙就是无关紧要的了。
现在你开始翻第二个口袋,这次你采取的方案就和最小
-
最大方案不同了。你每次看一件物品,并跟你能得到的最好的那件物品
(
三明治
)
去比较。只要物品比三明治更好,那么你就按照最小
-
最大方案来办——去找最糟的,或许最糟的要比三明治更好,那么你就可以挑这个口袋,它比装有三明治的那个口袋好。
比方这个口袋里的第一件物品是一张
20
美元的钞票,它比三明治好。如果包里其他东西都没比这个更糟了,那么如果你选了这个口袋,它就是对手必须给你的物品,这个口袋就成了你的选择。
这个口袋里的下一件物品是六合装的流行唱片。你认为它比三明治好,但比
20
美元差,那么这个口袋仍旧可以选择。再下一件物品是一条烂鱼,这回比三明治差了。于是你就说“不谢了”,把口袋放回去,不再考虑它了。
无论口袋里还有什么东西,或许还有另一辆汽车的钥匙,也没有用了,因为你会得到那条烂鱼。或许还有比烂鱼更糟的东西
(
那么你看着办吧
)
。无论如何烂鱼已经够糟的了,而你知道挑那个有三明治的口袋肯定会更好。
算法
Alpha-Beta
就是这么工作的,并且只能用递归来实现。稍后我们再来谈最小一方的策略,我希望这样可以更明白些。
这个思想是在搜索中传递两个值,第一个值是
Alpha
,即搜索到的最好值,任何比它更小的值就没用了,因为策略就是知道
Alpha
的值,任何小于或等于
Alpha
的值都不会有所提高。
第二个值是
Beta
,即对于对手来说最坏的值。这是对手所能承受的最坏的结果,因为我们知道在对手看来,他总是会找到一个对策不比
Beta
更坏的。如果搜索过程中返回
Beta
或比
Beta
更好的值,那就够好的了,走棋的一方就没有机会使用这种策略了。
在搜索着法时,每个搜索过的着法都返回跟
Alpha
和
Beta
有关的值,它们之间的关系非常重要,或许意味着搜索可以停止并返回。
如果某个着法的结果小于或等于
Alpha
,那么它就是很差的着法,因此可以抛弃。因为我前面说过,在这个策略中,局面对走棋的一方来说是以
Alpha
为评价的。
如果某个着法的结果大于或等于
Beta
,那么整个结点就作废了,因为对手不希望走到这个局面,而它有别的着法可以避免到达这个局面。因此如果我们找到的评价大于或等于
Beta
,就证明了这个结点是不会发生的,因此剩下的合理着法没有必要再搜索。
如果某个着法的结果大于
Alpha
但小于
Beta
,那么这个着法就是走棋一方可以考虑走的,除非以后有所变化。因此
Alpha
会不断增加以反映新的情况。有时候可能一个合理着法也不超过
Alpha
,这在实战中是经常发生的,此时这种局面是不予考虑的,因此为了避免这样的局面,我们必须在博弈树的上一个层局面选择另外一个着法。
在第二个口袋里找到烂鱼就相当于超过了
Beta
,如果口袋里没有烂鱼,那么考虑六盒装流行唱片的口袋会比三明治的口袋好,这就相当于超过了
Alpha(
在上一层
)
。算法如下,醒目的部分是在最小
-
最大算法上改过的:
int
AlphaBeta
(int depth
, int alpha, int beta
) {
if (depth == 0) {
return Evaluate();
}
GenerateLegalMoves();
while (MovesLeft()) {
MakeNextMove();
val = -
AlphaBeta
(depth - 1
, -beta, -alpha
);
UnmakeMove();
if (val >= beta) {
return beta;
}
if (val > alpha) {
alpha = val;
}
}
return alpha;
}
把醒目的部分去掉,剩下的就是最小-最大函数。可以看出现在的算法没有太多的改变。
这个函数需要传递的参数有:需要搜索的深度,负无穷大即
Alpha
,以及正无穷大即
Beta
:
val = AlphaBeta(5, -INFINITY, INFINITY);
这样就完成了
5
层的搜索。我在写最小
-
最大函数时,用了一个诀窍来避免用了“
Min
”还用“
Max
”函数。在那个算法中,我从递归中返回时简单地对返回值取了负数。这样就使函数值在每一次递归中改变评价的角度,以反映双方棋手的交替着子,并且它们的目标是对立的。
在
Alpha-Beta
函数中我们做了同样的处理。唯一使算法感到复杂的是,
Alpha
和
Beta
是不断互换的。当函数递归时,
Alpha
和
Beta
不但取负数而且位置交换了,这就使得情况比口袋的例子复杂,但是可以证明它只是比最小
-
最大算法更好而已。
最终出现的情况是,在搜索树的很多地方,
Beta
是很容易超过的,因此很多工作都免去了。
可能的弱点
这个算法严重依赖于着法的寻找顺序。如果你总是先去搜索最坏的着法,那么
Beta
截断就不会发生,因此该算法就如同最小
-
最大一样,效率非常低。该算法最终会找遍整个博弈树,就像最小
-
最大算法一样。
如果程序总是能挑最好的着法来首先搜索,那么数学上有效分枝因子就接近于实际分枝因子的平方根。这是
Alpha-Beta
算法可能达到的最好的情况。
由于国际象棋的分枝因子在
35
左右,这就意味着
Alpha-Beta
算法能使国际象棋搜索树的分枝因子变成
6
。
这是很大的改进,在搜索结点数一样的情况下,可以使你的搜索深度达到原来的两倍。这就是为什么使用
Alpha-Beta
搜索时,着法顺序至关重要的原因。
查看全文
相关阅读:
阅读
做人做事、原则
20150913HTML5心得
动画-七夕言情
20150818 句子
网站链接备份
javascript设计模式2
javascript设计模式1
sunlime操作
node系列4
原文地址:https://www.cnblogs.com/lanzhi/p/6470253.html
最新文章
Doxygen中文使用
在VS2010中建立Qt应用程序并打开控制台窗口
3Gear System
QTime使用中遇到的”not enough actual parameters for macro 'min'“问题
Capri 3D传感器
Qt界面美化
MATLAB抠图
关于感兴趣区域提取
6月25日下午小结
6月24日
热门文章
LBP学习之初步阶段
网站一大串
英文学习
office2013安装包
python学习小记0
学习小记
call, apply, bind解析
大厂燕郊香河房子
移动端页面调试
读书笔记
Copyright © 2011-2022 走看看