遗传算法的本质是一种随机搜索算法,结合了生物自然选择与遗传机理。和传统搜索算法不同,遗传算法从一组随机产生的初始解,称为种群开始搜索。种群中每个个体是问题的一个解,称为染色体。染色体是一串符号,比如一个二进制字符串。这些染色体在后续迭代中不断进化,称为遗传。染色体的好坏由与问题解的接近程度度量,称为适应值。生成的下一代染色体称为后代。新一代的形成中,适应值高的个体获得交配产生后代的机会大,适应值低的个体则被淘汰,模拟了自然界自然选择的过程。后代由前一代染色体通过交叉或变异得到。

基本遗传算法伪代码

/*
* Pc:交叉发生的概率
* Pm:变异发生的概率
* M:种群规模
* G:终止进化的代数
* Tf:进化产生的任何一个个体的适应度函数超过Tf,则可以终止进化过程
*/
初始化Pm,Pc,M,G,Tf等参数。随机产生第一代种群Pop

do

  计算种群Pop中每一个体的适应度F(i)。
  初始化空种群newPop
  do
  {
    根据适应度以比例选择算法从种群Pop中选出2个个体
    if ( random ( 0 , 1 ) < Pc )
    {
      对2个个体按交叉概率Pc执行交叉操作
    }
    if ( random ( 0 , 1 ) < Pm )
    {
      对2个个体按变异概率Pm执行变异操作
    }
将2个新个体加入种群newPop中
} until ( M个子代被创建 )
用newPop取代Pop
}until ( 任何染色体得分超过Tf, 或繁殖代数超过G )

染色体编码

编码是应用遗传算法时首先要解决的问题。所谓编码,就是将问题的解空间转换成遗传算法所能处理的搜索空间。

常用的编码方法有

(1)二进制编码

其编码符号为1和0,每个基因不是1就是0,一个染色体就是一个二进制符号串



适应度函数

适应度函数是决定遗传算法优劣的关键部分。好的适应度函数可以指导算法从非最优个体进化到最优个体,解决过早收敛和过慢结束的问题。

java 遗传算法包 遗传算法的结果_#define

java 遗传算法包 遗传算法的结果_#define_02

选择算子

(1)轮盘赌选择方法

也称比例选择法,此时个体被选中的概率与其适应值的大小成正比。模拟一个圆盘,每个个体在圆盘上所占的面积与其适应度的大小成正比,转动指针,指针最后指向那个圆盘,所代表的个体就被选中,这样适应度低的个体也有机会被选中。

(2)排序选择法

计算完每个个体的适应度并排序后,将事先设计好的概率值分配给每个个体,这样每个个体被选中的概率由序号确定。

(3)最优保存策略

始终用最优个体替换最差个体。这样的后果是容易陷入局部最小值。

交叉算子

(1)一点交叉

按选择概率PC 在两两配对的个体编码串cpairs 中随机设置一个交叉点cpoints ,然后在该点相互交换两个配对个体的部分基因,从而形成两个新的个体。

(2)两点交叉

按选择概率PC 在两两配对的个体编码串cpairs 中随机设置两个交叉点cpoints ,然后交换两点之间的的部分基因,从而形成两个新的个体。

交叉前:

00000|011100000000|10000

11100|000001111110|00101

交叉后:

00000|000001111110|10000

11100|011100000000|00101


(3)一致交叉

子代的每一位随机地从两个父代对应位取得

变异算子

对于二进制的基因串而言,变异操作就是按照变异概率pm随机选择变异点mpoints ,在变异点处将其位取反即可。

变异前:

000001110000000010000

变异后:

000001110000100010000


以下一个例子演示了如何用遗传算法去聚类。

将N个样品归为M个类别,可确定染色体长度为N,每个基因的值取1,2...M之间的数,代表相应的样本被归为哪一个类,这样一条染色体既代表了问题的一个解。适应度函数可设计为类内方差,如果类内各样本之间的差别越小,说明这些样本之间相似度越高,聚类也就越准确。


