当前位置: 首页 > 科技观察

遗传算法的基本概念和实现(附Java实现案例)

时间:2023-03-22 16:53:49 科技观察

如上图(左)所示,遗传算法是当一个个体由多条染色体组成,每条染色体又由多个基因组成。上图(右)显示了染色体是如何分裂和结合的。自然选择的概念自然选择的过程始于在种群中选择最适合环境的个体。后代继承父母的财产,并将这些财产添加到下一代。如果父母的健康状况更好,他们的后代就更有可能存活下来。迭代地执行这个自然选择过程,我们最终将拥有由最适合的个体组成的一代。这个概念可以应用于搜索问题。我们考虑一个问题的多种解决方案,并在其中寻找最佳解决方案。遗传算法包含以下五个步骤:初始化个体评价(适应度函数的计算)选择操作交叉操作变异操作初始化这个过程从种群中的一组个体开始,每个个体都是待解决问题的候选解.个体的特征是一组参数(变量),称为基因,这些参数串联形成染色体(问题的解决方案)。在遗传算法中,单个个体的基因组以字符串的形式呈现,通常我们可以使用二进制(1和0组成的字符串)编码,即二进制字符串表示染色体字符串。所以可以说,我们将基因串或候选解的特征编码在染色体中。种群、染色体和基因个体评价(适应度函数的计算)个体评价利用适应度函数评价个体对环境的适应度(与其他个体竞争的能力)。每个个体都有一个适应度分数,一个个体被选中进行繁殖的概率取决于它的适应度分数。适应度函数的值越大,解的质量越高。适应度函数是遗传算法进化的驱动力,是自然选择的唯一标准。其设计应结合解决问题本身的要求。选择操作选择操作的目的是选择适应度最好的个体,使他们把自己的基因传给下一代。根据他们的健康分数,我们选择一对更好的个体(父母)。适应度高的个体更容易被选择进行繁殖,即将更好的父母的基因传给下一代。交叉操作交叉操作是遗传算法中最重要的阶段。对于每对父母,都有随机选择的基因交集。比如下图中的交点是3,在交点之前,父母之间进行了基因交换,产生了后代。基因在父母之间交换,由此产生的新后代被添加到种群中。变异操作在一些新形成的后代中,它们的某些基因可能会受到低概率变异因素的影响。这意味着位串中的某些位可能会被翻转。变异操作之前和之后的变异操作可用于保持种群内的多样性并防止过早收敛。终止在群体收敛的情况下(该群体没有产生与上一代有显着差异的后代),算法终止。也就是说,遗传算法提供了一组问题的解决方案。该案例意识到人口规模是恒定的。当新一代形成时,最不适应的个体就会死亡,为后代腾出空间。这些阶段的顺序不断重复,以产生优于前一代的新一代。此迭代过程的伪代码:STARTGeneratetheinitialpopulationComputefitnessREPEATSelectionCrossoverMutationComputefitnessUNTILpopulationhasconvergedSTOPExampleimplementationinJava下面展示了遗传算法在Java中的示例实现,我们可以自由调试和修改代码。给定一组五个基因,每个基因可以保存二进制值0或1。这里的适应度是基因组中1的数量。如果基因组中有5个1,则个体的适应度达到最大值。如果基因组中没有1,则个体的适应度达到最小值。遗传算法希望最大化适应度并提供具有最佳适应度的个体种群。注:本例中,经过交叉操作和变异操作后,适应度最高的个体被新的适应度最高的后代所取代。importjava.util.Random;/****@authorVijini*///MainclasspublicclassSimpleDemoGA{Populationpopulation=newPopulation();个体适者;个人次优;intgenerationCount=0;publicstaticvoidmain(String[]args){Randomrn=newRandom();SimpleDemoGAdemo=newSimpleDemoGA();//初始化人口demo.population.initializePopulation(10);//计算每个个体的适应度demo.population.calculateFitness();System.out.println("世代:"+demo.generationCount+"最适者:"+demo.population.fittest);//当种群得到一个具有最大适应度的个体时while(demo.population.fittest<5){++demo.generationCount;//做选择demo.selection();//做交叉demo.crossover();//以随机概率进行变异if(rn.nextInt()%7<5){demo.mutation();}//将最适后代添加到种群中demo.addFittestOffspring();//计算新的适应度值demo.population.calculateFitness();System.out.println("世代:"+demo.generationCount+"最适者:"+demo.population.fittest);}System.out.println("\n在生成中找到的解决方案"+demo.generationCount);System.out.println("健身:"+demo.population.getFittest().fitness);System.out.print("基因:");对于(inti=0;i<5;i++){System.out.print(demo.population.getFittest().genes[i]);}System.out.println("");}//Selectionvoidselection(){//选择最合适的个体适者=population.getFittest();//选择第二个最适者secondFittest=population.getSecondFittest();}//交叉voidcrossover(){Randomrn=newRandom();//选择一个随机交叉点intcrossOverPoint=rn.nextInt(population.individuals[0].geneLength);//在父母之间交换值for(inti=0;isecondFittest.fitness){returnfittest;}返回secondFittest;}//从最适应的后代中替换最不适应的个体voidaddFittestOffspring(){//更新后代的适应度值fittest.calcFitness();secondFittest.calcFitness();//获取最不适合个体的索引intleastFittestIndex=population.getLeastFittestIndex();//从最适合的后代population.individuals[leastFittestIndex]=ge中替换最不适合的个体tFittestOffspring();}}//个体类个体{intfitness=0;int[]基因=新的int[5];int基因长度=5;publicIndividual(){Randomrn=newRandom();//为每个个体随机设置基因for(inti=0;iindividuals[maxFit1].fitness){maxFit2=maxFit1;maxFit1=i;}elseif(individuals[i].fitness>individuals[maxFit2].fitness){maxFit2=i;}}返回个人[maxFit2];}//获取最不适应个体的索引publicintgetLeastFittestIndex(){intminFit=0;对于(inti=0;i=individuals[i].fitness){minFit=i;}}返回minFit;}//计算每个个体的适应度publicvoidcalculateFitness(){for(inti=0;i