遗传算法Python实战004.八皇后问题

开通VIP,畅享免费电子书等14项超值服

首页

好书

留言交流

下载APP

联系客服

2023.04.21北京

本节我们主要讲解如何使用遗传算法解决八皇后问题

八皇后是算法界一个非常常见的问题,也经常用于各种大厂的面试中,题目如下:

在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法:

比如,我们在第一个位置上,放好一个皇后,那么蓝色的位置就不能在放置了:

只能在空白的地方挑选一个位置来放,比如:

之后,蓝色区域继续扩大,第三个也只能继续去找白色区域摆放:

比如下面就是其中的一种经典解法:

根据维基百科的说法,这个谜题只有92个答案,而把那些相似的变种(比如镜像和旋转)删掉,就只有12个特定的解决方案。

根据排列组合的算法,理论上皇后摆放的位置,有64×63×62×62×61×60×59×58×57中可能……我就不去计算了,如果不进行收敛而采用遍历的话,那几乎是一个不可能完成的任务。

如果用遗传算法来解决,我们会发现,每一次选择,不仅仅是个别基因的问题,而是会带来相互之间的约束,特别是算法不知道基因彼此之间的关系,我们就必须设计好各种约束条件。

前面几节的内容,有一个特点,就是基因本身的选择就是解决方案本身,所以我们只需要把选择结果进行比较,或者就展现出来就可以了。

但是很多的分析没有这么简单,他们有各式各样的约束和表达,所以在比较高的层次上,把最初的基因编码称之为基因型,而把最终形式称之为表型。

基因型是对问题的各个部分进行编码的方式,以便可以通过遗传算法以及功能函数对其进行操作。比如在八皇后问题上,基因型的示例如下:

表型就是如何使用已编/解码的基因来解决问题。比如在上面的每个示例中,表型如下:

首先还是一样,定义我们的基因库,这里用8个整数:0-7来表达就行:

size=8geneSet=[iforiinrange(size)]然后定义一个棋盘类,用来模拟棋盘:这个类一共有三个方法,分别是

classBoard:def__init__(self,genes,size):board=[['.']*sizefor_inrange(size)]forindexinrange(0,len(genes),2):row=genes[index]column=genes[index+1]board[column][row]='Q'self._board=boarddefget(self,row,column):returnself._board[column][row]defprint(self):foriinreversed(range(len(self._board))):print(''.join(self._board[i]))比如我构造这样一组基因组成的染色体:

x=[0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7]单数的索引代表列,双数的索引,代表行,这组染色体就表示把8个皇后全部摆在第0列上,运行结果如下:

Q.......Q.......Q.......Q.......Q.......Q.......Q.......Q.......或者都摆在第0行上(注意,国际象棋和中国象棋一样,下面表示朝向你这边的面,为起始行):

x=[0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0]运行结果如下:

defdisplay(candidate,startTime,size):timeDiff=datetime.datetime.now()-startTimeboard=Board(candidate.Genes,size)board.print()print("{0}\t-{1}\t{2}".format(''.join(map(str,candidate.Genes)),candidate.Fitness,str(timeDiff)))然后是老规矩的染色体类和进化变异函数:

从这里就可以看出遗传算法的鲁棒性来了,核心函数从来不用修改,在所有地方都适用

classChromosome:def__init__(self,genes,fitness):self.Genes=genesself.Fitness=fitnessdefmutate(parent):childGenes=parent.Genes[:]index=random.randrange(0,len(parent.Genes))newGene,alternate=random.sample(geneSet,2)childGenes[index]=alternateifnewGene==childGenes[index]elsenewGenefitness=get_fitness(childGenes,size)returnChromosome(childGenes,fitness)下面是最关键的健壮性验证方法,所有的遗传算法里面,这个方法都是最关键的,它用于评价你这次进化的效果好不好:

他的验证逻辑很简单:

可以看见,如果结果为0,则表示得到了正确的八皇后解。

