极小极大搜索方法、负值最大算法和Alpha-Beta搜索方法
1. 极小极大搜索方法
一般应用在博弈搜索中,比如:围棋,五子棋,象棋等。结果有三种可能:胜利、失败和平局。暴力搜索,如果想通过暴力搜索,把最终的结果得到的话,搜索树的深度太大了,机器不能满足,一般都是规定一个搜索的深度,在这个深度范围内进行深度优先搜索。
假设:A和B对弈,轮到A走棋了,那么我们会遍历A的每一个可能走棋方法,然后对于前面A的每一个走棋方法,遍历B的每一个走棋方法,然后接着遍历A的每一个走棋方法,如此下去,直到得到确定的结果或者达到了搜索深度的限制。当达到了搜索深度限制,此时无法判断结局如何,一般都是根据当前局面的形式,给出一个得分,计算得分的方法被称为评价函数,不同游戏的评价函数差别很大,需要很好的设计。
在搜索树中,表示A走棋的节点即为极大节点,表示B走棋的节点为极小节点。
如下图:A为极大节点,B为极小节点。称A为极大节点,是因为A会选择局面评分最大的一个走棋方法,称B为极小节点,是因为B会选择局面评分最小的一个走棋方法,这里的局面评分都是相对于A来说的。这样做就是假设A和B都会选择在有限的搜索深度内,得到的最好的走棋方法。
图-极大节点(A)与极小节点(B) 图-极大极小搜索
伪代码如下(来自维基百科):
// 如果能得到确定的结果或者深度为零,使用评估函数返回局面得分
if node is a terminal node or depth = 0
return the heuristic value of node
// 如果轮到对手走棋,是极小节点,选择一个得分最小的走法
if the adversary is to play at node
let α := +∞
foreach child of node
α := min(α, minimax(child, depth-1))
// 如果轮到我们走棋,是极大节点,选择一个得分最大的走法
else {we are to play at node}
let α := -∞
foreach child of node
α := max(α, minimax(child, depth-1))
return α;
更加具体一些的算法:
int MinMax(int depth) { // 函数的评估都是以白方的角度来评估的
return Max(depth);
} else { // 黑方是“最小”者
return Min(depth);
}
}
int Max(int depth) {
int best = -INFINITY;
if (depth <= 0) {
return Evaluate();
}
GenerateLegalMoves();
while (MovesLeft()) {
MakeNextMove();
val = Min(depth - 1);
UnmakeMove();
if (val > best) {
best = val;
}
}
return best;
}
int Min(int depth) {
int best = INFINITY; // 注意这里不同于“最大”算法
if (depth <= 0) {
return Evaluate();
}
GenerateLegalMoves();
while (MovesLeft()) {
MakeNextMove();
val = Max(depth - 1);
UnmakeMove();
if (val < best) { // 注意这里不同于“最大”算法
best = val;
}
}
return best;
}
上面这段代码与前面的伪代码的思路都是一样的,只不过把最大算法和最小算法分为了两个函数。
2. 负值最大算法
前面的两段代码都是分别用两部分代码处理了极大节点和极小节点两种情况,其实,可以只用一部分代码,既处理极大节点也处理极小节点。
不同的是,前面的评估函数是针对白方即,指定的一方来给出分数的,这里的评估函数是根据当前搜索节点来给出分数的。每个人都会选取最大的分数,然后,返回到上一层节点时,会给出分数的相反数。
int best = -INFINITY;
if (depth <= 0) {
return Evaluate();
}
GenerateLegalMoves();
while (MovesLeft()) {
MakeNextMove();
val = -NegaMax(depth - 1); // 注意这里有个负号
UnmakeMove();
if (val > best) { // 都是选择最大的分数,因为评估分数的对象变化了
best = val;
}
}
return best;
}
这个负值最大算法,主要是代码量上的减少,时间与空间上的效率没有什么提升。
3. Alpha-Beta搜索方法
举例来说,考虑下面的例子:
图-alpha-beta搜索
极小极大搜索是一个深度搜索,当搜索到第二层的第二个绿色的节点时,已知其第一个子节点返回值为2,因为这是一个极小节点,那么这个节点得到的值肯定是小于2的,而第二层的第一个绿色节点的值为7,因此这个节点后面即使都搜索了,也不会超过2,更不会超过7,因此这个节点后面的节点可以忽略,即图中第三册没有数字的节点。这属于Alpha剪枝,可能是剪掉的节点是极大节点的原因吧。相应的也有Beta剪枝,图中忽略了。
下面的维基百科伪代码,其中两个值,α表示搜索到的最好的值,β表示搜索到的最坏的值。
if depth = 0 or node is a terminal node
return the heuristic value of node
if Player = MaxPlayer // 极大节点
for each child of node // 极小节点
α := max(α, alphabeta(child, depth-1, α, β, not(Player) ))
if β ≤ α // 该极大节点的值>=α>=β,该极大节点后面的搜索到的值肯定会大于β,因此不会被其上层的极小节点所选用了。对于根节点,β为正无穷
return α
else // 极小节点
for each child of node // 极大节点
β := min(β, alphabeta(child, depth-1, α, β, not(Player) )) // 极小节点
break (* Alpha cut-off *)
return β
(* Initial call *)
alphabeta(origin, depth, -infinity, +infinity, MaxPlayer)
4. 参考资料
维基百科-极小化极大算法
最小-最大搜索 http://www.xqbase.com/computer/search_minimax.htm
Alpha-Beta搜索 http://www.xqbase.com/computer/search_alphabeta.htm
极小极大搜索方法、负值最大算法和Alpha-Beta搜索方法相关推荐
- prim算法求最小生成树_最小生成树的两种方法(Kruskal算法和Prim算法)
关于图的几个概念定义: 连通图:在无向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该无向图为连通图. 强连通图:在有向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该有向图为强连 ...
- 最小生成树的两种方法(Kruskal算法和Prim算法)
关于图的几个概念定义: 连通图:在无向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该无向图为连通图. 强连通图:在有向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该有向图为强连 ...
- E-R 图的不同表示方法(Chen 方法和 Crow‘s foot 方法)
E-R图,中文名称叫实体-关系图,是数据库设计所使用的重要模型. E-R图最早由Peter Chen提出,他现在是路易斯安那州立大学的教授,中文名叫陈品山,是出生于台湾的美国计算机科学家.这是他的照片 ...
- 线性判别函数(Python实现批感知器算法、Ho Kashyap算法和MSE多类扩展方法)——模式识别编程作业
文章目录 写在前面 批感知器算法 Ho Kashyap算法 MSE多类扩展方法 Ref. 写在前面 本博客为模式识别作业的记录,实现批感知器算法.Ho Kashyap算法和MSE多类扩展方法,可参考教 ...
- smoteenn算法_基于EasyEnsemble算法和SMOTE算法的不均衡数据分类方法与流程
本发明涉及不均衡数据二分类技术领域,尤其涉及一种基于EasyEnsemble算法和SMOTE算法的不均衡数据二分类方法. 背景技术: 数据不均衡指的是在一个样本数据集中,某一类的样本数远少于其他类的样 ...
- 最清晰易懂的MinMax算法和Alpha-Beta剪枝详解
最清晰易懂的MinMax算法和Alpha-Beta剪枝详解 参考文章 http://web.cs.ucla.edu/~rosen/161/notes/alphabeta.html https://ww ...
- Widar2.0:SAGE算法和SAGE算法在在无线信道参数估计中的应用
Widar2.0:SAGE算法和SAGE算法在在无线信道参数估计中的应用 C1 本文背景 C2 SAGE算法 C2.1 EM算法 C2.2 SAGE算法 C2.3 SAGE算法和SAGE算法在在无线信 ...
- pca算法python_PCA算法和python实现
第十三章 利用PCA来简化数据 一.降维技术 当数据的特征很多的时候,我们把一个特征看做是一维的话,我们数据就有很高的维度.高维数据会带来计算困难等一系列的问题,因此我们需要进行降维.降维的好处有很多 ...
- 游戏中DDA算法和Bresenham算法的应用
在角色扮演或即时战略游戏中,经常会将角色以最佳的方式走到指定地点.游戏场景的地面情况复杂,而且场面大,若采用盲目式搜索,例如盲目穷举法,则几乎要遍历整个场景,效率非常低,造成角色反应速度过慢,实践证明 ...
- 使用Apriori算法和FP-growth算法进行关联分析
目录 1. 关联分析 2. Apriori原理 3. 使用Apriori算法来发现频繁集 4. 使用FP-growth算法来高效发现频繁项集 5. 示例:从新闻网站点击流中挖掘新闻报道 扩展阅读 系列 ...
最新文章
- PHP函数stream_context_create()模拟POST/GET
- 跟着 Alex 学python 1.安装
- 把二元查找树转变成排序的双向链表(树)
- java单例注册表_Spring对单例的底层实现,单例注册表
- C++运行库 Neptune C++ Runtime Library(xbmc)
- 英语写作学习笔录 task1 conclusion
- TypeScript 里的 module 解析过程 - Module Resolution
- Synchronized 的 8 种使用场景!
- c语言作业模拟虚拟内存,如何用c语言实现虚拟内存
- [Java] 1001. 害死人不偿命的(3n+1)猜想 (15)-PAT乙级
- Eclipse插件开发之拖拽功能
- 打印机显示服务器脱机是什么原因,打印机显示“脱机”的原因和解决办法
- 华硕路由器流量管理QoS设置
- html js 在文本框选择自动计算乘,怎么让JS实现在文本框中输入数字时,同时输出这个数字,并再输出一个乘以0.39的值?...
- FlyThings OS:基于Linux实现现代化人机交互体验的新嵌入式操作系统
- LaTex使用技巧10:公式中的各种英文字体
- python求不规则图形面积_Python求阴影部分面积
- android获取来电号码,Android获取来电号码代码详解
- android 查看系统允许内存,查看Android系统内存使用的方法
- 基本排序算法01----选择排序(selection sort)
热门文章
- Win 10 深度隐藏文件夹命令
- movs 数据传送指令_数据传送汇编指令
- movs 数据传送指令_Introduction to CSAPP(十二):数据传送指令与 C 语言赋值
- FatFs 之三 FAT文件系统基础、FAT 数据格式、引导、编码
- C/C++KTV点歌系统
- 奇迹之剑萌新晋升大神辅助攻略 奇迹之剑游戏脚本挂机工具介绍
- 怎样修改一篇简历 简历怎么写
- MySQL曹操外卖项目--数据库设计
- 什么是网络流量劫持?
- Interactive Sketch-Based Normal Map Generation with Deep Neural Networks