openGauss源码解析(103)

openGauss源码解析:SQL引擎源解析(18)

2. 种群初始化

在使用遗传算法前,可以利用参数Gepo_threshold的数值来调整触发的条件。为了方便代码解读,将这个边界条件降低至4(即RelOptInfo数量或者说基表数量为4的时候就尝试使用遗传算法)。下面在解读代码的过程中,以t1,t2,t3,t4四个表为例进行说明。

RelOptInfo作为遗传算法的基因,首先需要进行基因编码,openGauss数据库采用实数编码的方式,也就是用{1,2,3,4}分别代表t1,t2,t3,t4这4个表。

然后通过gimme_pool_size函数来获得种群的大小,种群的大小受Geqo_pool_size和Geqo_effort两个参数的影响,种群用Pool结构体进行表示,染色体用Chromosome结构体来表示。代码如下:

/* 染色体Chromosome结构体 */

typedef struct Chromosome {

/* string实际是一个整型数组,它代表基因的一种排序方式,也就对应一棵连接树 */

/* 例如{1,2,3,4}对应的就是t1 JOIN t2 JOIN t3 JOIN t4 */

/* 例如{2,3,1,4}对应的就是t2 JOIN t3 JOIN t1 JOIN t4 */

Gene* string;

Cost worth; /* 染色体的适应度,实际上就是路径代价 */

} Chromosome;

/* 种群Pool结构体 */

typedef struct Pool {

Chromosome *data; /* 染色体数组,数组中每个元组都是一个连接树 */

int size; /* 染色体的数量,即data中连接树的数量,由gimme_pool_size生成 */

int string_length; /* 每个染色体中的基因数量,和基表的数量相同 */

} Pool;

另外通过gimme_number_generations函数来获取染色体交叉的次数,交叉的次数越多则产生的新染色体也就越多,也就更可能找到更好的解,但是交叉次数多也影响性能,用户可以通过Geqo_generations参数来调整交叉的次数。

在结构体中确定的变量如下。

(1) 通过gimme_pool_size确定的染色体的数量(Pool.size)。
(2) 每个染色体中基因的数量(Pool.string_length),和基表的数量相同。

然后就可以开始生成染色体,染色体的生成采用的是Fisher-Yates洗牌算法,最终生成Pool.size条染色体。具体的算法实现如下:

/* 初始化基因序列至{1,2,3,4} */

for (i = 0; i < num_gene; i++)

tmp[i] = (Gene)(i + 1);

remainder = num_gene - 1; /* 定义剩余基因数 */

/* 洗牌方法实现,多次随机挑选出基因,作为基因编码的一部分 */

for (i = 0; i < num_gene; i++) {

/* choose value between 0 and remainder inclusive */

next = geqo_randint(root, remainder, 0);

/* output that element of the tmp array */

tour[i] = tmp[next]; /* 基因编码 */

/* and delete it */

tmp[next] = tmp[remainder]; /* 将剩余基因序列更新 */

remainder--;

}

表6-18是生成一条染色体的流程,假设4次的随机结果为{1,1,1,0}。

表6-18 生成染色体的流程

基因备选集

Tmp

结果集

tour

随机数

范围

随机数

说明

1 2 3 4

2

0~3

1

随机数为1,结果集的第一个基因为tmp[1],值为2,更新备选集tmp,将未被选中的末尾值放在前面被选中的位置上

1 4 3

2 4

0~2

1

随机数为1,结果集的第二个基因为4,再次更新备选集tmp

1 3

2 4 3

0~1

1

随机数为1,结果集的第三个基因为3,由于末尾值被选,无须更新备选集

1

2 4 3 1

0~0

0

最后一个基因为1

在多次随机生成染色体后,得到一个种群,假设Pool种群中共有4条染色体,用图来描述其结构,如图6-13所示。

遗传算法1

图6-13 染色体结构

posted @ 2024-04-30 10:35  openGauss-bot  阅读(1)  评论(0)    收藏  举报