模式识别hw1-------遗传算法寻找最短路径

遗传算法以及求解TSP介绍http://blog.csdn.net/bizer_csdn/article/details/51760110

《模式识别hw1-------遗传算法寻找最短路径》

要求是从a点出发,对结束点没要求,但必须经过所有点,并且允许重复。

这个问题不同于TSP,但是稍加改进就可以了。

其实,主要就是邻接矩阵中,任意两点之间存储的是两点之间的最短距离,比如,a—f之间的最短距离是2+1+3=6。

关于两点之间最短路径问题,这题给出的权重是正值,感觉可以使用dijkstra之类的算法,当初是手算的,以后有机会慢慢补充。

下面给出代码:

GA.cpp

#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <vector>
#include <algorithm>

using namespace std;

const double P_MAT=0.8; //交配概率
const double P_VAR=0.001;  //变异概率
const int TMAX=150;   //最大迭代次数

const int N=11; //11个城市


const int INF=1000; //表示图中不连通部分权重

const int GROUP_SIZE=300;//种群大小,300
vector<int> GROUP[GROUP_SIZE]; //种群




//邻接矩阵中存的是任意两节点的最短路径
int pointdist[N][N]={{  0,  2,  7,  1,  3,  6, 10,  5, 12, 11, 14},
                     {  2,  0,  5,  3,  1,  4,  8,  3, 10, 11, 12},
                     {  7,  5,  0,  7,  4,  1,  5,  6,  7,  6,  9}, 
                     {  1,  3,  7,  0,  4,  7,  9,  6, 11, 10, 13},
                     {  3,  1,  4,  4,  0,  3,  7,  2,  9, 10, 11},
                     {  6,  4,  1,  7,  3,  0,  4,  5,  6,  5,  8},
                     { 10,  8,  5,  9,  7,  4,  0,  9,  2,  1,  4},
                     {  5,  3,  6,  6,  2,  5,  9,  0,  7,  8,  9},
                     { 12, 10,  7, 11,  9,  6,  2,  7,  0,  1,  2},
                     { 11, 11,  6, 10, 10,  5,  1,  8,  1,  0,  3},
                     { 14, 12,  9, 13, 11,  8,  4,  9,  2,  3,  0}};


//随机产生一个新的基因
void newChrom(vector<int>& chrom)
{
	chrom.clear();
	//保证第一城市为'a'
	for(int i=0;i<N;i++)
	{
		chrom.push_back(i);
	}

	int i=0,j=0;
	do 
	{
		i=rand()%(N-1)+1;
		j=rand()%(N-1)+1;
	} while (!(i<j));//生成两个不同随机数
	//逆序法生成新染色体
	while(i<j)
	{
		swap(chrom[i++],chrom[j--]);
	}
}




//种群初始化
void group_init()
{
	for(int i=0;i<GROUP_SIZE;i++){
		newChrom(GROUP[i]);
	}
}


//计算每个染色体的适应值函数,即距离
int chrom_len(vector<int> chrom)
{
	int len=0;
	for(int i=0;i<chrom.size()-1;i++){
		int p1=chrom[i];
		int p2=chrom[i+1];
		len=len+pointdist[p1][p2];
	}
	return len;
}

bool descend_by_len(vector<int> chrom1,vector<int> chrom2)
{
	return chrom_len(chrom1)>chrom_len(chrom2);
}



