alpha-beta剪枝算法

实验报告

alpha-beta剪枝算法

姓名:张楚明 学号:18342125 日期:2021.01.15

摘要

本实验将搜索深度为4的Alpha-Beta剪枝算法应用于中国象棋中黑方走棋,实现了中国象棋的人机博弈。博弈过程中综合考虑了棋力对敌方棋子的攻击力对己方棋子的保护能力棋子的灵活性及其位置等多种因素计算当前棋子的评估值

使用说明

vscode打开文件夹运行main.py即可(其中相应版本为Python3.8.2Pygame1.9.6

1. 导言

  • (1) 要解决的问题描述,问题背景介绍;

    目前国际上很多AI都是靠在棋类方面战胜人脑来衡量自身的智能,且五子棋、围棋等相关棋类AI目前已经能够战胜人类脑力,但由于中国象棋起步晚且复杂度高,设计相应的能够战胜人类顶尖棋手的AI仍然没有很好的实现。在本实验中,我们基于alpha-beta剪枝算法,综合考虑了棋力、对敌方棋子的攻击力、对己方棋子的保护能力、棋子的灵活性及其位置等多种因素计算当前棋子的评估值

  • (2) 拟使用的方法,方法的背景介绍;

    AlphaBeta剪枝算法是一个搜索算法旨在减少在其搜索树中,被极大极小算法评估的节点数。这是一个常用人机游戏对抗的搜索算法。它的基本思想是根据上一层已经得到的当前最优结果,决定目前的搜索是否要继续下去。

    Alpha-Beta只能用递归来实现。这个思想是在搜索中传递两个值,第一个值是Alpha,即搜索到的最好值,任何比它更小的值就没用了,因为策略就是知道Alpha的值,任何小于或等于Alpha的值都不会有所提高。

    第二个值是Beta,即对于对手来说最坏的值。这是对手所能承受的最坏的结果,因为我们知道在对手看来,他总是会找到一个对策不比Beta更坏的。如果搜索过程中返回Beta或比Beta更好的值,那就够好的了,走棋的一方就没有机会使用这种策略了

2. 实验过程

  • (1) 所用的具体的算法思想流程;

    • 轮到黑方走棋时,遍历当前走棋方棋子生成所有可能的走棋作为解空间
    • 调用alpha-beta剪枝算法遍历解空间,根据评估值设置剪枝
    • 根据棋力、攻击力、保护力、棋子灵活性及其位置计算当前棋盘的评估值
  • (2) 实现算法的程序主要流程,功能说明;

    • alpha-beta剪枝算法的伪代码如下,本文实现中引入负号来交替计算每一层取最大值/最小值(详见代码actions.py line38

      def AlphaBeta():
      	if depth == 0 or node为叶节点:
      		计算并返回当前棋盘的估计值作为alpha或者beta用于剪枝
      	
      	if 当前层求max(beta)剪枝:
      		遍历解空间中所有的走棋:
      			递归生成下一层的解并与其比较取最大值
      			val = self.AlphaBeta(depth - 1, alpha, beta)
      			alpha = max(val, alpha)
      			进行beta剪枝
      			if alpha >= beta:
      				break
      		return alpha
      	else 当前层求min(alpha)剪枝:
      		遍历解空间中所有的走棋:
      			递归生成下一层的解并与其比较取最小值
      			val = self.AlphaBeta(depth - 1, alpha, beta)
      			beta = min(val, beta)
      			进行alpha剪枝
      			if alpha >= beta:
      				break
      		return alpha
      
    • 评估值计算详解:

      评估值 = 当前棋盘所有棋子的棋力之和 + 当前棋盘所有棋子的攻击力之和 + 当前棋盘所有棋子的防守力 + 当前棋盘所有棋子灵活性和位置棋力之和

    • 棋力值设置如下

      • 因为加上了灵活性、位置、攻击力和防守力评估,兵和卒不分为是否过河、是否到底线
      • 帅/将设置为整型最大值sys.maxsize
      • 原为根据百度百科设置,以下是经过对此测试对比后效果较好的棋力值
      属性 兵/卒 帅/将
      棋力 80 300 500 300 250 250 sys.maxsize
    • 攻击力

      • 将棋子的攻击力定义为在所有可能的走棋中能攻击到的敌方棋子的棋力之和
    • 防守力

      • 将棋子的防守力定义为在所有可能的走棋中能保护到的己方棋子的棋力之和的一半(调整对应系数使之攻击欲望大于防守欲望)
    • 棋子灵活性设置如下

      属性 兵/卒 帅/将
      灵活性 1 15 15 12 6 3 0
    • 棋子位置

      • 为每类棋子在棋盘中的位置赋予得分(考虑到效率问题,只计算每个棋子在棋盘的位置,没有考虑棋子间的相对位置),详见constants.py line40
  • 经过上课演示后得到老师和同学的启发做了如下改进

    • 计算棋力时引入棋子灵活性和位置(见上评估值详解)

    • 引入历史启发算法增加搜索树的效率,效率增高后可以适当提高搜索深度以增强程序的智能性(详见代码actions.py line19

      根据部分已经搜索的结果来调整将要搜索的结点的顺序。通常一个局面经搜索被认为较好时,在其后继结点中往往有一些相似的局面(如某些无关紧要的棋子位置有所不同)也是较好的。在搜索的过程中,每当找到一个好的走法,就给该走法累加一个增量以记录其“历史得分”,一个多次被搜索并认为是好的走法的“历史得分”就会较高。对于即将搜索的结点,按 “历史得分”的高低对它们进行排序,保证较好的走法排在前面,Alpha-Beta搜索就可以尽可能早地进行“裁剪”,从而保证了搜索的效率

    • 随着棋盘中棋子数的减少逐渐增加搜索深度,以增强电脑残局能力

      搜索深度 = int(8 - 存活棋子数 / 8),场上的棋子每减少8个双方搜索深度各加1

3. 结果分析

  • (1) 交代实验环境,算法设计的参数说明;

    Python3.8.2,Pygame1.9.6。参数和使用说明见上

  • (2) 结果(图或表格),比如在若干次运行后所得的最好解,最差解,平均值,标准差。

    中间有展示按回车重新开始

  • (3) 分析算法的性能,包括解的精度,算法的速度,或者与其他算法的对比分析。

    算法的性能较低,目前搜索四层需要1s左右的时间,节点数根据存活棋子数量减少而降低,基本小于5000;由于效果已经较好(本人多次尝试无法战胜AI),所以没有尝试继续增加搜索深度的情况。

  • (4) 算法的优缺点;本实验的不足之处,进一步改进的设想。

    • 优点

      • 按照课堂上老师和同学的建议进行了完善(具体见上第二点实验过程最后部分)

      • 实现了重开、对当前选中棋子的位置和可能的走步进行了UI展示

      • 每次AI走棋时搜索的节点数和搜索时间也都进行了UI展示

    • 缺点

      • 搜索效率仍然较低
      • 开局较慢,寻找开局库时发现很多都是js相关资源,暂时不知道如何引入本文实验中的python程序
    • 进一步改进的设想

      • 查阅文献后得可以引入hash表结构加快搜索速度,提高搜索效率
      • 以后可以考虑引入一些简单且常见的开局库(中炮对反宫马、中炮对屏风马)

结论

  • 静态估计函数是本实验得关键,可以修改棋力、攻击力、防守力对应系数、位置棋力等等因素以达到更好的效果,为了保证较好的效果,4层搜索深度是必要的,所以要引入开局库、历史启发算法等加快搜索速度,以便在深度搜索时仍能保持较高的性能。

  • 之前一直好奇人机对战的游戏、比如电脑自带的一些棋类游戏如何设置难度等级,经过这次试验后明白了可以设置搜索树深度、或者应用深度学习时设置其网络层数来达到控制难度的目的。本文实现中实验深度为2时AI表现不够智能(未引入开局库的情况),如下:(实验深度为4时较为智能,具体见上动图,这里不再展示)

主要参考文献

  • 极大极小α-β剪枝算法
  • 基于alpha-beta剪枝搜索算法的中国象棋游戏设计-【信息通信期刊】
  • 象棋百科全书

你可能感兴趣的:(alpha-beta剪枝算法)