⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 遗传算法解tsp.cpp

📁 遗传算法解TSP问题的代码,vs2005编译
💻 CPP
字号:
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <time.h>
using namespace std;


#define N 100				//种群规模
#define M 80				//子代杂交的对数
#define GEN 5000			//种群遗传代数
#define MAX 32767
int *son[2*M],sontotal[2*M];
int city,*dis;


int* savedata(FILE *fp)
{
	char temp;
	short int i,j,t;
	int *a,n;
	while(1)
	{
		fread(&temp,sizeof(char),1,fp);
		if(temp=='\n')break;
		city=city*10+atoi(&temp);
	}
	n=city*(city+1)/2;
	a=(int*)malloc(n*sizeof(int));
	for(i=0;i<n;i++)
		a[i]=0;
	i=0;
	j=1;
	t=0;
	while(!feof(fp))
	{
		fread(&temp,sizeof(char),1,fp);
		if(temp==' ')
		{
			t++;
			if(t<j)i++;
			continue;
		}
		if(temp=='\n')
		{
			i++;
			j++;
			t=0;
			continue;
		}
		if(t>=j)continue;
		
		a[i]=a[i]*10+atoi(&temp);
	}
	return a;
}

/*	初始化种群 */
void RandInit(int*a[])
{
	short int i,j,k,u,v,tem;

	for(i=0;i<N;i++)
	{
		u=rand()%city;
		v=rand()%city;
		while(u==v)
			v=rand()%city;
		if(u>v)
		{
			tem=u;
			u=v;
			v=tem;
		}
		for(j=u,k=v;j<(u+v)/2.0+0.5;j++,k--)
		{
			tem=a[i][j];
			a[i][j]=a[i][k];
			a[i][k]=tem;
		}
	}
//	for (i=0;i<N;i++)
//		for(j=0;j<city;j++)
//			printf("%d ",a[i][j]);
//	printf("");
}

/* 计算每个个体的路程作为相应的适应值 */

void compdis(int* c[],int* t)
{
	int i,j,k,m,tem;
	for(i=0;i<N;i++)
	{
		t[i]=0;
		for(j=0;j<city;j++)
		{
			k=c[i][j];
			if (j==city-1) 
				m=c[i][0];
			else
				m=c[i][j+1];
			if(k>m)
				tem=k*(k+1)/2+m;
			else
				tem=m*(m+1)/2+k;
			t[i]+=dis[tem];
		}
			
	}
}

/* 计算每个个体的繁殖概率p[i] */

void comprate(int *t,float *p)
{
	int maxdis,i;

	for(i=0;i<N;i++)
		if(t[i]>maxdis)
			maxdis=t[i];
	for(i=0;i<N;i++)
		p[i]=t[i]*1.0/maxdis;

}

/* 
	两个个体进行杂交
	随机取A(B)中一段区域插入到B(A)前面,删除其后重复的城市编号
 */

void cross(int *cir[],int i,int k,int m)
{
	short int u,v,tem,j,t,r;

	u=rand()%city;
	v=rand()%city;
	while(u==v)
		v=rand()%city;
	if(u>v)
	{
		tem=u;
		u=v;
		v=tem;
	}
	for(j=0;j<city;j++){
		son[i][j]=cir[m][j];
		son[i+M][j]=cir[k][j];
	}
// 	for(j=0;j<city;j++)
// 	printf("%d ",son[i+M][j]);
// 	printf("\n");
// 	for(j=0;j<city;j++)
// 	printf("%d ",son[i][j]);
// 	printf("\n");

	
	for(j=city-1;j>=0;j--)					
		for(t=u;t<=v;t++)
			if(son[i][j]==cir[k][t]){
				for(r=j;r>0;r--)
					son[i][r]=son[i][r-1];
				son[i][r]=-1;
				j++;
				break;
			}
	for(j=0;j<v-u+1;j++)
		son[i][j]=cir[k][u+j];

// 	for(j=0;j<city;j++)
// 	printf("%d ",son[i][j]);
//  	printf("\n");

	u=rand()%city;
	v=rand()%city;
	while(u==v)
		v=rand()%city;
	if(u>v)
	{
		tem=u;
		u=v;
		v=tem;
	}
	for(j=city-1;j>=0;j--)					
	for(t=u;t<=v;t++)
		if(son[i+M][j]==cir[m][t]){
			for(r=j;r>0;r--)
				son[i+M][r]=son[i+M][r-1];
			son[i+M][r]=-1;
			j++;
			break;
		}
	for(j=0;j<v-u+1;j++)
		son[i+M][j]=cir[m][u+j];

// 	for(j=0;j<city;j++)
// 	printf("%d ",son[i+M][j]);
//  	printf("\n");
}

/* 
	变异函数 
	随机产生两个点,直接进行交换,迭代50次
*/

