def aimFunc(self, pop): # 目标函数 centers = pop.Phen.reshape(int(pop.sizes * self.k), int(pop.Phen.shape[1] / self.k)) # 得到聚类中心 dis = ea.cdist(centers, self.datas, 'euclidean') # 计算距离 dis_split = dis.reshape( pop.sizes, self.k, self.datas.shape[0]) # 分割距离矩阵,把各个聚类中心到各个点之间的距离的数据分开 labels = np.argmin(dis_split, 1)[0] # 得到聚类标签值 uni_labels = np.unique(labels) for i in range(len(uni_labels)): centers[uni_labels[i], :] = np.mean( self.datas[np.where(labels == uni_labels[i])[0], :], 0) # 直接修改染色体为已知的更优值,加快收敛 pop.Chrom = centers.reshape(pop.sizes, self.k * centers.shape[1]) pop.Phen = pop.decoding() # 染色体解码(要同步修改Phen,否则后面会导致数据不一致) dis = ea.cdist(centers, self.datas, 'euclidean') dis_split = dis.reshape(pop.sizes, self.k, self.datas.shape[0]) pop.ObjV = np.sum(np.min(dis_split, 1), 1, keepdims=True) # 计算个体的目标函数值
def run(self, prophetPop=None): # prophetPop为先知种群(即包含先验知识的种群) # ==========================初始化配置=========================== population = self.population self.initialization() # 初始化算法类的一些动态参数 # ===========================准备进化============================ uniformPoint, NIND = ea.crtup(self.problem.M, population.sizes) # 生成在单位目标维度上均匀分布的参考点集 population.initChrom( NIND ) # 初始化种群染色体矩阵,此时种群规模将调整为uniformPoint点集的大小,initChrom函数会把种群规模给重置 # 插入先验知识(注意:这里不会对先知种群prophetPop的合法性进行检查) if prophetPop is not None: population = (prophetPop + population)[:NIND] # 插入先知种群 self.call_aimFunc(population) # 计算种群的目标函数值 # 确定邻域大小 if self.neighborSize is None: self.neighborSize = population.sizes // 10 self.neighborSize = max(self.neighborSize, 2) # 确保不小于2 # 生成由所有邻居索引组成的矩阵 neighborIdx = np.argsort(ea.cdist(uniformPoint, uniformPoint), axis=1, kind='mergesort')[:, :self.neighborSize] neighborIdx_list = [] for i in range(population.sizes): neighborIdx_list.append(neighborIdx[i, :]) offspring = ea.Population(population.Encoding, population.Field, 1) # 实例化一个种群对象用于存储进化的后代(每一代只进化生成一个后代) # 计算理想点 idealPoint = ea.crtidp(population.ObjV, population.CV, self.problem.maxormins) # ===========================开始进化============================ while not self.terminated(population): select_rands = np.random.rand(population.sizes) # 生成一组随机数 Masks = np.random.rand(population.sizes, population.Lind) < self.Cr for i in range(population.sizes): if select_rands[i] < self.Ps: indices = neighborIdx_list[i] else: indices = np.arange(population.sizes) r = indices[ea.rps(len(indices), 2)] # 随机选择两个索引作为差分向量的索引 r1, r2 = r[0], r[1] # 得到差分向量索引 offspring.Chrom = population.Chrom[[i], :] Mask = Masks[i] offspring.Chrom[0][Mask] = offspring.Chrom[0][ Mask] + self.F * (population.Chrom[r1][Mask] - population.Chrom[r2][Mask]) offspring.Chrom = self.mutOper.do(offspring.Encoding, offspring.Chrom, offspring.Field) # 多项式变异 self.call_aimFunc(offspring) # 求进化后个体的目标函数值 # 更新理想点 idealPoint = ea.crtidp(offspring.ObjV, offspring.CV, self.problem.maxormins, idealPoint) # 重插入更新种群个体 self.reinsertion(indices, population, offspring, idealPoint, uniformPoint) return self.finishing(population) # 调用finishing完成后续工作并返回结果
def renewRefPoint(self, ObjV, refPoint): # 更新参考点 _ObjV = ObjV - np.min(ObjV, 0) linkIdx = np.argmax(ea.cdist(_ObjV, refPoint, 'cosine_similarity'), 1) # 找到与参考点关联的点的索引 noLinkIdx = list(set(range(refPoint.shape[0])) - set(linkIdx)) # 找到不与参考点关联的点的索引 refPoint[noLinkIdx, :] = np.random.rand( len(noLinkIdx), refPoint.shape[1]) * np.max(_ObjV, 0) return refPoint
def run(self, prophetPop=None): # prophetPop为先知种群(即包含先验知识的种群) # ==========================初始化配置=========================== population = self.population self.initialization() # 初始化算法类的一些动态参数 # ===========================准备进化============================ uniformPoint, NIND = ea.crtup(self.problem.M, population.sizes) # 生成在单位目标维度上均匀分布的参考点集 population.initChrom( NIND ) # 初始化种群染色体矩阵,此时种群规模将调整为uniformPoint点集的大小,initChrom函数会把种群规模给重置 # 插入先验知识(注意:这里不会对先知种群prophetPop的合法性进行检查) if prophetPop is not None: population = (prophetPop + population)[:NIND] # 插入先知种群 self.call_aimFunc(population) # 计算种群的目标函数值 # 确定邻域大小 if self.neighborSize is None: self.neighborSize = population.sizes self.neighborSize = max(self.neighborSize, 2) # 确保不小于2 # 生成由所有邻居索引组成的矩阵 neighborIdx = np.argsort(ea.cdist(uniformPoint, uniformPoint), axis=1, kind='mergesort')[:, :self.neighborSize] neighborIdx_list = [] for i in range(population.sizes): neighborIdx_list.append(neighborIdx[i, :]) offspring = ea.Population(population.Encoding, population.Field, 1) # 实例化一个种群对象用于存储进化的后代(每一代只进化生成一个后代) # 计算理想点 idealPoint = ea.crtidp(population.ObjV, population.CV, self.problem.maxormins) # ===========================开始进化============================ while not self.terminated(population): select_rands = np.random.rand(population.sizes) # 生成一组随机数 for i in range(population.sizes): indices = neighborIdx_list[i] # 得到邻居索引 if select_rands[i] < self.Ps: chooseIdx = indices[ea.rps(self.neighborSize, 2)] # 只从邻域中选择 else: chooseIdx = ea.rps(population.sizes, 2) matting_Chrom = population.Chrom[ chooseIdx, :] # 选出2条来自被选个体的染色体 # 对选出的个体进行进化操作 offspring.Chrom = self.recOper.do(matting_Chrom) # 重组 offspring.Chrom = self.mutOper.do(offspring.Encoding, offspring.Chrom, offspring.Field) # 变异 self.call_aimFunc(offspring) # 求进化后个体的目标函数值 # 更新理想点 idealPoint = ea.crtidp(offspring.ObjV, offspring.CV, self.problem.maxormins, idealPoint) # 重插入更新种群个体 self.reinsertion(indices, population, offspring, idealPoint, uniformPoint) return self.finishing(population) # 调用finishing完成后续工作并返回结果
def draw(self, centers): # 绘制聚类效果图 dis = ea.cdist(centers, self.datas, 'euclidean') dis_split = dis.reshape(1, self.k, self.datas.shape[0]) labels = np.argmin(dis_split, 1)[0] colors = ['r', 'g', 'b', 'y'] fig = plt.figure() ax = fig.add_subplot(111, projection='3d') for i in range(self.k): idx = np.where(labels == i)[0] # 找到同一类的点的下标 datas = self.datas[idx, :] ax.scatter(datas[:, 0], datas[:, 1], datas[:, 2], c=colors[i])
def run(self, prophetPop=None): # prophetPop为先知种群(即包含先验知识的种群) # ==========================初始化配置=========================== population = self.population self.initialization() # 初始化算法类的一些动态参数 pushStage = True # 一开始是push stage rk = 1.0 # 论文中的rk,k的含义在论文中是代数,这里保留名称不作变化,下同 epsilon_k = 0 # 论文中的𝜀(k) epsilon_0 = 0 # 论文中的𝜀(0) idealPoints = [] # 存储历代的理想点的列表 nadirPoints = [] # 存储历代的反理想点的列表 delta = np.array([1e-6] * self.problem.M) # 论文中为了避免分母为0而设的delta self.Tc *= self.MAXGEN self.LastLGen = min(self.LastLGen, self.MAXGEN) # ===========================准备进化============================ uniformPoint, NIND = ea.crtup(self.problem.M, population.sizes) # 生成在单位目标维度上均匀分布的参考点集 population.initChrom(NIND) # 初始化种群染色体矩阵,此时种群规模将调整为uniformPoint点集的大小,initChrom函数会把种群规模给重置 # 插入先验知识(注意:这里不会对先知种群prophetPop的合法性进行检查) if prophetPop is not None: population = (prophetPop + population)[:NIND] # 插入先知种群 self.call_aimFunc(population) # 计算种群的目标函数值 # 确定邻域大小 if self.neighborSize is None: self.neighborSize = population.sizes // 10 self.neighborSize = max(self.neighborSize, 2) # 确保不小于2 # 生成由所有邻居索引组成的矩阵 neighborIdx = np.argsort(ea.cdist(uniformPoint, uniformPoint), axis=1, kind='mergesort')[:, :self.neighborSize] # 计算理想点 idealPoint = ea.crtidp(population.ObjV, maxormins=self.problem.maxormins) # 创建全局存档 globalNDSet = self.updateNDSet(population) # ===========================开始进化============================ while not self.terminated(population): idealPoints.append(idealPoint) nadirPoints.append(ea.crtidp(population.ObjV, maxormins=self.problem.maxormins, reverse=True)) # 更新epsilon_k if self.currentGen < self.Tc: # 更新rk if self.currentGen >= self.LastLGen: past_gen = self.currentGen - self.LastLGen rk = np.max( [np.abs((idealPoints[-1] - idealPoints[past_gen]) / np.max([idealPoints[past_gen], delta], 0)), np.abs((nadirPoints[-1] - nadirPoints[past_gen]) / np.max([nadirPoints[past_gen], delta], 0))]) violation, count = ea.mergecv( population.CV if population.CV is not None else np.zeros((population.sizes, 1)), return_count=True) if rk <= self.varient_epsilon and pushStage: epsilon_0 = np.max(violation) epsilon_k = epsilon_0 pushStage = False if not pushStage: rf = count / population.sizes if rf < self.alpha: epsilon_k *= (1 - self.tao) else: epsilon_k = (1 - self.currentGen / self.Tc) ** self.cp * epsilon_0 else: epsilon_k = 0 # 分开push stage和pull stage进行进化 select_rands = np.random.rand(population.sizes) Masks = np.random.rand(population.sizes, population.Lind) < self.Cr if pushStage: for i in range(population.sizes): # 产生后代 offspring, indices, idealPoint = self.create_offspring(population, population.Chrom[[i], :], select_rands[i], Masks[i], neighborIdx[i, :], idealPoint) # 重插入 self.push_stage_reinsertion(indices, population, offspring, idealPoint, uniformPoint) # 重插入更新种群个体 else: for i in range(population.sizes): # 产生后代 offspring, indices, idealPoint = self.create_offspring(population, population.Chrom[[i], :], select_rands[i], Masks[i], neighborIdx[i, :], idealPoint) # 重插入 self.pull_stage_reinsertion(indices, population, offspring, idealPoint, uniformPoint, epsilon_k) # 完成当代的进化后,更新全局存档 globalNDSet = self.updateNDSet(population, globalNDSet) return self.finishing(population, globalNDSet) # 调用finishing完成后续工作并返回结果