def run(self, prophetPop=None): # prophetPop为先知种群(即包含先验知识的种群) #==========================初始化配置=========================== population = self.population NIND = population.sizes self.initialization() # 初始化算法模板的一些动态参数 #===========================准备进化============================ if population.Chrom is None: population.initChrom(NIND) # 初始化种群染色体矩阵 self.call_aimFunc(population) # 计算种群的目标函数值 # 插入先验知识(注意:这里不会对先知种群prophetPop的合法性进行检查,故应确保prophetPop是一个种群类且拥有合法的Chrom、ObjV、Phen等属性) if prophetPop is not None: population = (prophetPop + population)[:NIND] # 插入先知种群 population.FitnV = ea.ranking(self.problem.maxormins * population.ObjV, population.CV) # 计算适应度 #===========================开始进化============================ while self.terminated(population) == False: # 进行差分进化操作 r0 = ea.selecting(self.selFunc, population.FitnV, NIND) # 得到基向量索引 experimentPop = population.copy() # 存储试验个体 experimentPop.Chrom = self.mutOper.do(experimentPop.Encoding, experimentPop.Chrom, experimentPop.Field, [r0]) # 变异 tempPop = population + experimentPop # 当代种群个体与变异个体进行合并(为的是后面用于重组) experimentPop.Chrom = self.recOper.do(tempPop.Chrom) # 重组 self.call_aimFunc(experimentPop) # 计算目标函数值 tempPop = population + experimentPop # 临时合并,以调用otos进行一对一生存者选择 tempPop.FitnV = ea.ranking(self.problem.maxormins * tempPop.ObjV, tempPop.CV) # 计算适应度 population = tempPop[ea.selecting( 'otos', tempPop.FitnV, NIND)] # 采用One-to-One Survivor选择,产生新一代种群 return self.finishing(population) # 调用finishing完成后续工作并返回结果
def Evolution(self): start_time = time.time() Objv = self.get_Objv_i(self.chrom) best_ind = np.argmax(Objv * self.maxormins) for gen in range(self.MAXGEN): self.log.logger.info('==> This is No.%d GEN <==' % (gen)) FitnV = ea.ranking(Objv * self.maxormins) Selch = self.chrom[ea.selecting('rws', FitnV, self.Nind - 1), :] Selch = ea.recombin('xovsp', Selch, self.xov_rate) Selch = ea.mutate('mutswap', 'RI', Selch, self.FieldDR) NewChrom = np.vstack((self.chrom[best_ind, :], Selch)) Objv = self.get_Objv_i(NewChrom) best_ind = np.argmax(Objv * self.maxormins) self.obj_trace[gen, 0] = np.sum(Objv) / self.Nind #记录当代种群的目标函数均值 self.obj_trace[gen, 1] = Objv[best_ind] #记录当代种群最有给他目标函数值 self.var_trace[gen, :] = NewChrom[best_ind, :] #记录当代种群最有个体的变量值 self.log.logger.info( 'GEN=%d,best_Objv=%.5f,best_chrom_i=%s\n' % (gen, Objv[best_ind], str( NewChrom[best_ind, :]))) #记录每一代的最大适应度值和个体 end_time = time.time() self.time = end_time - start_time
def Evolution(self): # start_time = time.time() # 初始化种群 self.get_FieldDR() Init_chrom = self.get_init_chrom() # 开始进化 self.log.logger.info('==> This is Init GEN <==') Init_Objv = self.get_Objv_i(Init_chrom) best_ind = np.argmax(Init_Objv * self.maxormins) #记录最优个体的索引值 self.chrom_all = Init_chrom self.Objv_all = Init_Objv for gen in range(self.MAXGEN): self.log.logger.info('==> This is No.%d GEN <==' % (gen)) if gen == 0: #第一代和后面有所不同 chrom = Init_chrom Objv = Init_Objv else: chrom = NewChrom Objv = NewObjv FitnV = ea.ranking(Objv * self.maxormins) Selch = chrom[ea.selecting('rws', FitnV, self.Nind - 1), :] #轮盘赌选择 Nind-1 代,与上一代的最优个体再进行拼接 Selch = ea.recombin('xovsp', Selch, self.xov_rate) #重组,即交叉 Selch = ea.mutate('mutswap', 'RI', Selch, self.FieldDR) #变异 Objv_Selch = self.get_Objv_i(Selch) NewChrom = np.vstack( (chrom[best_ind, :], Selch)) #将上一代的最优个体与现在的种群拼接 NewObjv = np.vstack((Objv[best_ind, :], Objv_Selch)) best_ind = np.argmax(NewObjv * self.maxormins) self.chrom_all = np.vstack((self.chrom_all, NewChrom)) self.Objv_all = np.vstack((self.Objv_all, NewObjv)) self.obj_trace[gen, 0] = np.sum(NewObjv) / self.Nind # 记录当代种群的目标函数均值 self.obj_trace[gen, 1] = NewObjv[best_ind] # 记录当代种群最有给他目标函数值 self.var_trace[gen, :] = NewChrom[best_ind, :] # 记录当代种群最优个体的变量值 self.log.logger.info( 'GEN=%d,best_Objv=%.5f,best_chrom_i=%s\n' % (gen, NewObjv[best_ind], str( NewChrom[best_ind, :]))) # 记录每一代的最大适应度值和个体 self.Save_chroms(self.chrom_all) self.Save_objvs(self.Objv_all) end_time = time.time() self.time = end_time - start_time self.log.logger.info('The time of Evoluation is %.5f s. ' % self.time)
def i_awGA(AIM_M, AIM_F, NIND, ranges, borders, precisions, MAXGEN, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, maxormin): """==========================初始化配置===========================""" # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 FieldDR = ga.crtfld(ranges, borders, precisions) """=========================开始遗传算法进化=======================""" Chrom = ga.crtrp(NIND, FieldDR) # 创建简单离散种群 ObjV = aimfuc(Chrom) # 计算种群目标函数值 NDSet = np.zeros((0, ObjV.shape[1])) # 定义帕累托最优解集合(初始为空集) start_time = time.time() # 开始计时 # 开始进化!! for gen in range(MAXGEN): if NDSet.shape[0] > 2 * ObjV.shape[0]: break [CombinObjV, weight] = ga.awGA(ObjV) # 适应性权重法求聚合目标函数值 FitnV = ga.ranking(maxormin * CombinObjV) # 根据加权单目标计算适应度 [FitnV, frontIdx] = ga.ndominfast(maxormin * ObjV, FitnV) # 求种群的非支配个体,并更新适应度 # 更新帕累托最优集以及种群非支配个体的适应度 [FitnV, NDSet, repnum] = ga.upNDSet(FitnV, maxormin * ObjV, maxormin * NDSet, frontIdx) # 进行遗传操作!! SelCh = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh = ga.recombin(recombinStyle, SelCh, recopt, SUBPOP) #交叉 SelCh = ga.mutbga(SelCh, FieldDR, pm) # 变异 if repnum > Chrom.shape[0] * 0.1: # 进行一次高斯变异 SelCh = ga.mutgau(SelCh, FieldDR, pm) # 高斯变异 ObjVSel = aimfuc(SelCh) # 求育种个体的目标函数值 [CombinObjV, weight] = ga.awGA(maxormin * ObjVSel) # 适应性权重法求聚合目标函数值 FitnVSel = ga.ranking(maxormin * CombinObjV) # 根据聚合目标求育种个体适应度 [Chrom, ObjV] = ga.reins(Chrom, SelCh, SUBPOP, 1, 0.9, FitnV, FitnVSel, ObjV, ObjVSel) #重插入 end_time = time.time() # 结束计时 # 返回帕累托最优集以及执行时间 return [ObjV, NDSet, end_time - start_time]
def mintemp1(AIM_M, AIM_F, PUN_M, PUN_F, ranges, borders, MAXGEN, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, maxormin): """==========================初始化配置===========================""" # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 punishing = getattr(PUN_M, PUN_F) # 获得罚函数 FieldDR = ga.crtfld(ranges, borders) # 初始化区域描述器 NVAR = ranges.shape[1] # 得到控制变量的个数 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN, 3)) * np.nan).astype('int64') # 定义变量记录器,记录控制变量值,初始值为nan var_trace = (np.zeros((MAXGEN, NVAR)) * np.nan).astype('int64') """=========================开始遗传算法进化=======================""" Chrom = ga.crtip(NIND, FieldDR) # 根据区域描述器FieldDR生成整数型初始种群 LegV = np.ones((NIND, 1)) # 生成可行性列向量,元素为1表示对应个体是可行解,0表示非可行解 [ObjV, LegV] = aimfuc(Chrom, LegV) # 计算种群目标函数值,同时更新LegV start_time = time.time() # 开始计时 # 开始进化!! for gen in range(MAXGEN): FitnV = ga.ranking(maxormin * ObjV, LegV) # 计算种群适应度 FitnV = punishing(LegV, FitnV) # 调用罚函数 # 记录进化过程 bestIdx = np.argmax(FitnV) if LegV[bestIdx] != 0: feasible = np.where(LegV != 0)[0] # 排除非可行解 # 记录当代种群的适应度均值 pop_trace[gen, 1] = np.sum(FitnV[feasible]) / FitnV[feasible].shape[0] # 记录当代种群最优个体的目标函数值 pop_trace[gen, 0] = ObjV[bestIdx] # 记录当代种群的最优个体的适应度值 pop_trace[gen, 2] = FitnV[bestIdx] # 记录当代种群最优个体的变量值 var_trace[gen, :] = Chrom[bestIdx, :] # 进行遗传操作!! SelCh = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh = ga.recombin(recombinStyle, SelCh, recopt, SUBPOP) #交叉 SelCh = ga.mutint(SelCh, FieldDR, pm) # 实值变异 LegVSel = np.ones((SelCh.shape[0], 1)) # 创建育种个体的可行性列向量 [ObjVSel, LegVSel] = aimfuc(SelCh, LegVSel) # 求育种个体的目标函数值 FitnVSel = punishing(LegVSel, FitnV) # 调用罚函数 [Chrom, ObjV, LegV] = ga.reins(Chrom, SelCh, SUBPOP, 1, 1, FitnV, FitnVSel, ObjV, ObjVSel, LegV, LegVSel) #重插入 end_time = time.time() # 结束计时 # 后处理进化记录器 delIdx = np.where(np.isnan(pop_trace))[0] pop_trace = np.delete(pop_trace, delIdx, 0) var_trace = np.delete(var_trace, delIdx, 0) # 返回进化记录器、变量记录器以及执行时间 return [pop_trace, var_trace, end_time - start_time]
def mintemp1(AIM_M, AIM_F, PUN_M, PUN_F, ranges, borders, MAXGEN, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, maxormin): """==========================初始化配置===========================""" # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 punishing = getattr(PUN_M, PUN_F) # 获得罚函数 FieldDR = ga.crtfld(ranges, borders) # 初始化区域描述器 NVAR = ranges.shape[1] # 得到控制变量的个数 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN, 3)) * np.nan).astype('int64') # 定义变量记录器,记录控制变量值,初始值为nan var_trace = (np.zeros((MAXGEN, NVAR)) * np.nan).astype('int64') """=========================开始遗传算法进化=======================""" Chrom = ga.crtip(NIND, FieldDR) # 根据区域描述器FieldDR生成整数型初始种群 ObjV = aimfuc(Chrom) # 计算种群目标函数值 start_time = time.time() # 开始计时 # 开始进化!! for gen in range(MAXGEN): FitnV = ga.ranking(maxormin * ObjV) # 计算种群适应度 FitnV = punishing(Chrom, FitnV) # 调用罚函数 # 记录当代种群最优个体的目标函数值 pop_trace[gen, 0] = ObjV[np.argmax(FitnV)] # 记录当代种群的适应度均值 pop_trace[gen, 1] = np.sum(FitnV) / FitnV.shape[0] # 记录当代种群的最优个体的适应度值 pop_trace[gen, 2] = np.max(FitnV) # 记录当代种群最优个体的变量值 var_trace[gen, :] = Chrom[np.argmax(FitnV), :] # 进行遗传操作!! SelCh = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh = ga.recombin(recombinStyle, SelCh, recopt, SUBPOP) #交叉 SelCh = ga.mutint(SelCh, FieldDR, pm) # 实值变异 ObjVSel = aimfuc(SelCh) # 求育种个体的目标函数值 [Chrom,ObjV] = ga.reins(Chrom,SelCh,SUBPOP,2,1,maxormin*ObjV,\ maxormin*ObjVSel) #重插入 end_time = time.time() # 结束计时 # 返回进化记录器、变量记录器以及执行时间 return [pop_trace, var_trace, end_time - start_time]
def sga_permut_templet(AIM_M, AIM_F, PUN_M, PUN_F, NVAR, VarLen, maxormin, MAXGEN, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, distribute, drawing=1): """ sga_permut_templet.py - 单目标编程模板(排列编码) 排列编码即每条染色体的基因都是无重复正整数的编码方式。 语法: 该函数除了参数drawing外,不设置可缺省参数。当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: sga_permut_templet(AIM_M, 'aimfuc', None, None, ..., maxormin) 输入参数: AIM_M - 目标函数的地址,由AIM_M = __import__('目标函数所在文件名')语句得到 目标函数规范定义:[f,LegV] = aimfuc(Phen,LegV) 其中Phen是种群的表现型矩阵, LegV为种群的可行性列向量,f为种群的目标函数值矩阵 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,由PUN_M = __import__('罚函数所在文件名')语句得到 罚函数规范定义: newFitnV = punishing(LegV, FitnV) 其中LegV为种群的可行性列向量, FitnV为种群个体适应度列向量 一般在罚函数中对LegV为0的个体进行适应度惩罚,返回修改后的适应度列向量newFitnV PUN_F : str - 罚函数名 NVAR : int - 变量个数,排列编码的染色体长度等于变量个数 VarLen : int - 排列集合的大小 例如VarLen = 5表示是从1,2,3,4,5中抽取若干个数排列组成染色体 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,表示子代与父代染色体及性状不相同的概率 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 distribute : bool - 是否增强种群的分布性(可能会造成收敛慢) drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图。默认drawing为1 输出参数: pop_trace : array - 种群进化记录器(进化追踪器), 第0列记录着各代种群最优个体的目标函数值 第1列记录着各代种群的适应度均值 第2列记录着各代种群最优个体的适应度值 var_trace : array - 变量记录器,记录着各代种群最优个体的变量值,每一列对应一个控制变量 times : float - 进化所用时间 模板使用注意: 1.本模板调用的目标函数形如:[ObjV,LegV] = aimfuc(Phen,LegV), 其中Phen表示种群的表现型矩阵, LegV为种群的可行性列向量(详见Geatpy数据结构) 2.本模板调用的罚函数形如: newFitnV = punishing(LegV, FitnV), 其中FitnV为用其他算法求得的适应度 若不符合上述规范,则请修改算法模板或自定义新算法模板 3.关于'maxormin': geatpy的内核函数全是遵循“最小化目标”的约定的,即目标函数值越小越好。 当需要优化最大化的目标时,需要设置'maxormin'为-1。 本算法模板是正确使用'maxormin'的典型范例,其具体用法如下: 当调用的函数传入参数包含与“目标函数值矩阵”有关的参数(如ObjV,ObjVSel,NDSetObjV等)时, 查看该函数的参考资料(可用'help'命令查看,也可到官网上查看相应的教程), 里面若要求传入前对参数乘上'maxormin',则需要乘上。 里面若要求对返回参数乘上'maxormin'进行还原, 则调用函数返回得到的相应参数需要乘上'maxormin'进行还原,否则其正负号就会被改变。 """ """==========================初始化配置===========================""" # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 if PUN_F is not None: punishing = getattr(PUN_M, PUN_F) # 获得罚函数 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN, 2)) * np.nan) # 定义变量记录器,记录控制变量值,初始值为nan var_trace = (np.zeros((MAXGEN, NVAR)) * np.nan) ax = None # 存储上一帧图形 """=========================开始遗传算法进化=======================""" #生成初始种群 Chrom = ga.crtpp(NIND, NVAR, VarLen) LegV = np.ones((NIND, 1)) # 初始化种群的可行性列向量 [ObjV, LegV] = aimfuc(Chrom, LegV) # 求种群的目标函数值 gen = 0 badCounter = 0 # 用于记录在“遗忘策略下”被忽略的代数 # 开始进化!! start_time = time.time() # 开始计时 while gen < MAXGEN: if badCounter >= 10 * MAXGEN: # 若多花了10倍的迭代次数仍没有可行解出现,则跳出 break FitnV = ga.ranking(maxormin * ObjV, LegV, None, SUBPOP) if PUN_F is not None: FitnV = punishing(LegV, FitnV) # 调用罚函数 # 记录进化过程 bestIdx = np.argmax(FitnV) # 获取最优个体的下标 if LegV[bestIdx] != 0: feasible = np.where(LegV != 0)[0] # 排除非可行解 pop_trace[gen, 0] = np.sum( ObjV[feasible]) / ObjV[feasible].shape[0] # 记录种群个体平均目标函数值 pop_trace[gen, 1] = ObjV[bestIdx] # 记录当代目标函数的最优值 var_trace[gen, :] = Chrom[bestIdx, :] # 记录当代最优的控制变量值 # 绘制动态图 if drawing == 2: ax = ga.sgaplot(pop_trace[:, [1]], '种群最优个体目标函数值', False, ax, gen) badCounter = 0 # badCounter计数器清零 else: gen -= 1 # 忽略这一代(遗忘策略) badCounter += 1 # 进行遗传算子 SelCh = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh = ga.recombin(recombinStyle, SelCh, recopt, SUBPOP) # 对选择的个体进行重组 SelCh = ga.mutpp(SelCh, VarLen, pm) # 排列编码种群变异 LegVSel = np.ones((SelCh.shape[0], 1)) # 初始化育种种群的可行性列向量 [ObjVSel, LegVSel] = aimfuc(SelCh, LegVSel) # 求育种种群的目标函数值 FitnVSel = ga.ranking(maxormin * ObjVSel, LegVSel, None, SUBPOP) # 计算育种种群的适应度 if PUN_F is not None: FitnVSel = punishing(LegVSel, FitnVSel) # 调用罚函数 # 重插入 [Chrom, ObjV, LegV] = ga.reins(Chrom, SelCh, SUBPOP, 1, 1, FitnV, FitnVSel, ObjV, ObjVSel, LegV, LegVSel) gen += 1 end_time = time.time() # 结束计时 times = end_time - start_time # 后处理进化记录器 delIdx = np.where(np.isnan(pop_trace))[0] pop_trace = np.delete(pop_trace, delIdx, 0) var_trace = np.delete(var_trace, delIdx, 0) if pop_trace.shape[0] == 0: raise RuntimeError('error: no feasible solution. (有效进化代数为0,没找到可行解。)') # 绘图 if drawing != 0: ga.trcplot(pop_trace, [['种群个体平均目标函数值', '种群最优个体目标函数值']]) # 输出结果 if maxormin == 1: best_gen = np.argmin(pop_trace[:, 1]) # 记录最优种群是在哪一代 best_ObjV = np.min(pop_trace[:, 1]) elif maxormin == -1: best_gen = np.argmax(pop_trace[:, 1]) # 记录最优种群是在哪一代 best_ObjV = np.max(pop_trace[:, 1]) print('最优的目标函数值为:%f' % (best_ObjV)) print('最优的控制变量值为:') for i in range(NVAR): print(var_trace[best_gen, i]) print('有效进化代数:%d' % (pop_trace.shape[0])) print('最优的一代是第 %d 代' % (best_gen + 1)) print('时间已过 %f 秒' % (times)) # 返回进化记录器、变量记录器以及执行时间 return [pop_trace, var_trace, times]
def sga_code_templet(AIM_M, AIM_F, PUN_M, PUN_F, FieldD, problem, maxormin, MAXGEN, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, distribute, drawing=1): """ sga_code_templet.py - 单目标编程模板(二进制/格雷编码) 语法: 该函数除了参数drawing外,不设置可缺省参数。当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: sga_code_templet(AIM_M, 'aimfuc', None, None, ..., maxormin) 输入参数: AIM_M - 目标函数的地址,由AIM_M = __import__('目标函数所在文件名')语句得到 目标函数规范定义:[f,LegV] = aimfuc(Phen,LegV) 其中Phen是种群的表现型矩阵, LegV为种群的可行性列向量,f为种群的目标函数值矩阵 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,由PUN_M = __import__('罚函数所在文件名')语句得到 罚函数规范定义: newFitnV = punishing(LegV, FitnV) 其中LegV为种群的可行性列向量, FitnV为种群个体适应度列向量 一般在罚函数中对LegV为0的个体进行适应度惩罚,返回修改后的适应度列向量newFitnV PUN_F : str - 罚函数名 FieldD : array - 二进制/格雷码种群区域描述器, 描述种群每个个体的染色体长度和如何解码的矩阵,它有以下结构: [lens; (int) 每个控制变量编码后在染色体中所占的长度 lb; (float) 指明每个变量使用的下界 ub; (float) 指明每个变量使用的上界 codes; (0:binary | 1:gray) 指明子串是怎么编码的, 0为标准二进制编码,1为各类编码 scales; (0: rithmetic | 1:logarithmic) 指明每个子串是否使用对数或算术刻度, 1为使用对数刻度,2为使用算术刻度 lbin; (0:excluded | 1:included) ubin] (0:excluded | 1:included) lbin和ubin指明范围中是否包含每个边界。 选择lbin=0或ubin=0,表示范围中不包含相应边界。 选择lbin=1或ubin=1,表示范围中包含相应边界。 problem : str - 表明是整数问题还是实数问题,'I'表示是整数问题,'R'表示是实数问题 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,表示子代与父代染色体及性状不相同的概率 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 distribute : bool - 是否增强种群的分布性(可能会造成收敛慢) drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图。默认drawing为1 输出参数: pop_trace : array - 种群进化记录器(进化追踪器), 第0列记录着各代种群最优个体的目标函数值 第1列记录着各代种群的适应度均值 第2列记录着各代种群最优个体的适应度值 var_trace : array - 变量记录器,记录着各代种群最优个体的变量值,每一列对应一个控制变量 times : float - 进化所用时间 模板使用注意: 1.本模板调用的目标函数形如:[ObjV,LegV] = aimfuc(Phen,LegV), 其中Phen表示种群的表现型矩阵, LegV为种群的可行性列向量(详见Geatpy数据结构) 2.本模板调用的罚函数形如: newFitnV = punishing(LegV, FitnV), 其中FitnV为用其他算法求得的适应度 若不符合上述规范,则请修改算法模板或自定义新算法模板 3.关于'maxormin': geatpy的内核函数全是遵循“最小化目标”的约定的,即目标函数值越小越好。 当需要优化最大化的目标时,需要设置'maxormin'为-1。 本算法模板是正确使用'maxormin'的典型范例,其具体用法如下: 当调用的函数传入参数包含与“目标函数值矩阵”有关的参数(如ObjV,ObjVSel,NDSetObjV等)时, 查看该函数的参考资料(可用'help'命令查看,也可到官网上查看相应的教程), 里面若要求传入前对参数乘上'maxormin',则需要乘上。 里面若要求对返回参数乘上'maxormin'进行还原, 则调用函数返回得到的相应参数需要乘上'maxormin'进行还原,否则其正负号就会被改变。 """ #==========================初始化配置===========================""" # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 if PUN_F is not None: punishing = getattr(PUN_M, PUN_F) # 获得罚函数 NVAR = FieldD.shape[1] # 得到控制变量的个数 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN, 2)) * np.nan) # 定义变量记录器,记录控制变量值,初始值为nan var_trace = (np.zeros((MAXGEN, NVAR)) * np.nan) ax = None # 存储上一帧图形 """=========================开始遗传算法进化=======================""" Lind = np.sum(FieldD[0, :]) # 种群染色体长度 Chrom = ga.crtbp(NIND, Lind) # 生成初始种群 if problem == 'R': variable = ga.bs2rv(Chrom, FieldD) # 解码 elif problem == 'I': if np.any(FieldD >= sys.maxsize): variable = ga.bs2int(Chrom, FieldD).astype('object') # 解码 else: variable = ga.bs2int(Chrom, FieldD).astype('int64') # 解码 LegV = np.ones((NIND, 1)) # 生成可行性列向量,元素为1表示对应个体是可行解,0表示非可行解 [ObjV, LegV] = aimfuc(variable, LegV) # 求种群的目标函数值 gen = 0 badCounter = 0 # 用于记录在“遗忘策略下”被忽略的代数 # 开始进化!! start_time = time.time() # 开始计时 while gen < MAXGEN: if badCounter >= 10 * MAXGEN: # 若多花了10倍的迭代次数仍没有可行解出现,则跳出 break FitnV = ga.ranking(maxormin * ObjV, LegV, None, SUBPOP) if PUN_F is not None: FitnV = punishing(LegV, FitnV) # 调用罚函数 # 记录进化过程 bestIdx = np.argmax(FitnV) # 获取最优个体的下标 if LegV[bestIdx] != 0: feasible = np.where(LegV != 0)[0] # 排除非可行解 pop_trace[gen, 0] = np.sum( ObjV[feasible]) / ObjV[feasible].shape[0] # 记录种群个体平均目标函数值 pop_trace[gen, 1] = ObjV[bestIdx] # 记录当代目标函数的最优值 var_trace[gen, :] = variable[bestIdx, :] # 记录当代最优的控制变量值 # 绘制动态图 if drawing == 2: ax = ga.sgaplot(pop_trace[:, [1]], '种群最优个体目标函数值', False, ax, gen) badCounter = 0 # badCounter计数器清零 else: gen -= 1 # 忽略这一代(遗忘策略) badCounter += 1 if distribute == True: # 若要增强种群的分布性(可能会造成收敛慢) idx = np.argsort(ObjV[:, 0], 0) dis = np.diff(ObjV[idx, 0]) / (np.max(ObjV[idx, 0]) - np.min( ObjV[idx, 0]) + 1) # 差分计算距离的修正偏移量 dis = np.hstack([dis, dis[-1]]) dis = dis + np.min(dis) # 修正偏移量+最小量=修正绝对量 FitnV[idx, 0] *= np.exp(dis) # 根据相邻距离修改适应度,突出相邻距离大的个体,以增加种群的多样性 # 进行遗传算子 SelCh = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh = ga.recombin(recombinStyle, SelCh, recopt, SUBPOP) # 对所选个体进行重组 SelCh = ga.mutbin(SelCh, pm) # 变异 # 计算种群适应度 if problem == 'R': variable = ga.bs2rv(SelCh, FieldD) # 解码 elif problem == 'I': if np.any(FieldD >= sys.maxsize): variable = ga.bs2int(SelCh, FieldD).astype('object') # 解码 else: variable = ga.bs2int(SelCh, FieldD).astype('int64') LegVSel = np.ones((SelCh.shape[0], 1)) # 初始化育种种群的可行性列向量 [ObjVSel, LegVSel] = aimfuc(variable, LegVSel) # 求后代的目标函数值 FitnVSel = ga.ranking(maxormin * ObjVSel, LegVSel, None, SUBPOP) # 计算育种种群的适应度 if PUN_F is not None: FitnVSel = punishing(LegVSel, FitnVSel) # 调用罚函数 # 重插入 [Chrom, ObjV, LegV] = ga.reins(Chrom, SelCh, SUBPOP, 1, 1, FitnV, FitnVSel, ObjV, ObjVSel, LegV, LegVSel) # 计算新一代种群的控制变量解码值 if problem == 'R': variable = ga.bs2rv(Chrom, FieldD) # 解码 elif problem == 'I': if np.any(FieldD >= sys.maxsize): variable = ga.bs2int(Chrom, FieldD).astype('object') # 解码 else: variable = ga.bs2int(Chrom, FieldD).astype('int64') gen += 1 end_time = time.time() # 结束计时 times = end_time - start_time # 后处理进化记录器 delIdx = np.where(np.isnan(pop_trace))[0] pop_trace = np.delete(pop_trace, delIdx, 0) var_trace = np.delete(var_trace, delIdx, 0) if pop_trace.shape[0] == 0: raise RuntimeError('error: no feasible solution. (有效进化代数为0,没找到可行解。)') # 绘图 if drawing != 0: ga.trcplot(pop_trace, [['种群个体平均目标函数值', '种群最优个体目标函数值']]) # 输出结果 if maxormin == 1: best_gen = np.argmin(pop_trace[:, 1]) # 记录最优种群是在哪一代 best_ObjV = np.min(pop_trace[:, 1]) elif maxormin == -1: best_gen = np.argmax(pop_trace[:, 1]) # 记录最优种群是在哪一代 best_ObjV = np.max(pop_trace[:, 1]) print('最优的目标函数值为:%s' % (best_ObjV)) print('最优的控制变量值为:') for i in range(NVAR): print(var_trace[best_gen, i]) print('有效进化代数:%s' % (pop_trace.shape[0])) print('最优的一代是第 %s 代' % (best_gen + 1)) print('时间已过 %s 秒' % (times)) # 返回进化记录器、变量记录器以及执行时间 return [pop_trace, var_trace, times]
def sga_new_code_templet(AIM_M, AIM_F, PUN_M, PUN_F, FieldD, problem, maxormin, MAXGEN, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, drawing=1): """ sga_new_code_templet.py - 改进的单目标编程模板(二进制/格雷编码) 本模板实现改进单目标编程模板(二进制/格雷编码),将父子两代合并进行选择,增加了精英保留机制 语法: 该函数除了参数drawing外,不设置可缺省参数。当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: sga_new_code_templet(AIM_M, 'aimfuc', None, None, ..., maxormin) 输入参数: AIM_M - 目标函数的地址,传入该函数前通常由AIM_M = __import__('目标函数名')语句得到 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,传入该函数前通常由PUN_M = __import__('罚函数名')语句得到 PUN_F : str - 罚函数名 FieldD : array - 二进制/格雷码种群区域描述器,描 述种群每个个体的染色体长度和如何解码的矩阵,它有以下结构: [lens; (int) 每个控制变量编码后在染色体中所占的长度 lb; (float) 指明每个变量使用的下界 ub; (float) 指明每个变量使用的上界 codes; (0:binary | 1:gray) 指明子串是怎么编码的, 0为标准二进制编码,1为各类编码 scales; (0: rithmetic | 1:logarithmic) 指明每个子串是否使用对数或算术刻度, 1为使用对数刻度,2为使用算术刻度 lbin; (0:excluded | 1:included) ubin] (0:excluded | 1:included) lbin和ubin指明范围中是否包含每个边界。 选择lbin=0或ubin=0,表示范围中不包含相应边界。 选择lbin=1或ubin=1,表示范围中包含相应边界。 problem : str - 表明是整数问题还是实数问题,'I'表示是整数问题,'R'表示是实数问题 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,本模板中该参数为无用参数,仅为了兼容同类的其他模板而设 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图。默认drawing为1 输出参数: pop_trace : array - 种群进化记录器(进化追踪器), 第0列记录着各代种群最优个体的目标函数值 第1列记录着各代种群的适应度均值 第2列记录着各代种群最优个体的适应度值 var_trace : array - 变量记录器,记录着各代种群最优个体的变量值,每一列对应一个控制变量 times : float - 进化所用时间 """ """==========================初始化配置===========================""" GGAP = 0.5 # 因为父子合并后选择,因此要将代沟设为0.5以维持种群规模 # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 if PUN_F is not None: punishing = getattr(PUN_M, PUN_F) # 获得罚函数 NVAR = FieldD.shape[1] # 得到控制变量的个数 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN, 2)) * np.nan) # 定义变量记录器,记录控制变量值,初始值为nan var_trace = (np.zeros((MAXGEN, NVAR)) * np.nan) """=========================开始遗传算法进化=======================""" Lind = np.sum(FieldD[0, :]) # 种群染色体长度 Chrom = ga.crtbp(NIND, Lind) # 生成初始种 start_time = time.time() # 开始计时 # 开始进化!! for gen in range(MAXGEN): # 进行遗传算子产生子代 SelCh = ga.recombin(recombinStyle, Chrom, recopt, SUBPOP) # 重组 SelCh = ga.mutbin(SelCh, pm) # 变异 Chrom = np.vstack([Chrom, SelCh]) # 父子合并 # 计算种群适应度 if problem == 'R': variable = ga.bs2rv(Chrom, FieldD) # 解码 elif problem == 'I': if np.any(FieldD >= sys.maxsize): variable = ga.bs2int(Chrom, FieldD).astype('object') # 解码 else: variable = ga.bs2int(Chrom, FieldD).astype('int64') ObjV = aimfuc(variable) # 求后代的目标函数值 pop_trace[gen, 0] = np.sum(ObjV) // ObjV.shape[0] # 记录种群个体平均目标函数值 if maxormin == 1: pop_trace[gen, 1] = np.min(ObjV) # 记录当代目标函数的最优值 var_trace[gen, :] = variable[np.argmin(ObjV), :] # 记录当代最优的控制变量值 elif maxormin == -1: pop_trace[gen, 1] = np.max(ObjV) var_trace[gen, :] = variable[np.argmax(ObjV), :] # 记录当代最优的控制变量值 # 最后对合并的种群进行适应度评价并选出一半个体留到下一代 FitnV = ga.ranking(maxormin * ObjV, None, SUBPOP) if PUN_F is not None: FitnV = punishing(Chrom, FitnV) # 调用罚函数 Chrom = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 end_time = time.time() # 结束计时 # 绘图 if drawing == 1: ga.trcplot(pop_trace, [['种群个体平均目标函数值', '种群最优个体目标函数值']]) # 输出结果 if maxormin == 1: best_gen = np.argmin(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:' + str(np.min(pop_trace[:, 1]))) elif maxormin == -1: best_gen = np.argmax(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:' + str(np.max(pop_trace[:, 1]))) print('最优的控制变量值为:') for i in range(NVAR): print(var_trace[best_gen, i]) print('最优的一代是第' + str(best_gen + 1) + '代') times = end_time - start_time print('时间已过' + str(times) + '秒') # 返回进化记录器、变量记录器以及执行时间 return [pop_trace, var_trace, times]
def sga_new_permut_templet(AIM_M, AIM_F, PUN_M, PUN_F, NVAR, VarLen, maxormin, MAXGEN, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, drawing=1): """ sga_new_permut_templet.py - 改进的单目标编程模板(排列编码) 本模板实现改进单目标编程模板(排列编码),将父子两代合并进行选择,增加了精英保留机制 排列编码即每条染色体的基因都是无重复正整数的编码方式。 语法: 该函数除了参数drawing外,不设置可缺省参数。当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: sga_new_permut_templet(AIM_M, 'aimfuc', None, None, ..., maxormin) 输入参数: AIM_M - 目标函数的地址,由AIM_M = __import__('目标函数所在文件名')语句得到 目标函数规范定义:f = aimfuc(Phen) 其中Phen是种群的表现型矩阵 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,由PUN_M = __import__('罚函数所在文件名')语句得到 罚函数规范定义: f = punishing(Phen, FitnV) 其中Phen是种群的表现型矩阵, FitnV为种群个体适应度列向量 PUN_F : str - 罚函数名 NVAR : int - 变量个数,排列编码的染色体长度等于变量个数 VarLen : int - 排列集合的大小 例如VarLen = 5表示是从1,2,3,4,5中抽取若干个数排列组成染色体 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,本模板中该参数为无用参数,仅为了兼容同类的其他模板而设 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图。默认drawing为1 输出参数: pop_trace : array - 种群进化记录器(进化追踪器), 第0列记录着各代种群最优个体的目标函数值 第1列记录着各代种群的适应度均值 第2列记录着各代种群最优个体的适应度值 var_trace : array - 变量记录器,记录着各代种群最优个体的变量值,每一列对应一个控制变量 times : float - 进化所用时间 """ """==========================初始化配置===========================""" GGAP = 0.5 # 因为父子合并后选择,因此要将代沟设为0.5以维持种群规模 # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 if PUN_F is not None: punishing = getattr(PUN_M, PUN_F) # 获得罚函数 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN, 2)) * np.nan) # 定义变量记录器,记录控制变量值,初始值为nan var_trace = (np.zeros((MAXGEN, NVAR)) * np.nan) """=========================开始遗传算法进化=======================""" Chrom = ga.crtpp(NIND, NVAR, VarLen) #生成初始种群 start_time = time.time() # 开始计时 # 开始进化!! for gen in range(MAXGEN): # 进行遗传算子,生成子代 SelCh = ga.recombin(recombinStyle, Chrom, recopt, SUBPOP) # 重组 SelCh = ga.mutpp(SelCh, VarLen, pm) # 排列编码种群变异 Chrom = np.vstack([Chrom, SelCh]) # 父子合并 ObjV = aimfuc(Chrom) # 求后代的目标函数值 pop_trace[gen, 0] = np.sum(ObjV) / ObjV.shape[0] # 记录种群个体平均目标函数值 if maxormin == 1: pop_trace[gen, 1] = np.min(ObjV) # 记录当代目标函数的最优值 var_trace[gen, :] = Chrom[np.argmin(ObjV), :] # 记录当代最优的控制变量值 elif maxormin == -1: pop_trace[gen, 1] = np.max(ObjV) var_trace[gen, :] = Chrom[np.argmax(ObjV), :] # 记录当代最优的控制变量值 # 最后对合并的种群进行适应度评价并选出一半个体留到下一代 FitnV = ga.ranking(maxormin * ObjV, None, SUBPOP) if PUN_F is not None: FitnV = punishing(Chrom, FitnV) # 调用罚函数 Chrom = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 end_time = time.time() # 结束计时 # 绘图 if drawing == 1: ga.trcplot(pop_trace, [['种群个体平均目标函数值', '种群最优个体目标函数值']]) # 输出结果 if maxormin == 1: best_gen = np.argmin(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:', np.min(pop_trace[:, 1])) elif maxormin == -1: best_gen = np.argmax(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:', np.max(pop_trace[:, 1])) print('最优的控制变量值为:') for i in range(NVAR): print(var_trace[best_gen, i]) print('最优的一代是第', best_gen + 1, '代') times = end_time - start_time print('时间已过', times, '秒') # 返回进化记录器、变量记录器以及执行时间 return [pop_trace, var_trace, times]
def moea_awGA_templet(AIM_M, AIM_F, PUN_M, PUN_F, FieldDR, problem, maxormin, MAXGEN, MAXSIZE, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, distribute, drawing = 1): """ moea_awGA_templet.py - 基于适应性权重法(awGA)的多目标优化的进化算法模板 语法: 该函数除了参数drawing外,不设置可缺省参数。 当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: moea_awGA_templet(AIM_M, 'aimfuc', None, None, ..., maxormin,...) 输入参数: AIM_M - 目标函数的地址,由AIM_M = __import__('目标函数所在文件名')语句得到 目标函数规范定义:[f,LegV] = aimfuc(Phen,LegV) 其中Phen是种群的表现型矩阵, LegV为种群的可行性列向量,f为种群的目标函数值矩阵 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,由PUN_M = __import__('罚函数所在文件名')语句得到 罚函数规范定义: newFitnV = punishing(LegV, FitnV) 其中LegV为种群的可行性列向量, FitnV为种群个体适应度列向量 一般在罚函数中对LegV为0的个体进行适应度惩罚,返回修改后的适应度列向量newFitnV PUN_F : str - 罚函数名 FieldDR : array - 实际值种群区域描述器 [lb; (float) 指明每个变量使用的下界 ub] (float) 指明每个变量使用的上界 注:不需要考虑是否包含变量的边界值。在crtfld中已经将是否包含边界值进行了处理 本函数生成的矩阵的元素值在FieldDR的[下界, 上界)之间 problem : str - 表明是整数问题还是实数问题,'I'表示是整数问题,'R'表示是实数问题 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 MAXSIZE : int - 帕累托最优集最大规模,当设为np.inf(无穷)时,模板不对帕累托最优解集规模作限制 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,表示子代与父代染色体及性状不相同的概率 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 distribute : bool - 是否增强帕累托前沿的分布性(可能会造成收敛慢或帕累托前沿数目减少) drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图,2表示绘制进化过程的动画。 默认drawing为1 算法描述: 本模板实现了基于适应性权重聚合法(awGA)的多目标优化搜索, 通过维护一个全局帕累托最优集来实现帕累托前沿的搜索,故并不需要保证种群所有个体都是非支配的 模板使用注意: 1.本模板调用的目标函数形如:[ObjV,LegV] = aimfuc(Phen,LegV), 其中Phen表示种群的表现型矩阵, LegV为种群的可行性列向量(详见Geatpy数据结构) 2.本模板调用的罚函数形如: newFitnV = punishing(LegV, FitnV), 其中FitnV为用其他算法求得的适应度 若不符合上述规范,则请修改算法模板或自定义新算法模板 3.关于'maxormin': geatpy的内核函数全是遵循“最小化目标”的约定的,即目标函数值越小越好。 当需要优化最大化的目标时,需要设置'maxormin'为-1。 本算法模板是正确使用'maxormin'的典型范例,其具体用法如下: 当调用的函数传入参数包含与“目标函数值矩阵”有关的参数(如ObjV,ObjVSel,NDSetObjV等)时, 查看该函数的参考资料(可用'help'命令查看,也可到官网上查看相应的教程), 里面若要求传入前对参数乘上'maxormin',则需要乘上。 里面若要求对返回参数乘上'maxormin'进行还原, 则调用函数返回得到的相应参数需要乘上'maxormin'进行还原,否则其正负号就会被改变。 """ #==========================初始化配置=========================== # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 if PUN_F is not None: punishing = getattr(PUN_M, PUN_F) # 获得罚函数 #=========================开始遗传算法进化======================= if problem == 'R': Chrom = ga.crtrp(NIND, FieldDR) # 生成实数值种群 elif problem == 'I': Chrom = ga.crtip(NIND, FieldDR) # 生成整数值种群 LegV = np.ones((NIND, 1)) # 初始化种群的可行性列向量 [ObjV, LegV] = aimfuc(Chrom, LegV) # 计算种群目标函数值 NDSet = np.zeros((0, Chrom.shape[1])) # 定义帕累托最优解记录器 NDSetObjV = np.zeros((0, ObjV.shape[1])) # 定义帕累托最优解的目标函数值记录器 ax = None # 存储上一桢动画 start_time = time.time() # 开始计时 # 开始进化!! for gen in range(MAXGEN): [CombinObjV, weight] = ga.awGA(maxormin * ObjV, LegV) # 计算适应性权重以及多目标的加权单目标 CombinObjV *= maxormin # 还原在传入函数前被最小化处理过的目标函数值 FitnV = ga.ranking(maxormin * CombinObjV, LegV, None, SUBPOP) # 根据加权单目标计算适应度 if PUN_F is not None: FitnV = punishing(LegV, FitnV) # 调用罚函数作进一步的惩罚 # 更新帕累托最优集以及种群非支配个体的适应度 [FitnV, NDSet, NDSetObjV, repnum] = ga.upNDSet(Chrom, maxormin * ObjV, FitnV, NDSet, maxormin * NDSetObjV, None, LegV) NDSetObjV *= maxormin # 还原在传入upNDSet函数前被最小化处理过的NDSetObjV [NDSet, NDSetObjV] = ga.redisNDSet(NDSet, NDSetObjV, NDSetObjV.shape[1] * MAXSIZE) # 利用拥挤距离选择帕累托前沿的子集,在进化过程中最好比上限多筛选出几倍的点集 if distribute == True: # 若要增强种群的分布性(可能会导致帕累托前沿搜索效率降低) # 计算每个目标下相邻个体的距离(不需要严格计算欧氏距离) for i in range(ObjV.shape[1]): idx = np.argsort(ObjV[:, i], 0) dis = np.diff(ObjV[idx, i]) / (np.max(ObjV[idx, i]) - np.min(ObjV[idx, i]) + 1) # 差分计算距离的偏移量占比,即偏移量除以目标函数的极差。加1是为了避免极差为0 dis = np.hstack([dis, dis[-1]]) FitnV[idx, 0] *= np.exp(dis) # 根据相邻距离修改适应度,突出相邻距离大的个体,以增加种群的多样性 # 进行遗传操作!! SelCh=ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh=ga.recombin(recombinStyle, SelCh, recopt, SUBPOP) #交叉 if problem == 'R': SelCh=ga.mutbga(SelCh,FieldDR, pm) # 变异 if repnum > Chrom.shape[0] * 0.01: # 当最优个体重复率高达1%时,进行一次高斯变异 SelCh=ga.mutgau(SelCh, FieldDR, pm) # 高斯变异 elif problem == 'I': SelCh=ga.mutint(SelCh, FieldDR, pm) LegVSel = np.ones((SelCh.shape[0], 1)) # 初始化育种种群的可行性列向量 [ObjVSel, LegVSel] = aimfuc(SelCh,LegVSel) # 求育种个体的目标函数值 [CombinObjV, weight] = ga.awGA(maxormin * ObjVSel, LegVSel) CombinObjV *= maxormin # 还原在传入函数前被最小化处理过的目标函数值 FitnVSel = ga.ranking(maxormin * CombinObjV, LegVSel, None, SUBPOP) if PUN_F is not None: FitnVSel = punishing(LegVSel, FitnVSel) # 调用罚函数 [Chrom,ObjV,LegV] = ga.reins(Chrom,SelCh,SUBPOP,1,0.9,FitnV,FitnVSel,ObjV,ObjVSel,LegV,LegVSel) #重插入 if drawing == 2: ax = ga.frontplot(NDSetObjV, False, ax, gen + 1) # 绘制动态图 end_time = time.time() # 结束计时 [NDSet, NDSetObjV] = ga.redisNDSet(NDSet, NDSetObjV, MAXSIZE) # 最后根据拥挤距离选择均匀分布的点 #=========================绘图及输出结果========================= if drawing != 0: ga.frontplot(NDSetObjV,True) times = end_time - start_time print('用时:%s 秒'%(times)) print('帕累托前沿点个数:%s 个'%(NDSet.shape[0])) print('单位时间找到帕累托前沿点个数:%s 个'%(int(NDSet.shape[0] // times))) # 返回帕累托最优集以及执行时间 return [ObjV, NDSet, NDSetObjV, end_time - start_time]
MAXGN = 25 # 最大遗传代数 FieldD = ea.crtfld(Encoding, varTypes, ranges, borders, precisions, codes, scales) # 调用函数创建区域描述器 Lind = int(np.sum(FieldD[0, :])) # 计算编码后染色体长度 obj_trace = np.zeros((MAXGN, 2)) # 定于目标函数值记录器 var_trace = np.zeros((MAXGN, Lind)) # 定义染色体记录器, 记录每一代最优个体染色体 """遗传算法进化""" start_time = time.time() Chrom = ea.crtbp(NIND, Lind) # 生成种群染色体矩阵 variable = ea.bs2real(Chrom, FieldD) # 对初始种群编码 ObjV = aim(variable) # 计算初始种群个体目标函数值 best_ind = np.argmax(ObjV) # 计算当代最优个体序号 # 开始进化 for gen in range(MAXGN): FitnV = ea.ranking(-ObjV) # 根据目标函数大小分配适应度 Selch = Chrom[ea.selecting('rws', FitnV, NIND - 1), :] # 选择,采用'rws'轮盘选择 Selch = ea.recombin('xovsp', Selch, 0.7) # 重组(两点交叉,交叉概率0.7) Selch = ea.mutbin(Encoding, Selch) # 二进制种群变异 # 父代子代合并 Chrom = np.vstack([Chrom[best_ind, :], Selch]) variable = ea.bs2real(Chrom, FieldD) # 育种群体编码(2进制转10进制) ObjV = aim(variable) # 记录 best_ind = np.argmax(ObjV) # 计算当代最优个体序号 obj_trace[gen, 0] = np.sum(ObjV) / NIND # 记录当代种群目标函数均值 obj_trace[gen, 1] = ObjV[best_ind] # 记录当代种群最优个体目标函数值 var_trace[gen, :] = Chrom[best_ind, :] # 记录当代种群最优个体变量值 # 进化结束
def sga_new_real_templet(AIM_M, AIM_F, PUN_M, PUN_F, FieldDR, problem, maxormin, MAXGEN, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, drawing = 1): """ sga_new_real_templet.py - 改进的单目标编程模板(实值编码) 本模板实现改进单目标编程模板(实值编码),将父子两代合并进行选择,增加了精英保留机制 语法: 该函数除了drawing外,不设置可缺省参数。当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: sga_new_real_templet(AIM_M, 'aimfuc', None, None, ..., maxormin) 输入参数: AIM_M - 目标函数的地址,传入该函数前通常由AIM_M = __import__('目标函数名')语句得到 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,传入该函数前通常由PUN_M = __import__('罚函数名')语句得到 PUN_F : str - 罚函数名 FieldDR : array - 实际值种群区域描述器 [lb; (float) 指明每个变量使用的下界 ub] (float) 指明每个变量使用的上界 注:不需要考虑是否包含变量的边界值。在crtfld中已经将是否包含边界值进行了处理 本函数生成的矩阵的元素值在FieldDR的[下界, 上界)之间 problem : str - 表明是整数问题还是实数问题,'I'表示是整数问题,'R'表示是实数问题 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,本模板中该参数为无用参数,仅为了兼容同类的其他模板而设 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图。默认drawing为1 输出参数: pop_trace : array - 种群进化记录器(进化追踪器), 第0列记录着各代种群最优个体的目标函数值 第1列记录着各代种群的适应度均值 第2列记录着各代种群最优个体的适应度值 var_trace : array - 变量记录器,记录着各代种群最优个体的变量值,每一列对应一个控制变量 times : float - 进化所用时间 """ """==========================初始化配置===========================""" GGAP = 0.5 # 因为父子合并后选择,因此要将代沟设为0.5以维持种群规模 # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 if PUN_F is not None: punishing = getattr(PUN_M, PUN_F) # 获得罚函数 NVAR = FieldDR.shape[1] # 得到控制变量的个数 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN ,2)) * np.nan) # 定义变量记录器,记录控制变量值,初始值为nan var_trace = (np.zeros((MAXGEN ,NVAR)) * np.nan) """=========================开始遗传算法进化=======================""" if problem == 'R': Chrom = ga.crtrp(NIND, FieldDR) # 生成初始种群 elif problem == 'I': Chrom = ga.crtip(NIND, FieldDR) start_time = time.time() # 开始计时 # 开始进化!! for gen in range(MAXGEN): # 进行遗传算子,生成子代 SelCh=ga.recombin(recombinStyle, Chrom, recopt, SUBPOP) # 重组 if problem == 'R': SelCh=ga.mutbga(SelCh,FieldDR, pm) # 变异 elif problem == 'I': SelCh=ga.mutint(SelCh, FieldDR, pm) Chrom = np.vstack([Chrom, SelCh]) # 父子合并 ObjV = aimfuc(Chrom) # 求后代的目标函数值 pop_trace[gen,0] = np.sum(ObjV) / ObjV.shape[0] # 记录种群个体平均目标函数值 if maxormin == 1: pop_trace[gen,1] = np.min(ObjV) # 记录当代目标函数的最优值 var_trace[gen,:] = Chrom[np.argmin(ObjV), :] # 记录当代最优的控制变量值 elif maxormin == -1: pop_trace[gen,1] = np.max(ObjV) var_trace[gen,:] = Chrom[np.argmax(ObjV), :] # 记录当代最优的控制变量值 # 最后对合并的种群进行适应度评价并选出一半个体留到下一代 FitnV = ga.ranking(maxormin * ObjV, None, SUBPOP) if PUN_F is not None: FitnV = punishing(Chrom, FitnV) # 调用罚函数 Chrom=ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 end_time = time.time() # 结束计时 # 绘图 if drawing == 1: ga.trcplot(pop_trace, [['种群个体平均目标函数值', '种群最优个体目标函数值']]) # 输出结果 if maxormin == 1: best_gen = np.argmin(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:', np.min(pop_trace[:, 1])) elif maxormin == -1: best_gen = np.argmax(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:', np.max(pop_trace[:, 1])) print('最优的控制变量值为:') for i in range(NVAR): print(var_trace[best_gen, i]) print('最优的一代是第', best_gen + 1, '代') times = end_time - start_time print('时间已过', times, '秒') # 返回进化记录器、变量记录器以及执行时间 return [pop_trace, var_trace, times]
Lind = 64 # 计算染色体长度 pc = 0.9 # 交叉概率 pm = 1 / Lind # 变异概率 obj_trace = np.zeros((MAXGEN, 2)) # 定义目标函数值记录器 var_trace = np.zeros((MAXGEN, Lind)) # 染色体记录器,记录历代最优个体的染色体 """=========================开始遗传算法进化========================""" start_time = time.time() # 开始计时 Chrom = ea.crtpc(Encoding, NIND, FieldD) # 生成种群染色体矩阵 help(ea.ranking) for gen in range(MAXGEN): Phen = ea.bs2real(Chrom, FieldD) # 对种群进行解码(二进制转十进制) ObjV, CV = aim(Phen) # 求种群个体的目标函数值 FitnV = ea.ranking(maxormins * ObjV, CV) # 根据目标函数大小分配适应度值 # 记录 best_ind = np.argmax(FitnV) # 计算当代最优个体的序号 obj_trace[gen, 0] = np.sum(ObjV) / ObjV.shape[0] # 记录当代种群的目标函数均值 obj_trace[gen, 1] = ObjV[best_ind] # 记录当代种群最优个体目标函数值 var_trace[gen, :] = Chrom[best_ind, :] # 记录当代种群最优个体的染色体 SelCh = Chrom[ea.selecting(selectStyle, FitnV, NIND - 1), :] # 选择 SelCh = ea.recombin(recStyle, SelCh, pc) # 重组 SelCh = ea.mutate(mutStyle, Encoding, SelCh, pm) # 变异 # 把父代精英个体与子代的染色体进行合并,得到新一代种群 Chrom = np.vstack([var_trace[gen, :], SelCh]) print('第', gen, '代', '用时:', time.time() - start_time, '秒') # 进化完成 l = [
def awGA_templet(AIM_M, AIM_F, PUN_M, PUN_F, ranges, borders, precisions, maxormin, MAXGEN, MAXSIZE, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, drawing=1): """ awGA_templet.py - 基于awGA的多目标优化编程模板 语法: 该函数除了参数drawing外,不设置可缺省参数。 当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: awGA_templet(AIM_M, 'aimfuc', None, None, ..., maxormin) 输入参数: AIM_M - 目标函数的地址,传入该函数前通常由AIM_M = __import__('目标函数名')语句得到 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,传入该函数前通常由PUN_M = __import__('罚函数名')语句得到 PUN_F : str - 罚函数名 ranges : array - 代表自变量的范围矩阵,要求上界必须大于下界 例如:[[1, 2, 3], [3, 4, 5]] 表示有3个控制变量,其范围分别是1-3, 2-4, 3-5 borders : list -(可选参数)代表是否包含变量范围的边界,为1代表控制变量的范围包含该边界 当为None时,默认设置为全是1的矩阵 例如:[[1, 0, 1], [0, 1, 1]] 表示上面的三个控制变量的范围分别是:[1, 3)、(2, 4]、[3, 5] precisions : list -(可选参数)代表控制变量的精度, 如等于4,表示对应的控制变量的编码可以精确到小数点后4位。 当precisions为None时,默认precision为1*n的0矩阵(此时表示种群是离散编码的) precision的元素必须不小于0 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 MAXSIZE : int - 帕累托最优集最大规模 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,表示子代与父代染色体及性状不相同的概率 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图,2表示绘制进化过程的动画。 默认drawing为1 算法描述: 本模板实现了基于适应性权重聚合法(awGA)的多目标优化搜索, 通过维护一个全局帕累托最优集来实现帕累托前沿的搜索,故并不需要保证种群所有个体都是非支配的 """ #==========================初始化配置=========================== # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 FieldDR = ga.crtfld(ranges, borders, precisions) #=========================开始遗传算法进化======================= Chrom = ga.crtrp(NIND, FieldDR) # 创建简单离散种群 ObjV = aimfuc(Chrom) # 计算种群目标函数值 # 定义帕累托最优解记录器 NDSet = np.zeros((0, ObjV.shape[1])) ax = None start_time = time.time() # 开始计时 # 开始进化!! for gen in range(MAXGEN): if NDSet.shape[0] > MAXSIZE: break [CombinObjV, weight] = ga.awGA(maxormin * ObjV) # 计算适应性权重以及多目标的加权单目标 FitnV = ga.ranking(maxormin * CombinObjV) # 根据加权单目标计算适应度 # 更新帕累托最优集以及种群非支配个体的适应度 [FitnV, NDSet, repnum] = ga.upNDSet(FitnV, maxormin * ObjV, maxormin * NDSet) # 进行遗传操作!! SelCh = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh = ga.recombin(recombinStyle, SelCh, recopt, SUBPOP) #交叉 SelCh = ga.mutbga(SelCh, FieldDR, pm) # 变异 if repnum > Chrom.shape[0] * 0.1: # 进行一次高斯变异 SelCh = ga.mutgau(SelCh, FieldDR, pm) # 高斯变异 ObjVSel = aimfuc(SelCh) # 求育种个体的目标函数值 [CombinObjV, weight] = ga.awGA(maxormin * ObjVSel) FitnVSel = ga.ranking(maxormin * CombinObjV) [Chrom, ObjV] = ga.reins(Chrom, SelCh, SUBPOP, 1, 0.9, FitnV, FitnVSel, ObjV, ObjVSel) #重插入 if drawing == 2: ax = ga.frontplot(NDSet, False, ax, gen + 1) # 绘制动态图 end_time = time.time() # 结束计时 #=========================绘图及输出结果========================= if drawing != 0: ga.frontplot(NDSet, True) times = end_time - start_time print('用时:' + str(times) + '秒') print('帕累托前沿点个数:' + str(NDSet.shape[0]) + '个') print('单位时间找到帕累托前沿点个数:' + str(NDSet.shape[0] // times) + '个') # 返回帕累托最优集以及执行时间 return [ObjV, NDSet, end_time - start_time]
def awGA_templet(AIM_M, AIM_F, PUN_M, PUN_F, FieldDR, problem, maxormin, MAXGEN, MAXSIZE, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, distribute, drawing=1): """ awGA_templet.py - 基于awGA的多目标优化的进化算法模板 语法: 该函数除了参数drawing外,不设置可缺省参数。 当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: awGA_templet(AIM_M, 'aimfuc', None, None, ..., maxormin,...) 输入参数: AIM_M - 目标函数的地址,由AIM_M = __import__('目标函数所在文件名')语句得到 目标函数规范定义:f = aimfuc(Phen) 其中Phen是种群的表现型矩阵 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,由PUN_M = __import__('罚函数所在文件名')语句得到 罚函数规范定义: f = punishing(Phen, FitnV) 其中Phen是种群的表现型矩阵, FitnV为种群个体适应度列向量 PUN_F : str - 罚函数名 FieldDR : array - 实际值种群区域描述器 [lb; (float) 指明每个变量使用的下界 ub] (float) 指明每个变量使用的上界 注:不需要考虑是否包含变量的边界值。在crtfld中已经将是否包含边界值进行了处理 本函数生成的矩阵的元素值在FieldDR的[下界, 上界)之间 problem : str - 表明是整数问题还是实数问题,'I'表示是整数问题,'R'表示是实数问题 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 MAXSIZE : int - 帕累托最优集最大规模 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,表示子代与父代染色体及性状不相同的概率 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 distribute : bool - 是否增强帕累托前沿的分布性(可能会造成收敛慢或帕累托前沿数目减少) drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图,2表示绘制进化过程的动画。 默认drawing为1 算法描述: 本模板实现了基于适应性权重聚合法(awGA)的多目标优化搜索, 通过维护一个全局帕累托最优集来实现帕累托前沿的搜索,故并不需要保证种群所有个体都是非支配的 """ #==========================初始化配置=========================== # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 if PUN_F is not None: punishing = getattr(PUN_M, PUN_F) # 获得罚函数 #=========================开始遗传算法进化======================= if problem == 'R': Chrom = ga.crtrp(NIND, FieldDR) # 生成实数值种群 elif problem == 'I': Chrom = ga.crtip(NIND, FieldDR) # 生成整数值种群 ObjV = aimfuc(Chrom) # 计算种群目标函数值 NDSet = np.zeros((0, Chrom.shape[1])) # 定义帕累托最优解记录器 NDSetObjV = np.zeros((0, ObjV.shape[1])) # 定义帕累托最优解的目标函数值记录器 ax = None start_time = time.time() # 开始计时 # 开始进化!! for gen in range(MAXGEN): if NDSet.shape[0] > MAXSIZE: break [CombinObjV, weight] = ga.awGA(maxormin * ObjV) # 计算适应性权重以及多目标的加权单目标 FitnV = ga.ranking(maxormin * CombinObjV) # 根据加权单目标计算适应度 if PUN_F is not None: FitnV = punishing(Chrom, FitnV) # 调用罚函数 # 更新帕累托最优集以及种群非支配个体的适应度 [FitnV, NDSet, NDSetObjV, repnum] = ga.upNDSet(Chrom, maxormin * ObjV, FitnV, NDSet, maxormin * NDSetObjV) if distribute == True: # 若要增强帕累托解集的分布性 # 计算每个目标下个体的聚集距离(不需要严格计算欧氏距离,计算绝对值即可) for i in range(ObjV.shape[1]): idx = np.argsort(ObjV[:, i], 0) dis = np.abs(np.diff(ObjV[idx, i].T, 1).T) / ( np.max(ObjV[idx, i]) - np.min(ObjV[idx, i]) + 1) # 差分计算距离 dis = np.hstack([dis, dis[-1]]) dis = dis + np.min(dis) FitnV[idx, 0] *= np.exp(dis) # 根据聚集距离修改适应度,以增加种群的多样性 # 进行遗传操作!! SelCh = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh = ga.recombin(recombinStyle, SelCh, recopt, SUBPOP) #交叉 if problem == 'R': SelCh = ga.mutbga(SelCh, FieldDR, pm) # 变异 if repnum > Chrom.shape[0] * 0.01: # 当最优个体重复率高达1%时,进行一次高斯变异 SelCh = ga.mutgau(SelCh, FieldDR, pm) # 高斯变异 elif problem == 'I': SelCh = ga.mutint(SelCh, FieldDR, pm) ObjVSel = aimfuc(SelCh) # 求育种个体的目标函数值 [CombinObjV, weight] = ga.awGA(maxormin * ObjVSel) FitnVSel = ga.ranking(maxormin * CombinObjV) if PUN_F is not None: FitnVSel = punishing(Chrom, FitnVSel) # 调用罚函数 [Chrom, ObjV] = ga.reins(Chrom, SelCh, SUBPOP, 1, 0.9, FitnV, FitnVSel, ObjV, ObjVSel) #重插入 if drawing == 2: ax = ga.frontplot(NDSetObjV, False, ax, gen + 1) # 绘制动态图 end_time = time.time() # 结束计时 #=========================绘图及输出结果========================= if drawing != 0: ga.frontplot(NDSetObjV, True) times = end_time - start_time print('用时:', times, '秒') print('帕累托前沿点个数:', NDSet.shape[0], '个') print('单位时间找到帕累托前沿点个数:', int(NDSet.shape[0] // times), '个') # 返回帕累托最优集以及执行时间 return [ObjV, NDSet, NDSetObjV, end_time - start_time]
pm = 0.1 SUBPOP = 1 maxormin = 1 # Start of GA, please refer to Geatpy package for details FieldD = ga.crtfld(ranges, borders, precisions, codes, scales) Lind = np.sum(FieldD[0, :]) Chrom = ga.crtbp(NIND, Lind) Phen = ga.bs2rv(Chrom, FieldD) LegV = np.ones((NIND, 1)) [ObjV, LegV, Run] = aimfuc(Phen, LegV, Run, NIND) pop_trace = (np.zeros((MAXGEN,2)) * np.nan) ind_trace = (np.zeros((MAXGEN,Lind)) * np.nan) start_time = time.time() for gen in range(MAXGEN): FitnV = ga.ranking(maxormin * ObjV, LegV) SelCh = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) SelCh = ga.recombin(recombinStyle, SelCh, recopt, SUBPOP) SelCh = ga.mutbin(SelCh, pm) Phen = ga.bs2rv(SelCh, FieldD) LegVSel = np.ones((SelCh.shape[0], 1)) [ObjVSel, LegVSel, Run] = aimfuc(Phen, LegVSel, Run, NIND) [Chrom, ObjV, LegV] = ga.reins(Chrom, SelCh, SUBPOP, 1, 1, maxormin*ObjV, maxormin*ObjVSel, ObjV, ObjVSel, LegV, LegVSel) pop_trace[gen, 1] = np.sum(ObjV)/ObjV.shape[0] if maxormin == 1: best_ind = np.argmin(ObjV) elif maxormin == -1: best_ind = np.argmax(ObjV) pop_trace[gen, 0] = ObjV[best_ind] ind_trace[gen, :] = Chrom[best_ind, :]
def sga_code_templet(AIM_M, AIM_F, PUN_M, PUN_F, FieldD, problem, maxormin, MAXGEN, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, drawing=1): """ sga_code_templet.py - 单目标编程模板(二进制/格雷编码) 语法: 该函数除了参数drawing外,不设置可缺省参数。当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: sga_code_templet(AIM_M, 'aimfuc', None, None, ..., maxormin) 输入参数: AIM_M - 目标函数的地址,由AIM_M = __import__('目标函数所在文件名')语句得到 目标函数规范定义:f = aimfuc(Phen) 其中Phen是种群的表现型矩阵 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,由PUN_M = __import__('罚函数所在文件名')语句得到 罚函数规范定义: f = punishing(Phen, FitnV) 其中Phen是种群的表现型矩阵, FitnV为种群个体适应度列向量 PUN_F : str - 罚函数名 FieldD : array - 二进制/格雷码种群区域描述器, 描述种群每个个体的染色体长度和如何解码的矩阵,它有以下结构: [lens; (int) 每个控制变量编码后在染色体中所占的长度 lb; (float) 指明每个变量使用的下界 ub; (float) 指明每个变量使用的上界 codes; (0:binary | 1:gray) 指明子串是怎么编码的, 0为标准二进制编码,1为各类编码 scales; (0: rithmetic | 1:logarithmic) 指明每个子串是否使用对数或算术刻度, 1为使用对数刻度,2为使用算术刻度 lbin; (0:excluded | 1:included) ubin] (0:excluded | 1:included) lbin和ubin指明范围中是否包含每个边界。 选择lbin=0或ubin=0,表示范围中不包含相应边界。 选择lbin=1或ubin=1,表示范围中包含相应边界。 problem : str - 表明是整数问题还是实数问题,'I'表示是整数问题,'R'表示是实数问题 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,表示子代与父代染色体及性状不相同的概率 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图。默认drawing为1 输出参数: pop_trace : array - 种群进化记录器(进化追踪器), 第0列记录着各代种群最优个体的目标函数值 第1列记录着各代种群的适应度均值 第2列记录着各代种群最优个体的适应度值 var_trace : array - 变量记录器,记录着各代种群最优个体的变量值,每一列对应一个控制变量 times : float - 进化所用时间 模板使用注意: 1.本模板调用的目标函数形如: ObjV = aimfuc(Phen), 其中Phen表示种群的表现型矩阵 2.本模板调用的罚函数形如: [FitnV, punIdx] = punishing(Phen, FitnV), 其中输入参数的FitnV为惩罚前的适应度,输出参数的FitnV为惩罚后的适应度 punIdx为惩罚的个体所在的下标 在罚函数定义中,必须将不满足约束条件的个体对应的适应度设为0,否则请修改模板使用 """ #==========================初始化配置===========================""" # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 if PUN_F is not None: punishing = getattr(PUN_M, PUN_F) # 获得罚函数 exIdx = np.array([]) # 存储非可行解的下标 NVAR = FieldD.shape[1] # 得到控制变量的个数 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN, 2)) * np.nan) # 定义变量记录器,记录控制变量值,初始值为nan var_trace = (np.zeros((MAXGEN, NVAR)) * np.nan) """=========================开始遗传算法进化=======================""" Lind = np.sum(FieldD[0, :]) # 种群染色体长度 Chrom = ga.crtbp(NIND, Lind) # 生成初始种群 if problem == 'R': variable = ga.bs2rv(Chrom, FieldD) # 解码 elif problem == 'I': if np.any(FieldD >= sys.maxsize): variable = ga.bs2int(Chrom, FieldD).astype('object') # 解码 else: variable = ga.bs2int(Chrom, FieldD).astype('int64') # 解码 ObjV = aimfuc(variable) # 求种群的目标函数值 start_time = time.time() # 开始计时 # 开始进化!! for gen in range(MAXGEN): FitnV = ga.ranking(maxormin * ObjV, None, SUBPOP) if PUN_F is not None: [FitnV, exIdx] = punishing(Chrom, FitnV) # 调用罚函数 # 记录进化过程 bestIdx = np.argmax(FitnV) # 获取最优个体的下标 wrongSign = np.ones((FitnV.shape[0], 1)) wrongSign[list(exIdx)] = 0 # 对非可行解作标记 if wrongSign[bestIdx] != 0: feasible = np.where(wrongSign != 0)[0] # 排除非可行解 pop_trace[gen, 0] = np.sum( ObjV[feasible]) / ObjV[feasible].shape[0] # 记录种群个体平均目标函数值 pop_trace[gen, 1] = ObjV[bestIdx] # 记录当代目标函数的最优值 var_trace[gen, :] = variable[bestIdx, :] # 记录当代最优的控制变量值 # 进行遗传算子 SelCh = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh = ga.recombin(recombinStyle, Chrom, recopt, SUBPOP) # 重组 SelCh = ga.mutbin(SelCh, pm) # 变异 # 计算种群适应度 if problem == 'R': variable = ga.bs2rv(SelCh, FieldD) # 解码 elif problem == 'I': if np.any(FieldD >= sys.maxsize): variable = ga.bs2int(SelCh, FieldD).astype('object') # 解码 else: variable = ga.bs2int(SelCh, FieldD).astype('int64') ObjVSel = aimfuc(variable) # 求后代的目标函数值 # 重插入 [Chrom, ObjV] = ga.reins(Chrom, SelCh, SUBPOP, 2, 1, ObjV, ObjVSel) # 计算新一代种群的控制变量解码值 if problem == 'R': variable = ga.bs2rv(Chrom, FieldD) # 解码 elif problem == 'I': if np.any(FieldD >= sys.maxsize): variable = ga.bs2int(Chrom, FieldD).astype('object') # 解码 else: variable = ga.bs2int(SelCh, FieldD).astype('int64') end_time = time.time() # 结束计时 # 后处理进化记录器 delIdx = np.where(np.isnan(pop_trace))[0] pop_trace = np.delete(pop_trace, delIdx, 0) var_trace = np.delete(var_trace, delIdx, 0) # 绘图 if drawing == 1: ga.trcplot(pop_trace, [['种群个体平均目标函数值', '种群最优个体目标函数值']]) # 输出结果 if maxormin == 1: best_gen = np.argmin(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:', np.min(pop_trace[:, 1])) elif maxormin == -1: best_gen = np.argmax(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:', np.max(pop_trace[:, 1])) print('最优的控制变量值为:') for i in range(NVAR): print(var_trace[best_gen, i]) print('最优的一代是第', best_gen + 1, '代') times = end_time - start_time print('时间已过', times, '秒') # 返回进化记录器、变量记录器以及执行时间 return [pop_trace, var_trace, times]
selectStyle = 'sus' recStyle = 'xovdp' mutStyle = 'mutbin' Lind = int(np.sum(FieldD[0, :])) pc = 0.9 pm = 1 / Lind obj_trace = np.zeros((MAXGEN, 2)) var_trace = np.zeros((MAXGEN, Lind)) start_time = time.time() Chrom = ea.crtpc(Encoding, NIND, FieldD) variable = ea.bs2real(Chrom, FieldD) ObjV = aim(variable) best_ind = np.argmin(ObjV) for gen in range(MAXGEN): FitnV = ea.ranking(maxorins * ObjV) SelCh = Chrom[ea.selecting(selectStyle, FitnV, NIND - 1), :] SelCh = ea.recombin(recStyle, SelCh, pc) SelCh = ea.mutate(mutStyle, Encoding, SelCh, pm) Chrom = np.vstack([Chrom[best_ind, :], SelCh]) Phen = ea.bs2real(Chrom, FieldD) ObjV = aim(Phen) best_ind = np.argmin(ObjV) obj_trace[gen, 0] = np.sum(ObjV) / ObjV.shape[0] obj_trace[gen, 1] = ObjV[best_ind] var_trace[gen, :] = Chrom[best_ind, :] end_time = time.time() ea.trcplot(obj_trace, [['种族个体平均目标函数值', '种族最优个体目标函数值']]) best_gen = np.argmin(obj_trace[:, [1]]) print('最优解的目标值:', obj_trace[best_gen, 1])
[0, 0], # 是否采用对数刻度 0--算术刻度 1--对数刻度 [1, 1], # 范围是否包含下界 0--不含 1--包含 [1, 1], # 范围是否包含上界 0--不含 1--包含 [0, 0] ]) # 0--连续 1--离散 Chrom = crtpc(Encoding, Nind, FieldD) print(Chrom) # 解码,将二进制编码的矩阵转化为实数 help(bs2ri) Phen = bs2ri(Chrom, FieldD) print('表现型矩阵 = \n', Phen) def aim(Phen): x = Phen[:, [0]] y = Phen[:, [1]] CV = np.abs(x + y - 3) f = x + y return f, CV ObjV, CV = aim(Phen) print('目标函数矩阵:\n', ObjV) print('CV矩阵:\n', CV) # 求适应度 from geatpy import ranking help(ranking) fitnV = ranking(ObjV, CV) print('适应度函数:\n', fitnV)
maxormin = 1 # 设置最大最小化目标标记为1,表示是最小化目标,-1则表示最大化目标 """=========================开始遗传算法进化========================""" FieldD = ga.crtfld(ranges, borders, precisions, codes, scales) # 调用函数创建区域描述器 Lind = np.sum(FieldD[0, :]) # 计算编码后的染色体长度 Chrom = ga.crtbp(NIND, Lind) # 根据区域描述器生成二进制种群 Phen = ga.bs2rv(Chrom, FieldD) #对初始种群进行解码 LegV = np.ones((NIND, 1)) # 初始化种群的可行性列向量 [ObjV, LegV] = aimfuc(Phen, LegV) # 计算初始种群个体的目标函数值 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN, 2)) * np.nan) # 定义种群最优个体记录器,记录每一代最优个体的染色体,初始值为nan ind_trace = (np.zeros((MAXGEN, Lind)) * np.nan) # 开始进化!! start_time = time.time() # 开始计时 for gen in range(MAXGEN): FitnV = ga.ranking(maxormin * ObjV, LegV) # 根据目标函数大小分配适应度值 SelCh = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh = ga.recombin(recombinStyle, SelCh, recopt, SUBPOP) #交叉 SelCh = ga.mutbin(SelCh, pm) # 二进制种群变异 Phen = ga.bs2rv(SelCh, FieldD) # 对育种种群进行解码(二进制转十进制) LegVSel = np.ones((SelCh.shape[0], 1)) # 初始化育种种群的可行性列向量 [ObjVSel, LegVSel] = aimfuc(Phen, LegVSel) # 求育种个体的目标函数值 [Chrom, ObjV, LegV] = ga.reins(Chrom, SelCh, SUBPOP, 1, 1, maxormin * ObjV, maxormin * ObjVSel, ObjV, ObjVSel, LegV, LegVSel) # 重插入得到新一代种群 # 记录 pop_trace[gen, 1] = np.sum(ObjV) / ObjV.shape[0] # 记录当代种群的目标函数均值 if maxormin == 1: best_ind = np.argmin(ObjV) # 计算当代最优个体的序号 elif maxormin == -1: best_ind = np.argmax(ObjV)
def train_process(model, gt): def aim(Phen): # ld = Phen[:, [0]] # 取出第1列,得到所有个体的第1个自变量 # gm = Phen[:, [1]] # 取出第2列,得到所有个体的第2个自变量 fits = np.zeros((len(Phen),1)) # 所有个体的健康程度评估 # print(Phen) for idx in range(len(Phen)): model.omiga = Phen[idx][1] model.gamma = Phen[idx][0] # model.beta = Phen[idx][2] model.d = Phen[idx][2] model.deduce() # print(np.array(model.i * model.N)) exam_day = int(Phen[idx][3]) model_preds_i = model.i[exam_day:exam_day+len(gt)] * model.N gt_i = np.array(gt['confirmedCount']) model_preds_r = model.r[exam_day:exam_day+len(gt)] * model.N gt_r = np.array(gt['deadCount']+gt['curedCount']) infective_fitness = residual_square(model_preds_i, gt_i) recov_fitness = residual_square(model_preds_r, gt_r) fits[idx] = infective_fitness + recov_fitness # print(model_preds_i, gt_i) # print(fits) return fits # settings omiga = [0, 1] # 自变量范围 gamma = [0, 1] # beta = [0, 1] d = [0, 100] exam_d = [10, 60] b1 = [0, 0] # 自变量边界, 1 表示包含边界, 0 表示不包含边界 b2 = [0, 0] # b3 = [0, 0] b4 = [0, 0] b5 = [1, 1] varTypes = np.array([0, 0, 0, 0]) # 自变量的类型,0表示连续,1表示离散 Encoding = 'BG' # 'BG'表示采用二进制/格雷编码 codes = [1, 1, 1, 1] # 变量的编码方式,2个变量均使用格雷编码 precisions =[6, 6, 6, 6] # 变量的编码精度 scales = [0, 0, 0, 0] # 采用算术刻度 ranges=np.vstack([gamma, omiga, d, exam_d]).T # 生成自变量的范围矩阵 borders=np.vstack([b2, b1, b4, b5]).T # 生成自变量的边界矩阵 # params of GA NIND = 400 # 种群个体数目 MAXGEN = 100 # 最大遗传代数 maxormins = [1] # 最小化目标函数, 元素为-1表示最大化目标函数 FieldD = ea.crtfld(Encoding,varTypes, ranges, borders,precisions,codes,scales) # 调用函数创建区域描述器 Lind = int(np.sum(FieldD[0, :])) # 计算编码后的染色体长度 obj_trace = np.zeros((MAXGEN, 2)) # 定义目标函数值记录器 var_trace = np.zeros((MAXGEN, Lind)) # 定义染色体记录器,记录每一代最优个体的染色体 start_time = time.time() # 开始计时 Chrom = ea.crtbp(NIND, Lind) # 生成种群染色体矩阵 variable = ea.bs2real(Chrom, FieldD) # 对初始种群进行解码 ObjV = aim(variable) # 计算初始种群个体的目标函数值 best_ind = np.argmin(ObjV) # 计算当代最优个体的序号 # 开始进化 for gen in range(MAXGEN): FitnV = ea.ranking(maxormins * ObjV) # 根据目标函数大小分配适应度值(由于遵循目标最小化约定,因此最大化问题要对目标函数值乘上-1) SelCh=Chrom[ea.selecting('rws', FitnV, NIND-1), :] # 选择,采用'rws'轮盘赌选择 SelCh=ea.recombin('xovsp', SelCh, 0.7) # 重组(采用两点交叉方式,交叉概率为0.7) SelCh=ea.mutbin(Encoding, SelCh) # 二进制种群变异 # 把父代精英个体与子代合并 Chrom = np.vstack([Chrom[best_ind, :], SelCh]) variables = ea.bs2real(Chrom, FieldD) # 对育种种群进行解码(二进制转十进制) ObjV = aim(variables) # 求育种个体的目标函数值 # 记录 best_ind = np.argmin(ObjV) # 计算当代最优个体的序号 obj_trace[gen, 0] = np.sum(ObjV) / NIND # 记录当代种群的目标函数均值 obj_trace[gen, 1] = ObjV[best_ind] # 记录当代种群最优个体目标函数值 var_trace[gen, :] = Chrom[best_ind, :] # 记录当代种群最优个体的变量值 # 进化完成 end_time = time.time() # 结束计时 # 绘制图像 ea.trcplot(obj_trace, [['种群个体平均目标函数值', '种群最优个体目标函数值']]) best_gen = np.argmin(obj_trace[:, [1]]) print('最优解的目标函数值: ', obj_trace[best_gen, 1]) opt_variable = ea.bs2real(var_trace[[best_gen], :], FieldD) print('最优解的决策变量为:') for i in range(opt_variable.shape[1]): print(opt_variable[0, i]) print('用时: ', end_time - start_time, '秒') model.omiga = opt_variable[0, 1] model.gamma = opt_variable[0, 0] # model.beta = opt_variable[0, 2] model.d = opt_variable[0, 2] model.deduce() model.draw_curves() return opt_variable[0]
def sga_mps_real_templet(AIM_M, AIM_F, PUN_M, PUN_F, FieldDRs, problem, maxormin, MAXGEN, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, drawing=1): """ sga_mps_real_templet.py - 基于多种群独立进化单目标编程模板(实值编码) 基于多种群独立进化单目标编程模板(实值编码),各种群独立将父子两代合并进行选择,采取精英保留机制 语法: 该函数除了drawing外,不设置可缺省参数。当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: sga_mps_real_templet(AIM_M, 'aimfuc', None, None, ..., maxormin) 输入参数: AIM_M - 目标函数的地址,由AIM_M = __import__('目标函数所在文件名')语句得到 目标函数规范定义:f = aimfuc(Phen) 其中Phen是种群的表现型矩阵 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,由PUN_M = __import__('罚函数所在文件名')语句得到 罚函数规范定义: f = punishing(Phen, FitnV) 其中Phen是种群的表现型矩阵, FitnV为种群个体适应度列向量 PUN_F : str - 罚函数名 FieldDR : array - 实际值种群区域描述器 [lb; (float) 指明每个变量使用的下界 ub] (float) 指明每个变量使用的上界 注:不需要考虑是否包含变量的边界值。在crtfld中已经将是否包含边界值进行了处理 本函数生成的矩阵的元素值在FieldDR的[下界, 上界)之间 problem : str - 表明是整数问题还是实数问题,'I'表示是整数问题,'R'表示是实数问题 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,本模板中该参数为无用参数,仅为了兼容同类的其他模板而设 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图。默认drawing为1 输出参数: pop_trace : array - 种群进化记录器(进化追踪器), 第0列记录着各代种群最优个体的目标函数值 第1列记录着各代种群的适应度均值 第2列记录着各代种群最优个体的适应度值 var_trace : array - 变量记录器,记录着各代种群最优个体的变量值,每一列对应一个控制变量 times : float - 进化所用时间 模板使用注意: 1.本模板调用的目标函数形如:aimfuc(Phen), 其中Phen表示种群的表现型矩阵 2.本模板调用的罚函数形如: punishing(Phen, FitnV), 其中FitnV为用其他算法求得的适应度 在罚函数定义中,必须将不满足约束条件的个体对应的适应度设为0,否则请修改模板使用 """ #==========================初始化配置===========================""" GGAP = 0.5 # 因为父子合并后选择,因此要将代沟设为0.5以维持种群规模 # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 if PUN_F is not None: punishing = getattr(PUN_M, PUN_F) # 获得罚函数 exIdx = np.array([]) # 存储非可行解的下标 NVAR = FieldDRs[0].shape[1] # 得到控制变量的个数 # 定义全局进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN, 2)) * np.nan) pop_trace[:, 0] = 0 # 定义变量记录器,记录控制变量值,初始值为nan var_trace = (np.zeros((MAXGEN, NVAR)) * np.nan) """=========================开始遗传算法进化=======================""" start_time = time.time() # 开始计时 # 对于各个网格分别进行进化,采用全局进化记录器记录最优值 for index in range(len(FieldDRs)): FieldDR = FieldDRs[index] if problem == 'R': Chrom = ga.crtrp(NIND, FieldDR) # 生成初始种群 elif problem == 'I': Chrom = ga.crtip(NIND, FieldDR) repnum = 0 # 初始化重复个体数为0 # 开始进化!! for gen in range(MAXGEN): # 进行遗传算子,生成子代 SelCh = ga.recombin(recombinStyle, Chrom, recopt, SUBPOP) # 重组 if problem == 'R': SelCh = ga.mutbga(SelCh, FieldDR, pm) # 变异 if repnum > Chrom.shape[0] * 0.01: # 当最优个体重复率高达1%时,进行一次高斯变异 SelCh = ga.mutgau(SelCh, FieldDR, pm) # 高斯变异 elif problem == 'I': SelCh = ga.mutint(SelCh, FieldDR, pm) Chrom = np.vstack([Chrom, SelCh]) # 父子合并 ObjV = aimfuc(Chrom) # 求后代的目标函数值 FitnV = ga.ranking(maxormin * ObjV, None, SUBPOP) # 适应度评价 if PUN_F is not None: [FitnV, exIdx] = punishing(Chrom, FitnV) # 调用罚函数 repnum = len( np.where(ObjV[np.argmax(FitnV)] == ObjV)[0]) # 计算最优个体重复数 # 记录进化过程 bestIdx = np.argmax(FitnV) wrongSign = np.ones((FitnV.shape[0], 1)) wrongSign[list(exIdx)] = 0 # 对非可行解作标记 if FitnV[bestIdx] != 0: if (np.isnan(pop_trace[gen, 1])) or ( (maxormin == 1) & (pop_trace[gen, 1] >= ObjV[bestIdx])) or ( (maxormin == -1) & (pop_trace[gen, 1] <= ObjV[bestIdx])): feasible = np.where(wrongSign != 0)[0] # 排除非可行解 pop_trace[gen, 0] += np.sum( ObjV[feasible]) / ObjV[feasible].shape[0] / len( FieldDRs) # 记录种群个体平均目标函数值 pop_trace[gen, 1] = ObjV[bestIdx] # 记录当代目标函数的最优值 var_trace[gen, :] = Chrom[bestIdx, :] # 记录当代最优的控制变量值 Chrom = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 end_time = time.time() # 结束计时 # 后处理进化记录器 delIdx = np.where(np.isnan(pop_trace))[0] pop_trace = np.delete(pop_trace, delIdx, 0) var_trace = np.delete(var_trace, delIdx, 0) # 绘图 if drawing == 1: ga.trcplot(pop_trace, [['种群个体平均目标函数值', '种群最优个体目标函数值']]) # 输出结果 if maxormin == 1: best_gen = np.argmin(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:', np.min(pop_trace[:, 1])) elif maxormin == -1: best_gen = np.argmax(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:', np.max(pop_trace[:, 1])) print('最优的控制变量值为:') for i in range(NVAR): print(var_trace[best_gen, i]) print('最优的一代是第', best_gen + 1, '代') times = end_time - start_time print('时间已过', times, '秒') # 返回进化记录器、变量记录器以及执行时间 return [pop_trace, var_trace, times]
def sga_new_permut_templet(AIM_M, AIM_F, PUN_M, PUN_F, NVAR, VarLen, maxormin, MAXGEN, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, distribute, drawing=1): """ sga_new_permut_templet.py - 改进的单目标编程模板(排列编码) 本模板实现改进单目标编程模板(排列编码),将父子两代合并进行选择,增加了精英保留机制 排列编码即每条染色体的基因都是无重复正整数的编码方式。 语法: 该函数除了参数drawing外,不设置可缺省参数。当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: sga_new_permut_templet(AIM_M, 'aimfuc', None, None, ..., maxormin) 输入参数: AIM_M - 目标函数的地址,由AIM_M = __import__('目标函数所在文件名')语句得到 目标函数规范定义:[f,LegV] = aimfuc(Phen,LegV) 其中Phen是种群的表现型矩阵, LegV为种群的可行性列向量,f为种群的目标函数值矩阵 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,由PUN_M = __import__('罚函数所在文件名')语句得到 罚函数规范定义: newFitnV = punishing(LegV, FitnV) 其中LegV为种群的可行性列向量, FitnV为种群个体适应度列向量 一般在罚函数中对LegV为0的个体进行适应度惩罚,返回修改后的适应度列向量newFitnV PUN_F : str - 罚函数名 NVAR : int - 变量个数,排列编码的染色体长度等于变量个数 VarLen : int - 排列集合的大小 例如VarLen = 5表示是从1,2,3,4,5中抽取若干个数排列组成染色体 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,本模板中该参数为无用参数,仅为了兼容同类的其他模板而设 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 distribute : bool - 是否增强种群的分布性(可能会造成收敛慢) drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图。默认drawing为1 输出参数: pop_trace : array - 种群进化记录器(进化追踪器), 第0列记录着各代种群最优个体的目标函数值 第1列记录着各代种群的适应度均值 第2列记录着各代种群最优个体的适应度值 var_trace : array - 变量记录器,记录着各代种群最优个体的变量值,每一列对应一个控制变量 times : float - 进化所用时间 模板使用注意: 1.本模板调用的目标函数形如:[ObjV,LegV] = aimfuc(Phen,LegV), 其中Phen表示种群的表现型矩阵, LegV为种群的可行性列向量(详见Geatpy数据结构) 2.本模板调用的罚函数形如: newFitnV = punishing(LegV, FitnV), 其中FitnV为用其他算法求得的适应度 若不符合上述规范,则请修改算法模板或自定义新算法模板 3.关于'maxormin': geatpy的内核函数全是遵循“最小化目标”的约定的,即目标函数值越小越好。 当需要优化最大化的目标时,需要设置'maxormin'为-1。 本算法模板是正确使用'maxormin'的典型范例,其具体用法如下: 当调用的函数传入参数包含与“目标函数值矩阵”有关的参数(如ObjV,ObjVSel,NDSetObjV等)时, 查看该函数的参考资料(可用'help'命令查看,也可到官网上查看相应的教程), 里面若要求传入前对参数乘上'maxormin',则需要乘上。 里面若要求对返回参数乘上'maxormin'进行还原, 则调用函数返回得到的相应参数需要乘上'maxormin'进行还原,否则其正负号就会被改变。 """ """==========================初始化配置===========================""" GGAP = 0.5 # 因为父子合并后选择,因此要将代沟设为0.5以维持种群规模 # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 if PUN_F is not None: punishing = getattr(PUN_M, PUN_F) # 获得罚函数 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN, 2)) * np.nan) # 定义变量记录器,记录控制变量值,初始值为nan var_trace = (np.zeros((MAXGEN, NVAR)) * np.nan) ax = None # 存储上一帧图形 """=========================开始遗传算法进化=======================""" Chrom = ga.crtpp(NIND, NVAR, VarLen) #生成初始种群 LegV = np.ones((NIND, 1)) # 生成可行性列向量,元素为1表示对应个体是可行解,0表示非可行解 [ObjV, LegV] = aimfuc(Chrom, LegV) # 求初代的目标函数值 gen = 0 badCounter = 0 # 用于记录在“遗忘策略下”被忽略的代数 # 开始进化!! start_time = time.time() # 开始计时 while gen < MAXGEN: if badCounter >= 10 * MAXGEN: # 若多花了10倍的迭代次数仍没有可行解出现,则跳出 break # 进行遗传算子,生成子代 SelCh = ga.recombin(recombinStyle, Chrom, recopt, SUBPOP) # 重组 SelCh = ga.mutpp(SelCh, VarLen, pm) # 排列编码种群变异 LegVSel = np.ones((SelCh.shape[0], 1)) # 初始化育种种群的可行性列向量 [ObjVSel, LegVSel] = aimfuc(SelCh, LegVSel) # 求后代的目标函数值 # 父子合并 Chrom = np.vstack([Chrom, SelCh]) ObjV = np.vstack([ObjV, ObjVSel]) LegV = np.vstack([LegV, LegVSel]) # 对合并的种群进行适应度评价 FitnV = ga.ranking(maxormin * ObjV, LegV, None, SUBPOP) # 适应度评价 if PUN_F is not None: FitnV = punishing(LegV, FitnV) # 调用罚函数 # 记录进化过程 bestIdx = np.argmax(FitnV) # 获取最优个体的下标 if LegV[bestIdx] != 0: feasible = np.where(LegV != 0)[0] # 排除非可行解 pop_trace[gen, 0] = np.sum( ObjV[feasible]) / ObjV[feasible].shape[0] # 记录种群个体平均目标函数值 pop_trace[gen, 1] = ObjV[bestIdx] # 记录当代目标函数的最优值 var_trace[gen, :] = Chrom[bestIdx, :] # 记录当代最优的控制变量值 # 绘制动态图 if drawing == 2: ax = ga.sgaplot(pop_trace[:, [1]], '种群最优个体目标函数值', False, ax, gen) else: gen -= 1 # 忽略这一代 badCounter += 1 if distribute == True: # 若要增强种群的分布性(可能会造成收敛慢) idx = np.argsort(ObjV[:, 0], 0) dis = np.diff(ObjV[idx, 0]) / (np.max(ObjV[idx, 0]) - np.min( ObjV[idx, 0]) + 1) # 差分计算距离的修正偏移量 dis = np.hstack([dis, dis[-1]]) dis = dis + np.min(dis) # 修正偏移量+最小量=修正绝对量 FitnV[idx, 0] *= np.exp(dis) # 根据相邻距离修改适应度,突出相邻距离大的个体,以增加种群的多样性 [Chrom, ObjV, LegV] = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP, ObjV, LegV) # 选择个体生成新一代种群 gen += 1 end_time = time.time() # 结束计时 times = end_time - start_time # 绘图 if drawing != 0: ga.trcplot(pop_trace, [['种群个体平均目标函数值', '种群最优个体目标函数值']]) # 输出结果 if maxormin == 1: best_gen = np.argmin(pop_trace[:, 1]) # 记录最优种群是在哪一代 best_ObjV = np.min(pop_trace[:, 1]) elif maxormin == -1: best_gen = np.argmax(pop_trace[:, 1]) # 记录最优种群是在哪一代 best_ObjV = np.max(pop_trace[:, 1]) if np.isnan(best_ObjV): raise RuntimeError('error: no feasible solution. (没找到可行解。)') print('最优的目标函数值为:', best_ObjV) print('最优的控制变量值为:') for i in range(NVAR): print(var_trace[best_gen, i]) print('最优的一代是第', best_gen + 1, '代') print('时间已过', times, '秒') # 返回进化记录器、变量记录器以及执行时间 return [pop_trace, var_trace, times]
pm = 0.1 # 变异概率 SUBPOP = 1 # 设置种群数为1 """=========================开始遗传算法进化========================""" FieldD = ga.crtfld(ranges, borders, precisions, codes, scales) # 调用函数创建区域描述器 Lind = np.sum(FieldD[0, :]) # 计算编码后的染色体长度 Chrom = ga.crtbp(NIND, Lind) # 根据区域描述器生成二进制种群 Phen = ga.bs2rv(Chrom, FieldD) #对初始种群进行解码 ObjV = aimfuc(Phen) # 计算初始种群个体的目标函数值 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN, 2)) * np.nan) # 定义种群最优个体记录器,记录每一代最优个体的染色体,初始值为nan ind_trace = (np.zeros((MAXGEN, Lind)) * np.nan) # 开始进化!! start_time = time.time() # 开始计时 for gen in range(MAXGEN): FitnV = ga.ranking(ObjV) # 根据目标函数大小分配适应度值 SelCh = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh = ga.recombin(recombinStyle, SelCh, recopt, SUBPOP) #交叉 SelCh = ga.mutbin(SelCh, pm) # 二进制种群变异 Phen = ga.bs2rv(SelCh, FieldD) # 对育种种群进行解码(二进制转十进制) ObjVSel = aimfuc(Phen) # 求育种个体的目标函数值 [Chrom, ObjV] = ga.reins(Chrom, SelCh, SUBPOP, 2, 1, ObjV, ObjVSel) # 重插入得到新一代种群 # 记录 best_ind = np.argmin(ObjV) # 计算当代最优个体的序号 pop_trace[gen, 0] = ObjV[best_ind] # 记录当代种群最优个体目标函数值 pop_trace[gen, 1] = np.sum(ObjV) / ObjV.shape[0] # 记录当代种群的目标函数均值 ind_trace[gen, :] = Chrom[best_ind, :] # 记录当代种群最优个体的变量值 # 进化完成 end_time = time.time() # 结束计时 """============================绘图================================"""
def sga_permut_templet(AIM_M, AIM_F, PUN_M, PUN_F, NVAR, VarLen, maxormin, MAXGEN, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, drawing = 1): """ sga_permut_templet.py - 单目标编程模板(排列编码) 排列编码即每条染色体的基因都是无重复正整数的编码方式。 语法: 该函数除了参数drawing外,不设置可缺省参数。当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: sga_permut_templet(AIM_M, 'aimfuc', None, None, ..., maxormin) 输入参数: AIM_M - 目标函数的地址,由AIM_M = __import__('目标函数所在文件名')语句得到 目标函数规范定义:f = aimfuc(Phen) 其中Phen是种群的表现型矩阵 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,由PUN_M = __import__('罚函数所在文件名')语句得到 罚函数规范定义: f = punishing(Phen, FitnV) 其中Phen是种群的表现型矩阵, FitnV为种群个体适应度列向量 PUN_F : str - 罚函数名 NVAR : int - 变量个数,排列编码的染色体长度等于变量个数 VarLen : int - 排列集合的大小 例如VarLen = 5表示是从1,2,3,4,5中抽取若干个数排列组成染色体 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,表示子代与父代染色体及性状不相同的概率 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图。默认drawing为1 输出参数: pop_trace : array - 种群进化记录器(进化追踪器), 第0列记录着各代种群最优个体的目标函数值 第1列记录着各代种群的适应度均值 第2列记录着各代种群最优个体的适应度值 var_trace : array - 变量记录器,记录着各代种群最优个体的变量值,每一列对应一个控制变量 times : float - 进化所用时间 模板使用注意: 1.本模板调用的目标函数形如:aimfuc(Phen), 其中Phen表示种群的表现型矩阵 2.本模板调用的罚函数形如: punishing(Phen, FitnV), 其中FitnV为用其他算法求得的适应度 在罚函数定义中,必须将不满足约束条件的个体对应的适应度设为0,否则请修改模板使用 """ """==========================初始化配置===========================""" # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 if PUN_F is not None: punishing = getattr(PUN_M, PUN_F) # 获得罚函数 exIdx = np.array([]) # 存储非可行解的下标 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN ,2)) * np.nan) # 定义变量记录器,记录控制变量值,初始值为nan var_trace = (np.zeros((MAXGEN ,NVAR)) * np.nan) """=========================开始遗传算法进化=======================""" #生成初始种群 Chrom = ga.crtpp(NIND, NVAR, VarLen) ObjV = aimfuc(Chrom) # 求种群的目标函数值 start_time = time.time() # 开始计时 # 开始进化!! for gen in range(MAXGEN): FitnV = ga.ranking(maxormin * ObjV, None, SUBPOP) if PUN_F is not None: [FitnV, exIdx] = punishing(Chrom, FitnV) # 调用罚函数 # 记录进化过程 bestIdx = np.argmax(FitnV) # 获取最优个体的下标 wrongSign = np.ones((FitnV.shape[0], 1)) wrongSign[list(exIdx)] = 0 # 对非可行解作标记 if wrongSign[bestIdx] != 0: feasible = np.where(wrongSign != 0)[0] # 排除非可行解 pop_trace[gen,0] = np.sum(ObjV[feasible]) / ObjV[feasible].shape[0] # 记录种群个体平均目标函数值 pop_trace[gen,1] = ObjV[bestIdx] # 记录当代目标函数的最优值 var_trace[gen,:] = Chrom[bestIdx, :] # 记录当代最优的控制变量值 # 进行遗传算子 SelCh=ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh=ga.recombin(recombinStyle, Chrom, recopt, SUBPOP) # 重组 SelCh=ga.mutpp(SelCh, VarLen, pm) # 排列编码种群变异 ObjVSel = aimfuc(SelCh) # 求后代的目标函数值 # 重插入 [Chrom, ObjV]=ga.reins(Chrom, SelCh, SUBPOP, 2, 1, ObjV, ObjVSel) end_time = time.time() # 结束计时 # 后处理进化记录器 delIdx = np.where(np.isnan(pop_trace))[0] pop_trace = np.delete(pop_trace, delIdx, 0) var_trace = np.delete(var_trace, delIdx, 0) # 绘图 if drawing == 1: ga.trcplot(pop_trace, [['种群个体平均目标函数值', '种群最优个体目标函数值']]) # 输出结果 if maxormin == 1: best_gen = np.argmin(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:', np.min(pop_trace[:, 1])) elif maxormin == -1: best_gen = np.argmax(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:', np.max(pop_trace[:, 1])) print('最优的控制变量值为:') for i in range(NVAR): print(var_trace[best_gen, i]) print('最优的一代是第', best_gen + 1, '代') times = end_time - start_time print('时间已过', times, '秒') # 返回进化记录器、变量记录器以及执行时间 return [pop_trace, var_trace, times]
MAXGEN = 25 # 最大遗传代数 FieldD = ea.crtfld(Encoding, varTypes, ranges, borders, precisions, codes, scales) # 调用函数创建区域描述器 Lind = int(np.sum(FieldD[0, :])) # 计算编码后的染色体长度 obj_trace = np.zeros((MAXGEN, 2)) # 定义目标函数值记录器 var_trace = np.zeros((MAXGEN, Lind)) # 定义染色体记录器,记录每一代最优个体的染色体 """=========================开始遗传算法进化========================""" start_time = time.time() # 开始计时 Chrom = ea.crtbp(NIND, Lind) # 生成种群染色体矩阵 variable = ea.bs2real(Chrom, FieldD) # 对初始种群进行解码 ObjV = aim(variable) # 计算初始种群个体的目标函数值 best_ind = np.argmax(ObjV) # 计算当代最优个体的序号 # 开始进化 for gen in range(MAXGEN): FitnV = ea.ranking(-ObjV) # 根据目标函数大小分配适应度值(由于遵循目标最小化约定,因此最大化问题要对目标函数值乘上-1) SelCh = Chrom[ea.selecting('rws', FitnV, NIND - 1), :] # 选择,采用'rws'轮盘赌选择 SelCh = ea.recombin('xovsp', SelCh, 0.7) # 重组(采用两点交叉方式,交叉概率为0.7) SelCh = ea.mutbin(Encoding, SelCh) # 二进制种群变异 # 把父代精英个体与子代合并 Chrom = np.vstack([Chrom[best_ind, :], SelCh]) variable = ea.bs2real(Chrom, FieldD) # 对育种种群进行解码(二进制转十进制) ObjV = aim(variable) # 求育种个体的目标函数值 # 记录 best_ind = np.argmax(ObjV) # 计算当代最优个体的序号 obj_trace[gen, 0] = np.sum(ObjV) / NIND # 记录当代种群的目标函数均值 obj_trace[gen, 1] = ObjV[best_ind] # 记录当代种群最优个体目标函数值 var_trace[gen, :] = Chrom[best_ind, :] # 记录当代种群最优个体的变量值 # 进化完成 end_time = time.time() # 结束计时 """============================输出结果及绘图================================"""
def sga_permut_templet(AIM_M, AIM_F, PUN_M, PUN_F, NVAR, VarLen, maxormin, MAXGEN, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, drawing=1): """ sga_permut_templet.py - 单目标编程模板(排列编码) 排列编码即每条染色体的基因都是无重复正整数的编码方式。 语法: 该函数除了参数drawing外,不设置可缺省参数。当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: sga_permut_templet(AIM_M, 'aimfuc', None, None, ..., maxormin) 输入参数: AIM_M - 目标函数的地址,传入该函数前通常由AIM_M = __import__('目标函数名')语句得到 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,传入该函数前通常由PUN_M = __import__('罚函数名')语句得到 PUN_F : str - 罚函数名 NVAR : int - 变量个数,排列编码的染色体长度等于变量个数 VarLen : int - 排列集合的大小 例如VarLen = 5表示是从1,2,3,4,5中抽取若干个数排列组成染色体 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,表示子代与父代染色体及性状不相同的概率 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图。默认drawing为1 输出参数: pop_trace : array - 种群进化记录器(进化追踪器), 第0列记录着各代种群最优个体的目标函数值 第1列记录着各代种群的适应度均值 第2列记录着各代种群最优个体的适应度值 var_trace : array - 变量记录器,记录着各代种群最优个体的变量值,每一列对应一个控制变量 times : float - 进化所用时间 """ """==========================初始化配置===========================""" # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 if PUN_F is not None: punishing = getattr(PUN_M, PUN_F) # 获得罚函数 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN, 2)) * np.nan) # 定义变量记录器,记录控制变量值,初始值为nan var_trace = (np.zeros((MAXGEN, NVAR)) * np.nan) """=========================开始遗传算法进化=======================""" #生成初始种群 Chrom = ga.crtpp(NIND, NVAR, VarLen) ObjV = aimfuc(Chrom) # 求种群的目标函数值 start_time = time.time() # 开始计时 # 开始进化!! for gen in range(MAXGEN): FitnV = ga.ranking(maxormin * ObjV, None, SUBPOP) if PUN_F is not None: FitnV = punishing(Chrom, FitnV) # 调用罚函数 # 进行遗传算子 SelCh = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh = ga.recombin(recombinStyle, Chrom, recopt, SUBPOP) # 重组 SelCh = ga.mutpp(SelCh, VarLen, pm) # 排列编码种群变异 ObjVSel = aimfuc(SelCh) # 求后代的目标函数值 # 重插入 [Chrom, ObjV] = ga.reins(Chrom, SelCh, SUBPOP, 2, 1, ObjV, ObjVSel) pop_trace[gen, 0] = np.sum(ObjV) // ObjV.shape[0] # 记录种群个体平均目标函数值 if maxormin == 1: pop_trace[gen, 1] = np.min(ObjV) # 记录当代目标函数的最优值 var_trace[gen, :] = Chrom[np.argmin(ObjV), :] # 记录当代最优的控制变量值 elif maxormin == -1: pop_trace[gen, 1] = np.max(ObjV) var_trace[gen, :] = Chrom[np.argmax(ObjV), :] # 记录当代最优的控制变量值 end_time = time.time() # 结束计时 # 绘图 if drawing == 1: ga.trcplot(pop_trace, [['种群个体平均目标函数值', '种群最优个体目标函数值']]) # 输出结果 if maxormin == 1: best_gen = np.argmin(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:', np.min(pop_trace[:, 1])) elif maxormin == -1: best_gen = np.argmax(pop_trace[:, 1]) # 记录最优种群是在哪一代 print('最优的目标函数值为:', np.max(pop_trace[:, 1])) print('最优的控制变量值为:') for i in range(NVAR): print(var_trace[best_gen, i]) print('最优的一代是第', best_gen + 1, '代') times = end_time - start_time print('时间已过', times, '秒') # 返回进化记录器、变量记录器以及执行时间 return [pop_trace, var_trace, times]
def sga_real_templet(AIM_M, AIM_F, PUN_M, PUN_F, FieldDR, problem, maxormin, MAXGEN, NIND, SUBPOP, GGAP, selectStyle, recombinStyle, recopt, pm, distribute, drawing=1): """ sga_real_templet.py - 单目标编程模板(实值编码) 语法: 该函数除了参数drawing外,不设置可缺省参数。当某个参数需要缺省时,在调用函数时传入None即可。 比如当没有罚函数时,则在调用编程模板时将第3、4个参数设置为None即可,如: sga_real_templet(AIM_M, 'aimfuc', None, None, ..., maxormin) 输入参数: AIM_M - 目标函数的地址,由AIM_M = __import__('目标函数所在文件名')语句得到 目标函数规范定义:[f,LegV] = aimfuc(Phen,LegV) 其中Phen是种群的表现型矩阵, LegV为种群的可行性列向量,f为种群的目标函数值矩阵 AIM_F : str - 目标函数名 PUN_M - 罚函数的地址,由PUN_M = __import__('罚函数所在文件名')语句得到 罚函数规范定义: newFitnV = punishing(LegV, FitnV) 其中LegV为种群的可行性列向量, FitnV为种群个体适应度列向量 一般在罚函数中对LegV为0的个体进行适应度惩罚,返回修改后的适应度列向量newFitnV PUN_F : str - 罚函数名 FieldDR : array - 实际值种群区域描述器 [lb; (float) 指明每个变量使用的下界 ub] (float) 指明每个变量使用的上界 注:不需要考虑是否包含变量的边界值。在crtfld中已经将是否包含边界值进行了处理 本函数生成的矩阵的元素值在FieldDR的[下界, 上界)之间 problem : str - 表明是整数问题还是实数问题,'I'表示是整数问题,'R'表示是实数问题 maxormin int - 最小最大化标记,1表示目标函数最小化;-1表示目标函数最大化 MAXGEN : int - 最大遗传代数 NIND : int - 种群规模,即种群中包含多少个个体 SUBPOP : int - 子种群数量,即对一个种群划分多少个子种群 GGAP : float - 代沟,表示子代与父代染色体及性状不相同的概率 selectStyle : str - 指代所采用的低级选择算子的名称,如'rws'(轮盘赌选择算子) recombinStyle: str - 指代所采用的低级重组算子的名称,如'xovsp'(单点交叉) recopt : float - 交叉概率 pm : float - 重组概率 distribute : bool - 是否增强种群的分布性(可能会造成收敛慢) drawing : int - (可选参数),0表示不绘图,1表示绘制最终结果图。默认drawing为1 输出参数: pop_trace : array - 种群进化记录器(进化追踪器), 第0列记录着各代种群最优个体的目标函数值 第1列记录着各代种群的适应度均值 第2列记录着各代种群最优个体的适应度值 var_trace : array - 变量记录器,记录着各代种群最优个体的变量值,每一列对应一个控制变量 times : float - 进化所用时间 模板使用注意: 1.本模板调用的目标函数形如:[ObjV,LegV] = aimfuc(Phen,LegV), 其中Phen表示种群的表现型矩阵, LegV为种群的可行性列向量(详见Geatpy数据结构) 2.本模板调用的罚函数形如: newFitnV = punishing(LegV, FitnV), 其中FitnV为用其他算法求得的适应度 若不符合上述规范,则请修改算法模板或自定义新算法模板 3.关于'maxormin': geatpy的内核函数全是遵循“最小化目标”的约定的,即目标函数值越小越好。 当需要优化最大化的目标时,需要设置'maxormin'为-1。 本算法模板是正确使用'maxormin'的典型范例,其具体用法如下: 当调用的函数传入参数包含与“目标函数值矩阵”有关的参数(如ObjV,ObjVSel,NDSetObjV等)时, 查看该函数的参考资料(可用'help'命令查看,也可到官网上查看相应的教程), 里面若要求传入前对参数乘上'maxormin',则需要乘上。 里面若要求对返回参数乘上'maxormin'进行还原, 则调用函数返回得到的相应参数需要乘上'maxormin'进行还原,否则其正负号就会被改变。 """ """==========================初始化配置===========================""" # 获取目标函数和罚函数 aimfuc = getattr(AIM_M, AIM_F) # 获得目标函数 if PUN_F is not None: punishing = getattr(PUN_M, PUN_F) # 获得罚函数 NVAR = FieldDR.shape[1] # 得到控制变量的个数 # 定义进化记录器,初始值为nan pop_trace = (np.zeros((MAXGEN, 2)) * np.nan) # 定义变量记录器,记录控制变量值,初始值为nan var_trace = (np.zeros((MAXGEN, NVAR)) * np.nan) ax = None # 存储上一帧图形 repnum = 0 # 初始化重复个体数为0 """=========================开始遗传算法进化=======================""" if problem == 'R': Chrom = ga.crtrp(NIND, FieldDR) # 生成初始种群 elif problem == 'I': Chrom = ga.crtip(NIND, FieldDR) LegV = np.ones((NIND, 1)) # 初始化种群的可行性列向量 [ObjV, LegV] = aimfuc(Chrom, LegV) # 求种群的目标函数值 gen = 0 badCounter = 0 # 用于记录在“遗忘策略下”被忽略的代数 # 开始进化!! start_time = time.time() # 开始计时 while gen < MAXGEN: if badCounter >= 10 * MAXGEN: # 若多花了10倍的迭代次数仍没有可行解出现,则跳出 break FitnV = ga.ranking(maxormin * ObjV, LegV, None, SUBPOP) if PUN_F is not None: FitnV = punishing(LegV, FitnV) # 调用罚函数 # 记录进化过程 bestIdx = np.argmax(FitnV) # 获取最优个体的下标 if LegV[bestIdx] != 0: feasible = np.where(LegV != 0)[0] # 排除非可行解 pop_trace[gen, 0] = np.sum( ObjV[feasible]) / ObjV[feasible].shape[0] # 记录种群个体平均目标函数值 pop_trace[gen, 1] = ObjV[bestIdx] # 记录当代目标函数的最优值 var_trace[gen, :] = Chrom[bestIdx, :] # 记录当代最优的控制变量值 repnum = len( np.where(ObjV[np.argmax(FitnV)] == ObjV)[0]) # 计算最优个体重复数 # 绘制动态图 if drawing == 2: ax = ga.sgaplot(pop_trace[:, [1]], '种群最优个体目标函数值', False, ax, gen) badCounter = 0 # badCounter计数器清零 else: gen -= 1 # 忽略这一代(遗忘策略) badCounter += 1 if distribute == True: # 若要增强种群的分布性(可能会造成收敛慢) idx = np.argsort(ObjV[:, 0], 0) dis = np.diff(ObjV[idx, 0]) / (np.max(ObjV[idx, 0]) - np.min( ObjV[idx, 0]) + 1) # 差分计算距离的修正偏移量 dis = np.hstack([dis, dis[-1]]) dis = dis + np.min(dis) # 修正偏移量+最小量=修正绝对量 FitnV[idx, 0] *= np.exp(dis) # 根据相邻距离修改适应度,突出相邻距离大的个体,以增加种群的多样性 # 进行遗传算子 SelCh = ga.selecting(selectStyle, Chrom, FitnV, GGAP, SUBPOP) # 选择 SelCh = ga.recombin(recombinStyle, SelCh, recopt, SUBPOP) # 对所选个体进行重组 if problem == 'R': SelCh = ga.mutbga(SelCh, FieldDR, pm) # 变异 if repnum > Chrom.shape[0] * 0.01: # 当最优个体重复率高达1%时,进行一次高斯变异 SelCh = ga.mutgau(SelCh, FieldDR, pm) # 高斯变异 elif problem == 'I': SelCh = ga.mutint(SelCh, FieldDR, pm) LegVSel = np.ones((SelCh.shape[0], 1)) # 初始化育种种群的可行性列向量 [ObjVSel, LegVSel] = aimfuc(SelCh, LegVSel) # 求育种种群的目标函数值 FitnVSel = ga.ranking(maxormin * ObjVSel, LegVSel, None, SUBPOP) # 计算育种种群的适应度 if PUN_F is not None: FitnVSel = punishing(LegVSel, FitnVSel) # 调用罚函数 # 重插入 [Chrom, ObjV, LegV] = ga.reins(Chrom, SelCh, SUBPOP, 1, 1, FitnV, FitnVSel, ObjV, ObjVSel, LegV, LegVSel) gen += 1 end_time = time.time() # 结束计时 times = end_time - start_time # 后处理进化记录器 delIdx = np.where(np.isnan(pop_trace))[0] pop_trace = np.delete(pop_trace, delIdx, 0) var_trace = np.delete(var_trace, delIdx, 0) if pop_trace.shape[0] == 0: raise RuntimeError('error: no feasible solution. (有效进化代数为0,没找到可行解。)') # 绘图 if drawing != 0: ga.trcplot(pop_trace, [['种群个体平均目标函数值', '种群最优个体目标函数值']]) # 输出结果 if maxormin == 1: best_gen = np.argmin(pop_trace[:, 1]) # 记录最优种群是在哪一代 best_ObjV = np.min(pop_trace[:, 1]) elif maxormin == -1: best_gen = np.argmax(pop_trace[:, 1]) # 记录最优种群是在哪一代 best_ObjV = np.max(pop_trace[:, 1]) print('最优的目标函数值为:%s' % (best_ObjV)) print('最优的控制变量值为:') for i in range(NVAR): print(var_trace[best_gen, i]) print('有效进化代数:%s' % (pop_trace.shape[0])) print('最优的一代是第 %s 代' % (best_gen + 1)) print('时间已过 %s 秒' % (times)) # 返回进化记录器、变量记录器以及执行时间 return [pop_trace, var_trace, times]
def main(): """============================变量设置============================""" x1 = [50, 100] # 第一个决策变量范围 x2 = [50, 100] # 第二个决策变量范围 x3 = [50, 100] x4 = [50, 100] x5 = [50, 100] x6 = [50, 100] x7 = [50, 100] x8 = [50, 100] x9 = [50, 100] x10 = [50, 100] b1 = [1, 1] # 第一个决策变量边界,1表示包含范围的边界,0表示不包含 b2 = [1, 1] # 第二个决策变量边界,1表示包含范围的边界,0表示不包含 b3 = [1, 1] b4 = [1, 1] b5 = [1, 1] b6 = [1, 1] b7 = [1, 1] b8 = [1, 1] b9 = [1, 1] b10 = [1, 1] ranges = np.vstack([x1, x2, x3, x4, x5, x6, x7, x8, x9, x10]).T # 生成自变量的范围矩阵,使得第一行为所有决策变量的下界,第二行为上界 borders = np.vstack([b1, b2, b3, b4, b5, b6, b7, b8, b9, b10]).T # 生成自变量的边界矩阵 varTypes = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) # 决策变量的类型,0表示连续,1表示离散 """==========================染色体编码设置=========================""" Encoding = 'BG' # 'BG'表示采用二进制/格雷编码 codes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] # 决策变量的编码方式,设置两个0表示两个决策变量均使用二进制编码 precisions = [4, 4, 4, 4, 4, 4, 4, 4, 4, 4] # 决策变量的编码精度,表示二进制编码串解码后能表示的决策变量的精度可达到小数点后6位 scales = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] # 0表示采用算术刻度,1表示采用对数刻度 FieldD = ea.crtfld(Encoding, varTypes, ranges, borders, precisions, codes, scales) # 调用函数创建译码矩阵 """=========================遗传算法参数设置========================""" NIND = 30 # 种群个体数目 MAXGEN = 30 # 最大遗传代数 maxormins = [1] # 列表元素为1则表示对应的目标函数是最小化,元素为-1则表示对应的目标函数是最大化 selectStyle = 'rws' # 采用轮盘赌选择 recStyle = 'xovdp' # 采用两点交叉 mutStyle = 'mutbin' # 采用二进制染色体的变异算子 pc = 0.7 # 交叉概率 pm = 1 # 整条染色体的变异概率(每一位的变异概率=pm/染色体长度) Lind = int(np.sum(FieldD[0, :])) # 计算染色体长度 obj_trace = np.zeros((MAXGEN, 2)) # 定义目标函数值记录器 var_trace = np.zeros((MAXGEN, Lind)) # 染色体记录器,记录历代最优个体的染色体 """=========================开始遗传算法进化========================""" start_time = time.time() # 开始计时 Chrom = ea.crtpc(Encoding, NIND, FieldD) # 生成种群染色体矩阵 variable = ea.bs2real(Chrom, FieldD) # 对初始种群进行解码 ObjV = minfun(variable) # 计算初始种群个体的目标函数值 FitnV = ea.ranking(maxormins * ObjV) # 根据目标函数大小分配适应度值 best_ind = np.argmax(FitnV) # 计算当代最优个体的序号 # 开始进化 for gen in range(MAXGEN): print(gen) SelCh = Chrom[ea.selecting(selectStyle, FitnV, NIND - 1), :] # 选择 SelCh = ea.recombin(recStyle, SelCh, pc) # 重组 SelCh = ea.mutate(mutStyle, Encoding, SelCh, pm) # 变异 # 把父代精英个体与子代的染色体进行合并,得到新一代种群 Chrom = np.vstack([Chrom[best_ind, :], SelCh]) Phen = ea.bs2real(Chrom, FieldD) # 对种群进行解码(二进制转十进制) print(Phen) ObjV = minfun(Phen) # 求种群个体的目标函数值 FitnV = ea.ranking(maxormins * ObjV) # 根据目标函数大小分配适应度值 # 记录 best_ind = np.argmax(FitnV) # 计算当代最优个体的序号 obj_trace[gen, 0] = np.sum(ObjV) / ObjV.shape[0] # 记录当代种群的目标函数均值 obj_trace[gen, 1] = ObjV[best_ind] # 记录当代种群最优个体目标函数值 var_trace[gen, :] = Chrom[best_ind, :] # 记录当代种群最优个体的染色体 print(best_ind) # 进化完成 end_time = time.time() # 结束计时 ea.trcplot(obj_trace, [['种群个体平均目标函数值', '种群最优个体目标函数值']]) # 绘制图像 """============================输出结果============================""" best_gen = np.argmin(obj_trace[:, [1]]) print('最优解的目标函数值:', obj_trace[best_gen, 1]) variable = ea.bs2real(var_trace[[best_gen], :], FieldD) # 解码得到表现型(即对应的决策变量值) print('最优解的决策变量值为:') print(variable) print('用时:', end_time - start_time, '秒')