void mutation(int i)
{
	int k=0;
	int u,v,tem;
	
	while(k<50)
	{
		u=rand()%city;
		v=rand()%city;
		while(u==v)
			v=rand()%city;
//		for(j=0;j<city;j++)
//			printf("%d",son[i][j]);
		tem=son[i][u];
		son[i][u]=son[i][v];
		son[i][v]=tem;
//				for(j=0;j<city;j++)
// 			printf("%d",son[i][j]);
		u=rand()%city;
		v=rand()%city;
		while(u==v)
			v=rand()%city;
		//		for(j=0;j<city;j++)
		//			printf("%d",son[i][j]);
		tem=son[i+M][u];
		son[i+M][u]=son[i+M][v];
		son[i+M][v]=tem;
		k++;
	}

}

/************************************************************************/
/* 更新种群                                                             */
/************************************************************************/

void selectgen(int *cir[],int *total)
{
	short int father[N],f=0,genarate[N],s=0;
	short int i,j,k,u,v,j1,j2;
	int minf,mins;
	for (i=0;i<N;i++) {
		minf=10*MAX;
		mins=10*MAX;
		for (j=0;j<N;j++)
			if(total[j]<minf)
			{	
				j1=j;
				minf=total[j];
			}
// 			printf("");
// 			printf("");
		for(j=0;j<2*M;j++)
			if(sontotal[j]<mins)
			{
				j2=j;
				mins=sontotal[j];
			}
// 			printf("");
// 			printf("");
		if(minf<=mins){
			father[f]=j1;
			total[j1]=total[j1]+MAX;
			f++;
		}			
		else{
			genarate[s]=j2;
			sontotal[j2]=sontotal[j2]+MAX;
			s++;
		}
	}
	sort(father,father+f);
	j=0;
	k=0;
	for (i=0;i<N;i++) {
		if(i==father[j]&&j<f){
			j++;
			continue;
		}
		else{
			u=genarate[k];
			k++;
			total[i]=sontotal[u];
			for(v=0;v<city;v++)
				cir[i][v]=son[u][v];
		}
	}
	for(i=0;i<N;i++)
		total[i]=total[i]-MAX;
// 	for(i=0;i<N;i++)
// 		printf("%d ",total[i]);
	
}

int main()
{
	int *cir[N],total[N],temp[N],m,min;
	float p[N],pc,pm;
	short int i,j,k,u,v,gen=0,tem;
	FILE* fp;
	clock_t start,finish;

	start=clock();

	fp = fopen("disCHN144.txt","r");
	dis=savedata(fp);

	for(i=0;i<N;i++)
		cir[i]=(int*)malloc(city*sizeof(int));		//最后要释放
	for(i=0;i<2*M;i++)
		son[i]=(int*)malloc(city*sizeof(int));		//最后要释放	

	srand((unsigned int)time(NULL));
	for(i=0;i<N;i++)
		for(j=0;j<city;j++)
			cir[i][j]=j;
	RandInit(cir);						//初始化种群

	while(gen<GEN)
	{
		compdis(cir,total);					//计算每个个体的适应值--路程,在这里适应值越小越适应
		comprate(total,p);					//计算每个个体的繁殖概率p[i]
	
		m=0;
		k=0;

		pc=rand()%10000/10000.0;
		for(i=0;i<N;i++)
			if(p[i]>pc)					//temp[k]存放繁殖概率大于pc的个体编号,这些个体是准备杂交的个体
			{
				temp[k]=i;
				k++;
			}
		while(m<M)
		{
			u=rand()%k;
			v=rand()%k;
			while(u==v)
				v=rand()%k;
			i=temp[u];						//k,m是准备杂交的两个个体
			j=temp[v];
			cross(cir,m,i,j);
			pm=rand()%10000/10000.0;
			if(0.01>pm)						//变异概率为1%
				mutation(m);				
			m++;
		}
		for (i=0;i<2*M;i++)					//.................................
		{	sontotal[i]=0;
			for(j=0;j<city;j++)
			{
				k=son[i][j];
				if (j==city-1) 
					m=son[i][0];
				else
					m=son[i][j+1];
				if(k>m)
					tem=k*(k+1)/2+m;
				else
					tem=m*(m+1)/2+k;
				sontotal[i]+=dis[tem];
			}
/*			printf("%d ",sontotal[i]);*/
		}
// 		for (i=0;i<2*M;i++) 
// 			printf("%d ",sontotal[i]);
		selectgen(cir,total);						//在2M+N个体中选择N个最优个体作为下一代种群
		gen++;
	}
	min=10*MAX;
	for (i=0;i<N;i++)	
		if(total[i]<min)
		{
			min=total[i];
			j=i;
		}
	printf("%d\n",min);
	for (i=0;i<city;i++)
		if(i==city-1)
			printf("%d\n",cir[j][i]);
		else
			printf("%d->",cir[j][i]);
	for(i=0;i<N;i++)
		free(cir[i]);		
	for(i=0;i<2*M;i++)
		free(son[i]);		
/*	free(dis);*/
	finish=clock();
	printf("%.3f(s)\n",(finish-start)/1000.0);
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -