#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;
}
TSP问题源代码实现
最新推荐文章于 2023-04-09 20:03:45 发布