遗传算法中二进制编码的生成和解码-Python
以六峰值驼背函数为例,有两个变量,范围分别是[-3, 3], [-2, 2],精度要求为0.01
那么要使用二进制编码来表示的话,编码方法采用多参数级联编码方法,也就是把两个变量分别编码然后顺序拼接起来。根据遗传算法的编码方法,染色体的长度的计算公式应该是
np.ceil(np.log2((UB[i] - LB[i]) / EPS + 1))
代入[-3,3], [-2,2]和0.01,算得染色体长度分别为10和9,拼接起来就是19。
def encode(VAR_NUM, LB, UB, EPS): L = np.zeros(3) L[0] = 0 for i in range(VAR_NUM): L[i + 1] = np.ceil(np.log2((UB[i] - LB[i]) / EPS + 1)) # 计算染色体的长度 LS = int(np.sum(L)) # 初始化种群 01随机矩阵 pop = np.random.randint(0, 2, LS) # 要返回染色体切割点索引 return pop, np.cumsum(list(map(int, L))) if __name__ == '__main__': # 以六峰值驼背函数为例 # 六峰值驼背函数有两个自变量, # 元素x[0]的范围是[-3,3] # 元素x[1]的范围是[-2, 2] print("随机生成一个二进制编码:") bin_code, point = encode(2, [-3, -2], [3, 2], 0.01) print(bin_code) print("染色体切割点索引") print(point)
输出:
随机生成一个二进制编码:
[1 0 0 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0 1]
染色体切割点索引
[ 0 10 19]
解码的话,先把二进制转换为十进制,然后根据最大最小值标准化公式把数值限制到[-3,3]和[-2,2]即可。
# 二进制转化为十进制 def decode(bin_list, lb, ub): length = len(bin_list) temp = np.zeros(length) for j in range(1, length): # 注意索引 temp[j] = np.power(2, length-1-j) * bin_list[j] temp = np.sum(temp) # 0表示纵向求和,结果长度和列数相同 print("十进制数: ", temp) real = lb + temp * (ub - lb) / (np.power(2, length) - 1) return real if __name__ == '__main__': # 以六峰值驼背函数为例 # 六峰值驼背函数有两个自变量, # 元素x[0]的范围是[-3,3] # 元素x[1]的范围是[-2, 2] print("随机生成一个二进制编码:") bin_code, point = encode(2, [-3, -2], [3, 2], 0.01) print(bin_code) print("染色体切割点索引") print(point) print("解码为两个变量") print("二进制数", bin_code[point[0]: point[1]]) print("标准化到[-3, 3]范围内", decode(bin_code[point[0]: point[1]], -3, 3)) print("二进制数", bin_code[point[1]: point[2]]) print("标准化到[-2, 2]范围内", decode(bin_code[point[1]: point[2]], -2, 2))
输出结果:
随机生成一个二进制编码:
[1 0 0 0 0 0 1 0 1 1 0 0 1 1 0 0 0 0 1]
染色体切割点索引
[ 0 10 19]
解码为两个变量
二进制数 [1 0 0 0 0 0 1 0 1 1]
十进制数: 11.0
标准化到[-3, 3]范围内 -2.935483870967742
二进制数 [0 0 1 1 0 0 0 0 1]
十进制数: 97.0
标准化到[-2, 2]范围内 -1.2407045009784736