openGauss源码解析(106)
openGauss源码解析:SQL引擎源解析(21)
4. 交叉算子
通过选择算子选择出父母染色体之后,则可以对选出的父母染色体进行交叉操作,生成新的子代染色体。
openGauss提供了多种交叉方法,包括有基于边的重组交叉方法(edge combination crossover)、部分匹配交叉方法(partially matched crossover)、循环交叉(cycle crossover)、位置交叉(position crossover)、顺序交叉(order crossover)等。在源代码分析的过程中,以位置交叉方法为例进行说明。
假如选择父染色体的基因编码为{1, 3, 2, 4},适应度为100,母染色体的基因编码为{2, 3, 1, 4},适应度为200,在子染色体还没有生成,处于未初始化状态时,这些染色体的状态如图6-16所示。
图6-16 染色体状态
交叉操作需要生成一个随机数num_positions,这个随机数的位置介于基因总数的1/3~2/3区间的位置,这个随机数代表了有多少父染色体的基因要按位置遗传给子染色体。具体代码如下:
/* num_positions决定了父染色体遗传多少基因给子染色体 */
num_positions = geqo_randint(root, 2 * num_gene / 3, num_gene / 3);
/* 选择随机位置*/
for (i = 0; i < num_positions; i++)
{
/* 随机生成位置,将父染色体这个位置的基因遗传给子染色体 */
pos = geqo_randint(root, num_gene - 1, 0);
offspring[pos] = tour1[pos];
/* 标记这个基因已经使用,母染色体不能再遗传相同的基因给子染色体 */
city_table[(int) tour1[pos]].used = 1;
}
假设父染色体需要遗传2个基因给子染色体,分别传递第1号基因和第2号基因,那么子染色体目前的状态如图6-17所示。
图6-17 当前染色体状态
目前子染色体已经有了3和2两个基因,则母染色体排除这两个基因后,还剩下1和4两个基因,将这两个基因按照母染色体中的顺序写入子染色体,新的子染色体就生成了,如图6-18所示。
图6-18 新的染色体装状态