//选择
void choose()
{
	//适应值函数为距离之和
	//为了加速进化过程,按着适应值函数从大到小进行排序
	//排序后,第i染色体被选中概率为2*i/GROUP_SIZE/(GROUP_SIZE+1)
	//采样“轮盘赌”算法模拟第i染色体被选中

	//"轮盘赌"算法进行选择
	//按着适应值函数从大到小进行排序,并计算排序后每个染色体被选中的概率
	vector<int> new_group[GROUP_SIZE];

	sort(GROUP,GROUP+GROUP_SIZE,descend_by_len);
	double p[GROUP_SIZE]={0.0};
	for(int i=0;i<GROUP_SIZE;i++){
		p[i]=(double)2*(i+1)/GROUP_SIZE/(GROUP_SIZE+1);
	}
	

	//进行GROUP_SIZE次选择
	for(int i=0;i<GROUP_SIZE;){
		//当随机数大于累计概率时候,该染色体被选中
		double r=rand()/(RAND_MAX+1.0);
		double s=0;

		for(int j=1;j<GROUP_SIZE;j++)
		{
			if(s>r||s==r){
				new_group[i]=GROUP[j-1];
				i++;
				break;
			}
			s=s+p[j];
		}

	}


	//把新生成种群放入全局变量GROUP中
	for(int i=0;i<GROUP_SIZE;i++)
		GROUP[i]=new_group[i];

}


//交配
void mate()
{
	int mat_num=(int)(P_MAT*GROUP_SIZE);
	//保证两两配对
	if(mat_num%2!=0)
		mat_num--;

	for(int i=0;i<mat_num;i++)
	{
		int j=rand()%GROUP_SIZE;
		int k=rand()%GROUP_SIZE;
		if(j==k)
			continue;
		swap(GROUP[j],GROUP[k]);
	}
	//交配方法为两两配对,同时生成两个子代,交配位随机生成
	//子代1的基因依次从父代2中挑取不重复的,子代2的基因依次从父代1中挑不重复的
	for(int i=0;i<(mat_num/2);i++)
	{		
		int n=2*i;
		vector<int>& chrom1=GROUP[n];
		vector<int>& chrom2=GROUP[n+1];
		vector<int> temp=chrom1;

		int pos=rand()%N;

		//pos之前不变,pos之后从另一父代中依次选不重复的
		//子代1
		for(int j=pos+1;j<N;)
		{
			for(int k=0;k<N;k++)
			{
				for(int s=0;s<j;s++)
				{
					if (chrom1[s]==chrom2[k])
					{
						break;
					} 
					else if(s==(j-1))
					{
						chrom1[j]=chrom2[k];
						j++;
					}
				}
			}
		}


		//子代2
		for(int j=pos+1;j<N;)
		{
			for(int k=0;k<N;k++)
			{
				for(int s=0;s<j;s++)
				{
					if (chrom2[s]==temp[k])
					{
						break;
					} 
					else if(s==(j-1))
					{
						chrom2[j]=temp[k];
						j++;
					}
				}
			}
		}

	}//交配循环结束 


}





//变异
void vary()
{
	int var_num=(int)(P_VAR*GROUP_SIZE);
	for(int i=0;i<var_num;i++){
		//变异规则为随机生成变异位,从该位开始按图的邻接关系随机生成后续节点
		vector<int>& curr_chrom=GROUP[i];
		newChrom(curr_chrom);
	}
}




//找出当前种群最短路径,并输出控制台
vector<int> find_best_in_group(int& min)
{
	int len[GROUP_SIZE];
	for(int i=0;i<GROUP_SIZE;i++){
		len[i]=chrom_len(GROUP[i]);
	}
	min=len[0];
	int s=0;
	for(int i=0;i<GROUP_SIZE;i++){
		if(min<len[i]){
			min=len[i];
			s=i;
		}
	}

	vector<int> best_in_group=GROUP[s];
	
	return best_in_group;
}

