西南交大新秀杯数学建模.docx
《西南交大新秀杯数学建模.docx》由会员分享,可在线阅读,更多相关《西南交大新秀杯数学建模.docx(37页珍藏版)》请在冰豆网上搜索。
西南交大新秀杯数学建模
2015年西南交通大学
新秀杯数学建模竞赛
题目:
B(填写A或B题)
组别:
大二组(填写大一组或大二题)
参赛队员1
参赛队员2
参赛队员3
姓名
学号
学院
专业
电话
Email
西南交通大学教务处
西南交通大学实验室及设备管理处
西南交通大学数学建模创新实践基地
五子棋部分阵法研究的数学模型
摘要
五子棋游戏是一种益智类的博弈游戏,其开局阵型对棋局结果往往起决定性作用。
本文通过构造博弈树,结合极大极小算法、运用机理分析与计算机模拟的方法,讨论了在五种开局阵型下黑子获胜的策略,及该策略实现的概率大小问题。
对于问题一,首先我们将棋盘抽象为方阵,将方阵中对于元素的描述方式引入棋盘,从而建立起各棋子位置与数组
之间的映射关系;其次,我们做出博弈树表示黑白双方对弈的过程,从图像上表现了这一过程中随着搜索深度增加,博弈树的子节点将成指数增长的特点,又从实际出发阐述了对弈双方在“与”和“或”节点上存在明显对立的利害关系时,两方将如何选择;在此基础上,引入极大极小化搜索思想,结合实际情况,用价值大小量化对弈过程,设计出在估值函数用来比较不同局面的对某方的价值大小;此外,考虑到在按照极大极小搜索原理,搜索理想的博弈条件下,黑棋取胜的路径时搜索空间巨大,我们又对这一算法进行了搜索空间限定及搜索方式的优化;最后利用VC6.0编程,输入四种初始界面后经过一步步回溯,最终都得到了黑棋获胜的结果。
可见将极大极小算法应用到这四种局面,可以寻找到取胜的路径。
对于问题二,首先我们在问题二中做出了合理的假设,将问题转化为,在无初始阵型的前提下,若白棋随机性的落子,黑棋按照问题一中极大极小算法这一策略,取胜概率应如何;其次,我们首先考虑运用概率论的相关知识,通过机理分析,结合古典概型建立了在假设条件下黑棋不败的概率解析模型,但由于求解复杂,我们考虑采用蒙特卡罗模拟的方法,利用机理分析过程中的一系列结论,得到计算机模拟所需要的概率分布及随机数列,但编程结果并不理想;此外我们认为策略的合理性可以由其成功率决定,即这个策略的合理性较为欠缺;最后我们通过搜集资料,在问题结果的讨论中引入了部分算法优化的方法,相信将这些方法加以应用后,能够更好的解决此类博弈问题。
关键词:
博弈极大极小算法概率论蒙特卡罗模拟
一、问题重述
五子棋发源于中国,在中国民间流传着许多五子棋阵法,比如以下阵法:
(
斜三阵:
多由浦月、流星、丘月、游星、慧星演变而来。
见图一。
由本阵还可演变成一字长蛇阵,见图二。
以及长勾阵,见图三。
斜三阵的进攻多以成角或成半燕翼发起。
四角阵(图四):
黑方四子呈四方形的摆布,因而得名。
梅花阵:
下图所示阵形因黑方四子如梅花状而被称之为梅花阵。
1.请建立数学模型或算法讨论以上阵法中执黑方获胜的策略;
2.你的策略的合理性及获胜的概率如何?
请说明及验证。
(图片见附录)
二、模型假设
1.本文中不设置禁手。
2.执黑者先手。
3.棋盘规格为15行15列。
4.开局阵法与题目中相同。
5.下期过程假定为二人零和、全信息、非偶然的博弈过程。
6.黑棋和白棋在对弈时都足够理智。
三、符号说明
符号
说明
黑棋
白棋
估值函数
某局面下的估值
组合种类
白棋取胜的事件
取胜方式集合
扩展深度
当前局面子节点
四、问题分析
本文讨论了斜三阵、四角阵、梅花阵三种五子棋阵型中,先手必胜的策略及合理性检验。
从五子棋的游戏规则可知,这种黑白双方交替对抗的过程是一个博弈的过程。
由假设可知,我们讨论二人零和、全信息、非偶然、无禁手的情况,是因为下棋时满足如下特征:
1.对弈的双方轮流采取措施,博弈的结果只有三种情况,黑胜白负、白胜黑负及和局。
2.对弈过程中,任何一方都充分了解当前格局及历史格局。
3.在任何一方采取行动前都要根据当前情况分析得失,选择对自己有利而对对方不利的对策,而不存在运气因素。
对于一方而言,它的行动方案有若干选择,且方案之间是“与”的关系,因为此时任何一个方案都有可能被对方选中,故需讨论每一种情况的发生。
将这个“与”和“或”过程用图表示出来,就得到一棵博弈树。
由于五子棋的格局众多,故此博弈树很大,第一问中采用极大极小搜索原理,对一定深度的博弈树进行静态估值,通过比较找到当前最优行动方案,即黑棋所要采取的一种策略。
五、问题一的模型建立与分析
5.1模型准备
5.1.1做出博弈树
不妨设博弈的黑棋为
白棋为
,为了清楚的表现博弈的过程,下面站在黑棋一方作出一定深度的博弈树,定义如下:
1)将博弈的初始格局(斜三阵、四角阵、梅花阵)设为初始节点。
2)所有使自己一方“获胜”的终局认为是可解节点;所有是对方“获胜”的终局认为是不可解节点。
3)
一方扩展的节点之间是“或”的关系;
一方扩展的节点之间是“与”的关系。
可见在这棵博弈树中,每个格局可供选择的方案都很多,如果试图通过直到终点(一方五子相连或棋面无空位)的与或树搜索而得到最好的一步是难以实现的,考虑到计算机存储空间的限制,我们只生成一定深度为20的博弈树,即在棋面一共落子20个时停止扩展节点。
为了找到当前最优策略,需要对每个可能方案产生的后果进行比较,并将这一后果量化为得分。
图1
5.1.2构造估值函数
五子棋算法的评价函数需要考虑棋色,分别计算出它们各种组合(“眠三”、“眠四”、“活三”、“活四”等)的个数,根据经验及相关论文的结论[1]定义出各估价值,将个数乘以相应的估价值再求和,这样就得到了在某局面k下某种颜色棋子的估价
:
构造估价值时,根据假设,对于同一组合,黑棋的估价与白棋之和为0,即白棋各估价为黑棋的相反数。
表格1
黑棋
五连
活四
眠四
活三
眠三
活二
估价值
正无穷大
1000
300
300
120
30
白棋
五连
活四
眠四
活三
眠三
活二
估价值
负无穷大
-1000
-300
-300
-120
-30
5.2模型建立
易知,当
时,值越小局面对白棋越有利;大于0则反之。
故在每一个“或”节点,选取其子节点中一个最大的得分作为父节点的得分,使黑棋在可供选择的方案中选择对自己最有利的方案;对“与”节点,选取子节点中一个最小的得分作为父节点的得分,即白棋选择对黑棋最不利的方案。
即:
其中,
表示黑棋
对应的
个子节点
;
表示白棋
对应的
个子节点
。
这样可以得到一定深度的父节点的倒推值,如果一个行动方案中得到较大的倒推值,那么它就是当前最好的行动方案。
同理,若站在白棋的立场构造博弈树,在其他条件不变且组合估值仍为负时,最好的行动方案在倒推值较小时取得。
六、问题一的算法分析
6.1极大极小搜索算法
6.1.1算法说明
根据上述模型建立的过程可知,博弈的任务就是要对博弈树进行搜索找出当前最优的一步棋,对博弈树进行极大极小搜索(
)可以达到这一目的。
极大极小搜索,是因为对博弈双方而言,一方寻找的利益恰是一方失去的,这便形成极大极小的过程[1]。
6.1.2算法流程
第一步:
从初始节点出发生成一定深度的博弈树。
第二步:
用动态评估函数对每个终节点进行估值。
第三步:
用终节点的估值得到其搜索树上一层节点的估值。
若对方响应走步,再以当前状态为初始状态,转第一步。
6.2五子棋算法
6.2.1算法说明
五子棋博弈算法的设计是以极大极小搜索算法为基础的,相关说明如下:
1)没必要搜索整个博弈树的所有节点,对于一些容易确定的非极值节点,可以将它的子树剪掉。
2)由于树体庞大,终节点没有必要到达分出胜负的棋局,只需要在一定的深度范围内对局面进行评价,然后按照极大极小的原则选出最优,向上回溯到根节点,就可以得到最优走步。
这里我们取深度为2。
3)在根节点的初始局面的设定,由题目中给定的阵型决定。
4)五子棋棋盘为15*15的规格,因此每次走法近200多种,为简化搜索,可以根据下棋的实际经验,设落子与某棋子距离为
则只考虑
的位置。
如图2。
图2
6.2.2算法举例
下面以斜三阵(图3)为例对该算法进行解释。
首先,根据6.2.1中第四条说明,做出在初始局面下可以扩展的节点连成的轮廓线作为棋面,可知第一层局面为50个,对于它们的每一个都可扩展出对应节点,可知第二层共构成49*50个局面。
然后,根据极大极小化分析方法,计算出第二层子节点的估值后,第一层子节点估值取它对应扩展节点的极大值,根节点处的估值则取第一层子节点的最小值。
这个取得最小估计值的第一层子节点即为从初始局面出发的最佳落子方案。
从图3看出,搜索从第二层开始,由于初始节点A处在极小层(下一步走白棋),在求出
后,可知
,然后扩展出
节点。
计算可知
中第
个局面的估值满足:
而
。
而我们有
,故
现在我们假设白棋按照此方案行棋,则黑棋的回步则为使白棋落子点的估值取到极大值的第二层子节点。
这样就形成了新的局面。
下一步,白棋在此局面下搜索两层,又可以画出新的博弈树。
以此类推,直至某方五子相连。
若黑棋获胜,则这一系列的落子方案即为所需策略;若白棋取胜,可知在对弈双方都足够理智的假设下黑棋无法取胜。
图3
6.2.3程序设计
设扩展出深度为MaxD的博弈树,Childset为当前局面子节点的集合,则算法的程序描述如下[2]:
七、问题一的求解过程及结果分析
7.1求解过程
7.1.1输入说明
运行程序,弹出对话框后,首行输入任意字符,回车按照所示格式输入初始状态再回车,便可得到当前最优的一步所在棋盘上的位置。
其中o代表白棋,x代表黑棋,-代表空格键。
如下图,因为轮到白棋走步,故调用为白棋编写的程序。
当提示输入(4,7)时,白棋的下一步在第4行第7列;在此基础上调用黑棋走步的程序,在下方继续按照此格式输入,便得到黑棋的回步为(4,8)...以此类推,便可得到一系列对弈过程。
下面仅以阵型一(长钩阵)的截图为例进行说明(其余过程截图见附录)。
……
7.1.2模型求解结果
按上述输入说明依次运行程序,我们得到程序运行结果,及执黑方与执白方的各个走步,对于每一走步,我们用坐标(x,y)表示,其中x代表定x行,其取值为x=0,1,2,…;y代表第y列,其取值为y=0,1,2,…。
因此我们将每次运行程序后的结果依次列出即可得到执黑方与执白方的各个走步,为了区分执黑方与执白方走步的区别,我们用加粗的字体表示该步为执黑方的走步,按照这个方法我们可以得到图一的求解结果可以表述为:
(4,7)-(4,8)-(4,3)-(4,5)-(5,5)-(3,7)-(5,9)-(1,5)-(0,4)-(3,3)
-(3,8)-(3,4)-(3,3)-(6,6)-(2,2)-(1,1)-(2,3)-(1,3)-(5,3)-(6,3)-(5,6)
-(1,4)-(1,2)-(1,6)-执黑获胜
其余各个图的解法表述与此类似,具体求解结果见附件。
八、问题二的模型建立与分析
8.1黑棋获胜的解析模型
8.1.1模型准备
8.1.1.1古典概率模型[3]
如果一个随机试验所包含的单位事件是有限的,并且每个基本结果发生的概率是相同的,这种条件下的概率模型即为古典概型。
8.1.1.2解析模型假设
由第一问得到执黑方获胜的策略为:
结合博弈论的理论,利用极大极小原理,搜索当前局面下落子的最优方案。
若把对弈双方的每次落子视为一次随机试验,则落子的位置在棋盘上只有有限个,下面考虑把白棋的每次落子视为一个拉普拉斯实验,从而讨论在任意情形下该策略的获胜概率。
不妨假设:
1)不考虑禁手,白棋每次落一子,即每次随机试验中包含的基本事件互斥。
2)白棋不再理智,每次随机选择位置落子,即同一随机事件中基本事件发生的概率相同。
3)不考虑白棋获胜时有五子以上相连的情况。
4)不败即胜,即将平局视为取胜。
8.1.2解析模型建立与分析
由上述分析与假设,可知白棋落子这一事件满足古典概型的定义,首先计算白棋获胜的概率:
规格为15*15的棋盘,由五子相连即必胜可知:
1)若白棋横向上五子相连,则共有
种方案。
2)若白棋纵向上五子相连,同理共有
种方案。
3)若白棋正斜向五子相连,则共有
种方案。
4)若白棋反斜向五子相连,则共有
种方案。
综上,若白棋必胜,则相连五子的排列形式构成集合
。
设事件
,设白棋在第
步落到这一排列上,且
。
由黑棋先手及白棋落子的任意性可知有如下规律:
首次落子有
种方案;
第二次落子有
种方案;
......
第
次落子有
种方案;且每次选择都满足古典概型。
观察可知白棋落子在全局来看是第奇数步,即
是形如
的排列。
假定n不变,考虑
的排列组合共有
种,且有古典概型公式:
可知每种组合对应概率为:
又各组合相互独立,故由互斥事件的加法概率公式可得白棋必胜的概率为:
,
其中,
。
又白棋必胜与黑棋不败是对立事件,故黑棋取胜的概率为:
调用Matlab中的prod(n:
m)函数,设计有关k的循环命令可以解出这一概率,但显然会占用大量的内存空间且求解析解的过程繁琐,故考虑采用蒙特卡罗的方法模拟白棋在每处节点的选择,与极大极小分析原理相结合,得到在白棋出棋随机的前提下黑棋获胜次数与总次数之比,进而得到该策略取胜的概率及其合理性。
8.2黑棋获胜的计算机模拟模型
8.2.1求概率分布
由8.1.2的分析可知,白棋下棋过程是服从分布函数为:
的随机分布,其中
。
5.2.2实现从已知概率分布抽样
构造了概率模型之后,由于各种概率模型都可以看作是由各种各样的概率分布构成的,因此产生已知概率分布的随机变量(或随机向量),就成为实现蒙特卡罗方法模拟实验的基本手段。
即,考虑产生这样的随机数列决定白棋每次落子的位置。
观察分布函数可知,从每次落子的角度讲,棋盘上所有空位被选择的概率相同,故可视为一种特殊的均匀分布,区别在于此时基本事件的发生不再是(0,1)上的所有点,而是在一定范围内的所有自然数的取值。
为了更形象的说明,考虑在黑棋每轮落子后对棋盘上的所有空闲点重新按照1,2,3...标号,取最大标号为n,则根据线性同余法每次生成1到n之间的随机整数即可实现位置的随机抽样。
8.2.3计算概率
统计黑棋取胜的次数。
概率计算方法与古典概型的计算方法相同。
故不赘述。
九、问题二的求解及结果分析
我们的第二问没有时间计算了,数量不够多的有限次模拟尝试过但效果很差。
估计在第一问的估值函数设计过程中所设定的常数并不能满足实际搜索的需要,查看论文得知估值函数的优化主要体现在各种组合(活四、活三等)的估值常数的设定,以及估值函数形式上的设定;常数的优化涉及遗传算法[]等;这里想说一下一种比较简单的常数优化方法。
结合实际,我们通常发现会有这种比较极端的情况,自己有两个活三,也比不过对手的一个活四,甚至,自己有更多的活三也不例外。
同样的关系也适用于某种状态下的眠四和活三。
所以根据阿基米德公理推测,单纯用常数来统计一个局面的优劣并不很完善,故考虑到是否能用几种初等函数比如指数函数,对数函数,线性函数来刻画局面呢,即统计出各种组合的个数之后将其作为自变量代入对应的函数,用对应函数值代替之前的对应组合的估值。
这样就构造了一个形为
的估值函数,同时也取代了现有的大部分估值函数加权求和或取极值的局面。
通过查询资料我们发现在题目中所给的几个开局阵型中,除了梅花阵之外都是执黑必胜。
更惊人的是这一结果被一名外国数学家利用极大极小搜索原理和某棋手的下棋习惯,通过计算机编程证明过。
十、参考文献
[1].朱全民,五子棋算法的研究与思考,
[2]张明亮,五子棋机器博弈系统评估函数的设计,/,2012年01月16日.
[3]肖玉兰等,古典概型问题的数学模型,
十一、附录(c++程序及求解结果)
11.1c++程序
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineinf1<<30
#defineN50005
#definemaxn100005
#defineMin(a,b)((a)<(b)?
(a):
(b))
#defineMax(a,b)((a)>(b)?
(a):
(b))
#definepb(a)push_back(a)
#definemem(a,b)memset(a,b,sizeof(a))
#defineeps1e-9
#definezero(a)fabs(a)#defineLLlonglong
#defineULLunsignedlonglong
#definelson(step<<1)
#definerson(step<<1|1)
#defineMOD1000000007
#definemp(a,b)make_pair(a,b)
usingnamespacestd;
//charstr[5][5];
charstr[16][16];
intX,Y,chess;
//判断一个局面是否结束
boolcheck(intx,inty)//检查游戏是否有输赢
{
inttot=0;
intyy,xx;
//p=player==0?
2:
1;
if(str[x][y]=='o')
//continue;
//检查o列
{yy=y;xx=x;
while(--xx>=0&&str[xx][yy]=='o')tot++;xx=x;
while(++xx<15&&str[xx][yy]=='o')tot++;xx=x;
if(tot+1>=5)
returntrue;//returnfalse;
//检查o行
tot=0;
while(--yy>=0&&str[xx][yy]=='o')tot++;yy=y;
while(++yy<15&&str[xx][yy]=='o')tot++;yy=y;
if(tot+1>=5)
returntrue;//returnfalse;
//检查反斜边
//count=0;
yy--;xx--;
while((yy>=0||xx>=0)&&str[xx][yy]=='o'){tot++;yy--;xx--;}xx=x;yy=y;
yy++;xx++;
while((xx<15||yy<15)&&str[xx][yy]=='o'){tot++;yy++;xx++;}xx=x;yy=y;
if(tot+1>=5)
returntrue;//returnfalse;
tot=0;
//检查正斜边
//count=0;
yy++;xx--;
while((yy<15||xx>=0)&&str[xx][yy]=='o'){tot++;yy++;xx--;}xx=x;yy=y;
yy--;xx++;
while((yy>=0||xx<15)&&str[xx][yy]=='o'){tot++;yy--;xx++;}xx=x;yy=y;
if(tot+1>=5)
returntrue;//returnfalse;
tot=0;
}
elseif(str[x][y]=='x')
//continue;
//检查x列
{yy=y;xx=x;
while(--xx>=0&&str[xx][yy]=='x')tot++;xx=x;
while(++xx<15&&str[xx][yy]=='x')tot++;xx=x;
if(tot+1>=5)
returntrue;//returnfalse;
//检查o行
tot=0;
while(--yy>=0&&str[xx][yy]=='x')tot++;yy=y;
while(++yy<15&&str[xx][yy]=='x')tot++;yy=y;
if(tot+1>=5)
returntrue;//returnfalse;
//检查反斜边
//count=0;
yy--;xx--;
while((yy>=0||xx>=0)&&str[xx][yy]=='x'){tot++;yy--;xx--;}xx=x;yy=y;
yy++;xx++;
while((xx<15||yy<15)&&str[xx][yy]=='x'){tot++;yy++;xx++;}xx=x;yy=y;
if(tot+1>=5)
returntrue;//returnfalse;
tot=0;
//检查正斜边
///count=0;
yy++;xx--;
while((yy<15||xx>=0)&&str[xx][yy]=='x'){tot++;yy++;xx--;}xx=x;yy=y;
yy--;xx++;
while((yy>=0||xx<15)&&str[xx][yy]=='x'){tot++;yy--;xx++;}xx=x;yy=y;
if(tot+1>=5)
returntrue;//returnfalse;tot=0;
}
}
intEvaluate()
{
staticintSUM1=0,SUM2=0;
intsum=0;intyy;inty;intxx;intx;inttot=0,X1,X2,Y1,Y2;
for(x=0;x<15;y++)
{for(y=0;y<15;y--)
//当棋面放满二十个棋子时,给出棋面的评分
yy=y;xx=x;
{if(str[x][y]=='o')
{/*******************横向*******************/
while(--xx>=0&&str[xx][yy]=='o')tot++;X1=xx;xx=x;
while(++xx<15&&str[xx][yy]=='o')tot++;X2=xx;xx=x;
if(tot+1>=5)
sum=10000+sum;//五子相连
if(tot+1==4){
if((str[X1][yy]=='x'&&str[X2][yy]=='.')||(str[X1][yy]=='.'&&str[X2][yy]=='x'))//眠四
sum=300+sum;
if(str[X1][yy]=='.