一. 实验问题简介
问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
本次实验利用遗传算法求解八皇后问题的一个可行解。
二. 实验语言及算法
- 实验语言: C++
- 实验算法: 遗传算法
三. 实验思路
- Random_formation函数
杂交:利用初始化的两个父辈通过进行杂交,将通过父辈从某随机一点进行割分,通过两个for循环交换各部分拼接起来,生成两个子辈。(一代繁殖共生成16个子辈)
变异:利用随机函数分别生成两个生成子辈的随机变异结点进行随机变异(单点变异)。 - Fit_func函数
该函数将一个子辈序列作为输入,利用二重循环依次判断每个序列结点的不相互攻击皇后对数目,即(abs(son[i]-son[j])==abs(i-j))||(son[i]==son[j])。 - Heredity函数
该函数生成两个随机父辈,通过对这两个父辈利用random_formation函数进行杂交和变异生成两个子辈结果,并对其进行适应度计算,总共一代16个子辈,重复该过程8次。
对这一代的结果进行适应度排序,选出最优的两个子辈作为父辈进行下一代杂交繁殖。
结束出口,当当前父辈的适应度为28时,即符合八皇后问题条件,进行循环结束,并将其输出。 - 选择函数
本次实验使用最佳保留选择,选出最佳的子辈作为父辈。
四. 实验结果及分析
- 实验结果()
<——————初始化第一代繁殖种群结果——————>
父辈序列 8 5 6 6 4 3 1 2
母辈序列 5 3 2 1 5 1 6 6
<——————开始随机繁殖——————>
结束繁殖代数:13505
<——————最终繁殖结果序列——————>
3 5 2 8 1 7 4 6
<——————最终繁殖适应度——————>
28
第1次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 4 6 8 6 4 8 4 3
母辈序列 1 2 1 2 1 5 8 8
<——————开始随机繁殖——————>
结束繁殖代数:4180
<——————最终繁殖结果序列——————>
6 3 7 4 1 8 2 5
<——————最终繁殖适应度——————>
28
第2次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 7 6 3 7 4 4 7 3
母辈序列 6 2 8 2 4 1 2 2
<——————开始随机繁殖——————>
结束繁殖代数:9957
<——————最终繁殖结果序列——————>
1 6 8 3 7 4 2 5
<——————最终繁殖适应度——————>
28
第3次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 2 6 6 7 3 8 2 3
母辈序列 2 1 6 3 8 5 5 4
<——————开始随机繁殖——————>
结束繁殖代数:14896
<——————最终繁殖结果序列——————>
8 2 4 1 7 5 3 6
<——————最终繁殖适应度——————>
28
第4次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 1 6 3 8 2 8 8 3
母辈序列 3 7 4 4 8 5 1 8
<——————开始随机繁殖——————>
结束繁殖代数:5795
<——————最终繁殖结果序列——————>
6 3 7 2 4 8 1 5
<——————最终繁殖适应度——————>
28
第5次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 4 6 5 1 2 4 2 3
母辈序列 7 7 2 5 4 1 4 2
<——————开始随机繁殖——————>
结束繁殖代数:14357
<——————最终繁殖结果序列——————>
4 1 5 8 2 7 3 6
<——————最终繁殖适应度——————>
28
第6次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 7 7 8 1 2 8 5 4
母辈序列 4 6 1 6 8 5 6 5
<——————开始随机繁殖——————>
结束繁殖代数:4657
<——————最终繁殖结果序列——————>
2 5 7 1 3 8 6 4
<——————最终繁殖适应度——————>
28
第7次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 3 7 2 2 1 4 8 4
母辈序列 8 5 8 7 4 2 8 7
<——————开始随机繁殖——————>
结束繁殖代数:27492
<——————最终繁殖结果序列——————>
5 2 4 6 8 3 1 7
<——————最终繁殖适应度——————>
28
第8次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 6 7 5 2 1 8 3 4
母辈序列 5 5 7 7 8 6 3 1
<——————开始随机繁殖——————>
结束繁殖代数:8927
<——————最终繁殖结果序列——————>
6 8 2 4 1 7 5 3
<——————最终繁殖适应度——————>
28
第9次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 1 7 8 2 8 4 6 4
母辈序列 1 4 5 8 4 2 5 3
<——————开始随机繁殖——————>
结束繁殖代数:7984
<——————最终繁殖结果序列——————>
1 6 8 3 7 4 2 5
<——————最终繁殖适应度——————>
28
第10次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 8 7 5 3 8 5 4 4
母辈序列 2 3 3 2 4 2 2 7
<——————开始随机繁殖——————>
结束繁殖代数:870
<——————最终繁殖结果序列——————>
2 7 5 8 1 4 6 3
<——————最终繁殖适应度——————>
28
第11次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 3 8 7 4 7 1 7 5
母辈序列 6 2 2 2 8 6 4 1
<——————开始随机繁殖——————>
结束繁殖代数:5169
<——————最终繁殖结果序列——————>
3 6 8 1 4 7 5 2
<——————最终繁殖适应度——————>
28
第12次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 6 8 2 4 7 5 1 5
母辈序列 3 1 8 3 4 2 6 3
<——————开始随机繁殖——————>
结束繁殖代数:3568
<——————最终繁殖结果序列——————>
4 1 5 8 2 7 3 6
<——————最终繁殖适应度——————>
28
第13次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 1 8 4 5 6 1 4 5
母辈序列 7 1 7 4 8 6 1 5
<——————开始随机繁殖——————>
结束繁殖代数:25576
<——————最终繁殖结果序列——————>
6 3 1 7 5 8 2 4
<——————最终繁殖适应度——————>
28
第14次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 5 8 7 5 6 5 7 5
母辈序列 3 8 6 4 4 2 3 7
<——————开始随机繁殖——————>
结束繁殖代数:9063
<——————最终繁殖结果序列——————>
3 5 2 8 1 7 4 6
<——————最终繁殖适应度——————>
28
第15次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 8 8 2 6 6 1 2 5
母辈序列 8 7 4 5 7 6 5 1
<——————开始随机繁殖——————>
结束繁殖代数:5606
<——————最终繁殖结果序列——————>
5 7 2 6 3 1 8 4
<——————最终繁殖适应度——————>
28
第16次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 3 8 4 6 5 5 5 5
母辈序列 4 7 3 6 3 2 7 4
<——————开始随机繁殖——————>
结束繁殖代数:3268
<——————最终繁殖结果序列——————>
4 2 5 8 6 1 3 7
<——————最终繁殖适应度——————>
28
第17次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 2 1 1 7 4 5 3 6
母辈序列 5 5 1 7 3 2 4 8
<——————开始随机繁殖——————>
结束繁殖代数:11993
<——————最终繁殖结果序列——————>
2 7 5 8 1 4 6 3
<——————最终繁殖适应度——————>
28
第18次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 5 1 4 7 4 1 6 6
母辈序列 1 4 7 8 7 6 6 2
<——————开始随机繁殖——————>
结束繁殖代数:699
<——————最终繁殖结果序列——————>
4 2 7 3 6 8 1 5
<——————最终繁殖适应度——————>
28
第19次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 8 1 7 8 3 6 1 6
母辈序列 6 4 6 1 3 2 1 4
<——————开始随机繁殖——————>
结束繁殖代数:3698
<——————最终繁殖结果序列——————>
3 6 2 7 1 4 8 5
<——————最终繁殖适应度——————>
28
第20次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 4 1 1 8 3 2 3 6
母辈序列 2 3 5 2 7 6 3 6
<——————开始随机繁殖——————>
结束繁殖代数:4911
<——————最终繁殖结果序列——————>
2 5 7 1 3 8 6 4
<——————最终繁殖适应度——————>
28
第21次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 7 1 4 1 3 6 6 6
母辈序列 7 2 4 2 3 2 5 8
<——————开始随机繁殖——————>
结束繁殖代数:12138
<——————最终繁殖结果序列——————>
3 5 2 8 1 7 4 6
<——————最终繁殖适应度——————>
28
第22次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 2 2 6 1 2 2 1 7
母辈序列 3 2 2 3 7 6 8 2
<——————开始随机繁殖——————>
结束繁殖代数:2425
<——————最终繁殖结果序列——————>
6 3 7 4 1 8 2 5
<——————最终繁殖适应度——————>
28
第23次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 5 2 1 2 2 6 4 7
母辈序列 7 1 1 4 3 2 2 4
<——————开始随机繁殖——————>
结束繁殖代数:8015
<——————最终繁殖结果序列——————>
4 2 5 8 6 1 3 7
<——————最终繁殖适应度——————>
28
第24次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 1 2 3 2 1 2 7 7
母辈序列 4 8 8 4 7 6 4 6
<——————开始随机繁殖——————>
结束繁殖代数:28086
<——————最终繁殖结果序列——————>
7 4 2 8 6 1 3 5
<——————最终繁殖适应度——————>
28
第25次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 4 2 6 3 1 6 2 7
母辈序列 8 8 7 5 3 2 7 8
<——————开始随机繁殖——————>
结束繁殖代数:3297
<——————最终繁殖结果序列——————>
5 7 1 4 2 8 6 3
<——————最终繁殖适应度——————>
28
第26次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 7 2 1 3 1 2 5 7
母辈序列 5 7 5 6 7 6 1 3
<——————开始随机繁殖——————>
结束繁殖代数:1503
<——————最终繁殖结果序列——————>
3 6 8 1 4 7 5 2
<——————最终繁殖适应度——————>
28
第27次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 2 2 3 3 8 6 8 7
母辈序列 1 6 4 7 3 3 3 5
<——————开始随机繁殖——————>
结束繁殖代数:5789
<——————最终繁殖结果序列——————>
1 5 8 6 3 7 2 4
<——————最终繁殖适应度——————>
28
第28次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 6 3 6 4 8 2 2 8
母辈序列 6 6 3 7 6 7 6 7
<——————开始随机繁殖——————>
结束繁殖代数:10534
<——————最终繁殖结果序列——————>
6 3 1 7 5 8 2 4
<——————最终繁殖适应度——————>
28
第29次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 1 3 8 4 7 6 5 8
母辈序列 2 5 1 8 2 3 8 1
<——————开始随机繁殖——————>
结束繁殖代数:3
<——————最终繁殖结果序列——————>
6 3 1 7 5 8 2 4
<——————最终繁殖适应度——————>
28
第30次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 8 3 5 5 7 7 3 8
母辈序列 3 4 7 2 2 3 5 5
<——————开始随机繁殖——————>
结束繁殖代数:1210
<——————最终繁殖结果序列——————>
5 7 1 3 8 6 4 2
<——————最终繁殖适应度——————>
28
第31次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 3 3 8 6 6 3 6 8
母辈序列 7 3 6 2 6 7 7 7
<——————开始随机繁殖——————>
结束繁殖代数:19317
<——————最终繁殖结果序列——————>
7 4 2 8 6 1 3 5
<——————最终繁殖适应度——————>
28
第32次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 6 4 3 6 6 7 1 8
母辈序列 4 2 4 3 2 3 1 1
<——————开始随机繁殖——————>
结束繁殖代数:10289
<——————最终繁殖结果序列——————>
4 2 8 5 7 1 3 6
<——————最终繁殖适应度——————>
28
第33次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 1 4 5 7 5 3 4 8
母辈序列 8 1 3 4 6 7 4 3
<——————开始随机繁殖——————>
结束繁殖代数:6268
<——————最终繁殖结果序列——————>
4 7 1 8 5 2 6 3
<——————最终繁殖适应度——————>
28
第34次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 5 4 8 7 5 7 7 1
母辈序列 4 1 2 4 2 3 6 5
<——————开始随机繁殖——————>
结束繁殖代数:7596
<——————最终繁殖结果序列——————>
7 3 1 6 8 5 2 4
<——————最终繁殖适应度——————>
28
第35次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 8 4 2 8 4 3 1 1
母辈序列 1 8 1 5 6 7 8 7
<——————开始随机繁殖——————>
结束繁殖代数:12533
<——————最终繁殖结果序列——————>
6 3 1 7 5 8 2 4
<——————最终繁殖适应度——————>
28
第36次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 3 4 5 8 4 7 4 1
母辈序列 5 7 7 6 2 3 3 2
<——————开始随机繁殖——————>
结束繁殖代数:2
<——————最终繁殖结果序列——————>
6 3 1 7 5 8 2 4
<——————最终繁殖适应度——————>
28
第37次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 6 4 7 8 4 3 7 1
母辈序列 2 7 6 7 6 7 5 4
<——————开始随机繁殖——————>
结束繁殖代数:17019
<——————最终繁殖结果序列——————>
6 8 2 4 1 7 5 3
<——————最终繁殖适应度——————>
28
第38次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 2 5 2 1 3 7 2 1
母辈序列 6 6 5 7 2 3 7 6
<——————开始随机繁殖——————>
结束繁殖代数:12229
<——————最终繁殖结果序列——————>
4 2 5 8 6 1 3 7
<——————最终繁殖适应度——————>
28
第39次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 5 5 5 1 3 4 5 1
母辈序列 2 5 3 8 6 7 2 8
<——————开始随机繁殖——————>
结束繁殖代数:1099
<——————最终繁殖结果序列——————>
8 2 4 1 7 5 3 6
<——————最终繁殖适应度——————>
28
第40次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 8 5 7 2 2 8 8 2
母辈序列 7 5 2 1 2 3 4 2
<——————开始随机繁殖——————>
结束繁殖代数:2
<——————最终繁殖结果序列——————>
8 2 4 1 7 5 3 6
<——————最终繁殖适应度——————>
28
第41次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 3 5 2 2 2 4 3 2
母辈序列 3 4 1 2 6 7 6 4
<——————开始随机繁殖——————>
结束繁殖代数:34211
<——————最终繁殖结果序列——————>
4 7 1 8 5 2 6 3
<——————最终繁殖适应度——————>
28
第42次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 2 5 7 3 1 4 8 2
母辈序列 4 3 6 3 5 7 3 8
<——————开始随机繁殖——————>
结束繁殖代数:18148
<——————最终繁殖结果序列——————>
6 3 1 7 5 8 2 4
<——————最终繁殖适应度——————>
28
第43次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 5 6 1 4 1 8 3 2
母辈序列 8 2 5 4 1 3 5 2
<——————开始随机繁殖——————>
结束繁殖代数:2
<——————最终繁殖结果序列——————>
6 3 1 7 5 8 2 4
<——————最终繁殖适应度——————>
28
第44次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 1 6 4 4 8 4 6 2
母辈序列 5 1 4 4 5 7 8 4
<——————开始随机繁殖——————>
结束繁殖代数:6322
<——————最终繁殖结果序列——————>
6 8 2 4 1 7 5 3
<——————最终繁殖适应度——————>
28
第45次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 4 6 7 5 8 8 1 3
母辈序列 1 1 3 5 1 3 2 6
<——————开始随机繁殖——————>
结束繁殖代数:6371
<——————最终繁殖结果序列——————>
3 6 2 7 1 4 8 5
<——————最终繁殖适应度——————>
28
第46次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 7 6 1 5 8 4 4 3
母辈序列 6 8 1 6 5 8 4 1
<——————开始随机繁殖——————>
结束繁殖代数:21843
<——————最终繁殖结果序列——————>
7 4 2 8 6 1 3 5
<——————最终繁殖适应度——————>
28
第47次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 2 6 4 5 7 8 7 3
母辈序列 2 7 8 7 1 4 7 3
<——————开始随机繁殖——————>
结束繁殖代数:6391
<——————最终繁殖结果序列——————>
4 2 8 5 7 1 3 6
<——————最终繁殖适应度——————>
28
第48次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 6 6 6 6 7 4 2 3
母辈序列 6 7 7 7 5 8 1 5
<——————开始随机繁殖——————>
结束繁殖代数:1364
<——————最终繁殖结果序列——————>
3 6 8 1 4 7 5 2
<——————最终繁殖适应度——————>
28
第49次模拟结束
<——————初始化第一代繁殖种群结果——————>
父辈序列 1 7 1 6 6 1 5 3
母辈序列 3 6 5 8 1 4 3 7
<——————开始随机繁殖——————>
结束繁殖代数:16407
<——————最终繁殖结果序列——————>
4 1 5 8 2 7 3 6
<——————最终繁殖适应度——————>
28
第50次模拟结束
遗传算法运行平均时间:0.090240
- 性能分析
本次实验由于利用随机模拟来寻找最佳值,因此无法较难从理论分析其性能,因此利用重复循环运行Heredity函数统计多次运行的时间,求取平均时间,得到运行性能时间如图2所示。
五,实验代码
/*
2021/04/07
YNU-LSL code
*/
#include<bits/stdc++.h>
#include<unistd.h>
using namespace std;
#define N 8
#define M 3000
int son[N][N];
typedef struct
{
int v;int in;
}node;
bool cmp(const node x,const node y)
{
return x.v>y.v;
}
int fa[9];int ma[9];int result[55][10];
/*杂交变异过程函数*/
void random_formation(int k,int son[N][N])
{
/*<————杂交————>*/
int i = rand()%8+1;
for(int j=1;j<=i;j++)
{
son[k][j]=fa[j];
son[k+1][j]=ma[j];
}
for(int j=i+1;j<=N;j++)
{
son[k][j]=ma[j];
son[k+1][j]=fa[j];
}
/*<————变异————>*/
i = rand()%8+1;int j=rand()%8+1;
son[k][i]=(rand()%8+1),son[k+1][j]=(rand()%8+1);
}
/*适应度函数*/
int fit_func(int son[9])
{
int res=0;
for(int i=1;i<=8;i++)
{
for(int j=i+1;j<=8;j++)
{
if((abs(son[i]-son[j])==abs(i-j))||(son[i]==son[j]))
{
res++;
}
}
}
return 28-res;
}
/*遗传函数*/
ofstream file;
void heredity(int cts)
{
srand(time(0));
int f[9],m[9];node s[N*2];
for(int i=1;i<=N*2;i++)
s[i].in=0,s[i].v=0;
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
son[i][j]=j;
for(int i=1;i<=N;i++)
{
f[i]=rand()%8+1;
m[i]=rand()%8+1;
}
int k=1;
/*//random_formation(f,m,1);
for(int i=1;i<=N;i++)
cin>>son[1][i];
int v = fit_func(son[1]);
printf("s_V:%d",v);*/
printf("<——————初始化第一代繁殖种群结果——————>\n");
printf("父辈序列\t");
for(int i=1;i<=N;i++)
printf("%d ",f[i]);
printf("\n");
printf("母辈序列\t");
for(int i=1;i<=N;i++)
printf("%d ",m[i]);
printf("\n");
printf("<——————开始随机繁殖——————>\n");
for(int i=1;i<=k*M;i++)
{
//if(i%1000==0)
// printf("<——————第%d代繁殖——————>\n",i);
if(s[1].v==28) {printf("结束繁殖代数:%d\n",i);break;}
else if(i==k*M) k++;
for(int j=1;j<=2*N;j+=2)
{
random_formation(j,son);
s[j].v=fit_func(son[j]);
s[j+1].v=fit_func(son[j+1]);
s[j].in=j;
s[j+1].in=j+1;
}
sort(s+1,s+N*2+1,cmp);
for(int j=1;j<=N;j++)
f[j]=son[s[1].in][j];
for(int j=1;j<=N;j++)
m[j]=son[s[2].in][j];
}
printf("<——————最终繁殖结果序列——————>\n");
file<<'[';
for(int i=1;i<=N;i++)
{
file<<f[i];
result[cts][i]=f[i];
printf("%d ",result[cts][i]);
}
file<<']'<<endl<<endl;
printf("\n");
printf("<——————最终繁殖适应度——————>\n");
printf("%d\n",s[1].v);
printf("第%d次模拟结束\n",cts);
}
clock_t start,stop;
int main()
{
//时间作随机种子
double sumt=0;
file.open("results.txt");
for(int i=1;i<=50;i++)
{
start = clock();
heredity(i);
stop = clock();
sleep(1);
sumt+=((double)(stop-start)*10);
}
file.close();
printf("遗传算法运行平均时间:%lf\n",(double)((sumt)/500000));
printf("<——————统计所有产生结果——————>\n");
/*莫名错误???不明白为啥会输出数组保存结果不一样*/
/*for(int i=1;i<=50;i++)
{
printf("[");
for(int j=1;j<=N;j++)
file<<;
printf("]\n");
}*/
return 0;
}