遗传算法

Posted 光何

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了遗传算法相关的知识,希望对你有一定的参考价值。

摘要遗传算法(geneticalgorithmsGA)是模仿生物遗传学自然选择机理,在对随机自适应的全局搜索算法Holland霍兰德)及自然界的“自然选择”和“优胜劣汰”Darwin达尔文)和生物遗传学说( Gregor Johann Mendel格里果·约翰·孟德尔)的理论进行综合,通过人工方式所构造的一类随机自适应全局优化搜索算法,是对生物进化过程进行的一种数学仿真,是进化计算的最重要的形式。遗传算法为那些难以找到传统数学模型的难题指出了一个解决方法。进化计算和遗传算法借鉴了生物科学中的某些知识,这也体现了人工智能这一交叉学科的特点。本文主要论述计算机科学与技术专业大三下专业课《人工智能》第六个实验算法。

关键字:人工智能,遗传算法,进化计算

Production system

Abstract: Genetic algorithm (geneticalgorithms, GA) is mimic biological genetics and natural selection mechanism, the random global search algorithm of adaptive (Holland, Mr Rand) and the nature of "natural selection" and "evolution" Darwin (Charles Darwin) and biological genetic theory (Gregor Johann Mendel in fruit, John Mendel) theory synthetically, through artificial means the constructed a kind of random adaptive global optimization search algorithm, is a kind of mathematical simulation of biological evolution process, is the most important form of evolutionary computation. Genetic algorithm (ga) for those who are hard to find the problem of traditional mathematical model points out a solution. Evolutionary computation and genetic algorithm is used to refer to some knowledge of the biological sciences, this also reflected the characteristics of artificial intelligence in the interdisciplinary. This paper mainly discusses the computer science and technology under the junior in professional class "artificial intelligence" sixth experiment algorithm.

Keywords: Artificial intelligence, genetic algorithms, evolutionary computation

1,编码与译码

  进化计算求解问题的第一步是对问题的可能解进行编码,目的是为了有效地执行遗传操作。编码是一个从问题的解空间到编码空间的映射。如许多应用问题结构很复杂,但可以化为简单的位串形式编码表示,变换为位串形式编码表示的过程叫编码;将问题结构而相反将位串形式编码表示变换为原问题结构的过程叫译码。

 借用生物的术语,把位串形式的解的编码表示叫染色体基因型(基因表达),或叫个体原问题结构即一个染色体解码后所对应的解称为表现型编码空间也称为基因型空间或搜索空间。解空间也称为表现型空间。

    进化算法不是直接作用在问题的解空间上,而是交替地作用在编码空间和解空间上。编码空间对个体进行遗传操作,在解空间对问题的解进行评估
         技术分享

2,适应度函数

为了体现染色体的适应能力,引入了对问题中的每一个染色体都能进行度量的函数,叫适应度函数。通过适应度函数来决定染色体的优、劣程度,它体现了自然进化中的优胜劣汰原则。对优化问题,适应度函数就是目标函数。TSP的目标是路径总长度为最短,路径总长度的倒数就可以为TSP的适应度函数。
    
其中wn+1= w1。适应度函数要有效反映每一个染色体与问题的最优解染色体之间的差距,一个染色体与问题的最优解染色体之间的差距小,则对应的适应度函数值之差就小,否则就大。适应度函数的取值大小与求解问题对象的意义有很大的关系。 

技术分享
3,遗传操作

    简单遗传算法的遗传操作主要有三种:选择(selection)、交叉(crossover)、变异(mutation)改进的遗传算法大量扩充了遗传操作,以达到更高的效率。

    选择操作也叫复制操作,根据个体的适应度函数值所度量的优、劣程度决定它在下一代是被淘汰还是被遗传。一般地说,选择将使适应度较大(优良)个体有较大的存在机会,而适应度较小(低劣)的个体继续存在的机会也较小。

    1)计算各染色体适应度值

    2)累计所有染色体适应度值(或选择概率),记录每个个体的适应度累加值(或概率累加值)

    3) 产生一个随机数 r0< r < sumN(0< r < 1

    4)若sumk-1< r  sumk(qk-1< r  qk ,则选择第k个个体进入交配池。
 
5) 重复(3)和(4),直到获得足够的染色体。  
 

