• 遗传算法


    摘要:遗传算法(geneticalgorithms,GA)是模仿生物遗传学和自然选择机理,在对随机自适应的全局搜索算法(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) 产生一个随机数 r,0< r < sumN(或0< r < 1)

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

    4,程序流程
     一般遗传算法的主要步骤如下:

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

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

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

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

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

      1 #include<iostream>
      2 #include<cstdlib>
      3 #include<ctime>
      4 #include<cmath>
      5 #include<iomanip>
      6 using namespace std;
      7 
      8 const int NUM=1000;       //最大迭代次数
      9 const int POP_SIZE=50;   //种群规模:个体数量
     10 const int GENE=33;       //每个个体染色体个数
     11 const int GB1=18;        //染色体手段基因片段(二进制)
     12 const int GB2=15;        //染色体末端基因片段(二进制)
     13 const int GD=6;          //十进制保留小数点位数
     14 const double PI=3.1415926;
     15 
     16 void initialize(int v[][GENE])   //初始化群体
     17 {
     18     int ii,ij;
     19     srand(time(0));
     20     cout<<"基因初始化:"<<endl;
     21     for(ii=0;ii<POP_SIZE;ii++)
     22     {    
     23         cout<<endl<<"个体"<<setw(2)<<ii+1<<"基因型 ";
     24         for(ij=0;ij<GENE;ij++)
     25         {
     26             v[ii][ij]=2*rand()/RAND_MAX;
     27             cout<<v[ii][ij];
     28         }
     29     }
     30     cout<<endl;
     31 }
     32 
     33 void evaluation(int v[][GENE],double eval[]) //评估函数
     34 {    
     35     int ii,ij;
     36     double x1,x2;
     37     for(ii=0;ii<POP_SIZE;ii++)
     38     {    
     39         x1=x2=0;             
     40         for(ij=0;ij<GB1;ij++)   //二进制片段转为十进制编码
     41         {
     42             x1+=v[ii][ij]*pow(2,(GB1-(ij+1)));
     43         }
     44         for(ij=GB1;ij<GENE;ij++)
     45         {
     46             x2+=v[ii][ij]*pow(2,(GENE-(ij+1)));
     47         }
     48         x1=-3.0+x1*(12.1-(-3.0))/(pow(2,GB1)-1);   //十进制编码转为十进制值
     49         x2=4.1+x2*(5.8-4.1)/(pow(2,GB2)-1);
     50         eval[ii]=21.5+x1*sin(4*PI*x1)+x2*sin(20*PI*x2);
     51     }
     52 }
     53 
     54 int best_eval(double eval[])   //找出每代中最优秀个体基因值
     55 {    
     56     int ii,cursor=0;
     57     for(ii=0;ii<POP_SIZE;ii++)
     58     {    
     59         if(eval[ii]>eval[cursor])
     60         {
     61             cursor=ii;
     62         }
     63     }
     64     return cursor;
     65 }
     66 
     67 int worst_eval(double eval[])   //找出每代中最差个体基因值
     68 {    
     69     int ii,cursor=0;
     70     for(ii=0;ii<POP_SIZE;ii++)
     71     {    
     72         if(eval[ii]<eval[cursor])
     73         {
     74             cursor=ii;
     75         }
     76     }
     77     return cursor;
     78 }
     79 
     80 void selection(double eval[],int v[][GENE],int v_next[][GENE])
     81 {    
     82     int ii,ij,ik;
     83     double value;
     84     double p[POP_SIZE];         //选择概率
     85     double pp[POP_SIZE]={0};     //累积概率
     86     double total_value=0;
     87     for(ii=0;ii<POP_SIZE;ii++)
     88     {
     89         total_value+=eval[ii];
     90     }
     91     for(ii=0;ii<POP_SIZE;ii++)
     92     {
     93         p[ii]=eval[ii]/total_value;
     94     }
     95     pp[0]=p[0];
     96     for(ii=1;ii<POP_SIZE;ii++)
     97     {
     98         pp[ii]=pp[ii-1]+p[ii];
     99     }
    100     for(ii=0;ii<POP_SIZE;ii++)      //对于每个次代个体的基因型 
    101     {    
    102         value=(double)rand()/RAND_MAX;   //转动轮盘 
    103         for(ij=0;ij<POP_SIZE;ij++)       //搜索命中区域 
    104         {    
    105             if(value<pp[ij])             //找到后复制、跳出 
    106             {    
    107                 for(ik=0;ik<GENE;ik++)
    108                 {
    109                     v_next[ii][ik]=v[ij][ik];
    110                 }
    111                 break;
    112             }
    113         }
    114     }
    115 }
    116 
    117 void crossover(int v[][GENE])
    118 {    
    119     int ii,ij,ik;
    120     double p=0.8,value1;
    121     int n=0,tmp,value2;
    122     int cursor[POP_SIZE]={-1};     //被选中的染色体下标
    123     for(ii=0;ii<POP_SIZE;ii++)     //找被选中的染色体下标
    124     {    
    125         value1=(double)rand()/RAND_MAX;
    126         if(value1<p)
    127         {
    128             cursor[n++]=ii;
    129         }
    130     }
    131     for(ii=0;ii<n;ii+=2)              //两两配对,进行交叉
    132     {    
    133         value2=(int)(GENE-1)*rand()/RAND_MAX+1;
    134         for(ij=value2;ij<GENE;ij++)
    135         {    
    136             tmp=v[cursor[ii]][ij];
    137             v[cursor[ii]][ij]=v[cursor[ii+1]][ij];
    138             v[cursor[ii+1]][ij]=tmp;
    139         }
    140     }
    141 }
    142 
    143 void mutation(int v[][GENE])
    144 {    
    145     int ii,ij,ik;
    146     int sum,gene;     //基因变异数目
    147     double pm=0.01;   //变异概率
    148     sum=(int)(POP_SIZE*GENE*pm)+1;
    149     for(ii=0;ii<sum;ii++)
    150     {    
    151         gene=(int)(POP_SIZE*GENE)*rand()/RAND_MAX;
    152         ij=gene/(POP_SIZE*GENE);
    153         ik=gene%(POP_SIZE*GENE);
    154         v[ij][ik]=1-v[ij][ik];
    155     }
    156 }
    157 
    158 int main(int argc,char **argv)
    159 {    
    160     int ii,ij,ik,max=0;
    161     int v[POP_SIZE][GENE];          //本代群体基因库
    162     int v_next[POP_SIZE][GENE];     //次代群体基因库
    163     double eval[POP_SIZE];                   //本代群体评估值
    164     double eval_next[POP_SIZE];              //次代群体评估值
    165     int best_cursor;                //本代最优个体适值下标
    166     int best_next_cursor;           //次代最优个体适值下标
    167     int worst_next_cursor;          //次代最差个体适值下标
    168     int best_gene[GENE];            //本代最优个体基因型
    169     initialize(v);  
    170     for(ii=0;ii<NUM&&max<50;ii++)
    171     {    
    172         evaluation(v,eval);               //本代基因评估
    173         best_cursor=best_eval(eval);      //本代最优个体
    174         cout<<endl<<""<<setw(3)<<ii+1<<"代最优基因:";
    175         for(ij=0;ij<GENE;ij++)            //保存本代最优基因
    176         {
    177             best_gene[ij]=v[best_cursor][ij];
    178             cout<<best_gene[ij];
    179         }
    180         cout<<" 适值:"<<eval[best_cursor];
    181         selection(eval,v,v_next);       //选择    
    182         crossover(v_next);              //交叉
    183         mutation(v_next);               //变异
    184         evaluation(v_next,eval_next);  
    185         worst_next_cursor=worst_eval(eval_next); 
    186         for(ij=0;ij<GENE;ij++)
    187         {
    188             v_next[worst_next_cursor][ij]=best_gene[ij];
    189         }
    190         evaluation(v_next,eval_next);  
    191         best_next_cursor=best_eval(eval_next); 
    192         eval[best_cursor]==eval_next[best_next_cursor]?max++:max=0;
    193         for(ij=0;ij<POP_SIZE;ij++)
    194         {
    195             for(ik=0;ik<GENE;ik++)
    196             {
    197                 v[ij][ik]=v_next[ij][ik];
    198             }
    199         }
    200     }
    201     cout<<endl<<"最优基因适值为:"<<eval[best_cursor]<<endl;
    202     cout<<"迭代次数为:"<<ii<<endl;
    203     system("pause");
    204     return 0;
    205 }
    206 /*
    207 **本题最优值是38.818208
    208 
    209 (1)  初始化群体;
    210 (2)  计算群体上每个个体的适应度值;
    211 (3)  按由个体适应度值所决定的某个规则选    
    212        择将进入下一代的个体;
    213 (4)  按概率Pc进行交叉操作;
    214 (5)  按概率Pm进行突变操作;
    215 (6) 若没有满足某种停止条件,则转第(2)步,  
    216       否则进入下一步。
    217 (7) 输出群体中适应度值最优的染色体作为问题的
    218      满意解或最优解。
    219 */
  • 相关阅读:
    Android课程---Activity的跳转与传值(转自网上)
    Android课程---Activity中保存和恢复用户状态
    Android课程---Activity 的生命周期
    Android课程---Activity的创建
    初学JAVA随记——练习写代码(8种数据类型)
    资料——UTF-8
    资料——ASCII码
    初学JAVA随记——8bit(1byte)的取值范围是+127到—128
    初学JAVA随记——变量与常量
    进制转换
  • 原文地址:https://www.cnblogs.com/guanghe/p/5546750.html
Copyright © 2020-2023  润新知