zoukankan      html  css  js  c++  java
  • 遗传算法小结

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

    基本遗传算法伪代码


    /*
    * 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,一个染色体就是一个二进制符号串



    适应度函数

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


    选择算子

    (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]='';
    		}
    
    	}
    	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(),"
    ");
    		str.Insert(str.GetLength(),s);
    		str.Insert(str.GetLength(),"
    ");
    
    		for (int i=0;i<CHROMLENGTH;i++)
    		{
    			s.Format("%d",currentbest.chrom[i]);
    			str.Insert(str.GetLength(),s);
    		}
    		AfxMessageBox(str);
    
    	}
    </span>


    版权声明:

  • 相关阅读:
    ZOJ 2587 Unique Attack (最小割唯一性)
    POJ 2987 Firing (最大权闭合图)
    POJ 2987 Firing (最大权闭合图)
    POJ 3469 Dual Core CPU (最小割建模)
    POJ 3469 Dual Core CPU (最小割建模)
    UVA 11426 GCD-Extreme(II) ★ (欧拉函数)
    UVA 11426 GCD-Extreme(II) ★ (欧拉函数)
    HDU 4612 Warm up (边双连通分量+DP最长链)
    HDU 4612 Warm up (边双连通分量+DP最长链)
    hdu5531 Rebuild
  • 原文地址:https://www.cnblogs.com/walccott/p/4957103.html
Copyright © 2011-2022 走看看