4,程序流程
 

    
一般遗传算法的主要步骤如下:

(1) 随机产生一个由确定长度的特征字符串组成的初始群体。

(2) 对该字符串群体迭代的执行下面的步①和② ,直到满足停止标准:

①计算群体中每个个体字符串的适应值;

②应用选择、交叉和变异等遗传算子产生下一代群体。

      (3) 把在后代中出现的最好的个体字符串指定为遗传算法的执行结果,这个结果可以表示问题的一个解。 

        技术分享


5,问题解析


技术分享 


技术分享

技术分享 
技术分享

技术分享

技术分享


6,程序设计

技术分享 


#include<iostream>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<iomanip>
using namespace std;

const int NUM=1000;       //最大迭代次数
const int POP_SIZE=50;   //种群规模:个体数量
const int GENE=33;       //每个个体染色体个数
const int GB1=18;        //染色体手段基因片段(二进制)
const int GB2=15;        //染色体末端基因片段(二进制)
const int GD=6;          //十进制保留小数点位数
const double PI=3.1415926;

void initialize(int v[][GENE])   //初始化群体
{
	int ii,ij;
	srand(time(0));
	cout<<"基因初始化:"<<endl;
	for(ii=0;ii<POP_SIZE;ii++)
	{	
		cout<<endl<<"个体"<<setw(2)<<ii+1<<"基因型 ";
		for(ij=0;ij<GENE;ij++)
		{
			v[ii][ij]=2*rand()/RAND_MAX;
			cout<<v[ii][ij];
		}
	}
	cout<<endl;
}

void evaluation(int v[][GENE],double eval[]) //评估函数
{	
	int ii,ij;
	double x1,x2;
	for(ii=0;ii<POP_SIZE;ii++)
	{	
		x1=x2=0;             
		for(ij=0;ij<GB1;ij++)   //二进制片段转为十进制编码
		{
			x1+=v[ii][ij]*pow(2,(GB1-(ij+1)));
		}
		for(ij=GB1;ij<GENE;ij++)
		{
			x2+=v[ii][ij]*pow(2,(GENE-(ij+1)));
		}
		x1=-3.0+x1*(12.1-(-3.0))/(pow(2,GB1)-1);   //十进制编码转为十进制值
		x2=4.1+x2*(5.8-4.1)/(pow(2,GB2)-1);
		eval[ii]=21.5+x1*sin(4*PI*x1)+x2*sin(20*PI*x2);
	}
}

int best_eval(double eval[])   //找出每代中最优秀个体基因值
{	
	int ii,cursor=0;
	for(ii=0;ii<POP_SIZE;ii++)
	{	
		if(eval[ii]>eval[cursor])
		{
			cursor=ii;
		}
	}
	return cursor;
}

int worst_eval(double eval[])   //找出每代中最差个体基因值
{	
	int ii,cursor=0;
	for(ii=0;ii<POP_SIZE;ii++)
	{	
		if(eval[ii]<eval[cursor])
		{
			cursor=ii;
		}
	}
	return cursor;
}

void selection(double eval[],int v[][GENE],int v_next[][GENE])
{	
	int ii,ij,ik;
	double value;
	double p[POP_SIZE];         //选择概率
	double pp[POP_SIZE]={0};     //累积概率
	double total_value=0;
	for(ii=0;ii<POP_SIZE;ii++)
	{
		total_value+=eval[ii];
	}
	for(ii=0;ii<POP_SIZE;ii++)
	{
		p[ii]=eval[ii]/total_value;
	}
	pp[0]=p[0];
	for(ii=1;ii<POP_SIZE;ii++)
	{
		pp[ii]=pp[ii-1]+p[ii];
	}
	for(ii=0;ii<POP_SIZE;ii++)      //对于每个次代个体的基因型 
	{	
		value=(double)rand()/RAND_MAX;   //转动轮盘 
		for(ij=0;ij<POP_SIZE;ij++)       //搜索命中区域 
		{	
			if(value<pp[ij])             //找到后复制、跳出 
			{	
				for(ik=0;ik<GENE;ik++)
				{
					v_next[ii][ik]=v[ij][ik];
				}
				break;
			}
		}
	}
}