defget_fitness(genes,size):board=Board(genes,size)rowsWithQueens=set()colsWithQueens=set()northEastDiagonalsWithQueens=set()southEastDiagonalsWithQueens=set()forrowinrange(size):forcolinrange(size):ifboard.get(row,col)=='Q':rowsWithQueens.add(row)colsWithQueens.add(col)northEastDiagonalsWithQueens.add(row+col)southEastDiagonalsWithQueens.add(size-1-row+col)total=size-len(rowsWithQueens)\+size-len(colsWithQueens)\+size-len(northEastDiagonalsWithQueens)\+size-len(southEastDiagonalsWithQueens)returntotal下面就是执行函数了:

defget_best():random.seed()startTime=datetime.datetime.now()x=[random.randint(0,7)foriinrange(size*2)]bestParent=Chromosome(x,get_fitness(x,size))ifbestParent.Fitness<=0:returnbestParentnum=0whileTrue:num+=1child=mutate(bestParent)ifbestParent.Fitness

下面我们把这个过程执行100次,看看结果:

最多一次,一共用了6200多次进化才得到正确解,而最好一次仅用了106次就完成了,所以说,遗传算法这种随机优化的算法,完全就是拼人品的干活,就像0杀吃鸡这种事情:

——虾神语录

题外话,8x8的棋盘上,最多可以放入8个皇后,那么NxN的棋盘上,放置N个皇后,又如何放置呢?

我们仅需要修改一下size,就可以了,比如我做一个20X20的棋盘,放置20个皇后:

..............Q..........Q......................Q............Q..................................Q................Q.......................Q....Q............................Q..............Q................Q..........................Q.............Q.................................Q................Q.............Q......................Q.......Q..........................Q...............................Q518817186123108711314190155392121615021419941166104711111713-00:00:01.335459总计发生了5204次进化,最终得到了这个20皇后的解,大家有兴趣的话,可以去尝试更多的方案。

