1、遗传算法求解yx2副本初始遗传算法及一个简单的例子遗传算法(Genetic Algorithms, GA)是一类借鉴生物界自然选择和自然遗传机制的随机化搜索算法。它模拟自然选择和自然遗传过程中发生的繁殖、交叉和基因突变现象,在每次迭代中都保留一组候选解,并按某种指标从解群中选取较优的个体,利用遗传算子(选择、交叉和变异)对这些个体进行组合,产生新一代的候选解群,重复此过程,直到满足某种收敛指标为止。下面我以一个实例来详细表述遗传算法的过程例:求下述二元函数的最大值: 1、编码:用遗传算法求解问题时,不是对所求解问题的实际决策变量直接进行操作,而是对表示可行解的个体编码的操作,不断搜索出适应度较
2、高的个体,并在群体中增加其数量,最终寻找到问题的最优解或近似最优解。因此,必须建立问题的可行解的实际表示和遗传算法的染色体位串结构之间的联系。在遗传算法中,把一个问题的可行解从其解空间转换到遗传算法所能处理的搜索空间的转换方法称之为编码。反之,个体从搜索空间的基因型变换到解空间的表现型的方法称之为解码方法。编码是应用遗传算法是需要解决的首要问题,也是一个关键步骤。迄今为止人们已经设计出了许多种不同的编码方法。基本遗传算法使用的是二进制符号0和1所组成的二进制符号集0,1,也就是说,把问题空间的参数表示为基于字符集0,1构成的染色体位串。每个个体的染色体中所包含的数字的个数L称为染色体的长度或称
3、为符号串的长度。一般染色体的长度L为一固定的数,如本例的编码为s1 = 1 0 0 1 0 (17)s2 = 1 1 1 1 0 (30)s3 = 1 0 1 0 1 (21)s4 = 0 0 1 0 0 (4)表示四个个体,该个体的染色体长度L=5。2、个体适应度函数在遗传算法中,根据个体适应度的大小来确定该个体在选择操作中被选定的概率。个体的适应度越大,该个体被遗传到下一代的概率也越大;反之,个体的适应度越小,该个体被遗传到下一代的概率也越小。基本遗传算法使用比例选择操作方法来确定群体中各个个体是否有可能遗传到下一代群体中。为了正确计算不同情况下各个个体的选择概率,要求所有个体的适应度必须
4、为正数或为零,不能是负数。这样,根据不同种类的问题,必须预先确定好由目标函数值到个体适应度之间的转换规则,特别是要预先确定好目标函数值为负数时的处理方法。如所求解的问题为:直接设定个体的适应度函数值就等于相应的目标函数值,即 .3、遗传算子 (1)比例选择:选择或称复制,建立在对个体适应度进行评价的基础之上。其作用是从当前群体中选择出一些比较优良的个体,并将其复制到下一代群体中。基本遗传算法采用比例选择的方法,所谓比例选择,是指个体在选择操作中被选中的概率与该个体的适应度大小成正比。本例选择概率的计算公式为:其中f为适度函数;为个体的适应值,显然,适应值最高的个体被随机选定的概率就越大,被选择
5、的次数就越多,从而被繁殖的次数也就越多。(2)单点交叉。单点交叉又称简单交叉,是遗传算法所使用的交叉操作方法。选择一个交叉点,子代在交叉点前面的基因从一个父代基因那里得到,后面的部分从另外一个父代基因那里得到。如:交叉前:100|10101|01交叉后:100|01101|10(3)基本位变异。基本位变异石最简单和最基本的变异操作,也是基本遗传算法中所使用的变异操作方法。对于基本遗传算法中用二进制编码符号串所表示的个体,对需要进行变异操作的某一基因,若原有基因值为0,则变异操作将该基因值变为1;反之,若原有基因值为1,则变异操作将其变为0.基本位变异算子是指对个体编码串随机指定的某一位或某几位
6、基因作变异运算。对于基本遗传算法中用二进制编码符号串所表示的个体,若需要进行变异操作的某一基因座上的原有基因值为0,则变异操作将其变为1;反之,若原有基因值为1,则变异操作将其变为0。如:变异前:1001|0变异后:1001|1(4)基本遗传算法的运行参数本例中指定四个基本参数种群大小:popsize最大世代数 maxgeneration交叉率pc 变异率pm至于遗传算法的终止条件,还可以利用某种判定准则,当判定出群体已经进化成熟且不再有进化趋势时就可终止算法的运行过程。如连续几代个体平均适应度的差异小于某一个极小的值;或者群体中所有个体适应度的方差小于某一个极小的值。这4个参数对遗传算法的搜
7、索结果及搜索效率都有一定的影响,目前尚无合理选择它们的理论根据在遗传算法的实际应用中,往往需要经过多次的试算后才能确定出这些参数合理的取值范围或取值大小4、遗传算法的应用步骤如下:遗传算法提供了一种求解复杂系统优化问题的通用框架,它不依赖于问题的领域和种类。对一个需要进行优化计算的实际应用问题,一般可按下述步骤来构造求解该问题的遗传算法。第一步:建立优化模型,即确定出目标函数、决策变量及各种约束条件以及数学描述形式或量化方法。第二步:确定表示可行解的染色体编码方法,也即确定出个体的基因型x及遗传算法的搜索空间。第三步:确定解码方法,即确定出个体基因型x到个体表现型x的对应关系或转换方法。第四步
8、:确定个体适应度的量化评价方法,即确定出由目标函数值到个体适应度的转换规则。第五步:设计遗传操作方法,即确定出选择运算、交叉运算、变异运算等具体操作方法。第六步:确定遗传算法的有关运行参数,即确定出遗传算法的种群大小(popsize)、最大世代数 (maxgeneration)、交叉率(pc)、变异率(pm)等参数。由上述构造步骤可以看出,可行解的编码方法、遗传操作的设计是构造遗传算法时需要考虑的两个主要问题,也是设计遗传算法时的两个关键步骤。对不同的优化问题需要使用不同的编码方法和不同的遗传操作,它们与所求解的具体问题密切相关,因而对所求解问题的理解程度是遗传算法应用成功与否的关键。本例c语
9、言代码/遗传算法 解决 y=x2问题/编译环境 vc+6.0/声明:部分代码来自网#include #include#include#include#define POPSIZE 500 /种群大小#define chromlength 5 /染色体长int popsize ; /种群大小int maxgeneration; /最大世代数double pc = 0.0; /交叉率double pm = 0.0; /变异率struct individual /定义染色体个体结构体 int chromchromlength; /定义染色体二进制表达形式,edit by ppme 将char 转为
10、int double value; /染色体的值 double fitness; /染色体的适应值;int generation; /当前执行的世代数int best_index; /最好的染色体索引序号int worst_index; /最差的染色体索引序号struct individual bestindividual; /最佳染色体个体struct individual worstindividual; /最差染色体个体struct individual currentbest; /当前最好的染色体个体 currentbeststruct individual populationPOP
11、SIZE;/种群数组/函数声明 void generateinitialpopulation(); /ok-初始化当代种群 void generatenextpopulation(); /产生下一代种群void evaluatepopulation(); /评价种群void calculateobjectfitness(); /计算种群适应度double decodechromosome(int,int); /染色体解码void findbestandworstindividual(); /寻找最好的和最坏的染色体个体void performevolution(); /进行演变进化void s
12、electoperator(); /选择操作void crossoveroperator(); /交换操作void mutationoperator(); /变异操作void input(); /输入接口void outputtextreport(); /输出文字报告void main() /主函数 int i; srand(unsigned)time(NULL); /强制类型转化,以当前时间戳定义随机数种子 printf(本程序为求函数y=x*x的最大值n); generation=0; /初始化generation当前执行的代 input(); /初始化种群大小、交叉率、变异率 /*edi
13、t by ppme*/ /调试用。显示input()结果 printf(种群规模(popsize): %d;n最大世代数(maxgeneration) %d;n交叉率(pc) %f;变异率(pm) %fnn,popsize,maxgeneration,pc,pm); /*edit by ppme*/ generateinitialpopulation(); /产生初始化种群 evaluatepopulation(); /评价当前种群,(A.计算种群/个体的适应度;B.找出最好和最差的个体) while(generationmaxgeneration) /小于最大世代数,执行循环体 genera
14、tion+; generatenextpopulation(); /生成子代种群(A.选择; B.交叉; C.变异) evaluatepopulation(); /评价新生子代种群 performevolution(); /进行子代进化 outputtextreport(); /输入当代最终种群 printf(n); printf( 统计结果: ); printf(n); printf(最大函数值等于:%fn,currentbest.fitness); printf(其染色体编码为:); /计算currentbest的value for( i = 0 ; i chromlength ; i+
15、) printf( %d,currentbest.chromi); printf(n); void generateinitialpopulation( ) /种群初始化 int i,j; srand(unsigned)time(NULL); /强制类型转化,以当前时间戳定义随机数种子 for (i=0;ipopsize; i+) for(j=0;jchromlength;j+) populationi.chromj=(rand()%105)?0:1; /rand()%10随机产生0-9的整数 /,小于5标注0,否则标注1 /调试显示初始化结果 printf(显示初始化结果:n); for(i
16、 = 0 ; i popsize ; i+) for(j = 0 ; j chromlength ; j+) printf( %d,populationi.chromj); printf(n); void generatenextpopulation() /生成下一代 selectoperator(); crossoveroperator(); mutationoperator();void evaluatepopulation() /评价种群? calculateobjectfitness(); /计算种群?个体的适应度 findbestandworstindividual(); /赵到最好
17、和最差的染色体个体void calculateobjectfitness() /计算染色体个体适应值和适应度 int i; int j; printf(calculateobjectfitness is executing!n); for(i=0;ipopsize;i+) double temp; temp=decodechromosome(i,chromlength); /计算个体适应值 populationi.value=(double)temp; populationi.fitness=populationi.value*populationi.value; /调试用 printf(显示
18、当前种群结果:n); for(i = 0 ; i popsize ; i+) for(j = 0 ; j = 0 ; i- ) decimal += populationpop_index.chromi*pow(2,i); /遍历染色体二进制编码, return (decimal); /并计算出其10进制的value值void findbestandworstindividual( ) /求最佳个体和最差个体 int i; double sum=0.0; bestindividual=population0; worstindividual=population0; for (i=1;ibes
19、tindividual.fitness) /依次比较,找出最佳个体 bestindividual=populationi; best_index=i; else if (populationi.fitness=currentbest.fitness)/第n代最好的,通过比较大于以往最好个体的话, /暂时存放在currentbest currentbest=bestindividual; void performevolution() /演示评价结果 if (bestindividual.fitnesscurrentbest.fitness) currentbest=populationbest
20、_index; else populationworst_index=currentbest; void selectoperator() /比例选择算法 int i,index; double p,sum=0.0; /p存放随机概率,sum存放个体适应率和累计适应率 double cfitnessPOPSIZE; /当代种群染色体个体的适应率 struct individual newpopulationPOPSIZE; /新种群 srand(unsigned) time(NULL); /种下随机种子 for(i=0;ipopsize;i+) / sum+=populationi.fitne
21、ss; /sum存放种群适应值总和 for(i=0;ipopsize; i+) cfitnessi=populationi.fitness/sum; / cfitness = fitness/sum得到个体适应率 for(i=1;ipopsize; i+) cfitnessi=cfitnessi-1+cfitnessi; /cfitness= cfitnessi-1+cfitnessi得到种群 /累计适应率 for (i=0;icfitnessindex) index+; newpopulationi=populationindex; /选出的个体组成新的一代,暂时存放于newpopulati
22、on中 for(i=0;ipopsize; i+) populationi=newpopulationi; /全局变量populaiton存放新的种群(有重复的值) void crossoveroperator() /交叉算法 int i,j; int indexPOPSIZE; int point,temp; double p; srand(unsigned) time(NULL); /种下随机种子 for (i=0;ipopsize;i+) /初始化index数组 indexi=i; for (i=0;ipopsize;i+) /for 循环实现种群内随机两两交换 point=rand()
23、%(popsize-i); /打乱种群顺序 temp=indexi; indexi=indexpoint+i; indexpoint+i=temp; for (i=0;ipopsize-1;i+=2) p=rand()%1000/1000.0; if (ppc) /单点交叉算法 point=rand()%(chromlength-1)+1; for (j=point; jchromlength;j+) temp=populationindexi.chromj; populationindexi.chromj=populationindexi+1.chromj; populationindexi
24、+1.chromj=temp; void mutationoperator() /变异操作 int i,j; double p; srand(unsigned) time(NULL); /种下随机种子 for (i=0;ipopsize;i+) for(j=0;jchromlength;j+) p=rand()%1000/1000.0; if (ppm) populationi.chromj=(populationi.chromj=0)?1:0; void input() /数据输入 printf(初始化全局变量:n); printf(种群大小(4-500偶数):); scanf(%d, &p
25、opsize); /输入种群大小,必须为偶数 if(popsize%2) != 0) printf(种群大小已设置为偶数n); popsize+; ; printf(最大世代数(10-300):); /输入最大世代数 scanf(%d, &maxgeneration); printf(交叉率(0.2-1.0):); /输入交叉率 scanf(%lf, &pc); printf(变异率(0.00):); /输入变异率 scanf(%lf, &pm);void outputtextreport()/数据输出 int i; double sum; double average; sum=0.0; f
26、or(i=0;ipopsize;i+) sum+=populationi.value; average=sum/popsize; printf(当前世代=%dn当前世代染色体平均值=%fn当前世代染色体最高值=%fn,generation,average,populationbest_index.value);运行结果:/*本程序为求函数y=x*x的最大值初始化全局变量:种群大小(4-500偶数):4最大世代数(10-300):5交叉率(0.2-1.0):0.9变异率(0.00):0.01种群规模(popsize): 4;最大世代数(maxgeneration) 5;交叉率(pc) 0.900000;变异率(pm) 0.010000显示初始化结果: 0 1 0 0 1 1 1 1 1 1 0 0 0 1 0 0 1 1 1 1calculateobjectfitness is executing!显示当前种
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1