极大极小算法和AlphaBeta剪枝算法学习总结

2023-10-10 10:59

本文主要是介绍极大极小算法和AlphaBeta剪枝算法学习总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作为菜鸟,先贴上参考博文:

1.极小极大算法

2.<<CS 161 Recitation Notes - The Minimax Algorithm>>

3.《PC游戏编程-人机博弈》-作者陈其,王小春

本文目录:

  1. 直观图解
  2. 伪代码
  3. 习题实战

适用范围:极小极大算法常用于零和博弈游戏中,零和博弈指参与博弈的各方,在严格竞争下,一方的收益必然意味着另一方的损失,博弈各方的收益和损失相加总和永远为“零”,双方不存在合作的可能。博弈游戏,目的是寻找最优的方案使得自己能够利益最大化。

先来个直观理解

极大极小算法

基本思想就是假设自己足够聪明,总是选择最利于自己(A)的方案,而对手同样聪明,总是选择最不利与对方即A方的方案。

设:正方形代表自己(A),圆代表对手(B),节点的每个孩子节点代表一个候选方案。

                        

上图中显示了所有候选方案。让我们如下分析:(注意:根节点为当前局面,某一结点的子节点为下一步走法产生的局面。图中的所有数字都是A的利益值,可以由估值函数得出,越大越有利于A)

                                            

假设A选择第一个方案,B有两个候选方案,B为了使得A利益最小化,所有在7和3中选择了3,所以A只能获得3。  

                                               

假设A选择第二个方案,B只有一个选择,A最终可以获得15。

                     

假设A选择第三个方案,B有4个可选方案,为了使得A利益最小,B选择第一个方案,则A只能获得利益1。

                        

 

A为了使得自己利益最大,所以A会选择第二个方案,即获得利益15。

从上图可以看出,B总是选择候选方案中的最小值,而A总是选择候选方案中的最大值,极小极大的名字也就源于此。该算法使用深度优先搜索(Depth First Search)遍历决策树来填充树中间节点的利益值,叶子节点的利益值通常是通过一个利益评估函数算

有时候为了得到较好的效果不得不增加搜索树的深度,这样就增加了大量的计算。为了加快计算速度,减少计算量,可以使用Alpha-Beta剪枝算法(Alpha Beta Pruning)对搜索树进行剪枝。因为搜索树中有很多分支不需要遍历。

Alpha-Beta剪枝算法(Alpha Beta Pruning) 

Alpha-Beta剪枝用于裁剪搜索树中没有意义的不需要搜索的树枝,以提高运算速度。

假设α为下界,β为上界,对于α ≤ N ≤ β:

若 α ≤ β  则N有解。

 若 α > β 则N无解。

 下面通过一个例子来说明Alpha-Beta剪枝算法。

                   

上图为整颗搜索树。这里使用极小极大算法配合Alpha-Beta剪枝算法,正方形为自己(A),圆为对手(B)。

初始设置α为负无穷大,β为正无穷大。 

                                  

对于B(第四层)而已,尽量使得A获利最小,因此当遇到使得A获利更小的情况,则需要修改β。这里3小于正无穷大,所以β修改为3。

                                  

(第四层)这里17大于3,不用修改β。

                                  

对于A(第三层)而言,自己获利越大越好,因此遇到利益值大于α的时候,需要α进行修改,这里3大于负无穷大,所以α修改为3

                                   

B(第四层)拥有一个方案使得A获利只有2,α=3,  β=2, α > β, 说明A(第三层)只要选择第二个方案, 则B必然可以使得A的获利少于A(第三层)的第一个方案,这样就不再需要考虑B(第四层)的其他候选方案了,因为A(第三层)根本不会选取第二个方案,多考虑也是浪费.

                                        

B(第二层)要使得A利益最小,则B(第二层)的第二个方案不能使得A的获利大于β, 也就是3. 但是若B(第二层)选择第二个方案, A(第三层)可以选择第一个方案使得A获利为15, α=15,  β=3, α > β, 故不需要再考虑A(第三层)的第二个方案, 因为B(第二层)不会选择第二个方案.

 

A(第一层)使自己利益最大,也就是A(第一层)的第二个方案不能差于第一个方案, 但是A(第三层)的一个方案会导致利益为2, 小于3, 所以A(第三层)不会选择第一个方案, 因此B(第四层)也不用考虑第二个方案.

 

