本文代码:github.com/ParadeTo/ch…node
Demo地址:www.paradeto.com/chinese-che…python
在上一篇文章结尾提到了最大最小值算法有进一步优化的空间,接下来继续。git
上篇文章结尾提到了当最大最小值算法的搜索深度增大时,其计算复杂度会急剧上升。若是有办法能够去掉一些分支的话,算法的效率就会高一些了,这就轮到 alpha-beta 剪枝出场了。不过咱们先不讨论该算法,咱们先玩一下上一篇的那个游戏。github
上篇文章只是大概说了一下游戏的玩法,这里咱们一步一步来认真玩一下。算法
有两个袋子,袋子一中有一台小米9和一台华为p30,袋子二中有一颗螺丝,一粒芝麻,一台 Mac Pro,可是你和你朋友都不知道袋子里的是什么,游戏规则是你选择一个袋子,你朋友从中选择一个物品给你,你想要获得价值最大的物品,而你朋友则想方设法地要阻扰你(这样的朋友仍是早点弃了的好)。两我的都盲选的话就没意思了,因此你和你朋友商量了一下,每一个人均可以尽量的尝试屡次之后再作出最终的选择。游戏开始:多线程
你:选择袋子一。post
你朋友:从袋子里面拿出第一个物品,发现是华为p30。暂时决定:若是你选择袋子一,就给你华为p30。放回。优化
你朋友:从袋子里面拿出第二个物品,发现是小米9。跟华为p30比较后暂时决定:若是你选择袋子一,就给你小米9。放回。spa
你朋友:发现袋子中没有其余物品。作出最后决定:若是你选择袋子一,就给你小米9。线程
你:记录下能获得的物品暂时为小米9。
你:选择袋子二。
你朋友:从袋子里面拿出第一个物品,发现是一颗螺丝。跟你暂时能获得的物品小米9比较后,你朋友决定直接告诉你:若是你选择袋子二,就给你一颗螺丝。为何这里能够省去比较袋子二中的其余物品呢,明明一粒芝麻的价值更小啊?由于袋子二中的第一个物品的价值就已经小于你暂时能够获得的物品的价值了,这个信息已经足够让你放弃选择袋子二了。
通过这些尝试之后,最后你选择了袋子一,而后你朋友把小米9给了你。
上面这个过程其实就是最大最小值算法加 alpha-beta 剪枝。其中选择第二个袋子时你朋友决定放弃袋子中其余物品的尝试就体现了 alpha-beta 剪枝的思想。下面咱们来讲说 alpha-beta 剪枝。
alpha-beta 剪枝算法中咱们定义:
当最小值层的某个节点的 beta 小于 alpha 时,能够中止该节点其他子节点的搜索。当最大值层的某个节点的 alpha 大于 beta 时,能够中止该节点其他子节点的搜索。
这么说确定听不懂,下面就用下图例子来实战一下。
接下来就不一一赘述了,读者能够本身试试把剩下的完成,最后的结果是这样的:
结合代码看能够更好的理解:
function alphabeta(node, depth, α, β, maximizingPlayer) is
if depth = 0 or node is a terminal node then
return the heuristic value of node
if maximizingPlayer then
value := −∞
for each child of node do
value := max(value, alphabeta(child, depth − 1, α, β, FALSE))
α := max(α, value)
if α ≥ β then
break (* β cut-off *)
return value
else
value := +∞
for each child of node do
value := min(value, alphabeta(child, depth − 1, α, β, TRUE))
β := min(β, value)
if α ≥ β then
break (* α cut-off *)
return value
复制代码
这就是 alpha-beta 剪枝的规则,别看只是减去了几个分支不计算而已,若是每层每一个节点均可以排除掉几个分支的话,对速度的优化仍是很是明显的。
另一个优化的思路是并行计算,把每次产生的走法平均分红多个任务并行处理,每一个并行的任务分别产生局部的最优解,最后汇总获得全局的最优解便可。每个走法对应一个子任务是最快的,不过若是每一层都这样的话,最后的子任务数量也会很是巨大,不论是多进程仍是多线程实现都是很不现实的,因此须要限制并行处理的深度。即使仅在第一层开启并行计算,理论上也可使得计算速度快 30 倍(假设每一层平均产生 30 种走法)。
利用最大最小值和 alpha-beta 算法就能够实现简单的象棋 AI 程序,不过该 AI 的棋力仅够应付入门级的玩家。一个缘由是尽管采起了前面所说的优化方法后,实践发现当搜索深度达到 5 之后,算法的计算时间就慢得不能接受了,没法继续提升搜索的深度;另一个缘由是局势判断的方法略显简单,能够考虑加入一些象棋特有的“套路”来提升局势判断的准确性。后面针对这些问题再优化一下。