变异算子个体发生变异的概率为参数PMUTATION。当一个个体发生变异时,随机选择序列中一个基因与其相邻基因交换。
其他部分
数据输入为直接读取城市距离矩阵文本,本例中为ctsp.txt;
数据输出格式为:每代的最佳适应度,平均适应度和标准差,最终结果序列和相关参数。文件名galog.txt。
程序结构概要
#define CITYSIZE 31 /* 城市规模*/ #define POPSIZE 100 /* 种群大小*/ #define MAXGENS 20000 /* 最大代数*/ #define PXOVER 0.1 /* 交叉概率*/ #define PMUTATION 0.05 /* 突变概率*/ double citys[CITYSIZE][CITYSIZE]; /* 城市数据*/
struct genotype /*个体基因组*/ int path[CITYSIZE] double fitness /* 适应度*/ double rfitness /* 相对适应度*/ double cfitness /* 累积适应度*/
void initialize(void); /* 初始化 */
void randpath(genotype >); /* 产生随机路径 */ void evaluate(void); /* 计算适应度 */ void keep_the_best(void); /* 保留最优个体 */ void elitist(void); /* 保留最优个体 */ void swap(int &, int &); /* 交换 */ void select(void); /* 选择 */ void crossover(void); /* 交叉 */
void Xover(int,int); /* 顺序交叉,由crossover()函数调用 */ void mutate(void); /* 突变 */
void report(void); /* 报告,用于输出结果数据 */
测试及参数调整
在程序编写阶段,我们使用了10*10(GADATA),11*11(GADATA2),和20*20(GADATA3)的矩阵作为测试数据。由于基因太少,数值太小。在此不作讨论。
对于目标题目的数据,我们固定POPSIZE=100,作了针对交叉概率PXOVER和变异概率PMUTATION的测试,调整这两个参数,然后看相同MAXGEN = 10000之下的收敛状况。因为有随机性存在,每组参数我们都做3次测试,收敛性好的参数组做5次测试,以保证准确性。实验数据记录于testlog.txt。
最后我们发现,PXOVER = 0.1,PMUTATION = 0.01,MAXGEN = 20000时所得的解20310km是测试记录中最低的,而且在18000代左右就收敛到该值,比其他参数收敛更快,而且能多次重现,证明这组参数在解决本题目时可作为最佳参数。而20310km是最优解。测试数据分析如图:
PXOVER=0.1,PMUTATION=0.01,MAXGEN=20000best valueaverage fitnessstandard deviation700006000050000Fitness40000300002000010000012001400160018001Generation1000112001140011600118001
遇到的问题
在POPSIZE = 100时,概率为0.05,0.1或是0.2在群体中产生的影响是很小的,但是实验参数的小波动对于实验结果却有很大影响,甚至当MAXGEN = 50000,也无法收敛到接近最优的值,其中的原因涉及遗传算法的一些弱点,仍待深究。
总结
本次实验中,我们实现了用遗传算法解决旅行商问题。实验了遗传算法中算子选择和参数调整对于算法收敛性的影响。
遗传算法在解决TSP问题时体现了以下优越性:
1. 模块化结构是遗传算法的先天优越性,对于简单的TSP问题,程序编写难度不大,也可以尝试
各种不同的算子设计,寻求更优化的程序。 2. 容易测试和调整参数,寻找最优解答。