当A(第三层)考虑第二个方案时,发现获得利益为3,和A(第一层)使用第一个方案利益一样.如果根据上面的分析A(第一层)优先选择了第一个方案,那么B不再需要考虑第二种方案,如果A(第一层)还想进一步评估两个方案的优劣的话, B(第二层)则还需要考虑第二个方案,若B(第二层)的第二个方案使得A获利小于3,则A(第一层)只能选择第一个方案,若B(第二层)的第二个方案使得A获利大于3,则A(第一层)还需要根据其他因素来考虑最终选取哪种方案.

 再来看看伪代码

极大极小算法伪代码:

int MaxMin(position p,int d)
{int bestvalue,value;if(game over)   //检查游戏是否结束 return evaluation(p);// 游戏结束,返回估值 if(depth<=0)    //检查是否是叶子节点 return evaluation(p);//叶子节点,返回估值 if(max)         //极大值点 bestvalue=-INFINTY;else            //极小值点 bestvalue=INFINTY;for(each possibly move m){MakeMove(m);    //走棋 value=MaxMin(p,d-1);UnMakeMove(m);  //恢复当前局面 if(max)bestvalue=max(value,bestvalue);//取最大值 elsebestvalue=min(value,bestvalue);//取最小值 }return bestvalue;
}
//  end of MaxMin algorithm

 

 

 

将Alpha剪枝和Beta剪枝加入MaxMin搜索就得到AlphaBeta搜索,AlphaBeta搜索的伪代码如下

//伪代码,Alpha剪枝和Beta剪枝+MaxMin搜索
int AlphaBeta(nPlay,nAlpha,nBeta)
{if(game over)return Eveluation;   //胜负已分,返回估值if(nPly==0)return  Eveluation;  //叶子节点返回估值if(Is Min Node)          //判断 节点类型 {        // 极小值节点for(each possible move m){make move m;      //生成新节点score=AlphaBeta(nPly-1,nAlpha,nBeta)//递归搜索子节点unmake move m;//撤销搜索过的节点if(score<nBeta){nBeta=score;//取极小值if(nAlpha>=nBeta)return nAlpha;//alpha剪枝,抛弃后继节点 } }return nBeta;//返回最小值 }else{//取极大值的节点 for(each possible move m){make move m;      //生成新节点score=AlphaBeta(nPly-1,nAlpha,nBeta)//递归搜索子节点unmake move m;//撤销搜索过的节点if(score>nAlpha){nAlpha=score;//取极小值if(nAlpha>=nBeta)return nBeta;//nBeta剪枝,抛弃后继节点 } }return nAlpha;//返回最小值 } 
} 
//end of AlphaBeta pseudocode

来点真的

习题链接,真枪实战

1.三角点格棋

2.Stake Your Claim

 

3.Find the Winning Move

这篇关于极大极小算法和AlphaBeta剪枝算法学习总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/179975

相关文章

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

Python实现图片分割的多种方法总结

《Python实现图片分割的多种方法总结》图片分割是图像处理中的一个重要任务,它的目标是将图像划分为多个区域或者对象,本文为大家整理了一些常用的分割方法,大家可以根据需求自行选择... 目录1. 基于传统图像处理的分割方法(1) 使用固定阈值分割图片(2) 自适应阈值分割(3) 使用图像边缘检测分割(4)

Windows Docker端口占用错误及解决方案总结

《WindowsDocker端口占用错误及解决方案总结》在Windows环境下使用Docker容器时,端口占用错误是开发和运维中常见且棘手的问题,本文将深入剖析该问题的成因,介绍如何通过查看端口分配... 目录引言Windows docker 端口占用错误及解决方案汇总端口冲突形成原因解析诊断当前端口情况解

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

java常见报错及解决方案总结

《java常见报错及解决方案总结》:本文主要介绍Java编程中常见错误类型及示例,包括语法错误、空指针异常、数组下标越界、类型转换异常、文件未找到异常、除以零异常、非法线程操作异常、方法未定义异常... 目录1. 语法错误 (Syntax Errors)示例 1:解决方案:2. 空指针异常 (NullPoi

Java反转字符串的五种方法总结

《Java反转字符串的五种方法总结》:本文主要介绍五种在Java中反转字符串的方法,包括使用StringBuilder的reverse()方法、字符数组、自定义StringBuilder方法、直接... 目录前言方法一:使用StringBuilder的reverse()方法方法二:使用字符数组方法三:使用自