<span style="font-size:18px;">// YIchuansuanfa.cpp: implementation of the YIchuansuanfa class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "YIchuansuanfa.h"
#include  <stdio.h>
#include  <stdlib.h>
#include   <math.h>
#define   POPSIZE      500   //人群总数
#define   MAXIMIZATION 1
#define   MINIMIZATION 2
#define   Cmax         100
#define   Cmin         0
#define   LENGTH1      10//第一代变量的染色体长度
#define   LENGTH2      10//第二代变量的染色体长度
    
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

YIchuansuanfa::YIchuansuanfa()
{
    FunctionMode=MAXIMIZATION;
	PopSize=80;
	Pc=0.6;//交叉概率0.6
	Pm=0.05;//变异概率0.01
	index=1;
}

YIchuansuanfa::~YIchuansuanfa()
{

}
void YIchuansuanfa::  main()
	{
		if (centernum!=0)
		{
			generation=0;
			GenerationInitialPopulation();
			EvaluatePopulation();
			while (generation<MaxGeneration)
			{
				generation++;
				GenerateNextPopulation();
				EvaluatePopulation();
				PerformEvolution();
			}
			for (int i=0;i<patternnum;i++)
			{
				m_pattern[i].category=currentbest.chrom[i];
			}
			
			CString s;
			s.Format("最优解出现在第%d代",index);
			AfxMessageBox(s);
		}
		else
		{
			AfxMessageBox("类中心数目不能为0!");
			return;		
		}
	}
void YIchuansuanfa::GenerationInitialPopulation()
	{
		int  i,j;
		CHROMLENGTH=patternnum;
		for(i=0;i<PopSize;i++)
		{
			for(j=0;j<CHROMLENGTH;j++)//初始化染色体
			{
				population[i].chrom[j]=rand()%centernum+1;
			}
			population[i].chrom[CHROMLENGTH]='\0';
		}

	}
	void YIchuansuanfa::GenerateNextPopulation()
	{
		SelectionOperator();
		CrossoverOperator();
		MutationOperator();
	}
	void YIchuansuanfa::EvaluatePopulation()
	{
		CalculateObjectValue();
		CalculateFitnessValue();
		FindBestAndWorstIndividual();
	}
