遗传算法中的交叉操作是 对NSGA-II 源码分析的 最后一部分, 这一部分也是我 从读该算法源代码和看该算法论文理解偏差最大的 函数模块。
这里,首先提一下,遗传算法的 交叉操作、变异操作都是需要设定概率的, 即交叉概率和变异概率。
假设种群个体 大小为 popsize , 那么交叉操作需要进行 popsize/2 次 , 变异操作需要进行 popsize 次, 其中每次操作的时候都需要随机生成一个随机数来与给定的概率进行判断,若小于给定的概率则继续执行否则退出该操作。
如果继续操作的话 需要注意一个问题 对两个个体交叉 ,或 对单个个体进行变异 都是对 个体的所有变量 进行操作,其中变异对二进制编码的个体来说是对每个个体的每个变量 的二进制编码的 每个比特位进行变异。
包装函数,通过对标识位判断编码形式来决定 具体的核心功能 所调用的函数。
1 /*Crossover routines*/
2
3 # include
4 # include
5 # include
6
7 # include "global.h"
8 # include "rand.h"
9
10 /*Function to cross two individuals*/
11 void crossover (individual *parent1, individual *parent2, individual *child1, individual *child2)12 {13 if (nreal!=0)14 {15 realcross (parent1, parent2, child1, child2);16 }17 if (nbin!=0)18 {19 bincross (parent1, parent2, child1, child2);20 }21 return;22 }
实数编码的 两个个体交叉操作, 采用 SBX 方式交叉。需要交叉的两个个体 每个变量 都进行交叉操作。
1 /*Routine for real variable SBX crossover*/
2 void realcross (individual *parent1, individual *parent2, individual *child1, individual *child2)3 {4 inti;5 doublerand;6 doubley1, y2, yl, yu;7 doublealpha, beta, betaq;8 if (randomperc() <=pcross_real)9 {10 nrealcross++;11 for (i=0; ixreal[i] < parent2->xreal[i])16 {17 y1 = parent1->xreal[i];18 y2 = parent2->xreal[i];19 }20 else
21 {22 y1 = parent2->xreal[i];23 y2 = parent1->xreal[i];24 }25 if (fabs(parent1->xreal[i]-parent2->xreal[i]) >EPS)26 {27 yl =min_realvar[i];28 yu =max_realvar[i];29 rand =randomperc();30 beta = 1.0 + (2.0*(y1-yl)/(y2-y1));31 alpha = 2.0 - pow(beta,-(eta_c+1.0));32 if (rand <= (1.0/alpha))33 {34 betaq = pow ((rand*alpha),(1.0/(eta_c+1.0)));35 }36 else
37 {38 betaq = pow ((1.0/(2.0 - rand*alpha)),(1.0/(eta_c+1.0)));39 }40 child1->xreal[i] = 0.5*((y1+y2)-betaq*(y2-y1));41 beta = 1.0 + (2.0*(yu-y2)/(y2-y1));42 alpha = 2.0 - pow(beta,-(eta_c+1.0));43 if (rand <= (1.0/alpha))44 {45 betaq = pow ((rand*alpha),(1.0/(eta_c+1.0)));46 }47 else
48 {49 betaq = pow ((1.0/(2.0 - rand*alpha)),(1.0/(eta_c+1.0)));50 }51 child2->xreal[i] = 0.5*((y1+y2)+betaq*(y2-y1));52 if (child1->xreal[i]xreal[i]=yl;55 }56 if (child1->xreal[i]>yu)57 {58 child1->xreal[i]=yu;59 }60 if (child2->xreal[i]xreal[i]=yl;63 }64 if (child2->xreal[i]>yu)65 {66 child2->xreal[i]=yu;67 }68 }69 else
70 {71 child1->xreal[i] = parent1->xreal[i];72 child2->xreal[i] = parent2->xreal[i];73 }74 }75 else
76 {77 child1->xreal[i] = parent1->xreal[i];78 child2->xreal[i] = parent2->xreal[i];79 }80 }81 }82 else
83 {84 for (i=0; ixreal[i] = parent1->xreal[i];87 child2->xreal[i] = parent2->xreal[i];88 }89 }90 return;91 }
二进制编码 的 交叉操作:
(双点 交叉) 两个个体的 每个对应的变量 彼此交叉操作。这里每个变量的 二进制编码 段 随机选取两点, 将中间部门的二进制段 互换,两个交叉点。
1 /*Routine for two point binary crossover*/
2 void bincross (individual *parent1, individual *parent2, individual *child1, individual *child2)3 {4 inti, j;5 doublerand;6 inttemp, site1, site2;7 for (i=0; isite2)16 {17 temp =site1;18 site1 =site2;19 site2 =temp;20 }21 for (j=0; jgene[i][j] = parent1->gene[i][j];24 child2->gene[i][j] = parent2->gene[i][j];25 }26 for (j=site1; jgene[i][j] = parent2->gene[i][j];29 child2->gene[i][j] = parent1->gene[i][j];30 }31 for (j=site2; jgene[i][j] = parent1->gene[i][j];34 child2->gene[i][j] = parent2->gene[i][j];35 }36 }37 else
38 {39 for (j=0; jgene[i][j] = parent1->gene[i][j];42 child2->gene[i][j] = parent2->gene[i][j];43 }44 }45 }46 return;47 }