Alpha-Beta剪枝的原理的深入理解(无图预警)
转载请注明 原文链接 :https://www.cnblogs.com/Multya/p/17929261.html
考虑一个树:
一棵树上只有叶子节点有值,有确定的根节点的位置
根据层数来划分叶子节点和根节点之间的链接节点
偶数层上的值取子节点的最大值,奇数取最小
因为叶子节点上的值确定,在有这么个规则之后整棵树上所有节点就定下来了吧
现在我遮住全部叶子节点,让你通过打开尽量少次数叶子节点,确定根节点的值
我们通过alpha-beta 剪枝来实现
确定的事情:
- 一个节点上的值必定是长在它身上的所有叶子的值中的一个
- max{ a, min{b,x} } 如果b比a小,无论x取什么,结果都是a
- min{ a, max{b,x} } 如果b比a大,无论x取什么,结果都是a
为什么? 我们放慢这个思考过程看看背后的逻辑
我们用一个区间来表示这个算式最后的结果的范围,下界是a,上界是b
我们知道计算最大最小的过程,其实就是一个单边的区间不断根据新的值刷新的过程:
假设计算max{4,5,1}
第一个数是4暂定是表达式的值
然后4确定下界是4的区间,这个区间希望得到一个在这个区间内的数刷新区间下界和更新表达式的值。5在这个区间内,所以它能刷新表达式和更新区间下界
1不在这个区间内,所以它不能更新表达式和区间。所以表达式是最后更新状态下的5,计算正确
刷新区间的操作也可以用求交集来实现,这样的话就省了判断的那一步,然后结果也可以用最后的下界来确定
所以可以变成这样:
求区间(4,+∞)∩(5,+∞)∩(1,+∞)的下界
这样我们就实现了用区间来求最大(最小)的功能
再看max{ 4, min{3,1} }
第一个数是4暂定是表达式的值
然后4确定下界是4的区间,这个区间希望得到一个在这个区间内的数刷新区间下界和更新表达式的值。
这个区间希望表达式min{3,1}得到一个大于4的数刷新区间下界和更新表达式的值(这个过程区间原封不动传递下去)
先计算表达式min{3,1} 第一个数是3,然后5确定表达式在小于3的区间内,希望得到一个小于5的值刷新表达式
但是这个区间内所有的数都不在上个表达式期望的大于4的数区间内(区间不重合),也就是这个表达式所有可能的值都不能刷新上个表达式的值,所以跳过计算这个子表达式
由于上个表达式所有数遍历完了,最后更新的数是4,所以表达式值为4
我们再来看完全用区间来实现的方法:(【】内计算得到一个数)所有都是闭区间哈,意会就行
求(4,+∞)∩ ( min{3,1} ,+∞)的下界
即求(4,+∞)∩ (【(-∞,3)∩ (-∞,1)的上界】,+∞)的下界
我们定义空区间的上界是正无穷,下界是负无穷,这样做的理由是使空区间对结果不产生任何贡献(因为都是取交集)
然后是关键的一步:根据上面的启发,我们把前面得到的区间套一层壳,也就是:
等价为求(4,+∞)∩ (【(4,+∞)∩【(-∞,3)∩ (-∞,1)的上界】的上界】,+∞)的下界
这个结果不变。因为【(4,+∞)∩【(-∞,3)∩ (-∞,1)的上界】的上界】的结果不是空集的话对上界没有影响,是空集的话没有贡献。
可以等价为(4,+∞)∩ (【(4,+∞)∩(-∞,3)∩ (-∞,1)的上界】,+∞)的下界,因为取交集,先后没有影响。
此时可以先通过判断(4,+∞)∩(-∞,3)是空集来提前结束求值,得到最后区间(4,+∞)
像上面这样,如果把传递给子表达式期望的区间和子表达式结果的区间看成一回事的话,那就是alpha-beta剪枝的逻辑。回到最开始的那个树。这个区间能被固定在每一个节点身上,表示这个节点的状态:如果要刷新这个节点的值,要求新输入的值的区间范围。如果这个节点从未被刷新,那么这个节点的值就不会产生任何贡献来刷新上一个表达式的值。如果这个区间是一个空区间,那么所有的值都不能刷新这个节点的值,那么就没有必要继续给这个节点输入值了。
观察区间动向的话会发现有关区间的操作有以下几种:
- 把值改写为区间
- 区间取交集
- 取区间一端的数传递回去
- 把一个区间传递给子表达式内提前取交集
再看max{ 4, min{3,1} },这次我们加上树的形状和叶子节点遮挡的特性
自行画图:有4 3 1三个节点,一个根节点,两个链接节点,三个叶子节点
开始。打开叶子4,更新所连接的父节点
这里将每个节点区间初始化为全体实数,因为是MAX层,刷新这个节点的区间为(4,+∞)
传递(4,+∞)给链接3和1的链接节点(此时我们还不知道3和1)
链接节点打开叶子3,因为是MAX层,产生区间(-∞,3)
原来已经有集合了,取交集为空集,提前结束运算,不做任何贡献,不传递值回去
这样就完成了任务,只打开了4和3就知道了根节点的值是4
如果把前面的值用负号在min层取反,那么所有的层的操作逻辑都变成一样的了
alpha-beta剪枝的算法的代码:
//意义:目前棋盘的最值评分 分数的正负取决于一开始的isBlackNow
int abSearch(int floor, int alpha, int beta, bool isBlackNow, Coord &searchResult) {
int tmpScore, moveCount = 0;
Coord tempSearchResult{};
//优化1
std::vector<ScoreCoord> possibleMove = generatePossibleMove(isBlackNow);
for (auto &now: possibleMove) {
//优化2
moveCount++;
if (moveCount > 8) break; //只搜索前8个可能的落子点
int x = now.coord.x, y = now.coord.y;
m_map[x][y] = isBlackNow ? BLACK_CHESS : WHITE_CHESS;
//优化3
if (someoneWin({x, y})) {//如果有人赢了 必定是下这个子的人赢了
searchResult = {x, y};
tmpScore = evaluateAll(isBlackNow);//返回这个局面最高的得分,也就是赢局的分数
m_map[x][y] = NO_CHESS;
return tmpScore;
}
//单层搜索
if (floor == 1) {//如果只看这一步子 那就是这一步子所有可能的得分中的最大值
tmpScore = evaluateAll(isBlackNow);
m_map[x][y] = NO_CHESS;
if (tmpScore > alpha) {
alpha = tmpScore;
searchResult = {x, y};
}
continue;
}
tmpScore = -abSearch(floor - 1, -beta, -alpha, !isBlackNow, tempSearchResult);//不然得分就是我下了之后的对方的所能得到的最高分取负
m_map[x][y] = NO_CHESS;
if (tmpScore >= beta) {
return beta;
}
if (tmpScore > alpha) {//取对方尽所有努力后得到最大值中的最小的一个 取负值后变成最大的一个
alpha = tmpScore;
searchResult = {x, y};
}
}
return alpha;
}
抽象出来的伪代码:
//意义:目前棋盘的最值评分 分数的正负取决于一开始的isBlackNow
int abSearch(int floor, int alpha, int beta, bool isBlackNow, Coord &searchResult) {
possibleMove = generatePossibleMove();
for (auto &now: possibleMove) {
downOneStep();
if (someoneWin()) {//如果有人赢了 必定是下这个子的人赢了
saveSearchResult();
restoreLastStep();
return evaluateScore();
}
//单层搜索
if (floor == 1) {//如果只看这一步子 那就是这一步子所有可能的得分中的最大值
tmpScore = evaluateScore();
restoreLastStep();
if (tmpScore > alpha) {
alpha = tmpScore;
saveSearchResult();
}
continue;
}
tmpScore = -abSearch(floor - 1, -beta, -alpha, !isBlackNow, tempSearchResult);//不然得分就是我下了之后的对方的所能得到的最高分取负
restoreLastStep();
if (tmpScore >= beta) {
return beta;
}
if (tmpScore > alpha) {//取对方尽所有努力后得到最大值中的最小的一个 取负值后变成最大的一个
alpha = tmpScore;
saveSearchResult();
}
}
return alpha;
}
Alpha-Beta剪枝的原理的深入理解(无图预警)的更多相关文章
- 软件发布版本区别介绍-Alpha,Beta,RC,Release
Alpha: Alpha是内部测试版,一般不向外部发布,会有很多Bug.除非你也是测试人员,否则不建议使用. 是希腊字母的第一位,表示最初级的版本 alpha就是α,beta就是β alpha版就是比 ...
- 软工+C(4): Alpha/Beta换人
// 上一篇:超链接 // 下一篇:工具和结构化 注:在一次软件工程讨论课程进度设计的过程中,出现了这个关于 Alpha/Beta换人机制的讨论,这个机制在不同学校有不同的实施,本篇积累各方观点,持续 ...
- 软工+C(2017第4期) Alpha/Beta换人
// 上一篇:超链接 // 下一篇:工具和结构化 注:在一次软件工程讨论课程进度设计的过程中,出现了这个关于 Alpha/Beta换人机制的讨论,这个机制在不同学校有不同的实施,本篇积累各方观点,持续 ...
- K 班1-7,alpha,beta 作业成绩汇总
K 班1-7,alpha,beta 作业成绩汇总 千帆竞发 详细得分 短学号 名 1 2 3 4 5 6 7 alpha beta TOTAL 505 基智 4.55 1 -2 0 0 -10 4.3 ...
- 软件版本GA,RC,alpha,beta含义
软件版本GA,RC,alpha,beta含义 (1)RC:(Release Candidate) Candidate是候选人的意思,用在软件上就是候选版本.Release.Candidate.就是发行 ...
- 扩增子分析解读6进化树 Alpha Beta多样性
分析前准备 # 进入工作目录 cd example_PE250 上一节回顾:我们的OTU获得了物种注释,并学习OTU表的各种操作————添加信息,格式转换,筛选信息. 接下来我们学习对OTU序列的 ...
- mDNS 原理的简单理解
转自:http://www.binkery.com/post/318.html mDNS 原理的简单理解 mDNS multicast DNS , 使用5353端口. 在局域网内,你要通过一台主机和其 ...
- mDNS原理的简单理解——每个进入局域网的主机,如果开启了mDNS服务的话,都会向局域网内的所有主机组播一个消息,我是谁,和我的IP地址是多少。然后其他也有该服务的主机就会响应,也会告诉你,它是谁,它的IP地址是多少
MDNS协议介绍 mDNS multicast DNS , 使用5353端口,组播地址 224.0.0.251.在一个没有常规DNS服务器的小型网络内,可以使用mDNS来实现类似DNS的编程接口.包格 ...
- [转帖]mDNS原理的简单理解
mDNS原理的简单理解 https://binkery.com/archives/318.html 发现还有avahi-daemon mdns 设置ip地址 等等事项 网络部分 自己学习的还是不够多 ...
- javascript 数组排序原理的简单理解
js内置的Array函数原型对象有个sort方法,这个方法能按照顺序排序数组. 例如: var arr1 = [6, 4, 2, 5, 2]; arr1.sort((x, y) => x - y ...
随机推荐
- 创建Anaconda虚拟Python环境的方法
本文介绍在Anaconda环境下,创建.使用与删除Python虚拟环境的方法. 在Python的使用过程中,我们常常由于不同Python版本以及不同第三方库版本的支持情况与相互之间的冲突情况, ...
- PGO in Go 1.21
原文在这里. 由 Michael Pratt 发布于 2023年9月5日 在2023年早些时候,Go 1.20发布了供用户测试的概要版本的基于性能分析的优化(PGO).经过解决预览版已知的限制,并得益 ...
- 探析ElasticSearch Kibana在测试工作中的实践应用
一. 为什么使用ES Kibana 离线数据测试中最重要的就是数据验证,一部分需要测试es存储数据的正确性,另一部分就需要验证接口从es取值逻辑的正确性.而为了验证es取值逻辑的正确性,就需要用到Ki ...
- math 库中常用的数学运算和常量【GO 基础】
〇.关于 math GO 语言的 math 库是一个内置的标准库,其中包含了许多数学函数和常量,用于计算各种数学运算和统计学计算. 日常开发中,计算当然是少不了的,那么今天来梳理下备查. 一.测试示例 ...
- 前端三件套系例之HTML——HTML5基础
1.HTML 1-1 什么是HTML HTML是用来制作网页的标记语言 HTML是Hypertext Markup Language的英文缩写,即超文本标记语言 HTML语言是一种标记语言,不需要编译 ...
- unity利用Rigibody实现第一人称移动
1. CameraRotation脚本,将它给MainCamera,实现上下视角旋转 using System.Collections; using System.Collections.Generi ...
- 手撕Vuex-Vuex实现原理分析
本章节主要围绕着手撕 Vuex,那么在手撕之前,先来回顾一下 Vuex 的基本使用. 创建一个 Vuex 项目,我这里采用 vue-cli 创建一个项目,然后安装 Vuex. vue create v ...
- CF1707B [Difference Array]
Problem 题目简述 设序列 \(a\) ,并且是单调递增的.设 \(a\) 当前长度为 \(l\),你要对 \(a\) 作差分,即令 \(b_i = a_{i+1} - a_i(1\le i & ...
- 使用Python批量发送个性化邮件
前言 在现代工作环境中,我们经常需要向多个收件人发送个性化的邮件.通过使用Python编程语言,我们可以自动化这个过程,从Excel文件中读取收件人和相关数据,并发送定制的邮件. 首先,导入所需的库: ...
- 2007年对Youtube小视频的分析文章
Understanding the Characteristics of Internet Short Video Sharing: YouTube as a Case Study 视频的种类 该研究 ...