基于精英选择策略的遗传算法

应用于TSP问题,对其他NP问题可能需要改变编码策略,以下是C++实现


/*由Parrot改进的遗传算法求解TSP
*
*选择操作使用转赌轮算法
*变异算子采用逆转变异算法
*交叉时先使用顺序编码,单点交叉,然后解码 
*/

#include 
#include 
#include 
#include 
#include 
#include
#include
#include 
#include 
using namespace std;

unsigned int cityNum=20; //城市数目
double** dist;  //两两城市之间距离
const unsigned int generation = 5000;	 //迭代次数
const unsigned int populationSize = 50;  //染色体数目
unsigned int chromLen = cityNum;   //单条染色体序列长度,在这里为城市数目cityNum

const double mutationRate = 0.07;  //基因突变概率
const double crossoverRate = 0.95;	 //两条染色体交叉概率
const int select_chromPair = 30; //选择染色体交叉对的次数
//等级选择+轮盘赌算法
//无条件保留最优的5条解,其余的分成5个等级,选择rank[5,10)的概率为2%
//选择rank[10,20)的概率为10%, 选择rank[20,30)的概率为18%
//选择rank[30,40)的概率为30%,选择rank[40,50)的概率为40%
//每个等级内部则根据其适应函数按轮盘赌算法选择

//轮盘赌算法,用于等级算法的第二次选择
int roulette_select(const double *fitness,int p,int r)
{
	int i;
	double* stage=new double[r-p+1];
	stage[0] = fitness[p];
	for (i=1;istage[i]) i++;
	delete[] stage;
	return p+i;
}

int rank_select(const double* fitness,int sz)
{
	int i;
	//第一次选择等级区间
	int rand_num = rand()%100;
	if(rand_num<2) return roulette_select(fitness,5,9);
	if(rand_num<12) return roulette_select(fitness,10,19);
	if(rand_num<30) return roulette_select(fitness,20,29);
	if(rand_num<60) return roulette_select(fitness,30,39);
	return roulette_select(fitness,40,49);
}

//生成[0,n-1]的随机序列,保存到randorder中
void rand_int_order(vector& randorder,const int n)   
{   
	assert(n>1);  

	randorder.clear();
	randorder.resize(n);
	vector recoder;
	for (int i=0;i& chromosome)
{
	vector standard;
	for (int i=0;i::iterator ite;
	for (int i=0;i& chromosome)
{
	vectorstandard;
	for (int i=0;i &path)
{
	double sum=0;
	for(int i=1;i<=chromLen;i++) sum+=dist[path[i-1]][path[i%chromLen]];
	return sum;
}

//初始化各城市之间的距离
void init(){
	fstream fin("input_data.txt",ios::in);
	dist=new double*[cityNum];
	for (int i=0;i>data;
			if(i!=j) dist[i][j]=dist[j][i]=data;
			else dist[i][j]=0;
		}
	}
	fin.close();
}

void run()
{	
	fstream fout("output.txt",ios::out);
	int curTime=int(time(0));

	srand((unsigned)time(NULL));

	// 染色体数组
	vector > population; //第0代

	//随机化染色体序列
	for (int i=0;i chromo; 
		rand_int_order(chromo,chromLen); //随机产生一个可行解(用chromo表示)
		population.push_back(chromo); 
	} 

	double glob_best_len = INT_MAX;  //整个进化过程中得到的最优路径的长度
	vector glob_best_path; //整个进化过程中得到的最优路径

	//开始进化
	for (int g=0;g > parent;   //parent为population按适应函数插入排序后得到的染色体组
		for(int i=0;i=fitness[j]) j++;  //插入位置
			parent.insert(parent.begin()+j,population[i]);
			double tmp = fitness[i]; 
			for(int k=i;k>=j+1;k--) fitness[k]=fitness[k-1];    //同时更改fitness
			fitness[j]=tmp;  
		}

		population.clear(); //清空population,用以保存下一轮染色体
		fout<<"**************************************************************************\n";
		fout<<"第 "<";
			fout<<"\n\n";
		}
		fout<<"**************************************************************************\n";

		if(glob_best_len>fitness[0]){ glob_best_len=fitness[0]; glob_best_path = parent[0];} 

		//选择25对交叉的染色体序号,去掉重复的
		unordered_map tab;   //交叉对
		for(int i=0;i baby = parent[i];
				if(rand()*1.0/RAND_MAX < mutationRate){ //进行变异
					int p1 = rand()%chromLen, p2 = p1;
					while(p1==p2) p2=rand()%chromLen;

					//逆转baby染色体的某一段 
					reverse(baby.begin()+ min(p1,p2),baby.begin()+ max(p1,p2));
				}
				//精英策略,若是比当前代更差,则不保留baby
				if(caculate_fit(baby)::iterator it = tab.begin();
			int k1 = it->first, k2 = it->second;
			vector baby1 = parent[k1], baby2 = parent[k2];
			tab.erase(k1);
			tab.erase(k2);
			if (rand()*1.0/RAND_MAX


你可能感兴趣的:(算法,遗传算法,TSP,高级算法,C++)