遗传算法以及求解TSP介绍http://blog.youkuaiyun.com/bizer_csdn/article/details/51760110
要求是从a点出发,对结束点没要求,但必须经过所有点,并且允许重复。
这个问题不同于TSP,但是稍加改进就可以了。
其实,主要就是邻接矩阵中,任意两点之间存储的是两点之间的最短距离,比如,a---f之间的最短距离是2+1+3=6。
关于两点之间最短路径问题,这题给出的权重是正值,感觉可以使用dijkstra之类的算法,当初是手算的,以后有机会慢慢补充。
下面给出代码:
GA.cpp
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <vector>
#include <algorithm>
using namespace std;
const double P_MAT=0.8; //交配概率
const double P_VAR=0.001; //变异概率
const int TMAX=150; //最大迭代次数
const int N=11; //11个城市
const int INF=1000; //表示图中不连通部分权重
const int GROUP_SIZE=300;//种群大小,300
vector<int> GROUP[GROUP_SIZE]; //种群
//邻接矩阵中存的是任意两节点的最短路径
int pointdist[N][N]={{ 0, 2, 7, 1, 3, 6, 10, 5, 12, 11, 14},
{ 2, 0, 5, 3, 1, 4, 8, 3, 10, 11, 12},
{ 7, 5, 0, 7, 4, 1, 5, 6, 7, 6, 9},
{ 1, 3, 7, 0, 4, 7, 9, 6, 11, 10, 13},
{ 3, 1, 4, 4, 0, 3, 7, 2, 9, 10, 11},
{ 6, 4, 1, 7, 3, 0, 4, 5, 6, 5, 8},
{ 10, 8, 5, 9, 7, 4, 0, 9, 2, 1, 4},
{ 5, 3, 6, 6, 2, 5, 9, 0, 7, 8, 9},
{ 12, 10, 7, 11, 9, 6, 2, 7, 0, 1, 2},
{ 11, 11, 6, 10, 10, 5, 1, 8, 1, 0, 3},
{ 14, 12, 9, 13, 11, 8, 4, 9, 2, 3, 0}};
//随机产生一个新的基因
void newChrom(vector<int>& chrom)
{
chrom.clear();
//保证第一城市为'a'
for(int i=0;i<N;i++)
{
chrom.push_back(i);
}
int i=0,j=0;
do
{
i=rand()%(N-1)+1;
j=rand()%(N-1)+1;
} while (!(i<j));//生成两个不同随机数
//逆序法生成新染色体
while(i<j)
{
swap(chrom[i++],chrom[j--]);
}
}
//种群初始化
void group_init()
{
for(int i=0;i<GROUP_SIZE;i++){
newChrom(GROUP[i]);
}
}
//计算每个染色体的适应值函数,即距离
int chrom_len(vector<int> chrom)
{
int len=0;
for(int i=0;i<chrom.size()-1;i++){
int p1=chrom[i];
int p2=chrom[i+1];
len=len+pointdist[p1][p2];
}
return len;
}
bool descend_by_len(vector<int> chrom1,vector<int> chrom2)
{
return chrom_len(chrom1)>chrom_len(chrom2);
}
//选择
void choose()
{
//适应值函数为距离之和
//为了加速进化过程,按着适应值函数从大到小进行排序
//排序后,第i染色体被选中概率为2*i/GROUP_SIZE/(GROUP_SIZE+1)
//采样“轮盘赌”算法模拟第i染色体被选中
//"轮盘赌"算法进行选择
//按着适应值函数从大到小进行排序,并计算排序后每个染色体被选中的概率
vector<int> new_group[GROUP_SIZE];
sort(GROUP,GROUP+GROUP_SIZE,descend_by_len);
double p[GROUP_SIZE]={0.0};
for(int i=0;i<GROUP_SIZE;i++){
p[i]=(double)2*(i+1)/GROUP_SIZE/(GROUP_SIZE+1);
}
//进行GROUP_SIZE次选择
for(int i=0;i<GROUP_SIZE;){
//当随机数大于累计概率时候,该染色体被选中
double r=rand()/(RAND_MAX+1.0);
double s=0;
for(int j=1;j<GROUP_SIZE;j++)
{
if(s>r||s==r){
new_group[i]=GROUP[j-1];
i++;
break;
}
s=s+p[j];
}
}
//把新生成种群放入全局变量GROUP中
for(int i=0;i<GROUP_SIZE;i++)
GROUP[i]=new_group[i];
}
//交配
void mate()
{
int mat_num=(int)(P_MAT*GROUP_SIZE);
//保证两两配对
if(mat_num%2!=0)
mat_num--;
for(int i=0;i<mat_num;i++)
{
int j=rand()%GROUP_SIZE;
int k=rand()%GROUP_SIZE;
if(j==k)
continue;
swap(GROUP[j],GROUP[k]);
}
//交配方法为两两配对,同时生成两个子代,交配位随机生成
//子代1的基因依次从父代2中挑取不重复的,子代2的基因依次从父代1中挑不重复的
for(int i=0;i<(mat_num/2);i++)
{
int n=2*i;
vector<int>& chrom1=GROUP[n];
vector<int>& chrom2=GROUP[n+1];
vector<int> temp=chrom1;
int pos=rand()%N;
//pos之前不变,pos之后从另一父代中依次选不重复的
//子代1
for(int j=pos+1;j<N;)
{
for(int k=0;k<N;k++)
{
for(int s=0;s<j;s++)
{
if (chrom1[s]==chrom2[k])
{
break;
}
else if(s==(j-1))
{
chrom1[j]=chrom2[k];
j++;
}
}
}
}
//子代2
for(int j=pos+1;j<N;)
{
for(int k=0;k<N;k++)
{
for(int s=0;s<j;s++)
{
if (chrom2[s]==temp[k])
{
break;
}
else if(s==(j-1))
{
chrom2[j]=temp[k];
j++;
}
}
}
}
}//交配循环结束
}
//变异
void vary()
{
int var_num=(int)(P_VAR*GROUP_SIZE);
for(int i=0;i<var_num;i++){
//变异规则为随机生成变异位,从该位开始按图的邻接关系随机生成后续节点
vector<int>& curr_chrom=GROUP[i];
newChrom(curr_chrom);
}
}
//找出当前种群最短路径,并输出控制台
vector<int> find_best_in_group(int& min)
{
int len[GROUP_SIZE];
for(int i=0;i<GROUP_SIZE;i++){
len[i]=chrom_len(GROUP[i]);
}
min=len[0];
int s=0;
for(int i=0;i<GROUP_SIZE;i++){
if(min<len[i]){
min=len[i];
s=i;
}
}
vector<int> best_in_group=GROUP[s];
return best_in_group;
}
//还原真实路径并输出控制台
void print_real_path(vector<int> chrome,int& min)
{
vector<int> real;
for(int i=0;i<N-1;i++)
{
int c1=chrome[i];
int c2=chrome[i+1];
real.push_back(c1);
if (c1==0&&c2==2)//a-c最短路径:a-b-e-f-c:0-1-4-5-2
{
real.push_back(1);real.push_back(4);real.push_back(5);
}
else if (c1==2&&c2==0)//c-a最短路径:c-f-e-b-a:2-5-4-1-0
{
real.push_back(5);real.push_back(4);real.push_back(1);
}
else if ((c1==0&&c2==4)||(c1==4&&c2==0)) //a-e最短路径:a-b-e:0-1-4
{
real.push_back(1);
}
else if (c1==0&&c2==5) //a-f最短路径:a-b-e-f:0-1-4-5
{
real.push_back(1);real.push_back(4);
}
else if (c1==5&&c2==0) //f-a最短路径:f-e-b-a:5-4-1-0
{
real.push_back(4);real.push_back(1);
}
else if ((c1==0&&c2==6)||(c1==6&&c2==0)) //a-g最短路径:a-d-g:0-3-6
{
real.push_back(3);
}
else if (c1==0&&c2==7) //a-h最短路径:a-b-e-h:0-1-4-7
{
real.push_back(1);real.push_back(4);
}
else if (c1==7&&c2==0) //h-a最短路径:h-e-b-a:7-4-1-0
{
real.push_back(4);real.push_back(1);
}
else if (c1==0&&c2==8) //a-i最短路径:a-d-g-j-i:0-3-6-9-8
{
real.push_back(3);real.push_back(6);real.push_back(9);
}
else if (c1==8&&c2==0) //i-a最短路径:i-j-d-g-a:8-9-6-3-0
{
real.push_back(9);real.push_back(6);real.push_back(3);
}
else if (c1==0&&c2==9) //a-j最短路径:a-d-g-j:0-3-6-9
{
real.push_back(3);real.push_back(6);
}
else if (c1==9&&c2==0) //j-a最短路径:j-g-d-a:9-6-3-0
{
real.push_back(6);real.push_back(3);
}
else if (c1==0&&c2==10) //a-k最短路径:a-c-f-i-k:0-2-5-8-10
{
real.push_back(2);real.push_back(5);real.push_back(8);
}
else if (c1==10&&c2==0) //k-a最短路径:k-i-f-c-a:10-8-5-2-0
{
real.push_back(8);real.push_back(5);real.push_back(2);
}
else if (c1==1&&c2==2) //b-c最短路径:b-e-f-c:1-4-5-2
{
real.push_back(4);real.push_back(5);
}
else if (c1==2&&c2==1) //c-b最短路径:f-c-e-b:2-5-4-1
{
real.push_back(5);real.push_back(4);
}
else if ((c1==1&&c2==3)||(c1==3&&c2==1)) //b-d最短路径:b-a-d:1-0-3
{
real.push_back(0);
}
else if ((c1==1&&c2==5)||(c1==5&&c2==2)) //b-f最短路径:b-e-f:1-4-5
{
real.push_back(4);
}
else if (c1==1&&c2==6) //b-g最短路径:b-e-f-g:1-4-5-6
{
real.push_back(4);real.push_back(5);
}
else if (c1==6&&c2==1) //g-b最短路径:g-f-e-b:6-5-4-1
{
real.push_back(5);real.push_back(4);
}
else if ((c1==1&&c2==7)||(c1==7&&c2==1)) //b-h最短路径:b-e-h:1-4-7
{
real.push_back(4);
}
else if (c1==1&&c2==8) //b-i最短路径:b-e-h-i:1-4-7-8
{
real.push_back(4);real.push_back(7);
}
else if (c1==8&&c2==1) //i-b最短路径:i-h-e-b:8-7-4-1
{
real.push_back(7);real.push_back(4);
}
else if (c1==1&&c2==9) //b-j最短路径:b-e-h-i-j:1-4-7-8-9
{
real.push_back(4);real.push_back(7);real.push_back(8);
}
else if (c1==9&&c2==1) //j-b最短路径:j-i-h-e-b:9-8-7-4-1
{
real.push_back(8);real.push_back(7);real.push_back(4);
}
else if (c1==1&&c2==10) //b-k最短路径:b-e-h-k:1-4-7-10
{
real.push_back(4);real.push_back(7);
}
else if (c1==10&&c2==1) //k-b最短路径:k-h-e-b:10-7-4-1
{
real.push_back(7);real.push_back(4);
}
else if ((c1==2&&c2==4)||(c1==4&&c2==2)) //c-e最短路径:c-f-e:2-5-4
{
real.push_back(5);
}
else if ((c1==2&&c2==6)||(c1==6&&c2==2)) //c-g最短路径:c-f-g:2-5-6
{
real.push_back(5);
}
else if (c1==2&&c2==7) //c-h最短路径:c-f-e-h:2-5-4-7
{
real.push_back(5);real.push_back(4);
}
else if (c1==7&&c2==2) //h-c最短路径:h-e-f-c:7-4-5-2
{
real.push_back(4);real.push_back(5);
}
else if ((c1==2&&c2==8)||(c1==8&&c2==2)) //c-i最短路径:c-f-i:2-5-8
{
real.push_back(5);
}
else if (c1==2&&c2==9)//c-j最短路径:c-f-g-j:2-5-6-9
{
real.push_back(5);real.push_back(6);
}
else if (c1==9&&c2==2) //j-c最短路径:j-g-f-c:9-6-5-2
{
real.push_back(6);real.push_back(5);
}
else if (c1==2&&c2==10) //c-k最短路径:c-f-i-k:2-5-8-10
{
real.push_back(5);real.push_back(8);
}
else if (c1==10&&c2==2) //k-c最短路径:k-i-f-c:10-8-5-2
{
real.push_back(8);real.push_back(5);
}
else if (c1==3&&c2==4) //d-e最短路径:d-a-b-e:3-0-1-4
{
real.push_back(0);real.push_back(1);
}
else if (c1==4&&c2==3) //e-b最短路径:e-b-a-d:4-1-0-3
{
real.push_back(1);real.push_back(0);
}
else if (c1==3&&c2==5)//d-f最短路径:d-a-b-e-f:3-0-1-4-5
{
real.push_back(0);real.push_back(1);real.push_back(4);
}
else if (c1==5&&c2==3) //f-d最短路径:f-e-b-a-d:5-4-1-0-3
{
real.push_back(4);real.push_back(1);real.push_back(0);
}
else if (c1==3&&c2==7) //d-h最短路径:d-a-b-e-h:3-0-1-4-7
{
real.push_back(0);real.push_back(1);real.push_back(4);
}
else if (c1==7&&c2==3) //h-d最短路径:h-e-b-a-d:7-4-1-0-3
{
real.push_back(4);real.push_back(1);real.push_back(0);
}
else if (c1==3&&c2==8) //d-i最短路径:d-g-j-i:3-6-9-8
{
real.push_back(6);real.push_back(9);
}
else if (c1==8&&c2==3) //i-d最短路径:i-j-g-d:8-9-6-3
{
real.push_back(9);real.push_back(6);
}
else if ((c1==3&&c2==9)||(c1==9&&c2==3)) //d-j最短路径:d-g-j:3-6-9
{
real.push_back(6);
}
else if (c1==3&&c2==10) //d-k最短路径:d-g-j-k:3-0-9-10
{
real.push_back(0);real.push_back(9);
}
else if (c1==10&&c2==3) //k-d最短路径:k-j-g-d:10-9-0-3
{
real.push_back(9);real.push_back(0);
}
else if ((c1==4&&c2==6)||(c1==6&&c2==4)) //e-g最短路径:e-f-g:4-5-6
{
real.push_back(5);
}
else if ((c1==4&&c2==8)||(c1==8&&c2==4)) //e-i最短路径:e-h-i:4-7-8
{
real.push_back(7);
}
else if (c1==4&&c2==9) //e-j最短路径:e-h-i-j:4-7-8-9
{
real.push_back(7);real.push_back(8);
}
else if (c1==9&&c2==4) //j-e最短路径:j-i-h-e:9-8-7-4
{
real.push_back(8);real.push_back(7);
}
else if ((c1==4&&c2==10)||(c1==10&&c2==4)) //e-k最短路径:e-h-k:4-7-10
{
real.push_back(7);
}
else if ((c1==5&&c2==7)||(c1==7&&c2==5)) //f-h最短路径:f-e-h:5-4-7
{
real.push_back(4);
}
else if (c1==5&&c2==8) //f-i最短路径:f-g-j-i:5-6-9-8
{
real.push_back(6);real.push_back(9);
}
else if (c1==8&&c2==5) //i-f最短路径:i-j-g-f:8-9-6-5
{
real.push_back(9);real.push_back(6);
}
else if ((c1==5&&c2==9)||(c1==9&&c2==5)) //f-j最短路径:f-g-j:5-6-9
{
real.push_back(6);
}
else if ((c1==5&&c2==10)||(c1==10&&c2==5)) //f-k最短路径:f-i-k:5-8-10
{
real.push_back(4);
}
else if (c1==6&&c2==7) //g-h最短路径:g-j-i-h:6-9-8-7
{
real.push_back(9);real.push_back(8);
}
else if (c1==7&&c2==6) //h-g最短路径:h-j-i-g
{
real.push_back(8);real.push_back(9);
}
else if ((c1==6&&c2==8)||(c1==8&&c2==6)) //g-i最短路径:g-j-i:6-9-8
{
real.push_back(9);
}
else if (c1==6&&c2==10) //g-k最短路径:g-j-i-k:6-9-8-10
{
real.push_back(9);real.push_back(8);
}
else if (c1==10&&c2==6) //k-g最短路径:k-i-j-g:10-8-9-6
{
real.push_back(8);real.push_back(9);
}
else if ((c1==7&&c2==9)||(c1==9&&c2==7)) //h-j最短路径:h-i-j:7-8-9
{
real.push_back(8);
}
else if ((c1==9&&c2==10)||(c1==10&&c2==9)) //j-k最短路径:j-i-k:9-8-10
{
real.push_back(8);
}
}//for循环结束
real.push_back(chrome[N-1]);
//a,b,...,k(ASCII码97,...,107)分别对应0,1,...,10
cout<<"shortest in current group: ";
for(vector<int>::iterator iter=real.begin();iter!=real.end();iter++){
char ch=(*iter)+97;
if(iter!=real.end()-1)
cout<<ch<<"-";
else
cout<<ch;
}
cout<<" "<<min<<endl;
}
void main( )
{
clock_t start,end;
start=clock();
int best=0;//最短距离
vector<int> best_path;
//初始化随机数
srand((int)time(0));
//种群初始化
group_init();
best_path=find_best_in_group(best);
int curr_best=best;
vector<int> curr_best_path;
for(int t=0;t<TMAX;t++){
//选择
choose();
//交配
mate();
//变异
vary();
//找出当前种群最短路径,并输出控制台
curr_best_path=find_best_in_group(curr_best);
print_real_path(curr_best_path,curr_best);
if(curr_best<best)
{
best=curr_best;
best_path=curr_best_path;
}
}
end=clock();
printf("\nrun time: %fs\n\n\n",(double)(end-start)/CLOCKS_PER_SEC);
printf("shortest: ");
print_real_path(best_path,best);
getchar();
}
结果:
结果可能不唯一;
同时代码261-516行,最短路径转化为真实路径过程中,可能有点小bug……
希望能够指正