zoukankan      html  css  js  c++  java
  • 概率种群遗传算法解决TSP问题

    工作之余抽点时间出来写写博文,希望对新接触的朋友有帮助。今天在这里和大家一起学习一下概率种群

        遗传算法(Genetic Algorithm)是模拟达尔文生物进化论的天然选择和遗传学机理的生物进化过程的盘算模型,是一种通过模拟天然进化过程搜索最优解的方法

        遗传算法的基本运算过程如下:

        a)初始化:设置进化代数计数器t=0,设置最大进化代数T,随机生成M个个体作为初始群体P(0)。

        b)个体评价:盘算群体P(t)中各个个体的适应度。

        c)选择运算:将选择算子作用于群体。选择的目标是把优化的个体直接遗传到下一代或通过配对交叉发生新的个体再遗传到下一代。选择操作是建立在群体中个体的适应度评估基础上的。

        d)交叉运算:将交叉算子作用于群体。所谓交叉是指把两个父代个体的部份结构加以替换重组而生成新个体的操作。遗传算法中起核心作用的就是交叉算子。

        e)变异运算:将变异算子作用于群体。即是对群体中的个体串的某些基因座上的基因值作变动。

        群体P(t)经过选择、交叉、变异运算以后得到下一代群体P(t 1)。

        f)终止条件判断:若t=T,则以进化过程中所得到的拥有最大适应度个体作为最优解输出,终止盘算。

        上面用C语言模拟遗传算法模拟TSP问题

        TSP问题及旅行商问题,假设有一个旅行商人要拜访n个都会,他必须选择所要走的路径,路径的制约是每一个都会只能拜访一次,而且最后要回到本来出发的都会。路径的选择目标是要求得的路径行程为所有路径当中的最小值

        交叉的算法如下图

        概率和种群

        

        每日一道理
    俄国作家契诃夫说:“有大狗,有小狗,小狗不该因为大狗的存在而心慌意乱。所有的狗都应该叫,就让他各自用上帝给他的声音。
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<math.h>
    #include<time.h>
    #define cities 10  //都会的个数
    #define MAXX 100//迭代次数
    #define pc 0.8 //交配概率
    #define pm 0.05 //变异概率
    #define num 10//种群的大小
    int bestsolution;//最优染色体
    int distance[cities][cities];//都会之间的距离
    struct group  //染色体的结构
    {
    	int city[cities];//都会的顺序
    	int adapt;//适应度
    	double p;//在种群中的幸存概率
    }group[num],grouptemp[num];
    //随机发生cities个都会之间的相互距离
    void init()
    {
    	int i,j;
    	memset(distance,0,sizeof(distance));
    	srand((unsigned)time(NULL));
        for(i=0;i<cities;i++)
    	{
    	    for(j=i+1;j<cities;j++)
    		{
    		   distance[i][j]=rand()%100;
    		   distance[j][i]=distance[i][j];
    		}
    	}
    	//打印距离矩阵
    	printf("都会的距离矩阵如下\n");
    	for(i=0;i<cities;i++)
    	{
    		for(j=0;j<cities;j++)
    		printf("%4d",distance[i][j]);
    		printf("\n");
    	}
    }
    //随机发生初试群
    void groupproduce()
    {
    	int i,j,t,k,flag;
    	for(i=0;i<num;i++)  //初始化
    	for(j=0;j<cities;j++)
    	group[i].city[j]=-1;
    	srand((unsigned)time(NULL));
        for(i=0;i<num;i++)
    	{
    		//发生10个不相同的数字
    		for(j=0;j<cities;)
    		{
    			t=rand()%cities;
    			flag=1;
    			for(k=0;k<j;k++)
    			{
    				if(group[i].city[k]==t)
    				{
    					flag=0;
    					break;
    				}
    			}
    			if(flag)
    			{
    				group[i].city[j]=t;
    				j++;
    			}
    		}
    	}
    	//打印种群基因
    	printf("初始的种群\n");
    	for(i=0;i<num;i++)
    	{
    		for(j=0;j<cities;j++)
    		printf("%4d",group[i].city[j]);
    		printf("\n");
    	}
    }
    //评价函数,找出最优染色体
    void pingjia()
    {
    	int i,j;
    	int n1,n2;
    	int sumdistance,biggestsum=0;
    	double biggestp=0;
    	for(i=0;i<num;i++)
    	{
    		sumdistance=0;
    		for(j=1;j<cities;j++)
    		{
    			n1=group[i].city[j-1];
    			n2=group[i].city[j];
    			sumdistance+=distance[n1][n2];
    		}
    		group[i].adapt=sumdistance; //每条染色体的路径总和
    		biggestsum+=sumdistance; //种群的总路径
    	}
    	//盘算染色体的幸存能力,路劲越短生活概率越大
    	for(i=0;i<num;i++)
    	{
    		group[i].p=1-(double)group[i].adapt/(double)biggestsum; 
    		biggestp+=group[i].p;
    	}
    	for(i=0;i<num;i++)
    	group[i].p=group[i].p/biggestp;  //在种群中的幸存概率,总和为1
    	//求最佳路劲
    	bestsolution=0;
    	for(i=0;i<num;i++)
    	if(group[i].p>group[bestsolution].p)
    	bestsolution=i;
    	//打印适应度
    	for(i=0;i<num;i++)
    	printf("染色体%d的路径之和与生活概率分别为%4d  %.4f\n",i,group[i].adapt,group[i].p);
    	printf("当前种群的最优染色体是%d号染色体\n",bestsolution);
    }
    //选择
    void xuanze()
    {
    	int i,j,temp;
    	double gradient[num];//梯度概率
    	double xuanze[num];//选择染色体的随机概率
    	int xuan[num];//选择了的染色体
    	//初始化梯度概率
    	for(i=0;i<num;i++)
    	{
    		gradient[i]=0.0;
    		xuanze[i]=0.0;
    	}
    	gradient[0]=group[0].p;
    	for(i=1;i<num;i++)
    	gradient[i]=gradient[i-1]+group[i].p;
    	srand((unsigned)time(NULL));
    	//随机发生染色体的存活概率
    	for(i=0;i<num;i++)
    	{
    		xuanze[i]=(rand()%100);
    		xuanze[i]/=100;
    	}
    	//选择能生活的染色体
    	for(i=0;i<num;i++)
    	{
    		for(j=0;j<num;j++)
    		{
    			if(xuanze[i]<gradient[j])
    			{
    				xuan[i]=j; //第i个位置存放第j个染色体
    				break;
    			}
    		}
    	}
    	//拷贝种群
    	for(i=0;i<num;i++)
    	{
    		grouptemp[i].adapt=group[i].adapt;
    		grouptemp[i].p=group[i].p;
    		for(j=0;j<cities;j++)
    		grouptemp[i].city[j]=group[i].city[j];
    	}
    	//数据更新
    	for(i=0;i<num;i++)
    	{
    		temp=xuan[i];
    		group[i].adapt=grouptemp[temp].adapt;
    		group[i].p=grouptemp[temp].p;
    		for(j=0;j<cities;j++)
    		group[i].city[j]=grouptemp[temp].city[j];
    	}
    	//用于测试
    	/*
    	printf("<------------------------------->\n");
    	for(i=0;i<num;i++)
    	{
    		for(j=0;j<cities;j++)
    		printf("%4d",group[i].city[j]);
    		printf("\n");
    		printf("染色体%d的路径之和与生活概率分别为%4d  %.4f\n",i,group[i].adapt,group[i].p);
    	}
    	*/
    }
    //交配,对每一个染色体发生交配概率,满意交配率的染色体停止交配
    void  jiaopei()
    {
    	int i,j,k,kk;
    	int t;//介入交配的染色体的个数
    	int point1,point2,temp;//交配断点
    	int pointnum;
    	int temp1,temp2;
    	int map1[cities],map2[cities];
    	double jiaopeip[num];//染色体的交配概率
    	int jiaopeiflag[num];//染色体的可交配情况
    	for(i=0;i<num;i++)//初始化
    	jiaopeiflag[i]=0;
    	//随机发生交配概率
    	srand((unsigned)time(NULL));
    	for(i=0;i<num;i++)
    	{
    		jiaopeip[i]=(rand()%100);
    		jiaopeip[i]/=100;
    	}
    	//肯定可以交配的染色体
    	t=0;
    	for(i=0;i<num;i++)
    	{
    		if(jiaopeip[i]<pc)
    		{
    			jiaopeiflag[i]=1;
    			t++;
    		}
    	}
    	t=t/2*2;//t必须为偶数
    	//发生t/2个0-9交配断点
        srand((unsigned)time(NULL));
    	temp1=0;
    	//temp1号染色体和temp2染色体交配
    	for(i=0;i<t/2;i++)
    	{
    		point1=rand()%cities;
    		point2=rand()%cities;
    		for(j=temp1;j<num;j++)
    		if(jiaopeiflag[j]==1)
    		{
    			temp1=j;
    			break;
    		}
    		for(j=temp1+1;j<num;j++)
    		if(jiaopeiflag[j]==1)
    		{
    			temp2=j;
    			break;
    		}
    		//停止基因交配
    		if(point1>point2) //保障point1<=point2
    		{
    			temp=point1;
    			point1=point2;
    			point2=temp;
    		}
            memset(map1,-1,sizeof(map1));
    		memset(map2,-1,sizeof(map2));
    		//断点之间的基因发生映射
    		for(k=point1;k<=point2;k++)
    		{
    			map1[group[temp1].city[k]]=group[temp2].city[k];
    			map2[group[temp2].city[k]]=group[temp1].city[k];
    		}
    		//断点两边的基因互换
    		for(k=0;k<point1;k++)
    		{
    			temp=group[temp1].city[k];
    			group[temp1].city[k]=group[temp2].city[k];
    			group[temp2].city[k]=temp;
    		}
    		for(k=point2+1;k<cities;k++)
    		{
    			temp=group[temp1].city[k];
    			group[temp1].city[k]=group[temp2].city[k];
    			group[temp2].city[k]=temp;
    		}
    		//处理发生的冲突基因
    		for(k=0;k<point1;k++)
    		{
    			for(kk=point1;kk<=point2;kk++)
    			if(group[temp1].city[k]==group[temp1].city[kk])
    			{
    				group[temp1].city[k]=map1[group[temp1].city[k]];
    				break;
    			}
    		}
    		for(k=point2+1;k<cities;k++)
    		{
    			for(kk=point1;kk<=point2;kk++)
    			if(group[temp1].city[k]==group[temp1].city[kk])
    			{
    				group[temp1].city[k]=map1[group[temp1].city[k]];
    				break;
    			}
    		}
    		for(k=0;k<point1;k++)
    		{
    			for(kk=point1;kk<=point2;kk++)
    			if(group[temp2].city[k]==group[temp2].city[kk])
    			{
    				group[temp2].city[k]=map2[group[temp2].city[k]];
    				break;
    			}
    		}
    		for(k=point2+1;k<cities;k++)
    		{
    			for(kk=point1;kk<=point2;kk++)
    			if(group[temp2].city[k]==group[temp2].city[kk])
    			{
    				group[temp2].city[k]=map2[group[temp2].city[k]];
    				break;
    			}
    		}
            temp1=temp2+1;
    	}
    }
    //变异
    void bianyi()
    {
    	int i,j;
    	int t;
    	int temp1,temp2,point;
    	double bianyip[num]; //染色体的变异概率
    	int bianyiflag[num];//染色体的变异情况
    	for(i=0;i<num;i++)//初始化
    	bianyiflag[i]=0;
    	//随机发生变异概率
    	srand((unsigned)time(NULL));
    	for(i=0;i<num;i++)
    	{
    		bianyip[i]=(rand()%100);
    		bianyip[i]/=100;
    	}
    	//肯定可以变异的染色体
    	t=0;
    	for(i=0;i<num;i++)
    	{
    		if(bianyip[i]<pm)
    		{
    			bianyiflag[i]=1;
    			t++;
    		}
    	}
    	//变异操作,即交换染色体的两个节点
    	srand((unsigned)time(NULL));
    	for(i=0;i<num;i++)
    	{
    		if(bianyiflag[i]==1)
    		{
    	        temp1=rand()%10;
    			temp2=rand()%10;
    			point=group[i].city[temp1];
                group[i].city[temp1]=group[i].city[temp2];
    			group[i].city[temp2]=point;
    		}
    	}
    }
    int main()
    {
    	int i,j,t;
        init();
    	groupproduce();
    	//初始种群评价
    	pingjia();
    	t=0;
        while(t++<MAXX)
    	{
    	     xuanze();
    		 //jiaopei();
    		 bianyi();
    		 pingjia();
    	}
    	//最终种群的评价
    	printf("\n输出最终的种群评价\n");
    	for(i=0;i<num;i++)
    	{
    		for(j=0;j<cities;j++)
    		{
    			printf("%4d",group[i].city[j]);
    		}
    		printf("  adapt:%4d, p:%.4f\n",group[i].adapt,group[i].p);
    	}
    	printf("最优解为%d号染色体\n",bestsolution);
    	return 0;
    }

        概率和种群

    文章结束给大家分享下程序员的一些笑话语录: 人在天涯钻,哪儿能不挨砖?日啖板砖三百颗,不辞长做天涯人~

    --------------------------------- 原创文章 By
    概率和种群
    ---------------------------------

  • 相关阅读:
    最常用和最难用的控件--ListView(Android第一行代码)
    LayoutInflater的使用
    JAVA的网络编程【转】
    Android 程序调试
    android Log日志使用
    Android Animation
    实现ImageView宽度填满屏幕
    Android ViewPager使用详解
    对另一个布局文件里的Button按钮进行监听
    如何在一个Activity里使用另一个xml布局文件
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3100712.html
Copyright © 2011-2022 走看看