//还原真实路径并输出控制台
void print_real_path(vector<int> chrome,int& min)
{
	vector<int> real;


	for(int i=0;i<N-1;i++)
	{	
		int c1=chrome[i];
		int c2=chrome[i+1];
		real.push_back(c1);
		if (c1==0&&c2==2)//a-c最短路径:a-b-e-f-c:0-1-4-5-2
		{
			real.push_back(1);real.push_back(4);real.push_back(5);
		}
		else if (c1==2&&c2==0)//c-a最短路径:c-f-e-b-a:2-5-4-1-0
		{
			real.push_back(5);real.push_back(4);real.push_back(1);
		}
		else if ((c1==0&&c2==4)||(c1==4&&c2==0)) //a-e最短路径:a-b-e:0-1-4
		{
			real.push_back(1);
		}
		else if (c1==0&&c2==5) //a-f最短路径:a-b-e-f:0-1-4-5
		{
			real.push_back(1);real.push_back(4);
		}
		else if (c1==5&&c2==0) //f-a最短路径:f-e-b-a:5-4-1-0
		{
			real.push_back(4);real.push_back(1);
		}
		else if ((c1==0&&c2==6)||(c1==6&&c2==0)) //a-g最短路径:a-d-g:0-3-6
		{
			real.push_back(3);
		}
		else if (c1==0&&c2==7) //a-h最短路径:a-b-e-h:0-1-4-7
		{
			real.push_back(1);real.push_back(4);
		}
		else if (c1==7&&c2==0) //h-a最短路径:h-e-b-a:7-4-1-0
		{
			real.push_back(4);real.push_back(1);
		}
		else if (c1==0&&c2==8) //a-i最短路径:a-d-g-j-i:0-3-6-9-8
		{
			real.push_back(3);real.push_back(6);real.push_back(9);
		}
		else if (c1==8&&c2==0) //i-a最短路径:i-j-d-g-a:8-9-6-3-0
		{
			real.push_back(9);real.push_back(6);real.push_back(3);
		}
		else if (c1==0&&c2==9) //a-j最短路径:a-d-g-j:0-3-6-9
		{
			real.push_back(3);real.push_back(6);
		}
		else if (c1==9&&c2==0) //j-a最短路径:j-g-d-a:9-6-3-0
		{
			real.push_back(6);real.push_back(3);
		}
		else if (c1==0&&c2==10) //a-k最短路径:a-c-f-i-k:0-2-5-8-10
		{
			real.push_back(2);real.push_back(5);real.push_back(8);
		}
		else if (c1==10&&c2==0) //k-a最短路径:k-i-f-c-a:10-8-5-2-0
		{
			real.push_back(8);real.push_back(5);real.push_back(2);
		}
		else if (c1==1&&c2==2) //b-c最短路径:b-e-f-c:1-4-5-2
		{
			real.push_back(4);real.push_back(5);
		}
		else if (c1==2&&c2==1) //c-b最短路径:f-c-e-b:2-5-4-1
		{
			real.push_back(5);real.push_back(4);
		}
		else if ((c1==1&&c2==3)||(c1==3&&c2==1)) //b-d最短路径:b-a-d:1-0-3
		{
			real.push_back(0);
		}
		else if ((c1==1&&c2==5)||(c1==5&&c2==2)) //b-f最短路径:b-e-f:1-4-5
		{
			real.push_back(4);
		}
		else if (c1==1&&c2==6) //b-g最短路径:b-e-f-g:1-4-5-6
		{
			real.push_back(4);real.push_back(5);
		}
		else if (c1==6&&c2==1) //g-b最短路径:g-f-e-b:6-5-4-1
		{
			real.push_back(5);real.push_back(4);
		}
		else if ((c1==1&&c2==7)||(c1==7&&c2==1)) //b-h最短路径:b-e-h:1-4-7
		{
			real.push_back(4);
		}
		else if (c1==1&&c2==8) //b-i最短路径:b-e-h-i:1-4-7-8
		{
			real.push_back(4);real.push_back(7);
		}
		else if (c1==8&&c2==1) //i-b最短路径:i-h-e-b:8-7-4-1
		{
			real.push_back(7);real.push_back(4);
		}
		else if (c1==1&&c2==9) //b-j最短路径:b-e-h-i-j:1-4-7-8-9
		{
			real.push_back(4);real.push_back(7);real.push_back(8);
		}
		else if (c1==9&&c2==1) //j-b最短路径:j-i-h-e-b:9-8-7-4-1
		{
			real.push_back(8);real.push_back(7);real.push_back(4);
		}
		else if (c1==1&&c2==10) //b-k最短路径:b-e-h-k:1-4-7-10
		{
			real.push_back(4);real.push_back(7);
		}
		else if (c1==10&&c2==1) //k-b最短路径:k-h-e-b:10-7-4-1
		{
			real.push_back(7);real.push_back(4);
		}
		else if ((c1==2&&c2==4)||(c1==4&&c2==2)) //c-e最短路径:c-f-e:2-5-4
		{
			real.push_back(5);
		}
		else if ((c1==2&&c2==6)||(c1==6&&c2==2)) //c-g最短路径:c-f-g:2-5-6
		{
			real.push_back(5);
		}
		else if (c1==2&&c2==7) //c-h最短路径:c-f-e-h:2-5-4-7
		{
			real.push_back(5);real.push_back(4);
		}
		else if (c1==7&&c2==2) //h-c最短路径:h-e-f-c:7-4-5-2
		{
			real.push_back(4);real.push_back(5);
		}
		else if ((c1==2&&c2==8)||(c1==8&&c2==2)) //c-i最短路径:c-f-i:2-5-8
		{
			real.push_back(5);
		}
		else if (c1==2&&c2==9)//c-j最短路径:c-f-g-j:2-5-6-9
		{
			real.push_back(5);real.push_back(6);
		}
		else if (c1==9&&c2==2) //j-c最短路径:j-g-f-c:9-6-5-2
		{
			real.push_back(6);real.push_back(5);
		}
		else if (c1==2&&c2==10) //c-k最短路径:c-f-i-k:2-5-8-10
		{
			real.push_back(5);real.push_back(8);
		}
		else if (c1==10&&c2==2) //k-c最短路径:k-i-f-c:10-8-5-2
		{
			real.push_back(8);real.push_back(5);
		}
		else if (c1==3&&c2==4) //d-e最短路径:d-a-b-e:3-0-1-4
		{
			real.push_back(0);real.push_back(1);
		}
		else if (c1==4&&c2==3) //e-b最短路径:e-b-a-d:4-1-0-3
		{
			real.push_back(1);real.push_back(0);
		}
		else if (c1==3&&c2==5)//d-f最短路径:d-a-b-e-f:3-0-1-4-5
		{
			real.push_back(0);real.push_back(1);real.push_back(4);
		}
		else if (c1==5&&c2==3) //f-d最短路径:f-e-b-a-d:5-4-1-0-3
		{
			real.push_back(4);real.push_back(1);real.push_back(0);
		}
		else if (c1==3&&c2==7) //d-h最短路径:d-a-b-e-h:3-0-1-4-7
		{
			real.push_back(0);real.push_back(1);real.push_back(4);
		}
		else if (c1==7&&c2==3) //h-d最短路径:h-e-b-a-d:7-4-1-0-3
		{
			real.push_back(4);real.push_back(1);real.push_back(0);
		}
		else if (c1==3&&c2==8) //d-i最短路径:d-g-j-i:3-6-9-8
		{
			real.push_back(6);real.push_back(9);
		}
		else if (c1==8&&c2==3) //i-d最短路径:i-j-g-d:8-9-6-3
		{
			real.push_back(9);real.push_back(6);
		}
		else if ((c1==3&&c2==9)||(c1==9&&c2==3)) //d-j最短路径:d-g-j:3-6-9
		{
			real.push_back(6);
		}
		else if (c1==3&&c2==10) //d-k最短路径:d-g-j-k:3-0-9-10
		{
			real.push_back(0);real.push_back(9);
		}
		else if (c1==10&&c2==3) //k-d最短路径:k-j-g-d:10-9-0-3
		{
			real.push_back(9);real.push_back(0);
		}
		else if ((c1==4&&c2==6)||(c1==6&&c2==4)) //e-g最短路径:e-f-g:4-5-6
		{
			real.push_back(5);
		}
		else if ((c1==4&&c2==8)||(c1==8&&c2==4)) //e-i最短路径:e-h-i:4-7-8
		{
			real.push_back(7);
		}
		else if (c1==4&&c2==9) //e-j最短路径:e-h-i-j:4-7-8-9
		{
			real.push_back(7);real.push_back(8);
		}
		else if (c1==9&&c2==4) //j-e最短路径:j-i-h-e:9-8-7-4
		{
			real.push_back(8);real.push_back(7);
		}
		else if ((c1==4&&c2==10)||(c1==10&&c2==4)) //e-k最短路径:e-h-k:4-7-10
		{
			real.push_back(7);
		}
		else if ((c1==5&&c2==7)||(c1==7&&c2==5)) //f-h最短路径:f-e-h:5-4-7
		{
			real.push_back(4);
		}
		else if (c1==5&&c2==8) //f-i最短路径:f-g-j-i:5-6-9-8
		{
			real.push_back(6);real.push_back(9);
		}
		else if (c1==8&&c2==5) //i-f最短路径:i-j-g-f:8-9-6-5
		{
			real.push_back(9);real.push_back(6);
		}
		else if ((c1==5&&c2==9)||(c1==9&&c2==5)) //f-j最短路径:f-g-j:5-6-9
		{
			real.push_back(6);
		}
		else if ((c1==5&&c2==10)||(c1==10&&c2==5)) //f-k最短路径:f-i-k:5-8-10
		{
			real.push_back(4);
		}
		else if (c1==6&&c2==7) //g-h最短路径:g-j-i-h:6-9-8-7
		{
			real.push_back(9);real.push_back(8);
		}
		else if (c1==7&&c2==6) //h-g最短路径:h-j-i-g
		{
			real.push_back(8);real.push_back(9);
		}
		else if ((c1==6&&c2==8)||(c1==8&&c2==6)) //g-i最短路径:g-j-i:6-9-8
		{
			real.push_back(9);
		}
		else if (c1==6&&c2==10) //g-k最短路径:g-j-i-k:6-9-8-10
		{
			real.push_back(9);real.push_back(8);
		}
		else if (c1==10&&c2==6) //k-g最短路径:k-i-j-g:10-8-9-6
		{
			real.push_back(8);real.push_back(9);
		}
		else if ((c1==7&&c2==9)||(c1==9&&c2==7)) //h-j最短路径:h-i-j:7-8-9
		{
			real.push_back(8);
		}
		else if ((c1==9&&c2==10)||(c1==10&&c2==9)) //j-k最短路径:j-i-k:9-8-10
		{
			real.push_back(8);
		}

	}//for循环结束
	real.push_back(chrome[N-1]);

	//a,b,...,k(ASCII码97,...,107)分别对应0,1,...,10
	cout<<"shortest in current group: ";
	for(vector<int>::iterator iter=real.begin();iter!=real.end();iter++){
		char ch=(*iter)+97;
		if(iter!=real.end()-1)
			cout<<ch<<"-";
		else
			cout<<ch;

	}
	cout<<"   "<<min<<endl;
}



void main( )
{
	
	clock_t start,end;
	start=clock();

	int best=0;//最短距离
	vector<int> best_path;



	//初始化随机数
	srand((int)time(0));
	//种群初始化
	group_init();
	best_path=find_best_in_group(best);

	int curr_best=best;
	vector<int> curr_best_path;


	for(int t=0;t<TMAX;t++){

		//选择
		choose();
		//交配
		mate();
		//变异
		vary();

		//找出当前种群最短路径,并输出控制台
		curr_best_path=find_best_in_group(curr_best);
		print_real_path(curr_best_path,curr_best);

		if(curr_best<best)
		{
			best=curr_best;
			best_path=curr_best_path;
		}
	}


	end=clock();
	printf("\nrun time:  %fs\n\n\n",(double)(end-start)/CLOCKS_PER_SEC);


	printf("shortest: ");
	print_real_path(best_path,best);


	getchar();

}

结果:

《模式识别hw1-------遗传算法寻找最短路径》

《模式识别hw1-------遗传算法寻找最短路径》

结果可能不唯一;

同时代码261-516行,最短路径转化为真实路径过程中,可能有点小bug……

希望能够指正

    原文作者:遗传算法
    原文地址: https://blog.csdn.net/bizer_csdn/article/details/51789491
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