void crossover(int v[][GENE])
{	
	int ii,ij,ik;
	double p=0.8,value1;
	int n=0,tmp,value2;
	int cursor[POP_SIZE]={-1};     //被选中的染色体下标
	for(ii=0;ii<POP_SIZE;ii++)     //找被选中的染色体下标
	{	
		value1=(double)rand()/RAND_MAX;
		if(value1<p)
		{
			cursor[n++]=ii;
		}
	}
	for(ii=0;ii<n;ii+=2)              //两两配对,进行交叉
	{	
		value2=(int)(GENE-1)*rand()/RAND_MAX+1;
		for(ij=value2;ij<GENE;ij++)
		{	
			tmp=v[cursor[ii]][ij];
			v[cursor[ii]][ij]=v[cursor[ii+1]][ij];
			v[cursor[ii+1]][ij]=tmp;
		}
	}
}

void mutation(int v[][GENE])
{	
	int ii,ij,ik;
	int sum,gene;     //基因变异数目
	double pm=0.01;   //变异概率
	sum=(int)(POP_SIZE*GENE*pm)+1;
	for(ii=0;ii<sum;ii++)
	{	
		gene=(int)(POP_SIZE*GENE)*rand()/RAND_MAX;
		ij=gene/(POP_SIZE*GENE);
		ik=gene%(POP_SIZE*GENE);
		v[ij][ik]=1-v[ij][ik];
	}
}

int main(int argc,char **argv)
{	
	int ii,ij,ik,max=0;
	int v[POP_SIZE][GENE];          //本代群体基因库
	int v_next[POP_SIZE][GENE];     //次代群体基因库
	double eval[POP_SIZE];                   //本代群体评估值
	double eval_next[POP_SIZE];              //次代群体评估值
	int best_cursor;                //本代最优个体适值下标
	int best_next_cursor;           //次代最优个体适值下标
	int worst_next_cursor;          //次代最差个体适值下标
	int best_gene[GENE];            //本代最优个体基因型
	initialize(v);  
	for(ii=0;ii<NUM&&max<50;ii++)
	{	
		evaluation(v,eval);               //本代基因评估
		best_cursor=best_eval(eval);      //本代最优个体
		cout<<endl<<"第"<<setw(3)<<ii+1<<"代最优基因:";
		for(ij=0;ij<GENE;ij++)            //保存本代最优基因
		{
			best_gene[ij]=v[best_cursor][ij];
			cout<<best_gene[ij];
		}
		cout<<" 适值:"<<eval[best_cursor];
		selection(eval,v,v_next);       //选择    
		crossover(v_next);              //交叉
		mutation(v_next);               //变异
		evaluation(v_next,eval_next);  
		worst_next_cursor=worst_eval(eval_next); 
		for(ij=0;ij<GENE;ij++)
		{
			v_next[worst_next_cursor][ij]=best_gene[ij];
		}
		evaluation(v_next,eval_next);  
		best_next_cursor=best_eval(eval_next); 
		eval[best_cursor]==eval_next[best_next_cursor]?max++:max=0;
		for(ij=0;ij<POP_SIZE;ij++)
		{
			for(ik=0;ik<GENE;ik++)
			{
				v[ij][ik]=v_next[ij][ik];
			}
		}
	}
	cout<<endl<<"最优基因适值为:"<<eval[best_cursor]<<endl;
	cout<<"迭代次数为:"<<ii<<endl;
	system("pause");
	return 0;
}
/*
**本题最优值是38.818208

(1)  初始化群体;
(2)  计算群体上每个个体的适应度值;
(3)  按由个体适应度值所决定的某个规则选    
       择将进入下一代的个体;
(4)  按概率Pc进行交叉操作;
(5)  按概率Pm进行突变操作;
(6) 若没有满足某种停止条件,则转第(2)步,  
      否则进入下一步。
(7) 输出群体中适应度值最优的染色体作为问题的
     满意解或最优解。
*/












































以上是关于遗传算法的主要内容,如果未能解决你的问题,请参考以下文章

遗传算法

详解智能优化算法:遗传算法和蚁群算法

用遗传算法进行智能排课,相信老师会很喜欢

基于遗传算法寻优的多核支持向量机故障诊断系统

遗传算法-总结

遗传算法