import numpy as np
import random as rd
import seaborn as sns
import matplotlib.pyplot as plt
def F(x, y):#目标函数
return 3*(1-x)**2*np.exp(-(x**2)-(y+1)**2)- 10*(x/5 - x**3 - y**5)*np.exp(-x**2-y**2)- 1/3**np.exp(-(x+1)**2 - y**2)
class GA():
def __init__(self,lb,ub,fitF):
self.fitF= fitF#目标函数
self.lb = lb#约束下线
self.ub = ub#约束上限
self.size = 2#变量个数
self.len = 22#基因长度
self.popsize = 100#种群大小
self.inti_pop = np.random.randint(0,2,size=(self.popsize,self.len*self.size)).astype('str')#初始化种群2^10=1024 2^22=4194304
self.x = np.zeros((self.popsize*2,self.size))#记录每个基因产生的X
self.mutation_P = 0.1#变异概率
self.cross_P = 0.3#交叉的概率
self.bestX = None#最优解
self.bestY = None#最优值
self.Y_container = []#记录每次的最优值
def Decode(self,inti_pop):#二进制解码并计算轮盘赌所需的概率值
for i in range(self.popsize*2):#遍历每一个基因,然后计算对应的X值
single = inti_pop[i].reshape(self.size,self.len)#每个个体拆分成x1,x2,x3,...,xn
for j in range(self.size):
bin_x = ''.join(single[j])
self.x[i][j] = self.lb[j] + int(bin_x,2)/(2**self.len-1)*(self.ub[j]-self.lb[j])
x1 =self.x[:,0];x2=self.x[:,1]#因为有两个参数:x,y
values = self.fitF(x1,x2)
fitness = values-values.min()+1e-1
return fitness/fitness.sum()
def mutation(self,child):#每一个child执行变异
ind = rd.randint(0,self.len*2-1)#随机选取变异点 randint包含末位树 是个坑
child[ind] = str(int(child[ind])^1)#执行变异 python 特殊规则 1^1 = 0 ; 0^1 =1
return child
##产新种群的策略:先交差变异产生同等popsize的种群,然后从这个种群和之前的种群中轮盘度选择最有的种群 作为新种群,循环操作即可
def cross_mutation(self):#交叉遗传 一部分不变 ,一部分子代变异 {这里包含了交叉变异遗传}
chiledren = []
for i in range(self.popsize):
child = self.inti_pop[i]#可以看做 father 或者 child
if rd.random()<self.cross_P:#交叉操作
ind_mom = self.inti_pop[rd.randint(0,self.popsize-1)]#随机挑选一个作为mom randint包含末位树 是个坑
cross_d = rd.randint(0,self.len*self.size)#随机选取交叉点
child[:cross_d] = ind_mom[:cross_d]#完成交叉
if rd.random() < self.mutation_P: # 按照变异概率进行点位变异
child = self.mutation(child=child)#执行变异
chiledren.append(child)
#交叉变异执行完毕后,新种群与旧种群,结合在一起,等待使用轮盘度挑选下一代种群
inti_pop = np.vstack((np.array(chiledren),self.inti_pop))
#执行完毕,轮盘度产生新的pop
ind = np.random.choice(np.arange(self.popsize*2), size=int(self.popsize), replace=True, p=self.Decode(inti_pop))
self.inti_pop = inti_pop[ind]
def run(self,iteration):#循环迭代
for _ in range(iteration):
self.cross_mutation()
a = self.fitF(self.x[:,0],self.x[:,1]).tolist()#计算最后一次的结果值
ind = a.index(max(a))
self.bestY = a[ind]
self.bestX = self.x[ind]
self.Y_container.append(self.bestY)
pop = GA(lb=[1,3],ub=[-3,3],fitF=F)
pop.run(1000)
plt.plot(pop.Y_container)
plt.show()
print(pop.bestY)