TSP_遗传算法求解
head.h
#define N 10 class Generation { public: int state[4][N+1];//染色体---种群规模为4,有10个城市 float loadlength[4];//染色体的路径长度 float Fitness[4];//适应度 float SPro[4];//选择概率 float AcPro[4];//累积概率 int ChoiceNum[4];//选择次数 Generation() { int i; for(i=0;i<4;i++) for(int j=0;j<N+1;j++) state[i][j]=-1; for(i=0;i<4;i++) { loadlength[i]=0; Fitness[i]=0; SPro[i]=0; AcPro[i]=0; ChoiceNum[i]=0; } } }; class Point { public: int x; int y; Point(int a,int b) { x=a; y=b; } }; void RAND(double *r); Generation Init(Generation G);//初始化群体 void count_distance();//计算各个城市之间的直线距离 float count_loadlegth(Generation* G);//计算路径长度 void count_fitness(Generation* G);//计算适应度 void count_pro(Generation* G);//计算选择概率和累计概率 void count_choiceNum(Generation* G);//计算被选中的次数 void addtoopen(Generation G); void Copy_Generation(Generation* G1,Generation G0);//根据被选中次数复制上一代染色体 void Variation(Generation *G1); void Cross(Generation *G1);
Main.cpp
#include<iostream> #include"head.h" using namespace std; #define N 10 Generation OPEN[5000];//队列-----(数据保护)每一代各染色体的情况 int OPhead=0,OPtail=0,openlen=5000; float Distance[N][N]={0};//存储各个城市之间的直线距离 float MinShort=3000;//最短路径长度 int MinShortLoad[N+1]={0};//最短路径 int main() { int i; //计算各个城市之间的直线距离 count_distance(); Generation G0,G1; G0=Init(G0);//初始种群 G1=G0; int GNUM=0; while(MinShort>167) { G0=G1; printf("第%d代染色体情况:\n",GNUM); count_loadlegth(&G0);//计算路径长度 printf("已搜索到的路径中最短为: %f\n",MinShort); printf("已搜索到的路径中最短路径: "); for(i=0;i<N+1;i++) printf("%d ",MinShortLoad[i]); printf("\n"); count_fitness(&G0);//计算适应度 count_pro(&G0); //计算选择概率和累计概率 count_choiceNum(&G0);//计算被选中的次数 addtoopen(G0);//保护每一代的记录 printf("下一代:\n"); //复制 printf("复制后:\n"); Copy_Generation(&G1,G0);//根据被选中次数复制上一代染色体G0 //交叉 printf("交叉后:\n"); Cross(&G1);/////////// //变异 if(GNUM%5==0)//每5代(20条染色体)里变异一次(约0.5条染色体变异)-----变异率2.5% { printf("变异后:\n"); Variation(&G1); } printf("\n\n"); GNUM++; } return 0; }
Function.cpp
#include<iostream> #include<stdlib.h>//for rand(),srand() #include<time.h> //for time() #include<math.h> #include<string.h> #include"head.h" #define N 10 extern Generation OPEN[5000];//队列-----(数据保护)每一代各染色体的情况 extern int OPhead,OPtail,openlen; extern float Distance[N][N];//存储各个城市之间的直线距离 extern float MinShort;//最短路径长度 extern int MinShortLoad[N+1];//最短路径 void count_distance() { //各个城市的位置坐标 Point Position[N]={ Point(87,7),Point(91,38),Point(83,46),Point(71,44),Point(64,60), Point(68,58),Point(83,69),Point(87,76),Point(74,78),Point(71,71) //Point(58,69),Point(54,62),Point(51,67),Point(37,84),Point(41,94), //Point(2,99),Point(7,64),Point(22,60)//,Point(25,62),Point(18,54) //Point(4,50),Point(13,40),Point(18,40),Point(24,42),Point(25,38), //Point(41,26),Point(45,21),Point(44,35),Point(58,35),Point(62,32) }; int i,j; for(i=0;i<N;i++) for(j=0;j<N;j++) Distance[i][j]=sqrt(pow(Position[i].x-Position[j].x,2)+pow(Position[i].y-Position[j].y,2)); } Generation Init(Generation G) { int i,j; int Arr[4][N+1]={0}; /*={{7,8,9,4,5,6,1,2,3,0,7},// {9,8,7,3,2,1,6,5,4,0,9},// {1,3,5,7,9,2,4,6,8,0,1},// {0,1,2,3,4,5,6,7,8,9,0}};// //初始四条路径*/ for(i=0;i<4;i++)//产生随机初始种群 { for(j=0;j<N;j++)//j---已经得到的序列个数 { int temp=rand()%N; for(int t=0;t<j ;t++) if(temp==Arr[i][t]) { temp=rand()%N; t=-1; } Arr[i][j]=temp; } Arr[i][N]=Arr[i][0]; } for(i=0;i<4;i++) for(j=0;j<N+1;j++) G.state[i][j]=Arr[i][j];//初始化第0代的的种群状态 return G; } float count_loadlegth(Generation* G)//计算路径长度 { int i,j; float Short=10000.0; int Snum; for(i=0;i<4;i++) { float DistanceAdd=0.0; for(j=0;j<N;j++)//11-1 { int c1=(*G).state[i][j]; int c2=(*G).state[i][j+1]; DistanceAdd += Distance[c1][c2]; } (*G).loadlength[i]=DistanceAdd; if(DistanceAdd<Short) { Short=DistanceAdd ; Snum=i; } } for(i=0;i<4;i++) { for(j=0;j<N+1;j++) printf("%d ",(*G).state[i][j]); printf(" ----路径长: %f\n",(*G).loadlength[i]); } printf("最短路径为: "); for(j=0;j<N+1;j++) printf("%d ",(*G).state[Snum][j]); printf("\n最短路径长: ---%f\n",Short);//输出当代最短路径 if(Short<MinShort)//获取全局最短路径长度及其最短路径 { MinShort=Short; for(j=0;j<N+1;j++) MinShortLoad[j]=(*G).state[Snum][j]; } return Short;//返回当代最短路径 } void count_fitness(Generation* G)//计算适应度 { for(int i=0;i<4;i++) (*G).Fitness[i]=(float)1000/(*G).loadlength[i];//计算得每个染色体的适应度((float)10000用于调整数值) } void count_pro(Generation* G)//计算选择概率和累计概率 { int i; float ALL_fitness=(*G).Fitness[0]+(*G).Fitness[1]+(*G).Fitness[2]+(*G).Fitness[3]; for(i=0;i<4;i++)//选择概率 (*G).SPro[i]=(*G).Fitness[i]/ALL_fitness; for(i=0;i<4;i++)//累计概率 { if(i==0) (*G).AcPro[i]=(*G).SPro[i]; else (*G).AcPro[i]=(*G).SPro[i]+(*G).AcPro[i-1]; } } void RAND(double *r)//产生随机数 { //获得当前的时间作为随机数的种子//seed=time(0) srand(time(0));//两次获取随机数时间之差大于1s产生的随机数才会不同 int i; for(i=0;i<4;i++) { r[i]=(double)rand()/(double)RAND_MAX;//RAND_MAX=32767 } } void count_choiceNum(Generation* G)//计算被选中的次数 { //产生随机数 double r[4]={0.0}; RAND(&r[0]); int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++)//对于每一个随机概率 { if(i==0) { if(r[j]<(*G).AcPro[i]) (*G).ChoiceNum[i]++; } else { if(r[j]>=(*G).AcPro[i-1] && r[j]<(*G).AcPro[i] ) (*G).ChoiceNum[i]++; } } printf("被选中的次数: "); for(i=0;i<4;i++) printf("%d ",(*G).ChoiceNum[i]); printf("\n"); } void addtoopen(Generation G) { OPEN[OPtail++]=G; //向尾部添加节点 OPtail = OPtail%openlen; }
Cross.cpp(交叉)
#include<iostream> #include<stdlib.h>//for rand(),srand() #include<time.h> //for time() #include"head.h" #define N 10 extern Generation OPEN[5000];//队列-----(数据保护)每一代各染色体的情况 extern int OPhead,OPtail,openlen; extern float Distance[N][N];//存储各个城市之间的直线距离 //交叉 void Cross(Generation *G1) { int i; char OffSpr_A[N+1]={0},OffSpr_B[N+1]={0}, OffSpr_C[N+1]={0},OffSpr_D[N+1]={0};//记录交叉序列 int kk; //*****获取1、2号后的交叉**************************// Generation Gt=*G1;//保护G1 int C=rand()%N;//获取随机城市代号 //int CV=C;//保护C OffSpr_A[0]=C;//将城市C加入记录---第1个子孙 int count=N;//对前10个基因进行交叉(最后一个是重复的城市) kk=1; while(count!=1) { int Ra,Rb; for(i=0;i<N;i++)//求城市C在Gt.state[0][]、Gt.state[1][]中的下标位置 { if(Gt.state[0][i]==C) Ra=i;//记录下标 if(Gt.state[1][i]==C) Rb=i; } //printf("随机起始城市: %d---下标: %d %d ",C,Ra,Rb); int Cright_A,Cright_B; for(i=(Ra+1)%N; ;)/////////寻找C在G1.state[0][]中的右城市号 { if(Gt.state[0][i]!=-1) { Cright_A=Gt.state[0][i]; break; } i=(i+1)%N; } //printf("右城市A:%d ",Cright_A); for(i=(Rb+1)%N; ;)/////////寻找C在G1.state[1][]中的右城市号 { if(Gt.state[1][i]!=-1) { Cright_B=Gt.state[1][i]; break; } i=(i+1)%N; } //printf("右城市B:%d\n",Cright_B); float da,db; da=Distance[C][Cright_A]; db=Distance[C][Cright_B]; if(da<=db) { OffSpr_A[kk++]=Cright_A;//加入记录 C=Cright_A; }else { OffSpr_A[kk++]=Cright_B; C=Cright_B; } Gt.state[0][Ra]=-1;//删除城市G1.state[0][Ra]---标记为-1 Gt.state[1][Rb]=-1; count--; } OffSpr_A[N]=OffSpr_A[0];//最后一个城市与第一个城市相同 Gt=*G1;//保护G1 //C=CV; C=rand()%N;//获取随机城市代号 OffSpr_B[0]=C;//第2个子孙 count=N; kk=1; while(count!=1) { int Ra,Rb; for(i=0;i<N;i++)//求城市C在Gt.state[0][]、Gt.state[1][]中的下标位置 { if(Gt.state[0][i]==C) Ra=i;//记录下标 if(Gt.state[1][i]==C) Rb=i; } //printf("随机起始城市: %d---%d %d ",C,Ra,Rb); int Cleft_A,Cleft_B; for(i=(Ra-1+N)%N; ;)/////////寻找C在G1.state[0][]中的左城市号 { if(Gt.state[0][i]!=-1) { Cleft_A=Gt.state[0][i]; break; } i=(i-1+N)%N; } //printf("右城市A:%d ",Cleft_A); for(i=(Rb-1+N)%N; ;)/////////寻找C在G1.state[1][]中的左城市号 { if(Gt.state[1][i]!=-1) { Cleft_B=Gt.state[1][i]; break; } i=(i-1+N)%N; } //printf("右城市B:%d\n",Cleft_B); float da,db; da=Distance[C][Cleft_A]; db=Distance[C][Cleft_B]; if(da<=db) { OffSpr_B[kk++]=Cleft_A;//加入记录 C=Cleft_A; }else { OffSpr_B[kk++]=Cleft_B; C=Cleft_B; } Gt.state[0][Ra]=-1;//删除城市G1.state[0][Ra]---标记为-1 Gt.state[1][Rb]=-1; count--; } OffSpr_B[N]=OffSpr_B[0];//最后一个城市与第一个城市相同 ////////////////////////////////////////////////////// //*****获取3、4号后代的交叉**************************// Gt=*G1;//保护G1 C=rand()%N;//获取随机城市代号 //CV=C;//保护C OffSpr_C[0]=C;//将城市C加入记录---第3个子孙 count=N; kk=1; while(count!=1) { int Ra,Rb; for(i=0;i<N;i++)//求城市C在Gt.state[0][]、Gt.state[1][]中的下标位置 { if(Gt.state[2][i]==C) Ra=i;//记录下标 if(Gt.state[3][i]==C) Rb=i; } //printf("随机起始城市: %d---%d %d ",C,Ra,Rb); int Cright_A,Cright_B; for(i=(Ra+1)%N; ;)/////////寻找C在G1.state[0][]中的右城市号 { if(Gt.state[2][i]!=-1) { Cright_A=Gt.state[2][i]; break; } i=(i+1)%N; } //printf("右城市A:%d ",Cright_A); for(i=(Rb+1)%N; ;)/////////寻找C在G1.state[1][]中的右城市号 { if(Gt.state[3][i]!=-1) { Cright_B=Gt.state[3][i]; break; } i=(i+1)%N; } //printf("右城市B:%d\n",Cright_B); float da,db; da=Distance[C][Cright_A]; db=Distance[C][Cright_B]; if(da<=db) { OffSpr_C[kk++]=Cright_A;//加入记录 C=Cright_A; }else { OffSpr_C[kk++]=Cright_B; C=Cright_B; } Gt.state[2][Ra]=-1;//删除城市G1.state[0][Ra]---标记为-1 Gt.state[3][Rb]=-1; count--; } OffSpr_C[N]=OffSpr_C[0];//最后一个城市与第一个城市相同 Gt=*G1;//保护G1 //C=CV; C=rand()%N;//获取随机城市代号 OffSpr_D[0]=C;//第4个子孙 count=N; kk=1; while(count!=1) { int Ra,Rb; for(i=0;i<N;i++)//求城市C在Gt.state[0][]、Gt.state[1][]中的下标位置 { if(Gt.state[2][i]==C) Ra=i;//记录下标 if(Gt.state[3][i]==C) Rb=i; } //printf("随机起始城市: %d---%d %d ",C,Ra,Rb); int Cleft_A,Cleft_B; for(i=(Ra-1+N)%N; ;)/////////寻找C在G1.state[0][]中的左城市号 { if(Gt.state[2][i]!=-1) { Cleft_A=Gt.state[2][i]; break; } i=(i-1+N)%N; } //printf("右城市A:%d ",Cleft_A); for(i=(Rb-1+N)%N; ;)/////////寻找C在G1.state[1][]中的左城市号 { if(Gt.state[3][i]!=-1) { Cleft_B=Gt.state[3][i]; break; } i=(i-1+N)%N; } //printf("右城市B:%d\n",Cleft_B); float da,db; da=Distance[C][Cleft_A]; db=Distance[C][Cleft_B]; if(da<=db) { OffSpr_D[kk++]=Cleft_A;//加入记录 C=Cleft_A; }else { OffSpr_D[kk++]=Cleft_B; C=Cleft_B; } Gt.state[2][Ra]=-1;//删除城市G1.state[0][Ra]---标记为-1 Gt.state[3][Rb]=-1; count--; } OffSpr_D[N]=OffSpr_D[0];//最后一个城市与第一个城市相同 ////////////////////////////////////////////// for(i=0;i<N+1;i++)//将交叉得到的序列复制回G1 (*G1).state[0][i]=OffSpr_A[i]; for(i=0;i<N+1;i++) (*G1).state[1][i]=OffSpr_B[i]; for(i=0;i<N+1;i++) (*G1).state[2][i]=OffSpr_C[i]; for(i=0;i<N+1;i++) (*G1).state[3][i]=OffSpr_D[i]; for(i=0;i<4;i++) { for(int j=0;j<N+1;j++) printf("%d ",(*G1).state[i][j]); printf("\n"); } }
Copy_Variation.cpp(复制和变异)
#include<iostream> #include<stdlib.h>//for rand(),srand() #include<time.h> //for time() #include<math.h> #include<string.h> #include"head.h" #define N 10 extern Generation OPEN[5000];//队列-----(数据保护)每一代各染色体的情况 extern int OPhead,OPtail,openlen; extern float Distance[N][N];//存储各个城市之间的直线距离 extern float MinShort;//最短路径长度 extern int MinShortLoad[N+1];//最短路径 void Copy_Generation(Generation* G1,Generation G0)//根据被选中次数复制上一代染色体G0 { int i,j; int k=0; float maxloadlen=0;//选取路径最长的用MinShortLoad[]替换 int maxindex; for(i=0;i<4;i++) if(G0.loadlength[i]>maxloadlen) { maxloadlen=G0.loadlength[i]; maxindex=i;//记录最长路径下标 } for(j=0;j<N+1;j++) G0.state[i][j]=MinShortLoad[j];//替换最长的路径为搜索过的最短路径 for(i=0;i<4;i++)//对于G0的每一个染色体 for(j=0;j<G0.ChoiceNum[i];j++)//根据被选中次数复制G0染色体 { for(int t=0;t<N+1;t++) (*G1).state[k][t]=G0.state[i][t]; k++; } for(i=0;i<3;i++)//交换子染色体的位置(减少相同染色体相邻) { for(int k=0;k<N+1;k++) if((*G1).state[i][k]!=(*G1).state[i+1][k])//判断第[i]个和第[i+1]个是否相同 break; if(k==N+1)//相邻染色体相同 { char temp[N+1]={0}; for(j=0;j<N+1;j++) temp[j]=(*G1).state[i+1][j]; for(j=0;j<N+1;j++) (*G1).state[i+1][j]=(*G1).state[(i+2)%4][j]; for(j=0;j<N+1;j++) (*G1).state[(i+2)%4][j]=temp[j]; } } for(i=0;i<4;i++)//输出复制后的情况 { for(j=0;j<N+1;j++) printf("%d ",(*G1).state[i][j]); printf("\n"); } } void Variation(Generation *G1) { int i,j; int k=rand()%4;//取其中一条进行变异 int R=rand()%N;//产生随机起始城市下标 //printf("%d %d\n",k,R); //printf("随机起始城市: %d\n",(*G1).state[k][R]); float D=10000; int City=0; for(i=0;i<N;i++)//寻找距离起始城市最近的非邻城市 { if(i!=(*G1).state[k][R] && i!=(*G1).state[k][(R-1+N)%N] && i!=(*G1).state[k][(R+1)%N]) if(Distance[ (*G1).state[k][R] ][i]<D) { D=Distance[ (*G1).state[k][R] ][i];//取离城市G1.state[0][R]最小距离 City=i;//距离最近的城市号 } } //printf("最近城市: %d 距离: %f\n",City,D); //倒位 int Sindex=(R+1)%N;//从随机起始城市的--右边城市开始进行倒位 int Eindex; for(i=0;i<N;i++)//扫描染色体 if((*G1).state[k][i]==City) Eindex=i; if(Sindex>Eindex) //保证起点下标<终点下标 { int temp=Sindex; Sindex=Eindex; Eindex=temp; } //printf("起点下标: %d 终点下标: %d\n",Sindex,Eindex); for(i=Sindex,j=Eindex;i<j;i++,j--) { int temp=(*G1).state[k][i]; (*G1).state[k][i]=(*G1).state[k][j]; (*G1).state[k][j]=temp; } (*G1).state[k][N]=(*G1).state[k][0]; for(i=0;i<4;i++) { for(j=0;j<N+1;j++) printf("%d ",(*G1).state[i][j]); printf("\n"); } }