TSP问题源代码实现

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<math.h>
#include<time.h>

#define num_C  10 //城市个数
#define N 100//群体规模
#define pc 0.9 //交叉概率为0.9
#define pm 0.1 //变异概率为0.1
//#define ps 0.6 //进行选择时保留的比例
#define genmax 500//最大遗传的代数

double Cost_table[10][10];//各个城市之间的距离
double RandomInteger(int low,int high);//生成一个介于两个整数之间的数
int RandomInteger1(int low,int high);//生成一个介于两个整数之间的整数
void Initial_gen(struct unit group[N]);//初始化种群
void Sort(struct unit group[N]);//将种群个体按代价从小到大排序
void Copy_unit(struct unit *p1,struct unit *p2);//复制种群p1到p2中
int search_son(int son[num_C],int k);//检查k是否在son[num_C]中已出现过
void Cross(struct unit *p1,struct unit *p2);//交叉
void Varation(struct unit group[N],int flag_v);//变异
void Evolution(struct unit group[N]);//种群进化有genmax决定
void Caculate_cost(struct unit *p);//计算某个路径的代价值
void Print_optimum(struct unit group[N]);//输出当代种群中的每个个体
void Cprobability(struct unit group[N]);//计算选择概率
void Cqprobability(struct unit group[N]);//计算累计概率
void Select(struct unit group[N]);//选择

//定义个体信息
typedef struct unit
{
	int path[num_C];//个体的路径信息
	double cost;//个体代价值
	double fitness;//个体适应度
	double probability;//选择概率
	double qprobability;//累计概率
};

struct unit group[N];
int num_gen=0;//记录当前达到第几代

//定义十个城市的坐标
typedef struct in
{
	int x;
	int y;
};

struct in city[num_C];//记录各个城市的坐标

void Cprobability(struct unit group[N])//计算选择概率
{
	double sum=0;
	int i;
	for(i=0;i<N;i++)
	{
		group[i].probability=0;
	}
	for(i=0;i<N;i++)
	{
		sum+=group[i].fitness;
	}
	for(i=0;i<N;i++)
	{
		group[i].probability=group[i].fitness/sum;
	}
}

void Cqprobability(struct unit group[N])//计算累计概率
{
	int i;
	double sum1=0;
	for(i=0;i<N;i++)
	{
		group[i].qprobability=0;
	}
	for(i=0;i<N;i++)
	{
		sum1+=group[i].probability;
		group[i].qprobability=sum1;
	}
	group[N-1].qprobability=1;
}

void Select(struct unit group[N])//进行染色体的选择
{
	int i,j,sum=1;
	double k;
	Cprobability(group);
	Cqprobability(group);
	for(i=0;i<N-1;i++)
	{
		k=RandomInteger(0,1);
		for(j=0;j<N-1;j++)//进行N-1次选择,group[0]不变
		{
			if(k<group[j].qprobability)
			{
				Copy_unit(&group[j],&group[sum]);//将p2赋值给p1
				sum++;
				break;
			}
		}
	}
}

void input()  //输入各个城市的坐标
{
	int i;
	printf("请输入十个城市的坐标:\n");
	for(i=0;i<num_C;i++)
	{
		scanf("%d %d",&city[i].x,&city[i].y);
	}
}

void caceverycity_cost()//计算各个城市之间互相的距离
{
	int i,j;
	for(i=0;i<num_C;i++)
	{
		for(j=0;j<num_C;j++)
		{
			if(i==j)
			{
				Cost_table[i][j]=0;
			}
			else
			{
				Cost_table[i][j]=sqrt(pow((city[i].x-city[j].x),2)+pow((city[i].y-city[j].y),2));
			}
		}
	}
}

void print()//输出各个城市之间的互相距离
{
	int i,j;
	printf("	城市0	城市1	城市2	城市3	城市4	城市5	城市6	城市7	城市8	城市9\n");
	for(i=0;i<num_C;i++)
	{
		printf("城市%d	",i);
		for(j=0;j<num_C;j++)
		{
			printf("%.2lf	",Cost_table[i][j]);
		}
		printf("\n");
	}
}

void Initial_gen(struct unit group[N])//初始化种群
{
	int i,j,k;
	struct unit *p;
	for(i=0;i<N;i++)//初始化种群里的100个个体
	{
		p=&group[i];//p指向种群的第i个个体
		for(j=0;j<num_C;j++)//生成10个城市间的一个随机路径
		{
			k=0;
			if(j==0)
			{
				p->path[j]=RandomInteger1(0,num_C-1);
			}
			else
			{
				p->path[j]=(int)RandomInteger1(0,num_C-1);
				while(k<j)//与之前城市重复,重新生成一个城市
				{
					if(p->path[j]==p->path[k])
					{
						p->path[j]=RandomInteger1(0,num_C-1);
						k=0;
					}
					else
						k++;
				}
			}
		}
		Caculate_cost(p);//计算该路径的代价值
	}
}

void Print_optimum(struct unit group[N],int k)//输出当代种群中的每个个体
{
	int j;
	struct unit *p;
	printf("当前第%d代:\n",k);
	p=&group[0];
	for(j=0;j<num_C;j++)
		printf("%d	",p->path[j]);
	printf("最小代价为:%lf\n",p->cost);
}

