用遗传算法解决tsp旅行商问题

问题为:30城市TSP问题(d*=423.741 by D B Fogel)TSP Benchmark 问题

城市坐标:

41 94;37 84;54 67;25 62;7 64;2 99;68 58;71 44;5462;83 69;64 60;18 54;2260;83 46;91 38;25 38;2442;58 69;71 71;74 78;8776;18 40;13 40;82 7;62 32;58 35;45 21;41 26;44 35;4 50

《用遗传算法解决tsp旅行商问题》

程序为:

采用轮盘赌选择、基于位置交叉PBX、两点互换变异

#include<iostream>
#include<ctime>
#include<cstdlib>
#include<cmath>
#include<cstdio>
using namespace std;
const int M=100,T=500,N=30;//种群大小和迭代次数和城市个数
const double pc=0.6,pm=0.05;//交叉率、变异率
int condition[30][2]={
	{41,94},{37,84},{54,67},{25,62},{7,64},{2,99},{68,58},{71,44},{54,62},{83,69},
	{64,60},{18,54},{22,60},{83,46},{91,38},{25,38},{24,42},{58,69},{71,71},{74,78},
	{87,76},{18,40},{13,40},{82,7},{62,32},{58,35},{45,21},{41,26},{44,35},{4,50}
};//30个城市的坐标
struct chromo//构造染色体
{
	int code[N];
	double fit;
	double sumfit;
};

chromo p[M];//定义一个种群
chromo fitmax,fitmin;//一个种群中的最长路径和最短路径的染色体个体
int min,max;
double randab(double a,double b)		//在区间(a,b)内生成一个随机数
{
	double c,r;
	c=b-a;
	r=a+c*rand()/(RAND_MAX+1.0);
	return r;
}

void initial();//初始化函数
void evluate();//计算适值的函数
void print();//显示函数
void select();//选择函数
void crossover();//交叉函数
void mutation();//变异函数


void main()
{
	cout<<"初始化种群:"<<endl;
	initial();
	evluate();
	print();
	int gen=1;//迭代次数
	while(gen<=T)
	{
		cout<<"第"<<gen<<"次迭代"<<endl;
		select();
		evluate();
		crossover();
		evluate();
		mutation();
		evluate();
		print();
		gen++;
	}
	system("pause");
}
/******种群的初始化********/
void initial()
{
	int i,j,k;
	double squence[2][N],temp;
	srand((unsigned)time(NULL));  
	for(k=0;k<M;k++)
	{
		for(i=0;i<N;i++)
		{
			squence[0][i]=randab(0,1);//二维数组的第一位存放生成的随机数
			squence[1][i]=i+1;//第二维放城市的号码
		}
		for(i=0;i<N;i++)//按照随机数的由大到小顺序随机排列城市
		{
			for(j=i+1;j<N;j++)
			{
				if(squence[0][i]<squence[0][j])
				{
					temp=squence[0][i];
					squence[0][i]=squence[0][j];
					squence[0][j]=temp;
					temp=squence[1][i];
					squence[1][i]=squence[1][j];
					squence[1][j]=temp;
				}
			}
		}
		for(j=0;j<N;j++)
			p[k].code[j]=(int)squence[1][j];
	}
}
/*********计算适值函数*********/
void evluate()
{
	int i,j,a,b;
	for(i=0;i<M;i++)
	{
		p[i].fit=0;
		p[i].sumfit=0;
		for(j=0;j<N-1;j++)//每一个染色体的适应值是所有点按顺序之间的距离之和
		{
			a=p[i].code[j];
			b=p[i].code[j+1];
			p[i].fit+=sqrt(pow((double)(condition[b][0]-condition[a][0]),2.0)+pow((double)(condition[b][1]-condition[a][1]),2.0));
		}
		p[i].fit+=sqrt(pow((double)(condition[0][0]-condition[N-1][0]),2.0)+pow((double)(condition[0][1]-condition[N-1][1]),2.0));
	}
	p[0].sumfit=p[0].fit;
	for(i=1;i<M;i++)
	{
		p[i].sumfit=p[i-1].sumfit+p[i].fit;
	}
}
/**********显示函数*********/
void print()
{
	int i,min,max;
	fitmin.fit=p[M-1].sumfit;
	fitmax.fit=0;
	for(i=0;i<M;i++)
	{
		if(fitmin.fit>p[i].fit)
		{
			fitmin=p[i];
			min=i;
		}
		if(fitmax.fit<p[i].fit)
		{
			fitmax=p[i];
			max=i;
		}
	}
	cout<<"当前种群中最短路径的顺序为:"<<endl;
	for(i=0;i<N;i++)
		cout<<fitmin.code[i]<<" ";
	cout<<"当前种群中最短路径的距离为:"<<endl;
	cout<<fitmin.fit<<endl;
	cout<<"当前种群中最长路径的顺序为:"<<endl;
	for(i=0;i<N;i++)
		cout<<fitmax.code[i]<<" ";
	cout<<"当前种群中最长路径的距离为:"<<endl;
	cout<<fitmax.fit<<endl;
}
/*********选择函数*********/
void select()
{
	int i,j;
	double s;
	chromo pt[M];
	srand((unsigned)time(NULL));

	p[0].sumfit=fitmax.fit*1.1-p[0].fit;//采用轮盘赌选择
	for(i=1;i<M;i++)
	{
		p[i].sumfit=p[i-1].sumfit+fitmax.fit*1.1-p[i].fit;
	}
	for(i=0;i<M;i++)
	{
		s=randab(p[0].sumfit,p[M-1].sumfit);
		for(int j=0;j<M;j++)
		{
			if(p[j].sumfit>=s)
			{
				pt[i]=p[j];
				break;
			}
			else continue;
		}
	}
	for(i=0;i<M;i++)
		p[i]=pt[i];
}
/*********交叉函数**********/
void crossover()
{
	int i,j,k,t,s;
	int te[N];
	
	chromo po[M];
	for(i=0;i<M;i++)
		for(j=0;j<N;j++)
		po[i].code[j]=0;
	srand((unsigned)time(NULL));
	for(i=0;i<M;i++)
	{
		for(j=0;j<N;j++)//数组te记录子代染色体的某个位置是否已经有基因
			te[j]=0;
		double q=randab(0,1);
		if(q<pc)
		{
			for(j=0;j<M;j++)//随机选择交叉对象为第t个染色体
			{
				t=rand()%M;
				if(t!=i)
					break;
			}
			for(j=0;j<N/2;j++)
			{
				s=rand()%N;//pbx 在父代1上随机取N/2个位置,s为位置
				if(te[s]!=0)//取得位置重复的话重新取
				{
					j--;
					continue;
				}
				else 
				{
						te[s]=1;//记录这个位置被取过了
						po[i].code[s]=p[i].code[s];//对应位置的基因放入子代
				}
			}
			for(j=0;j<N;j++)
			{
				for(k=0;k<N;k++)
				{
					if(p[t].code[j]==po[i].code[k])
						break;
				}//找出父代2中子代还没有的基因
				if(k==N)
				{
					for(int l=0;l<N;l++)
					{
						if(te[l]==0)//子代还没有基因的位置
						{
							po[i].code[l]=p[t].code[j];
							te[l]=1;
							break;
						}
					}
				}
			}
		}
		else 
			po[i]=p[i];
	}
	for(i=0;i<M;i++)
		p[i]=po[i];
}
/********变异函数********/
void mutation()
{
	int i,j,c1,c2,temp;
	double q;
	srand((unsigned)time(NULL));
	for(i=0;i<M;i++)
	{
		q=randab(0,1);
		if(q<pm)
		{
			for(j=0;j<2;j++)
			{
				c1=rand()%N;//随机选取两个位置,交换位置
				c2=rand()%N;
				if(c2==c1)
				{
					j--;
					continue;
				}
				else break;
			}
			temp=p[i].code[c1];
			p[i].code[c1]=p[i].code[c2];
			p[i].code[c2]=temp;
		}
		else continue;
	}
}
    原文作者:遗传算法
    原文地址: https://blog.csdn.net/lszdh/article/details/16944585
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