二进制编码:用一个二进制串 表示 这个十进制数值 。
个体进行复制,以概率进行基因的交叉,注意 复制交叉方式多种多样 。
复制
交叉
变异
轮盘赌基本思想:适应度越高的解,按道理越应该高概率的进行复制,且复制的份数应该越多。
对于个体 x i x_i xi,计算对应适应度 ( ) (_) f(xi) ==> = ( ) ∑ ( ) _ = \frac{(_)}{\sum{(_)}} pi=∑f(xi)f(xi)
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation as animation # 动画
import math
from numpy import random
# 解所在的可能区间
start = 0 # 起始
end = 8 # 结尾
# 迭代次数
iteration = 200
# 种群大小
size = 50
# 交叉概率
pc = 0.85
# 变异概率
pm = 0.05
# 表达式
def fitness(x):
y = x * np.sin(4 * x) + 3 * x * np.cos(x) + 15
return y
# 二进制编码
def getStrLen(precision):
# 根据精度求串长
l = math.ceil(math.log2((end - start) / precision + 1))
return l
# 二进制解码: 二进制转十进制
def binaryDecode(matrix):
len = getStrLen(1e-5)
realValue = np.zeros(size)
for i in range(size): # 按照行来遍历
for j in range(len): # 对第i行进行遍历
realValue[i] += matrix[i][j] * math.pow(2, j)
for i in range(size):
realValue[i] = start + realValue[i] * (end - start) / (math.pow(2, len) - 1)
return realValue
# 复制
def copyX(parentX, fitness): # martix 二进制基因片段;fitness种群的适应度
l = getStrLen(1e-5)
newX = np.random.randint(0, 2, (size, l)) #初始化一个下一代矩阵空间
# print("初始化下一代矩阵")
# print(newX)
p = fitness / np.sum(fitness) #概率
cs = np.cumsum(p) #累积概率
# print("累积概率")
# print(cs)
cps= np.sort(np.random.rand(size)) # 轮盘赌,每个个体复制的概率
# print("每个个体复制的概率")
# print(cps)
for i in range(size):
if cps[i] < cs[i]:
newX[i,:] = parentX[i,:]
# print("复制后的种群")
# print(newX)
return newX
# 交叉方式 第i行的[crossStart, crossEnd]片段 与 第 i + 1行的[crossStart, crossEnd]片段交换
def crossX(matrix):
i = 0
l = getStrLen(1e-5)
while i < size:
if np.random.rand(1) < pc:
positions = np.random.choice(l, 2, False)
crossStart = positions.min()
crossEnd = positions.max()
np.random.choice(l, 2, False) # 在[0, len)之间选择两个不重复的数字
j = (i + 1) % size
pre = matrix[i: j, crossStart: crossEnd + 1]
if j > i:
matrix[i: j, crossStart: crossEnd + 1] = matrix[j: j + 1, crossStart: crossEnd + 1]
matrix[j: j + 1, crossStart: crossEnd + 1] = pre
i = i + 2
else:
i = i + 1
if i >= size:
break
# print("交叉后的种群")
# print(matrix)
return matrix
# 变异
def mutationX(matrix):
l = getStrLen(1e-5)
for i in range(size):
if np.random.rand(1) < pm:
position = np.random.choice(l, 1, False)
matrix[i][position] = np.mod((matrix[i][position] + 1), 2)
# print("变异后的种群")
# print(matrix)
return matrix
if __name__ == '__main__':
l = getStrLen(1e-5)
# 生成初代种群,size--种群大小;len--串长
matrix = np.random.randint(0, 2, (size, l))
print("初代矩阵")
print(matrix)
# 绘制函数图像
t = np.arange(start, end, 0.001)
for i in range(iteration):
dec = binaryDecode(matrix) # 上一代解的十进制
fit = fitness(dec) # 上一代适应值
# print("上代适应值")
# print(fit)
# print("******* 复制操作 ********")
newX = copyX(matrix, fit)
# print("******* 交叉操作 ********")
newX = crossX(newX)
# print("******* 变异操作 ********")
newX = mutationX(newX)
# 对下一代择优保留
newDec = binaryDecode(newX) #新一代十进制
newFit = fitness(newDec) # 新一代适应度
for j in range(size):
if newFit[j] > fit[j]:
matrix[j,:] = newX[j,:] # 将好的子代替换进父代
# 动态每一代最优值图像
dec = binaryDecode(matrix) # 择优后最终新一代解的十进制
fit = fitness(dec) # 择优后最终新一代适应值
plt.plot(t, fitness(t), color='black')
plt.scatter(dec, fit, s=5, c='red')
plt.draw()
plt.pause(0.2)
plt.clf()
dec = binaryDecode(matrix) # 最终一代解的十进制
fit = fitness(dec) # 最一代适应值
maxIndex = fit.argmax()
plt.plot(t,fitness(t),color = 'black')
plt.scatter(dec, fit, s=5, c='red')
plt.scatter(dec[maxIndex], fit.max(), s=5, c = 'blue')
plt.show()
# 取矩阵的第一行 matrix[0,:]
# 取矩阵的第一列 matrix[:,0]
# 取部分矩阵,行[i, j),列[m,n):matrix[i: j, m: n]
# 产生一个随机小数:np.random.rand(1)
# -------------------动态图-----------------------
# fig:窗口画布,用 fig, ax = plt.subplots() 生成
# func:要反复调用的函数(至少要传入一个参数),用该函数生成、更改图像
# frames:向要调用的函数传递的参数(默认依次传入0,1,2,3…)
# init_func:用于给定图像初始信息的函数