THE END
1.2024年12月17日随笔档案木偶人怪咖摘要: 题目 Description 众所周知, “八皇后” 问题是求解在国际象棋棋盘上摆放 8 个皇后,使得两两之间互不攻击的方案数。已经学习了很多算法的小蓝觉得 “八皇后” 问题太简单了,意犹末尽。作为一个国际象棋迷,他想研究在 N×M 的棋盘上,摆放 K 个马,使得两两之间互不攻击有多少种摆放方案。由阅读全文https://www.cnblogs.com/wzx-RS-STHN/p/archive/2024/12/17
2.八皇后问题算法详解八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不https://www.jianshu.com/p/4fa6e29449a5
3.C语言回溯法解八皇后问题(八皇后算法)C语言C语言回溯法解八皇后问题(八皇后算法)更新时间:2021年12月28日 08:47:54 作者:是八阿哥不是bug 这篇文章介绍了C语言回溯法解八皇后问题,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下GPT4.0+Midjourney绘画+国内大模型 会员永久免费使用!【 如果你想靠AI翻身https://www.jb51.net/article/233081.htm
4.八皇后问题的两种解法java八皇后问题java算法八皇后问题的两种解法java 八皇后问题java算法 本题主要考察递归回溯! 一维数组解决八皇后问题思路: 1.用一维数组中的索引表示皇后所在的行,一维数组中的每个值表示皇后所在的列;a[i]=val表示第i+1个皇后放在第i+1行的第val+1列。 例如:a[0]=0表示第1个皇后放在第1行第1列;https://blog.51cto.com/u_14457/6524567
5.经典回溯算法——八皇后问题经典回溯算法——八皇后问题 八皇后问题是由19世纪数学家“搞死先生”(高斯先生)提出的,具体的问题是这样的: 在国际象棋的棋盘中(有8×8格)摆放8个皇后,这八个皇后不能相互攻击到(皇后的攻击方向很广:横着,竖着,斜着都能攻击),即8个皇后不能处于同行、同列、同一正反对角线上,这样就不能相互攻击到了。那么https://www.nowcoder.com/discuss/83692
6.八皇后问题入门指南:解密棋盘上的策略艺术八皇后问题是19世纪数学家卡尔·冯·本德利提出的经典谜题,涉及在一个8x8的国际象棋棋盘上放置8个皇后,确保任意皇后都不位于同一行、列或对角线上。文章深入探讨了问题的基础理解,包括棋盘布局限制、攻击条件解析,以及为何穷举法不是最优解。通过介绍回溯算法,文章提供了解决八皇后问题的高效方法,并指导如何将理论知识https://www.imooc.com/article/347049
7.8种人工智能算法求解八皇后问题+原理分析2 AI算法 2.1 局部贪婪搜索 2.2 随机行走爬山法 2.3 首选爬山法 2.4 随机重启爬山法 2.5 模拟退火算法 2.6 局部束搜索 2.7 随机束搜索 2.8 遗传算法 3 结果展示 1 问题描述 八皇后问题——在8×8格的国际象棋盘上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。 https://developer.aliyun.com/article/889745
8.小朋友学经典算法(14):回溯法和八皇后问题腾讯云开发者社区算法是逐行安排皇后的,其参数row为现在正执行到第几行。n是皇后数,在八皇后问题里当然就是8啦。 if(row == n)这句代码好理解,如果程序执行了row == n,说明从0到n-1的位置都放上了皇后,那自然是找到了一种解法,于是八皇后问题解法数加1。 否则进入else语句。遍历所有列col,将当前col存储在数组c里,然后https://cloud.tencent.com/developer/article/1373221
9.JAVA实现的八皇后问题java8皇后资源java 八皇后算法 需积分: 34 95 浏览量 2013-07-24 上传 评论 1 收藏 2KB JAVA 举报 立即下载 开通VIP(低至0.43/天) 买1年送1年 用JAVA实现的八皇后问题。学习JAVA时练手写的程序,分享下。我真是各种喜欢写八皇后算法资源推荐 资源评论 Java实现八皇后问题 浏览:108 4星 · 用户满意度95% 用Javahttps://download.csdn.net/download/amber_amber/5809065
10.科学网—经典的算法回顾回溯法(backtracking)是穷尽搜索算法(Brute-force search)中的一种。回溯法采用试错的思想,它尝试分步的去解决一个问题。如十九世纪著名的数学家高斯1850年提出八皇后问题的回溯法求解。在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通https://blog.sciencenet.cn/blog-315535-665392.html
11.算法学习与应用从入门到精通2.5.1 贪心算法基础 23 2.5.2 实践演练—解决“装箱” 问题24 2.5.3 实践演练—解决 “找零方案”问题 26 2.6 试探法算法思想 27 2.6.1 试探法算法基础 27 2.6.2 实践演练—解决 “八皇后”问题 28 2.6.3 实践演练—体彩29选 7彩票组合 29 2.7 迭代算法 30 2.7.1 迭代算法基础 30 2.7.2 实践演练—http://reader.hnlib.com/Book/Detail/377965
12.算法精粹:经典计算机科学问题的Python实现数字图书馆灯塔3.3 八皇后问题 3.4 单词搜索 3.5 字谜(SEND+MORE=MONEY) 3.6 电路板布局 3.7 现实世界的应用 3.8 习题 第4 章 图问题 4.1 地图就是图 4.2 搭建图的框架 4.3 查找最短路径 4.4 最小化网络构建成本 4.4.1 权重的处理 4.4.2 查找最小生成树 4.5 在加权图中查找最短路径 4.6 现实世界的应用 4.7 习题 https://www.dtdjzx.gov.cn/szlib/jykj/2817585.jhtml
13.算法精粹:经典计算机科学问题的Java实现PDF下载本书是一本面向中高级程序员的算法教程,借助Java语言,用经典的算法、编码技术和原理来求解计算机科学的一些经典问题。全书共10章,讲述了常见的搜索算法、常见的图算法、遗传算法、k均值聚类算法、简单的神经网络、对抗搜索算法等,通过丰富的方案、示例和习题展开具体实践。本书将计算机科学与应用程序、数据、性能等现实http://www.java1234.com/a/javabook/javabase/2024/0425/25187.html
14.《算法分析与设计》教学大纲第八章基于搜索的算法设计技术 1.教学基本要求 掌握利用回溯法解决问题的基本思想,并能用此方法解法实际的应用问题。 2.要求学生掌握的基本概念、理论、技能 通过本章教学使学生了回溯算法的设计思想、时间性能,能够用回溯法解决:n个皇后问题,图的m着色问题,批处理作业调度问题等,并能准确地分析回溯法的效率及稳定https://jsj.xxu.edu.cn/images/jxdg/jsjkxyjs/2013/0611102103.htm