python实现遗传算法
最优化问题描述
求
min
[
3
−
sin
2
(
2
x
)
−
sin
2
(
2
y
)
]
\min [3 - {\sin ^2}(2x) - {\sin ^2}(2y)]
min[3−sin2(2x)−sin2(2y)]
所对应的点(x,y)
已知最小值:1.000
代码
import matplotlib.pyplot as plt
import random
import math
class GA(object):
def __init__(self,paras):
self.generation = paras[0]
self.group_size = paras[1]
self.chrom_length = paras[2]
self.min_value = paras[3]
self.max_value = paras[4]
self.pc = paras[5] # 交叉概率
self.pm = paras[6] # 变异概率
self.divid = [399,self.chrom_length -1]
# 计算函数
def f(self,args):
return self.f1(args)
def f1(self,args):
return (3 - (math.sin(2 * args[0])) ** 2 - (math.sin(2 * args[1])) ** 2)
# 适应函数
def s(self,x):
return self.s1(x)
def s1(self,x):
return math.exp(-abs(x - 1))
# 计算二进制序列代表的数值
def b2d(self,b):
self.rwno = []
for i in range(len(self.divid)):
if i == 0:
star = 0
end = self.divid[i]
else:
star = self.divid[i - 1] + 1
end = self.divid[i]
t = 0
for j in range(star, end): # 分隔参数[1,2,3||4,5,6]
t += b[j] * (math.pow(2, j - star))
t = t * self.max_value / (math.pow(2, end - star + 1) - 1) - self.min_value
self.rwno.append(t)
return self.rwno # 这是一个list
'''
计算当前函数值
group 染色体
chrom_length 染色体长度
max_value,min_value 最大最小值
divid 分割
'''
def calobjValue(self,group):
self.obj_value = []
for i in range(len(group)):
x = self.b2d(group[i]) # 这里面可能是多个变量
self.obj_value.append(self.f(x))
return self.obj_value
# 获取适应值
def calfitValue(self,obj_value):
self.fit_value = []
for i in range(len(obj_value)):
temp = self.s(obj_value[i]) # 调用适应函数计算
self.fit_value.append(temp)
return self.fit_value
# 累计适应值方便计算平均
def sum_fit(self,fit_value):
self.total = 0
for i in range(len(fit_value)):
self.total += fit_value[i]
return self.total
# 转轮盘选择法
def selection(self,group, fit_value):
newfit_value = [] # [ [[染色体], [锚点]],... ]
self.newgroup = [] # [ [父], [母], [父], [母],....]
# 适应度总和
total_fit = self.sum_fit(fit_value)
# 设置各个的锚点
t = 0
for i in range(len(group)):
t += fit_value[i] / total_fit
newfit_value.append([group[i], t])
# 转轮盘选择法
for i in range(len(newfit_value)):
parents = len(newfit_value) # 初始化指针
r = random.random() # 指针
for j in range(len(newfit_value)): # 看看指针指到谁了
if newfit_value[j][1] > r:
parents = j
break
self.newgroup.append(newfit_value[parents][0])
return self.newgroup
# 交叉
def crossover(self,group, fit_value):
parents_group = self.selection(group, fit_value) # [ [[父], [母]],....]
group_len = len(parents_group)
for i in range(0, group_len, 2):
if (random.random() < self.pc): # 看看是否要交配
cpoint = random.randint(0, len(parents_group[0])) # 随机交叉点
temp1 = []
temp2 = []
temp1.extend(parents_group[i][0:cpoint])
temp1.extend(parents_group[i + 1][cpoint:len(parents_group[i])])
temp2.extend(parents_group[i + 1][0:cpoint])
temp2.extend(parents_group[i][cpoint:len(parents_group[i])])
group[i] = temp1
group[i + 1] = temp2
return group
# 基因突变
def mutation(self,group):
px = len(group)
py = len(group[0])
for i in range(px): # 遍历
if (random.random() < self.pm):
mpoint = random.randint(0, py - 1) # 取要变异哪个
if (group[i][mpoint] == 1):
group[i][mpoint] = 0
else:
group[i][mpoint] = 1
return group
'''
找出最优解和最优解的基因编码
group 种群染色去
fit_value 种群适应
'''
def best(self,group, fit_value):
px = len(group)
best_in = group[0]
best_fit = fit_value[0]
for i in range(1, px):
if (fit_value[i] > best_fit):
best_fit = fit_value[i]
best_in = group[i]
# print(best_in)
return [best_in, best_fit]
'''
创建初代种群
group_size 种群大小
chrom_length 染色体长度
'''
def getFisrtGroup(self):
# print('初代种群:')
self.group = []
for i in range(self.group_size):
temp = []
for j in range(self.chrom_length):
temp.append(random.randint(0, 1))
self.group.append(temp)
# print(group)
return self.group
def run(self):
points = []
results = [] # 存储每一代的最优解
fit_value = [] # 个体适应度
group = self.getFisrtGroup()
for i in range(self.generation):
print("generation{}".format(i))
if i > 200:
pm = 0.01
if i > 1000:
pm = 0.001
obj_value = self.calobjValue(group) # 个体评价
fit_value = self.calfitValue(obj_value) # 获取群体适应值
best_individual, best_fit = self.best(group, fit_value) # 返回最优基因, 最优适应值
xx = self.b2d(best_individual)
if (abs(self.f(xx) - 1) < 0.000001): # 找到最优解
flag = False
for p in points:
if ((abs(xx[0] - p[0]) < 0.01) and (abs(xx[1] - p[1]) < 0.01)): # 剔除重复解
flag = True
break
if flag == False:
print(xx)
points.append(xx)
results.append(
[i, best_fit, self.b2d(best_individual),
best_individual]) # 加进坐标里
self.crossover(group, fit_value) # 交叉
self.mutation(group) # 变异
# results.sort(key=lambda x:x[1])
rank = sorted(results, key=lambda x: x[1])
# print('\n', rank[-1])
# print(results)
x = self.b2d(rank[-1][3])
# 最终结果
print("f(x) = ", self.f(x), "x = ", x, " 染色体 = ", rank[-1][3], " 适应值 = ", rank[-1][1], "代数:", rank[-1][0])
# 输出适应图
X = []
Y = []
for i in range(generation):
X.append(i)
Y.append(results[i][1])
plt.plot(X, Y)
plt.show()
if __name__ == '__main__':
generation = 500 # 繁衍代数
group_size = 400 # 染色体数量,偶数
max_value = 6 # 最大范围
min_value = 0 # 最小范围
chrom_length = 800 # 染色体长度
pc = 0.7 # 交配概率
pm = 0.1 # 变异概率
paras = [generation, group_size, chrom_length, min_value, max_value, pc, pm]
Gene = GA(paras)
Gene.run()
结果
f(x) = 1.0000201347927486
x = [2.3560175849594, 2.358431102830412]