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

    遗传算法是解决搜索问题的一种通用算法。

    模拟自然界优胜劣汰的进化现象,把搜索问题转化为遗传问题,把可能的解转为成一个向量——染色体,向量的每个元素称为基因。通过不断计算各染色体的适应值,选择最好的染色体,获得最优解。
    基本概念 (以下均以二进制串 a=<1000101110110101000111> 为例)
    1. 遗传:子代和父代具有相同或相似的性状,保证物种的稳定性;
    2. 变异:子代与父代,子代不同个体之间总有差异,是生命多样性的根源;
    3. 生存斗争和适者生存:具有适应性变异的个体被保留,不具适应性变异的个体被淘汰。
    自然选择过程是长期的、缓慢的、连续的过程。
    4. 个体与种群
    个体就是模拟生物个体而对问题中的对象(一般就是问题的解)的一种称呼,一个个体也就是搜索空间中的一个点。
    种群就是模拟生物种群而由若干个体组成的群体, 它一般是整个搜索空间的一个很小的子集。
    5. 适应度与适应度函数
    适应度就是借鉴生物个体对环境的适应程度,而对问题中的个体对象所设计的表征其优劣的一种测度。
    适应度函数就是问题中的全体个体与其适应度之间的一个对应关系。它一般是一个实值函数。该函数就是遗传算法中指导搜索的评价函数,数值越接近目标值则说明适应度越高。
    6. 染色体与基因
    染色体(chromosome)就是问题中个体的某种字符串形式的编码表示。字符串中的字符也就称为基因。
    7. 遗传操作
      亦称遗传算子(genetic operator),就是关于染色体的运算。遗传算法中有三种遗传操作:
    选择 (selection)
    交叉(crossover,亦称交换、交配或杂交)
    变异(mutation,亦称突变)

    这里写图片描述


    现在写个简单的例子:设 f(x) = -x2 + 2x + 0.5,求 max f(x), x在[-1, 2]之间。

    对于二进制串 a=<1000101110110101000111> ;

    1.先将其转为十进制数:ve=2288967

    2.将其转化为[-1,2]内的实数为:
    X=-1+ve*(2-(-1))/((2^22)-1)=0.631797

    3.随机的产生一个初始群体(这里假设初始群体的个体数为 4)
    pop1={
    <1101011101001100011110>, % a1
    <1000011001010001000010>, % a2
    <0001100111010110000000>, % a3
    <0110101001101110010101>} % a4

    4.转化成 [-1, 2] 之间的十进制数即为
    pop1={ 1.523032,0.574022,-0.697235,0.247238}

    5.定义适应函数和求适应值

    由于目标函数 f(x)[-1, 2] 内的值有正有负,所以必须通过建立适应函数与目标函数的映射关系,保证映射后的适应值非负,而且目标函数的优化方向应对应于适应值增大的方向,也为以后计算各个体的入选概率打下基础。

    最后假设得到适应值:
    g(pop1)={2.226437,2.318543, 0,1.933350}

    6.算出入选下一代的概率:
    p(pop1)=g(pop1)/sum(g(pop1))
    ={0.343675, 0.357892, 0, 0.298433}

    7.产生种群
    newpop1={
    <110101110 1001100011110>, % a1
    <100001100 1010001000010>, % a2
    <10000110010100 01000010>, % a2
    <01101010011011 10010101>} % a4
    8.交叉:
    将第七步的加粗部分交换,(a1与a2,a3与a4)得到如下结果:
    <1101011101010001000010>, % a1
    <1000011001001100011110>, % a2
    <10000110 0 1010010010101>, % a2
    <0110101001101101000010>} % a4

    9.变异:将a3中加粗基因变异:

    <1101011101010001000010>, % a1
    <1000011001001100011110>, % a2
    <10000110 1 1010010010101>, % a2
    <0110101001101101000010>} % a4

    10.终止:我们可以采用遗传指定代数的方法进行停止程序的运行,但是精确度较低,亦可以根据个体的差异来判断,通过计算种群中基因多样性测度,即所有基因位相似程度来进行控制


    来一个实际的例子加代码(本人也正在学习java,如有不足之处欢迎指出)

    用遗传算法( GA )求如下问题的最优解, x1, x2精确到小数点后2位。 (采用二进制编码方法)
    max f (x1, x2) = 2x1·sin(8p x2) +x2·cos(13p x1)
    x1:[-3,7]
    x2:[-4,10]

    代码如下:

    
    class chromasome{//染色体
        public static final int DNAsize1=10;
        public static final int DNAsize2=11;
        int []DNA1=new int[DNAsize1];
        int []DNA2=new int[DNAsize2];
        chromasome(){
            int a,b;
    
            for(int i=0;i<DNAsize1;i++){
                a=(int)(0+Math.random()*(1-0+1));
                DNA1[i]=a;
            }
            for(int i=0;i<DNAsize2;i++){
                b=(int)(0+Math.random()*(1-0+1));
                DNA2[i]=b;
            }
        }
        double twoToten1(){
            String a ;
            a=moeth.velueTostr(this.DNA1);
            int d = Integer.parseInt(a, 2); // 2进制
            double b=Math.pow(2, this.DNAsize1);
            return -3+(d*(7+3)/(b-1));
        }
        double twoToten2(){
            String a ;
            a=moeth.velueTostr(this.DNA2);
            int d = Integer.parseInt(a, 2); // 2进制
            double b=Math.pow(2, this.DNAsize2);
            return -4+(d*(10+4)/(b-1));
        }
        void variation(){//变异函数
    
        }
        void getChromasome(){//输出看看染色体
            System.out.println("-------------------");
            for(int i=0;i<this.DNAsize1;i++){
                System.out.print(this.DNA1[i]);
            }
            System.out.println();
            for(int i=0;i<this.DNAsize2;i++){
                System.out.print(this.DNA2[i]);
            }
            System.out.println();
            System.out.println(this.adapt()-20);
        }
        double adapt(){//求适应值
    
            //2x1·sin(8p x2) +x2·cos(13p x1)
            double x1=this.twoToten1();
            //System.out.println("x1="+x1);
            double x2=this.twoToten2();
            //System.out.println("x2="+x2);
            double value=2*x1*Math.sin(8*Math.PI*x2)+x2*Math.cos(13*Math.PI*x1);    
            //System.out.println("value="+value);
            return value+20;
        }
    }
    public class genetic {
        /**
         * @param args
         */
        int TEXT=1;//调试用的
        static final int DNAnum=220;
        chromasome[] DNAarr=new chromasome[DNAnum];
        double []adapt_arr=new double[DNAnum];
        double []select_rate=new double [DNAnum];
        static final double copulationRate=0.5;//交配概率
        static final double variationRate=0.01;//变异概率
        static int generationNum=0;//遗传代数
        genetic(){
            this.initDNA();
            if(TEXT==1){
    
            }
        }
        //--------------------------------------------------------------------------
        void TEXToutput(){
            for(int i=0;i<DNAnum;i++){
                DNAarr[i].getChromasome();
                }
            System.out.println();
    
        }
        //--------------------------------------------------------------------------
        void initDNA(){//随机生成多条染色体
            for(int i=0;i<DNAnum;i++){
                DNAarr[i]=new chromasome();
            }
        }
        void formDNA(){
            int a=this.DNAnum/6;
            DNAarr[DNAnum-1]=DNAarr[0];
            //DNAarr[DNAnum-3]=DNAarr[0];
            //DNAarr[DNAnum-5]=DNAarr[0];
            //DNAarr[DNAnum-7]=DNAarr[0];
            //DNAarr[DNAnum-2]=DNAarr[1];
            //DNAarr[DNAnum-4]=DNAarr[1];
    //      for(int i=0;i<a;i++){
    //          DNAarr[DNAnum-i-1]=DNAarr[i];
    //      }
            //DNAarr[DNAnum-2]=DNAarr[0];
            //DNAarr[DNAnum-3]=DNAarr[0];
            //DNAarr[DNAnum-4]=DNAarr[1];
        }
    //  int chance(){//计算概率
    //      return 1;
    //  }
        void select(){
            double num=0;
            for(int i=0;i<this.DNAnum;i++){
                //System.out.println("------------------------"+i+1+"---------------");
                //DNAarr[i].getChromasome();
                adapt_arr[i]=DNAarr[i].adapt();
                num+=adapt_arr[i];
                //System.out.println("-----------------------------------------------");
            }
            for(int i=0;i<this.DNAnum;i++){
                select_rate[i]=adapt_arr[i]/num;
                //System.out.println("------------------------"+i+1+"---------------");
                //System.out.println("select_rate="+select_rate[i]);
                //System.out.println("----------------------------------------------");
            }
        }
        void paixu(){
            for(int i=1;i<select_rate.length;i++){
                double m=select_rate[i];
                chromasome n=DNAarr[i];
                int k=i;
                for(int j=i-1;j>=0&&select_rate[j]<m;j--){
                    select_rate[j+1]=select_rate[j];
                    DNAarr[j+1]=DNAarr[j];
                    k--;
                }
                select_rate[k]=m;
                DNAarr[k]=n;
            }
        }
        void copulation(){//交配函数
            int a;
            for(int j=1;j<DNAnum;j++){
                a=(int)(1+Math.random()*(DNAarr[0].DNAsize1-1-1+1));
                for(int i=a;i<DNAarr[j].DNAsize1;i++){
                    int b=DNAarr[j-1].DNA1[i];
                    this.DNAarr[j-1].DNA1[i]=DNAarr[j].DNA1[i];
                    this.DNAarr[j].DNA1[i]=b;
                }
                j++;
            }
    
            for(int j=1;j<DNAnum;j++){
                a=(int)(1+Math.random()*(DNAarr[0].DNAsize2-1-1+1));
                for(int i=a;i<DNAarr[j].DNAsize2;i++){
                    int l=DNAarr[j-1].DNA2[i];
                    this.DNAarr[j-1].DNA2[i]=DNAarr[j].DNA2[i];
                    this.DNAarr[j].DNA2[i]=l;
                }
                j++;
            }
    
        }
        void getDNA(){
            for(int i=0;i<DNAnum;i++){
                DNAarr[i].getChromasome();
            }
        }
        void variation(){
            //int m=(int)(1+Math.random()*(5-1+1));
            //System.out.println(m);
            int m=3;
            while(m--!=0){
            for(int a=0;a<DNAnum;a++){
                int b=a;
                int a_1=(int)(0+Math.random()*(DNAarr[0].DNAsize1-1-0+1));
                //int b=(int)(0+Math.random()*(DNAnum-1-0+1));
                int b_1=(int)(0+Math.random()*(DNAarr[0].DNAsize2-1-0+1));
                //System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$"+"a="+a+"b="+b+"a_1="+a_1+"b_1="+b_1);
                if(DNAarr[a].DNA1[a_1]==1){
                    DNAarr[a].DNA1[a_1]=0;
                }else{
                    DNAarr[a].DNA1[a_1]=1;
                }
                if(DNAarr[b].DNA2[b_1]==1){
                    DNAarr[b].DNA2[b_1]=0;
                }else{
                    DNAarr[b].DNA2[b_1]=1;
                }
            }
            }
    
        }
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            int nn=20 ;
            while(nn--!=0){
    
            int m=200;
            genetic g=new genetic();
            g.select();
            g.paixu();
            int oo=0;
            while(m--!=0){
                //System.out.println("##################################");
    
                //g.getDNA();
                //g.select();
                g.copulation();
                //System.out.println("--------------------交配-------------------");
                //g.getDNA();
    
                g.variation();
                //System.out.println("-------------------变异------------------");
                //g.getDNA();
                g.select();
                //System.out.println("--------------------选择-------------------");
                //g.getDNA();
    
                g.paixu();
                //System.out.println("-------------------形成-------------------");
                g.formDNA();
    
                //g.select();
                //g.getDNA();
            }
            //g.getDNA();
            //System.out.println(g.DNAarr[0].twoToten1());
            //System.out.println(g.DNAarr[0].twoToten2());
            System.out.println(g.DNAarr[0].adapt()-20);
    
        }
        }
    }
    
    

    结果:
    这里写图片描述

  • 相关阅读:
    python bilibili(一)获取直播间标题
    反射机制
    如何修改excel转换csv的分隔符
    Timer和TimerTask详解——(转)
    Android完全退出应用程序(一)
    动态设置ImageView中的图片
    excel导入sqlite (命令方式)
    Android开发中完全退出程序的三种方法
    Android实现回退
    如何把批量数据导入到android 的 sqlite 数据库(转)
  • 原文地址:https://www.cnblogs.com/leishitou/p/5436191.html
Copyright © 2011-2022 走看看