void Evolution(struct unit group[N])//种群进化有genmax决定
{
	int i,j,m,n;
	double k;
	for(i=1;i<genmax;i++)
	{
		Sort(group);//排序
		Print_optimum(group,i-1);  //输出当代(第i-1代)种群
		Select(group);//染色体选择
		for(j=0;j<N;j++)//染色体交叉
		{
			k=RandomInteger(0,1);
			if(k<pc)
			{
				m=RandomInteger1(1,N-1);
				n=RandomInteger1(1,N-1);
				Cross(&group[m],&group[n]);
			}
		}
		Varation(group,i);//变异
	}
	Sort(group);
	Print_optimum(group,i-1);//输出当代(第i-1代)种群
}

void Cross(struct unit *p1,struct unit *p2)//交叉
{
	int i,j,cross_point;
	int son1[num_C],son2[num_C];
	for(i=0;i<=num_C-1;i++)//初始化son1,son2
	{
		son1[i]=-1;
		son2[i]=-1;
	}
	cross_point=RandomInteger1(1,num_C-1);//交叉位随机生成
	//交叉,生成子代
	//子代1
	//子代1前半部分直接从父代复制
	for(i=0;i<cross_point;i++)
	{
		son1[i]=p1->path[i];
	}
	for(i=cross_point;i<=num_C-1;i++)
	{
		for(j=0;j<=num_C-1;j++)//补全p1
		{
			if(search_son(son1,p2->path[j])==1)
			{
				son1[i]=p2->path[j];
				break;
			}
		}
	}//end子代1
	//子代2
	//子代1后半部分直接从父代复制
	for(i=cross_point;i<=num_C-1;i++)
	{
		son2[i]=p2->path[i];
	}
	for(i=0;i<=cross_point+1;i++)
	{
		for(j=0;j<=num_C-1;j++)//补全p2
		{
			if(search_son(son2,p1->path[j])==1)
			{
				son2[i]=p1->path[j];
				break;
			}
		}
	}
	//end子代2
	//end交叉
	for(i=0;i<=num_C-1;i++)
	{
		p1->path[i]=son1[i];
		p2->path[i]=son2[i];
	}
	Caculate_cost(p1);//计算子代p1的代价
	Caculate_cost(p2);//计算子代p2的代价
}

void Varation(struct unit group[N],int flag_v)//变异
{
	int i,j,k,temp,c;
	struct unit *p;
	double flag;
	for(c=1;c<N;c++)
	{
		flag=RandomInteger(0,1);
		if(flag<pm)
		{
			i=RandomInteger1(1,N-1);//确定发生变异的个体
			j=RandomInteger1(0,num_C-1);//确定发生变异的位
			k=RandomInteger1(0,num_C-1);//确定发生变异的位
			p=&group[i];//变异
			temp=p->path[j];
			p->path[j]=p->path[k];
			p->path[k]=temp;
			Caculate_cost(p);//重新计算变异后路径的代价
		}
	}	
}

int search_son(int son[num_C],int k)//检查k是否在son[num_C]中已出现过
{
	int i;
	for(i=0;i<num_C;i++)
	{
		if(son[i]==k)
			return 0;
		else;
	}
	return 1;
}

void Sort(struct unit group[N])//将种群个体按代价从小到大排序
{
	int i,j;
	struct unit temp,*p1,*p2;
	for(i=0;i<=N-1;i++)//排序总共需要进行N-1轮
	{
		for(j=i+1;j<=N-1;j++)
		{
			p1=&group[i];
			p2=&group[j];
			if(p1->cost>p2->cost)
			{
				Copy_unit(p1,&temp);
				Copy_unit(p2,p1);//将p2赋值给p1
				Copy_unit(&temp,p2);
			}
		}
	}
}

void Caculate_cost(struct unit *p)//计算某个路径的代价值
{
	int j;
	p->cost=0;
	p->fitness=0;
	for(j=1;j<=num_C-1;j++)
	{
		p->cost+=Cost_table[p->path[j-1]][p->path[j]];
	}
	p->cost+=Cost_table[p->path[num_C-1]][p->path[0]];
	p->fitness=(double)1.0/p->cost;
}

void Copy_unit(struct unit *p1,struct unit *p2)//复制种群p1到p2中
{
	int i;
	for(i=0;i<num_C;i++)
		p2->path[i]=p1->path[i];
	p2->cost=p1->cost;
}

double RandomInteger(int low,int high)//生成一个介于两个整数之间的小数
{
	int k;
	double d,m;
	k=rand();
	k=(k!=RAND_MAX?k:(k-1));//RAND_MAX是VC中可以表示的最大整数
	d=(double)k/((double)(RAND_MAX));
	m=(d*(high-low));
	return (low+m);
}

int RandomInteger1(int low,int high)//生成一个介于两个整数之间的整数
{
	int k;
	double d;
	k=rand();
	k=(k!=RAND_MAX?k:(k-1));//RAND_MAX是VC中可以表示的最大整数
	d=(double)k/((double)(RAND_MAX));
	k=(int)(d*(high-low+1));
	return (low+k);
}



int main()
{
	input();//输入各个城市的坐标
	caceverycity_cost();//计算各个城市之间互相的距离
	print();
	srand((int)time(NULL));//初始化随机数发生器
	Initial_gen(group);//初始化种群
	Evolution(group);//进化:选择,交叉,变异
	return 0;
}





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值