遗传算法(GA)解决旅行商问题–C
思路
给出常数:城市数量、变异概率、种群数、子群数,父代传递比例
随机生成城市距离矩阵,将经过城市的顺序作为基因序列进行编码,适应度和走过n个城市的总距离成反比。
先随机构建出第一批种群的个体,按照父代传递比例按适应度从高到底选出个体复制进子群(我选的是0.2),之后子群其他个体通过父代种群进行杂交和变异生成,杂交的可能性和适应度呈正比,我使用了一个线性函数计算可能性,函数代码如下
double SelectFunction(Cell c)
{
//基因更优秀的更容易被选中
double longth=c.longth;
double k=(double)1/(Group[GROUP_NUM-1].longth-Group[0].longth);
return 1-(k*(longth-Group[0].longth));
}
就是一个x从种群最短路径到最长路径,y从1到0的一次函数
按上面的函数选出父母之后进行杂交,父亲的基因随机插入到母亲的基因序列中,插入的过程分为两个部分,先敲除,再插入。其实就是数组的插入删除数据。代码如下:
int GeneSearch(Cell c,int x)
{
if (x<0||x>=CITY_NUM)
{
printf("Error");
return -1;
}
for(int i=0; i<CITY_NUM; i++)
{
if(c.mypath[i]==x)
return i;
}
}
void GeneKnockout(Cell &c,int x)
{
int loc=GeneSearch(c,x);
if(loc!=-1)
{
for(int i=loc; i<(c.pathlong-1); i++)
{
c.mypath[i]=c.mypath[i+1];
}
c.pathlong--;
}
}
void GeneInsert(Cell &c,int x,int loc)
{
if(x>CITY_NUM||loc>CITY_NUM||x<0||loc<0)
{
printf("Loc or x Error\n");
return;
}
for(int i=c.pathlong-1; i>=loc; i--)
{
c.mypath[i+1]=c.mypath[i];
}
c.mypath[loc]=x;
c.pathlong++;
}
我使用了50个城市的距离矩阵,大概一万代左右就得到比较好的结果了,总代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<algorithm>
using namespace std;
const int CITY_NUM=50; //城市数
const int GROUP_NUM=100; //种群数
const int SON_NUM=150; //子群数
const double P_HYBRID=0.8; //子群中新生儿比例
const double P_MUTATION=0.07; //变异概率
const int CYC_NUM=10000; //循环次数
int CITY_MATRIX[CITY_NUM][CITY_NUM];//城市距离矩阵
typedef struct
{