#include<iostream>
#include<vector>
#include<algorithm>//random_shuffle();sort();lower_bound();
#include<cmath>
#include<ctime>
using namespace std;
typedef vector<int> VI;
typedef vector<VI> VVI;
#define PB push_back //在vector尾部加入一个数据
#define MP make_pair //1.将2个数据组合成一个数据//2.当一个函数需要返回2个数据的时候,可以选择pair
//pair的实现是一个结构体,主要的两个成员变量是first、second
//因为是使用struct不是class,所以可以直接使用pair的成员变量
int next_int();
double next_double();
void pmx(VI& a,VI& b,int pointcnt);//PMX交叉
double fitness(const VI& v,int pointcnt);//计算适应度
void change0(vector<int>& K,int N);//变异策略:两点互换
void mutate(VI& route,int mutate_type,int pointcnt);
bool pair_dec(const pair<double,VI*>& a,const pair<double,VI*>& b);
vector<double> x,y;//全局函数,记录城市坐标
class other_population
{
public:
int popsize,pointcnt;//种群规模,染色体长度
double pc,pm;//交叉概率,变异概率
vector<pair<double,VI*> >pop;//种群
pair<double,VI*> bestofpop;//最好个体
int cross_type;//交叉类型
int mutate_type;//变异类型
int make_p;//个体概率分配策略类型
int select_type;//个体选择类型
int toursize;//竞赛规模
double bestp;//最好个体选择概率
other_population(int a,int b,int c,int f,int g,double d,double e,int h,double j,int m)
{
popsize=a,pointcnt=b,cross_type=c,mutate_type=f,make_p=g,pc=d,pm=e,toursize=h,bestp=j,select_type=m;
for(int i=0;i<popsize;i++)//初始化种群
{
VI* v=new VI(pointcnt);
for(int j=0;j<pointcnt;j++)
(*v)[j]=j;
random_shuffle(v->begin(),v->end());
pop.PB(MP(fitness(*v,pointcnt),v));
}
sort(pop.begin(),pop.end(),pair_dec);
bestofpop.first=pop[0].first;//初始时最好个体的适应度
bestofpop.second=new VI(*pop[0].second);//初始时最好个体的染色体
}
~other_population()
{
for(int i=0;i<pop.size();i++)
delete pop[i].second;
delete bestofpop.second;
}
void next()//产生下一代种群
{
vector<double> ps(popsize);
if(make_p==0) //按适应度比例分配个体的选择概率
{
double sum=0;
for(int i=0;i<popsize;i++)
sum+=pop[i].first;
for(i=0;i<popsize;i++)
ps[i]=pop[i].first/sum;
}
if(select_type==0)//轮盘赌选择个体
{
vector<pair<double,VI*> > select_res;
vector<double> addsum(popsize);
for(int i=0;i<popsize-1;i++)//计算个体的累计概率
{
if(i==0)
addsum[i]=ps[0];
else
addsum[i]=addsum[i-1]+ps[i];
}
addsum[popsize-1]=1.5;
for(i=0;i<popsize;i++)
{
double rd=next_double();
int r=lower_bound(addsum.begin(),addsum.end(),rd)-addsum.begin();
//lower_bound()返回一个 iterator 它指向在[first,last)标记的有序序列中可以插入value,
//而不会破坏容器顺序的第一个位置,而这个位置标记了一个大于等于value 的值。
VI* v=new VI(*pop[r].second);
select_res.PB(MP(fitness(*v,pointcnt),v));
}
for(i=0;i<popsize;i++)
delete pop[i].second;
pop=select_res;
////////////////////////////////
/*cout<<"选择后共"<<pop.size()<<"个子染色体\n";
for(i=0;i<pop.size();i++)
{
VI temp=*pop[i].second;
for(int j=0;j<10;j++)
cout<<temp[j]<<" ";
cout<<"\n";
}*/
//////////////////////////////
}
int Count_cross=0;
for(int cc=0;cc<popsize/2;cc++)//随机选择两个个体,然后进行交叉
{
int a=next_int()%popsize;
int b=(a+1+(next_int()%(popsize-1)))%popsize;
if(next_double()<pc)//随机数小于交叉概率,进行交叉
{
if(cross_type==0)//pmx交叉
pmx(*pop[a].second,*pop[b].second,pointcnt);
///////////////////////////////
/*Count_cross+=2;
cout<<"交叉后第"<< a <<"条子染色体: ";
VI temp=*pop[a].second;
for(int j=0;j<10;j++)
cout<<temp[j]<<" ";
cout<<"\n";
//////////////////////////////
cout<<"交叉后第"<< b <<"条子染色体: ";
temp=*pop[b].second;
for(j=0;j<10;j++)
cout<<temp[j]<<" ";
cout<<"\n";*/
////////////////////////////////
pop[a].first=fitness(*pop[a].second,pointcnt);//计算交叉后个体a的适应度
if(bestofpop.first<pop[a].first)//更新最好个体
{
bestofpop.first=pop[a].first;
delete bestofpop.second;
bestofpop.second=new VI(*pop[a].second);
}
pop[b].first=fitness(*pop[b].second,pointcnt);//计算交叉后个体b的适应度
if(bestofpop.first<pop[b].first)//更新最好个体
{
bestofpop.first=pop[b].first;
delete bestofpop.second;
bestofpop.second=new VI(*pop[b].second);
}
}
}
//////////////////////////////////////
//cout<<"交叉"<<Count_cross<<"条染色体\n";
//cout<<"交叉后共"<<pop.size()<<"个子染色体\n";
/////////////////////////////////////
int Count_mutate=0;//变异染色体条数
for(int i=pop.size()-1;i>=0;i--)//进行变异
if(next_double()<pm)//随机数小于变异概率,进行变异
{
mutate(*pop[i].second,mutate_type,pointcnt);//变异
pop[i].first=fitness(*pop[i].second,pointcnt);//计算变异后个体的适应度
///////////////////////////////
/*Count_mutate++;
cout<<"变异后第"<< i <<"个子染色体: ";
VI temp=*pop[i].second;
for(int j=0;j<10;j++)
cout<<temp[j]<<" ";
cout<<"\n";*/
///////////////////////////////
}
///////////////////////////////
//cout<<"变异"<<Count_mutate<<"条染色体\n";
//cout<<"变异后共"<<pop.size()<<"个子染色体\n\n\n";
///////////////////////////////
sort(pop.begin(),pop.end(),pair_dec);//从大到小排序
if(bestofpop.first<pop[0].first)//更新最好个体
{
delete bestofpop.second;
bestofpop.first=pop[0].first;
bestofpop.second=new VI(*pop[0].second);
}
}
};
int next_int()
{
return rand()*(RAND_MAX+1)+rand();
}
double next_double()
{
return (double(rand()*(RAND_MAX+1)+rand()))/((RAND_MAX+1)*RAND_MAX+RAND_MAX);
}
double fitness(const VI& v,int pointcnt)//计算适应度
{
double r=0;
for(int i=0;i<pointcnt;i++)
{
double dx=x[v[i]]-x[v[(i+1)%pointcnt]];
double dy=y[v[i]]-y[v[(i+1)%pointcnt]];
r+=sqrt(dx*dx+dy*dy);//个体的适应度为相邻两城市之间的距离平方的平方根和
}
return 1.0/r;
}
int flag=0;
void pmx(VI& a,VI& b,int pointcnt)//PMX交叉
{
int i;
int sa=next_int()%pointcnt,sb=next_int()%pointcnt;//随机选择两交叉位
if (sa>sb)
{
swap(sa,sb);
}//保证交叉位sa<=sb
/*if(flag==0)
{
cout<<"互换前(互换位:"<<sa<<" "<<sb<<")\n";
for(i=0;i<10;i++)
cout<<a[i]<<" ";
cout<<"\n";
for(i=0;i<10;i++)
cout<<b[i]<<" ";
cout<<"\n";
}*/
VI m1(pointcnt,-1);
VI m2(pointcnt,-1);
for (i = sa; i <= sb; ++i) //互换交叉位之间的基因
{
//相当于a中将城市a[i]删了,用城市b[i]取代,从而出现城市b[i](替换后的a'[i])重复
// b中将城市b[i]删了,用城市a[i]取代,从而出现城市a[i](替换后的b'[i])重复
swap(a[i], b[i]);
m1[a[i]] = b[i];//记录a'[i]所取代的城市a[i],用于替换非交叉部分的a'[i]的元素重复
m2[b[i]] = a[i];
}
///////////////////////
/*if(flag==0)
{
cout<<"互换后(未调整)\n";
for(i=0;i<10;i++)
cout<<a[i]<<" ";
cout<<"\n";
for(i=0;i<10;i++)
cout<<b[i]<<" ";
cout<<"\n";
for(i=0;i<10;i++)
cout<<m1[i]<<" ";
cout<<"\n";
for(i=0;i<10;i++)
cout<<m2[i]<<" ";
cout<<"\n";
}*/
///////////////////////
for (i = 0; i < pointcnt; ++i)//调整交叉位之前、之后的基因,防止和交叉位之间的基因重复
if (i < sa || i > sb)
{
if (m2[b[i]] != -1)
{
while (m2[b[i]] != -1)
b[i] = m2[b[i]];
}
if (m1[a[i]] != -1)
{
while (m1[a[i]] != -1)
a[i] = m1[a[i]];
}
}
/////////////////////
/*if(flag==0)
{
cout<<"互换调整后\n";
for(i=0;i<10;i++)
cout<<a[i]<<" ";
cout<<"\n";
for(i=0;i<10;i++)
cout<<b[i]<<" ";
cout<<"\n";
}
flag=1;*/
////////////////////
}
void mutate(VI& route,int mutate_type,int pointcnt)//变异
{
if(mutate_type==0)//两点互换
change0(route,pointcnt);
}
void change0(vector<int>& K,int N)//变异策略:两点互换
{
int i=next_int()%N;
int d=next_int()%(N-1);
int j=(i+1+d)%N;
swap(K[i],K[j]);
}
bool pair_dec(const pair<double,VI*>& a,const pair<double,VI*>& b)//比较因子,用于sort()函数
{
return a>b;
}
int main()
{
srand((unsigned)time(NULL));
int CASNUM,POINTCNT,POPSIZE,GENERATIONS;
//scanf("%d",&CASNUM);
CASNUM=10;//实验次数
//scanf("%d%d%d",&POINTCNT,&POPSIZE,&GENERATIONS);
POINTCNT=10, POPSIZE=100,GENERATIONS=100;//染色体长度(城市数),种群规模,最大迭代步数
cout<<"城市数="<<POINTCNT<<endl;
x.resize(POINTCNT);
y.resize(POINTCNT);
x[0]=87, x[1]=91,x[2]=83,x[3]=71,x[4]=64,x[5]=68,x[6]=83,x[7]=87,x[8]=74,x[9]=71;
y[0]=7, y[1]=38,y[2]=46,y[3]=44,y[4]=60,y[5]=58,y[6]=69,y[7]=76,y[8]=78,y[9]=71;
cout<<"各城市坐标:"<<endl;
for(int i=0;i<POINTCNT;i++)
{
//scanf("%lf%lf",&x[i],&y[i]);//输入各个城市的坐标
cout<<"["<<x[i]<<", "<<y[i]<<"]"<<endl;//输出各个城市的坐标
}
int select_type,make_p_type,k,cross_type,mutate_type;
double q,pc,pm;
//scanf("%d%d%d",&select_type,&make_p_type,&k);
//scanf("%lf%lf%lf",&q,&pc,&pm);
//scanf("%d%d",&cross_type,&mutate_type);
select_type=0,make_p_type=0,k=5;//个体选择方法类型,个体选择概率分配类型,竞赛规模
q=0.5,pc=0.85,pm=0.15;//最好个体选择概率,交叉概率,变异概率
cross_type=0,mutate_type=0;//交叉类型,变异类型
double best=1e9,worst=0,sum=0;
VI res;
for(int cas=0;cas<CASNUM;cas++)//进行10代的试验
{
other_population gen(POPSIZE,POINTCNT,cross_type,mutate_type,make_p_type,pc,pm,k,q,select_type);//初始化
for(int g=0;g<GENERATIONS;g++)//每次试验进行迭代进化(100代进化)
gen.next();//每代进化过程中都会记录最更好的染色体
if(best>1.0/gen.bestofpop.first)//更新历次最好适应度
{
best=1.0/gen.bestofpop.first;
res=*gen.bestofpop.second;//存放最好个体的染色体
}
if(worst<1.0/gen.bestofpop.first)//更新历次最差适应度
worst=1.0/gen.bestofpop.first;
sum+=1.0/gen.bestofpop.first;//计算各次最好个体的适应度之和
}
sum/=CASNUM;//计算平均适应度
cout<<endl;
cout<<"历次最好适应度:"<<best<<"\n"<<"历次最差适应度:"<<worst<<"\n"<<"平均适应度:"<<sum<<"\n";
cout<<"输出最好解:";
for(i=0;i<POINTCNT;i++)//输出解
{
cout<<res[i];//输出各城市
if (i<POINTCNT-1)
cout<<"-";
}
cout<<endl;
return 0;
}