/*	long YIchuansuanfa::DecodeChromosome(char *string,int point,int length)
	{
		int i;
		long decimal=0L;
		char *pointer;
		for(i=0,pointer=string+point;i<length;i++,pointer++)
		{
			decimal+=(*pointer-'0')<<(length-1-i);
		}
		return (decimal);
	}*/
	void YIchuansuanfa::CalculateObjectValue()
	{
		if (m_center!=NULL)
			delete []m_center;
		m_center=new Center[patternnum];
		for (int t=0;t<centernum;t++)
		{
			m_center[t].index=t+1;
			m_center[t].patternnum=0;
			for (int m=0;m<N*N;m++)
				m_center[t].feature[m]=0.0;
		}

		double sumdistance;

		for(int i=0;i<PopSize;i++)//计算population[i]的value
		{
			for (int t=0;t<centernum;t++)
			{
				m_center[t].patternnum=0;
				for (int m=0;m<N*N;m++)
				m_center[t].feature[m]=0.0;
			}
			for (int j=0;j<centernum;j++)//算中心
			{
				for(int k=0;k<patternnum;k++)
				{
					if (population[i].chrom[k]==j+1)
					{
						m_center[j].patternnum++;
						for(int n=0;n<N*N;n++ )
							m_center[j].feature[n]+=m_pattern[k].feature[n];
					}
				}
				if (m_center[j].patternnum!=0)
				{
					for(int n=0;n<N*N;n++ )
						m_center[j].feature[n]/=(double)m_center[j].patternnum;
				}
			}

			sumdistance=0.0;	//cal value
			for ( j=0;j<centernum;j++)
			{
				for(int k=0;k<patternnum;k++)
				{
					if (population[i].chrom[k]==j+1)
					{
						sumdistance+=GetDistance(m_pattern[k],m_center[j],1);
					}
				}
			
			}
		
	    	population[i].value=sumdistance	;
		}

	}
	void YIchuansuanfa::CalculateFitnessValue()
	{	
		//按照value排序由小到大
		int i,j;
		for(i=0;i<PopSize;i++)
		{
			population[i].index=-1;
		}

		for (i=1;i<=PopSize;i++)
		{
			int index=0;
			for (j=0;j<PopSize;j++)
			{
				if (population[j].index==-1)
				{
					index=j;
					break;
				}
			}
			for(j=0;j<PopSize;j++)
			{
				if(population[j].index==-1 && population[j].value<population[index].value)
					index=j;
			}
			population[index].index=i;
		}
		//计算适应度
		for(i=0;i<PopSize;i++)
		{
			double a=0.6;
			population[i].fitness=a*pow((1-a),population[i].index-1);
		}
	

	}
	void YIchuansuanfa::FindBestAndWorstIndividual()
	{
		int i;
		bestindividual=population[0];
		worstindividual=population[0];
		for(i=1;i<PopSize;i++)
		{
			if(population[i].value<bestindividual.value)
			{
				bestindividual=population[i];
				best_index=i;
			}else if(population[i].value>worstindividual.value)
			{
				worstindividual=population[i];
				worst_index=i;
			}
		}
		if(generation==0)
		{
			currentbest=bestindividual;
		}
		else
		{
			if(bestindividual.value<currentbest.value)
			{
				currentbest=bestindividual;
				index=generation;
			}
		}
	}
	void YIchuansuanfa::PerformEvolution()
	{
		if(bestindividual.value<currentbest.value)
		{
			currentbest=population[best_index];
		}else
		{
			population[worst_index]=currentbest;
		}
	}
	void YIchuansuanfa::SelectionOperator()
	{
		int i,index;
		double p,sum=0.0;
		double cfitness[POPSIZE];
		struct individual newpopulation[POPSIZE];
		for(i=0;i<PopSize;i++)
		{
			sum+=population[i].fitness;
		}
		for(i=0;i<PopSize;i++)
		{
			cfitness[i]=population[i].fitness/sum;
		}
		for(i=1;i<PopSize;i++)
		{
			cfitness[i]=cfitness[i-1]+cfitness[i];
		}
		for(i=0;i<PopSize;i++)
		{
			p=rand()%1000/1000.0;
			index=0;
			while(p>cfitness[index])
			{
				index++;
			}
			newpopulation[i]=population[index];
		}
		//选择下一代群体
		for(i=0;i<PopSize;i++)
		{
			population[i]=newpopulation[i];
		}
	}
	void YIchuansuanfa::CrossoverOperator()
	{
		int i,j;
		int index[POPSIZE];
		int point=0,temp;
		double p;
		int  ch;
		for(i=0;i<PopSize;i++)
		{
			index[i]=i;
		}
		for(i=0;i<PopSize;i++)
		{
			point=rand()%PopSize-i;
			temp=index[i];
			index[i]=index[point+i];
			index[point+i]=temp;
		}
		//交叉操作
		for(i=0;i<PopSize-1;i+=2)
		{
			p=rand()%1000/1000.0;
			if(p<Pc)
			{
				point=(rand()%CHROMLENGTH-1)+1;
				for(j=point;j<CHROMLENGTH;j++)
				{
					ch=population[index[i]].chrom[j];
					population[index[i]].chrom[j]=population[index[i+1]].chrom[j];
					population[index[i+1]].chrom[j]=ch;
				}
			}
		}
	}
	void YIchuansuanfa::MutationOperator()
	{
		int i,j;
		double p;
		//变异
		for(i=0;i<PopSize;i++)
		{
			for(j=0;j<CHROMLENGTH;j++)
			{
				p=rand()%1000/1000.0;
				if(p<Pm)
				{
					population[i].chrom[j]=rand()%centernum+1;
				}
			}
		}
	}
	void YIchuansuanfa::OutputTextReport()
	{

		CString str,s;
		s.Format("%f",currentbest.value);
		str.Insert(str.GetLength(),"present best value: ");
		str.Insert(str.GetLength(),s);


		s.Format("第 %d 代",generation);
        str.Insert(str.GetLength(),"\n");
		str.Insert(str.GetLength(),s);
		str.Insert(str.GetLength(),"\n");

		for (int i=0;i<CHROMLENGTH;i++)
		{
			s.Format("%d",currentbest.chrom[i]);
			str.Insert(str.GetLength(),s);
		}
		AfxMessageBox(str);

	}
</span>