python博弈树_博弈树alpha-beta剪枝搜索的五子棋AI

更新时间:2023-07-14 22:17:55 阅读: 评论:0

python博弈树_博弈树alpha-beta剪枝搜索的五⼦棋AI
最近机器学习很⽕, 乘着这把⽕,我也学习了⼀把,但是没有直接学习深度学习,⽽是遵从⼀位⽼前辈,⼀定要把⼈⼯智能的所有⽅法都了解掌握了,才能真正的掌握⼈⼯智能。。。 我只能说, 路漫漫。。
对于博弈类⼈⼯智能,其中⼀个⽅法就是:博弈树极⼤极⼩值alpha-beta剪枝搜索。
是不是觉得这个名字很⽜逼, 但经过我的详细解读, 你马上就会发现,原来不过如此。
对于要实现⼀个会智能下五⼦棋的AI,要怎么去实现呢?⾃然想到的⽅法就是,让计算机把每⼀步的可能性都试⼀遍,看⾛在那效果最好。其实就是搜索的⽅法,搜索所有的下⼀步可能性,择优选择。这就是博弈树搜索。
博弈树搜索
什么是博弈树搜素呢?博弈就是相互采取最优策略⽃争的意思。⽐如说下五⼦棋,你下⼀步,我下⼀步,这就是相互博弈。假设棋盘的⼤⼩是10*10,那就是100个点可以下, 那么第⼀步可选择的可能就是100, 假设是下在了A点, 那么第⼆步就有除了A点的剩下的99个点的可能。 假设下在了B点, 那么第⼆步就有除了B点的剩下的99个点的可能,假设下在了C点...
看到没有, 我上⾯的假设可以复制100次, 同时基于其中的⼀个点,第⼆步⼜可以复制99次, 以此类推,就构成了⼀个树状的结构:Paste_Image.png
好了, 问题来了, 这么多可能性, ⾛哪⼀步才是最优的呢? 这就是下⼀步,极⼤极⼩值搜索。
极⼤极⼩值搜索
对于⼀个棋局, 判断它对我来说是占优势还是劣势, 能不能⽤个⽐较确定的数值来评估呢?答案是可以的。 对于五⼦棋就是统计⽬前的棋型,并累加分数。 ⽐如如果有4个⼦连起来了, 那就给个很⾼的评分,因为下⼀步就可以赢了, 如果是3个⼦连起来了,给个相对较低的评分,因为不⼀定就能赢,对⽅会堵你呢, 但是⽐只有2 个⼦连在⼀起的得分要⾼吧, 如是就有了下⾯的棋型评分表:
# 棋型的评估分数
shape_score = [(50, (0, 1, 1, 0, 0)),
(50, (0, 0, 1, 1, 0)),
(200, (1, 1, 0, 1, 0)),
(500, (0, 0, 1, 1, 1)),
(500, (1, 1, 1, 0, 0)),
(5000, (0, 1, 1, 1, 0)),
(5000, (0, 1, 0, 1, 1, 0)),
(5000, (0, 1, 1, 0, 1, 0)),
(5000, (1, 1, 1, 0, 1)),
(5000, (1, 1, 0, 1, 1)),
婚姻法案例
(5000, (1, 0, 1, 1, 1)),
(5000, (1, 1, 1, 1, 0)),
(5000, (0, 1, 1, 1, 1)),
(50000, (0, 1, 1, 1, 1, 0)),
(99999999, (1, 1, 1, 1, 1))]
这篇⽂章的⽰例是⽤python代码实现, 上⾯是我列出的⼀些常见的五⼦棋形状,1代表有⼦落在此处,0代表是空位,下⼀步可以下在此处。 前⾯是对应的分值。
那么对应评估局⾯上的分数, 就是统计所有匹配的棋型得分并累加。这个分数的统计就叫做评估函数,⽽这个评估函数的好坏是⾮常重要的, 下⾯的算法都是固定的,任何博弈类游戏都适合, 但评估函数就千差万别了。
# 评估函数
def evaluation(is_ai):
total_score = 0
if is_ai:
my_list = list1葱青
enemy_list = list2
el:
京杭大运河始建于
my_list = list2
enemy_list = list1
# 算⾃⼰的得分
score_all_arr = [] # 得分形状的位置 ⽤于计算如果有相交 得分翻倍
my_score = 0
for pt in my_list:
m = pt[0]
n = pt[1]
my_score += cal_score(m, n, 0, 1, enemy_list, my_list, score_all_arr)
my_score += cal_score(m, n, 1, 0, enemy_list, my_list, score_all_arr)
my_score += cal_score(m, n, 1, 1, enemy_list, my_list, score_all_arr)
my_score += cal_score(m, n, -1, 1, enemy_list, my_list, score_all_arr)
# 算敌⼈的得分, 并减去
score_all_arr_enemy = []
enemy_score = 0
for pt in enemy_list:
名片样式m = pt[0]
n = pt[1]
enemy_score += cal_score(m, n, 0, 1, my_list, enemy_list, score_all_arr_enemy)
enemy_score += cal_score(m, n, 1, 0, my_list, enemy_list, score_all_arr_enemy)
enemy_score += cal_score(m, n, 1, 1, my_list, enemy_list, score_all_arr_enemy)
enemy_score += cal_score(m, n, -1, 1, my_list, enemy_list, score_all_arr_enemy)
total_score = my_score - enemy_score*ratio*0.1
return total_score
对于AI要⾛在那⾥最好,那就是计算它在⾛在某⼀个点后, 计算局⾯的得分,然后取得分最⼤的那个点,不就是最应该下的点吗? so easy! 这就是极⼤值搜索。
但不要忘了, 你这是只考虑了⼀步啊, 搜索的深度只有1, 没听说⽼谋深算的家伙都是考虑3步的吗, 也就是要考虑下了这⼀步后,对⼿下⼀步会怎么下。对⼿不傻,肯定会在我得分最⼩的那个点上下, 这个得分是相对于我⽽⾔的,我的得分最⼩, 那就是对⼿的最优策略了, 这就是极⼩值搜索。
Paste_Image.png
AI要考虑3步的话, 那就是搜索深度为3,那就是搜索落在那个点,3步后得分最⼤。这就可以和看能看3步棋的⽼家伙对抗了。
关于极⼤极⼩值的伪代码(注意是伪代码,不是本⽂的⽰例的python代码):
这⾥⾯有递归,相信能很好理解吧。
int MinMax(int depth) { // 函数的评估都是以⽩⽅的⾓度来评估的
if (SideToMove() == WHITE) { // ⽩⽅是“最⼤”者
return Max(depth);狐狸尾巴歇后语
} el {           // ⿊⽅是“最⼩”者
return Min(depth);
}
}
int Max(int depth) {
int best = -INFINITY;
if (depth <= 0) {
return Evaluate();
}
为学校设计一个吉祥物GenerateLegalMoves();
while (MovesLeft()) {
MakeNextMove();
val = Min(depth - 1);
UnmakeMove();
if (val > best) {
best = val;
}
}
return best;
}
int Min(int depth) {
int best = INFINITY; // 注意这⾥不同于“最⼤”算法
if (depth <= 0) {
return Evaluate();
}
GenerateLegalMoves();
while (MovesLeft()) {
MakeNextMove();
val = Max(depth - 1);
UnmakeMove();
if (val < best) {  // 注意这⾥不同于“最⼤”算法
best = val;
}
}
return best;
}
到这⾥, 感觉不就完了吗?可以和⽼家伙⼀决⾼下了? 这就错了, 忽略了⼀个很重要的问题, 就是搜索的计算量, 你以为计算机是机器,cpu是 intel i7就瞬间完成计算啊, 这个博弈树,之所以叫树,那么他的枝点的数量,是以指数增长的,搜索深度3和搜索深度5那计算量差的可不是⼏倍的概念。⽽是差指数倍的概念。 所以虽然五⼦棋棋盘没围棋⼤, 但是按照这种全部可能性都搜索的⽅法去搜索,是要死电脑的。
于是,聪明的⼈对其进⾏了优化, 这就是alpha-beta剪枝搜索。
alpha-beta剪枝搜索
假设博弈树的搜索情况如下图:
Paste_Image.png
α为已知的最⼤值, β为已知的最⼩值, 因为还没搜索不知道是多少,保险起见,初始化为-∞ 和+∞。
搜索到D的时候,局⾯得分是5,(顺便说⼀句,这样的搜索是深度优先搜索,什么是深度优先搜索,可百度)那么也就是说要搜索最⼤值,那么只可能会在(5,+∞) 之间, 同理,要搜索最⼩值,也只会在(-∞,5)之间。
继续搜索, 搜索到G时,F暂时等于6 ,F是要找最⼤值, 那么F不可能再⼩于6了, ⽽B是要找最⼩值的,B的已知最⼩值是在(-∞,5)之间的, 你F还不可能⽐6⼩了, 我还要搜索你F后⾯的情况⼲嘛?不是浪费时间吗, 于是果断咔嚓掉F这个分⽀,不搜索了, 这就是剪枝。
同样对于另外⼀边的已知可能的极限范围β也是⼀样的情况,遇到就算是搜索也是浪费时间的情况,就剪枝不搜索了。
这样就减少了很多不必要是搜索步骤, 特别是⼀开始就找到最有可能的极⼤极⼩值, 更能迅速的剪枝。 怎么⼀开始尽快的找到可能的极⼤极⼩值呢, 后⾯再说。 先插播⼀下,负值极⼤法。
负值极⼤法
上⾯的伪代码有求极⼤值, 极⼩值, 还要两个函数, 其实都求各⾃的最⼤值, 这个各⾃的最⼤值是值, 都站在⾃⼰的⼀⽅来求最⼤值,对⼿的最⼤值前⾯加个负号,不就是对我来说的最⼩值吗? 有点绕, 但道理相信很容易理解, 这样的好处就是把求最⼤最⼩值写在⼀个函数⾥了, 看代码:
# 负值极⼤算法搜索 alpha + beta剪枝
def negamax(is_ai, depth, alpha, beta):
# 游戏是否结束 | | 探索的递归深度是否到边界
if game_win(list1) or game_win(list2) or depth == 0:
return evaluation(is_ai)
blank_list = list(t(list_all).difference(t(list3)))
order(blank_list) # 搜索顺序排序 提⾼剪枝效率
# 遍历每⼀个候选步
for next_step in blank_list:
global arch_count
arch_count += 1
# 如果要评估的位置没有相邻的⼦, 则不去评估 减少计算
if not has_neightnor(next_step):
continue
if is_ai:
list1.append(next_step)
el:
list2.append(next_step)
list3.append(next_step)
value = -negamax(not is_ai, depth - 1, -beta, -alpha)
if is_ai:
el:
if value > alpha:
print(str(value) + "alpha:" + str(alpha) + "beta:" + str(beta)) print(list3)
if depth == DEPTH:
next_point[0] = next_step[0]
next_point[1] = next_step[1]
# alpha + beta剪枝点
if value >= beta:
global cut_count
cut_count += 1
return beta
alpha = value
return alpha
变的作文
梦见打架是什么意思此处实际的代码可能不太好理解,上伪代码应该好看些,如下:

本文发布于:2023-07-14 22:17:55,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1096811.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:搜索   评估   深度   可能   博弈   得分   代码   计算
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图