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 ...
随机推荐
- [Python3] 初识py, 一个简单练手的小玩意. 快递查询
有图有真相 脚本代码 最近刚入门py, 准备写点小玩意练练手. 于是决定拿快递100开刀. 因为它的api很简单. # 快递100 API # 作者: 剑齿虎 # 邮箱: yuxiaobo64@gma ...
- glog 日志库简介与测试【GO 常用的库】
〇.前言 golang/glog 是 C++ 版本 google/glog 的 Go 版本实现,基本实现了原生 glog 的日志格式. 在 Kuberntes 中,glog 是默认日志库.因此需要详细 ...
- Python 有趣的模块之pynupt——通过pynput控制鼠标和键盘
写在前面 Python中有许多有趣和强大的模块,其中一个非常有趣的模块就是pynupt.pynupt是基于pynput模块的一个封装,用于控制鼠标和键盘.它可以实现自动化操作和游戏外挂等功能. 本文将 ...
- 基于go语言gin框架的web项目骨架
该骨架每个组件之间可单独使用,组件之间松耦合,高内聚,组件的实现基于其他三方依赖包的封装. 目前该骨架实现了大多数的组件,比如事件,中间件,日志,配置,参数验证,命令行,定时任务等功能,目前可以满足大 ...
- 使用ensp搭建路由拓扑,并使用isis协议实现网络互通实操
转载请注明出处: 1.通过拓扑搭建如下拓扑: 其中R7.R8为L1,R6为L1/2,R9为L2. 2.配置isis实现网络互通 R7配置如下: [Huawei]isis 1 [Huawei-isis- ...
- Django框架——forms组件、cookie与session
文章目录 1 forms 组件 1 校验字段功能 2 渲染标签功能 渲染方式1 渲染方式2 渲染方式3 3 渲染错误信息功能 视图 模板 4 组件的参数配置 5 局部钩子 6 全局钩子 2 cooki ...
- Java虚拟机(JVM):第五幕:自动内存管理 - HotSpot算法细节以及低延迟垃圾收集器
一.HotSpot算法细节 1.根节点枚举:所有的收集器在根节点枚举的时候,必须暂停用户线程,同时要保证一致性的快照中得以进行.一致性:整个枚举期间执行子系统看起来就像是冻结在某一个时间点上,不会出现 ...
- 利用信号量SemaphoreSlim实现PaddleOCR的线程安全访问
Wlkr.Core.ThreadUtils 项目背景 早在PaddleOCR 2.2版本时期,认识了周杰大佬的PaddleSharp项目,试用其中PaddleOCR时,发现它在改为web api调用时 ...
- 虹科案例 | 石油天然气行业CFD高性能计算解决方案
公司简介 DNV GL 是全球领先的能源.石油和海事行业风险管理及资产绩效提升的软件供应商,主要为客户提供全面的风险管理和各类评估认证服务,认证涉及信息通信技术.汽车及航空天.食品与饮料.医疗等方面. ...
- 字符串匹配|kmp笔记
很久之前学的了. 我很懒,不太喜欢画图. 做个笔记回忆一下: kmp 朴素比对字符串 所谓字符串匹配,是这样一种问题:"字符串 T 是否为字符串 S 的子串?如果是,它出现在 S 的哪些位置 ...