以六峰值駝背函數為例,有兩個變量,范圍分別是[-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
