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 ...
随机推荐
- 【krpano】淘宝buy+案例
这是一个类似淘宝buy+的案例,是基于krpano全景开发工具二次开发的全景视频.WebVR.360°环物.全景视频热点添加于一身的综合性案例.现在将案例上传网站供krpano技术人员和爱好者大家共同 ...
- PostgreSQL-分区表介绍
一.分区简介 表分区是解决一些因单表过大引用的性能问题的方式,比如某张表过大就会造成查询变慢,可能分区是一种解决方案.一般建议当单表大小超过内存就可以考虑表分区了. 表的分区就是将一个逻辑上的大表(主 ...
- RK3568开发笔记(十一):开发版buildroot固件移植一个ffmpeg播放rtsp的播放器Demo
前言 目标开发任务还有个功能,就是播放rtsp摄像头,当然为了更好的坐这个个,我们必须支持rtsp播放失败之后重新尝试,比如5s重新尝试打开一次,从而保障联网后重新打开,然后达成这个功能. D ...
- 解决SpringBoot3.X中starter配置自动注入失效问题
在自定义 starter 项目时,如果组件无法被 @ComponentScan 扫描并且想自动注册到 IOC 中,在springboot2.7之前 我们会采用 spring,factories 方式, ...
- MySql 数据 管理表的操作
管理表的操作 use scoredb; -- 查看数据库中有哪些表 show tables; show tables from bipowernode; -- 查看数据表的基础结构 show colu ...
- Fisher线性判别分析(二分类)
LDA(Linear Discriminant Analysis)是一种经典的线性判别方法,又称Fisher判别 分析.该方法思想比较简单:给定训练集样例,设法将样例投影到一维的直线 上,使得同类样例 ...
- PostgreSQL学习笔记-3.基础知识:CROSS、INNER、LEFT OUTER、RIGHT OUTER、FULL OUTER、UNION
PostgreSQL JOIN 子句用于把来自两个或多个表的行结合起来,基于这些表之间的共同字段. 在 PostgreSQL 中,JOIN 有五种连接类型: CROSS JOIN :交叉连接INNER ...
- [SWPUCTF 2021 新生赛]sql
看到网站上写着参数是wllm,就用wllm=1试了一下,发现是SQL注入 查找字段数时,提示请勿非法操作 说明空格出现过滤,可以用/**/绕过 http://1.14.71.254:28347/?wl ...
- 记一次MySQL5初始化被kill的问题排查
写在前面 由于测试环境JED申请比较繁琐,所以Eone提供了单机版Mysql供用户使用,近期Eone搭建Mysql5的时候发现莫名被kill了,容器规格是4C8G,磁盘30G 这不科学,之前都是可以的 ...
- 【PHP正则表达式】
[PHP正则表达式] 最近写题总是遇到php正则表达式的匹配函数,于是进行一个总结. 1.什么是正则表达式 是php在进行搜索时用于匹配的模式字符串.一般用于php对特定字符序列的替换和搜索. 2.正 ...