Пример #1
0
 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函数会把种群规模给重置
     self.call_aimFunc(population) # 计算种群的目标函数值
     # 插入先验知识(注意:这里不会对先知种群prophetPop的合法性进行检查,故应确保prophetPop是一个种群类且拥有合法的Chrom、ObjV、Phen等属性)
     if prophetPop is not None:
         population = (prophetPop + population)[:NIND] # 插入先知种群
     # 确定邻域大小
     if self.neighborSize is None:
         self.neighborSize = population.sizes
     self.neighborSize = max(self.neighborSize, 2) # 确保不小于2
     # 生成由所有邻居索引组成的矩阵
     neighborIdx = np.argsort(cdist(uniformPoint, uniformPoint), axis=1, kind='mergesort')[:, :self.neighborSize]
     # 计算理想点
     idealPoint = ea.crtidp(population.ObjV, population.CV, self.problem.maxormins)
     # 创建全局存档
     if self.MAXSIZE is None:
         self.MAXSIZE = 10 * population.sizes # 默认为10倍的种群个体数
     [levels, criLevel] = ea.ndsortDED(population.ObjV, NIND, None, population.CV, self.problem.maxormins) # 对NIND个个体进行非支配分层
     globalNDSet = population[np.where(levels == 1)[0]] # 创建全局存档,该全局存档贯穿进化始终,随着进化不断更新
     if globalNDSet.CV is not None: # CV不为None说明有设置约束条件
         globalNDSet = globalNDSet[np.where(np.all(globalNDSet.CV <= 0, 1))[0]] # 排除非可行解
     #===========================开始进化============================
     while self.terminated(population) == False:
         select_rands = np.random.rand(population.sizes) # 生成一组随机数
         for i in range(population.sizes):
             indices = neighborIdx[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 = ea.Population(population.Encoding, population.Field, 1) # 实例化一个种群对象用于存储进化的后代(这里只进化生成一个后代)
             # 对选出的个体进行进化操作
             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)
         # 完成当代的进化后,更新全局存档
         globalNDSet = population + globalNDSet # 将population与全局归档集合并
         [levels, criLevel] = ea.ndsortDED(globalNDSet.ObjV, None, None, globalNDSet.CV, self.problem.maxormins) # 非支配排序
         globalNDSet = globalNDSet[np.where(levels == 1)[0]]
         if globalNDSet.CV is not None: # CV不为None说明有设置约束条件
             globalNDSet = globalNDSet[np.where(np.all(globalNDSet.CV <= 0, 1))[0]] # 排除非可行解
         if globalNDSet.sizes > self.MAXSIZE:
             globalNDSet = globalNDSet[ea.rps(globalNDSet.sizes, self.MAXSIZE)] # 采用rps随机排列选择,控制全局存档的大小
     self.passTime += time.time() - self.timeSlot # 更新用时记录
     #=========================绘图及输出结果=========================
     if self.drawing != 0:
         ea.moeaplot(globalNDSet.ObjV, 'Pareto Front', saveFlag = True, gridFlag = True)
     # 返回帕累托最优集
     return globalNDSet
Пример #2
0
    def finishing(self, population):
        """
        进化完成后调用的函数
        """

        # 得到非支配种群
        [levels,
         criLevel] = ea.ndsortDED(self.problem.maxormins * population.ObjV,
                                  None, 1, population.CV)  # 非支配分层
        NDSet = population[np.where(levels == 1)[0]]  # 只保留种群中的非支配个体,形成一个非支配种群
        if NDSet.CV is not None:  # CV不为None说明有设置约束条件
            NDSet = NDSet[np.where(np.all(NDSet.CV <= 0, 1))[0]]  # 最后要彻底排除非可行解
        self.passTime += time.time() - self.timeSlot  # 更新用时记录
        # 绘图
        if self.drawing != 0:
            if NDSet.ObjV.shape[1] == 2 or NDSet.ObjV.shape[1] == 3:
                ea.moeaplot(NDSet.ObjV,
                            'Pareto Front',
                            saveFlag=True,
                            gridFlag=True)
            else:
                ea.moeaplot(NDSet.ObjV,
                            'Value Path',
                            saveFlag=True,
                            gridFlag=False)
        # 返回帕累托最优集
        return NDSet
Пример #3
0
def updateNDSet(population, maxormins, MAXSIZE, NDSet=None):
    """
描述:
    用于计算种群个体的适应度及更新全局非支配种群。
输入参数:
    population : Population - 种群对象。
    
    maxormins  : list - 优化目标的最大最小化标记列表。
    
    MAXSIZE    : int - 示全局非支配个体的最大数目。
    
    NDSet      : Population - (可选参数)全局非支配个体,
                              若缺省或为None时,NDSet为所传入种群的非支配个体组成的种群。

输出参数:
    NDSet      : Population - (可选参数)全局非支配种群。
    
    种群适应度FitnV已经在函数中进行更新,因此这该参数不用返回。
    """

    ObjV = maxormins * population.ObjV  # 对目标进行统一最小化
    [levels, criLevel] = ea.ndsortDED(ObjV, None, 1,
                                      population.CV)  # 只对个体划分出第一层
    [CombinObjV, weight] = ea.awGA(ObjV, population.CV)  # 计算适应性权重以及多目标的加权单目标
    population.FitnV = (np.max(CombinObjV) - CombinObjV + 0.5) / (
        np.max(CombinObjV) - np.min(CombinObjV) + 0.5)  # 计算种群适应度
    # 更新NDSet
    if NDSet is None:
        return population[np.where(levels == 1)[0]]
    else:
        tempPop = population[np.where(
            levels == 1)[0]] + NDSet  # 将种群可行个体与NDSet合并
        [levels, criLevel] = ea.ndsortDED(maxormins * tempPop.ObjV, None, 1,
                                          tempPop.CV)  # 只对个体划分出第一层
        liveIdx = np.where(levels == 1)[0]  # 选择非支配个体
        NDSet = tempPop[liveIdx]
        # 对种群中被NDSet支配的个体进行惩罚
        punishFlag = np.zeros(population.sizes)
        punishFlag[np.where(liveIdx < population.sizes)[0]] == 1
        population.FitnV[np.where(punishFlag == 0)[0]] *= 0.5
        if len(liveIdx) > MAXSIZE:  # 若要保留下来的NDSet个体数大于MAXSIZE,则根据拥挤距离进行筛选
            dis = ea.crowdis(NDSet.ObjV, levels[liveIdx])  # 计算拥挤距离
            NDSet = NDSet[ea.selecting('dup',
                                       np.array([dis]).T, MAXSIZE)]  # 进行筛选
        return NDSet
Пример #4
0
 def calReferObjV(self): # 设定目标数参考值(本问题目标函数参考值设定为理论最优值,即“真实帕累托前沿点”)
     Num = 10000 # 生成10000个参考点
     temp = np.linspace(0, 1, Num)
     ObjV1 = 1 + np.cos(temp * np.pi * 10) / 5 - temp
     ObjV2 = temp
     referenceObjV = np.array([ObjV1, ObjV2]).T
     [levels, criLevel] = ea.ndsortDED(referenceObjV, None, 1)
     referenceObjV = referenceObjV[np.where(levels == 1)[0], :]
     return referenceObjV
Пример #5
0
    def updateNDSet(self, population, globalNDSet=None):

        """
        描述:
            更新globalNDSet。
        """

        if globalNDSet is None:
            globalNDSet = population
        else:
            globalNDSet = population + globalNDSet  # 将population与全局归档集合并
        if globalNDSet.CV is not None:  # CV不为None说明有设置约束条件
            globalNDSet = globalNDSet[np.where(np.all(globalNDSet.CV <= 0, 1))[0]]  # 排除非可行解
        if globalNDSet.sizes != 0:
            [levels, criLevel] = ea.ndsortDED(globalNDSet.ObjV, None, None, globalNDSet.CV,
                                              self.problem.maxormins)  # 非支配排序
            globalNDSet = globalNDSet[np.where(levels == 1)[0]]
        if globalNDSet.sizes > self.MAXSIZE:
            globalNDSet = globalNDSet[ea.rps(globalNDSet.sizes, self.MAXSIZE)]  # 采用rps随机排列选择,控制全局存档的大小
        return globalNDSet
Пример #6
0
    def logging(self, pop):
        """
        描述:
            用于在进化过程中记录日志。该函数在stat()函数里面被调用。
            如果需要在日志中记录其他数据,需要在自定义算法模板类中重写该函数。

        输入参数:
            pop : class <Population> - 种群对象。

        输出参数:
            无输出参数。

        """

        self.passTime += time.time() - self.timeSlot  # 更新用时记录,不计算logging的耗时
        if len(self.log['gen']) == 0:  # 初始化log的各个键值
            if self.problem.ReferObjV is not None:
                self.log['gd'] = []
                self.log['igd'] = []
            self.log['hv'] = []
            self.log['spacing'] = []
        self.log['gen'].append(self.currentGen)
        self.log['eval'].append(self.evalsNum)  # 记录评价次数
        [levels, _] = ea.ndsortDED(pop.ObjV,
                                   needLevel=1,
                                   CV=pop.CV,
                                   maxormins=self.problem.maxormins)  # 非支配分层
        NDSet = pop[np.where(levels == 1)[0]]  # 只保留种群中的非支配个体,形成一个非支配种群
        if self.problem.ReferObjV is not None:
            self.log['gd'].append(
                ea.indicator.GD(NDSet.ObjV, self.problem.ReferObjV))  # 计算GD指标
            self.log['igd'].append(
                ea.indicator.IGD(NDSet.ObjV,
                                 self.problem.ReferObjV))  # 计算IGD指标
            self.log['hv'].append(
                ea.indicator.HV(NDSet.ObjV, self.problem.ReferObjV))  # 计算HV指标
        else:
            self.log['hv'].append(ea.indicator.HV(NDSet.ObjV))  # 计算HV指标
        self.log['spacing'].append(ea.indicator.Spacing(
            NDSet.ObjV))  # 计算Spacing指标
        self.timeSlot = time.time()  # 更新时间戳
Пример #7
0
    def finishing(self, pop, globalNDSet=None):
        """
        描述:
            进化完成后调用的函数。

        输入参数:
            pop : class <Population> - 种群对象。
            
            globalNDSet : class <Population> - (可选参数)全局存档。

        输出参数:
            [NDSet, pop],其中pop为种群类型;NDSet的类型与pop的一致。

        """
        if globalNDSet is None:
            # 得到非支配种群
            [levels,
             _] = ea.ndsortDED(pop.ObjV,
                               needLevel=1,
                               CV=pop.CV,
                               maxormins=self.problem.maxormins)  # 非支配分层
            NDSet = pop[np.where(levels == 1)[0]]  # 只保留种群中的非支配个体,形成一个非支配种群
            if NDSet.CV is not None:  # CV不为None说明有设置约束条件
                NDSet = NDSet[np.where(np.all(NDSet.CV <= 0,
                                              1))[0]]  # 最后要彻底排除非可行解
        else:
            NDSet = globalNDSet
        if self.logTras != 0 and NDSet.sizes != 0 and (
                len(self.log['gen']) == 0
                or self.log['gen'][-1] != self.currentGen):  # 补充记录日志和输出
            self.logging(NDSet)
            if self.verbose:
                self.display()
        self.passTime += time.time(
        ) - self.timeSlot  # 更新用时记录,因为已经要结束,因此不用再更新时间戳
        self.draw(NDSet, EndFlag=True)  # 显示最终结果图
        if self.plotter is not None:
            self.plotter.show()
        # 返回帕累托最优个体以及最后一代种群
        return [NDSet, pop]
    def updateNDSet(self, population, globalNDSet=None):

        """
        描述:
            更新globalNDSet。
            
        """

        if globalNDSet is None:
            globalNDSet = population
        else:
            globalNDSet = population + globalNDSet  # 将population与全局归档集合并
        if globalNDSet.CV is not None:  # CV不为None说明有设置约束条件
            globalNDSet = globalNDSet[np.where(np.all(globalNDSet.CV <= 0, 1))[0]]  # 排除非可行解
        if globalNDSet.sizes != 0:
            [levels, criLevel] = ea.ndsortDED(globalNDSet.ObjV, None, None, globalNDSet.CV,
                                              self.problem.maxormins)  # 非支配排序
            globalNDSet = globalNDSet[np.where(levels == 1)[0]]
        if globalNDSet.sizes > self.MAXSIZE:
            dis = ea.crowdis(globalNDSet.ObjV, np.ones(globalNDSet.sizes))  # 计算拥挤距离
            globalNDSet = globalNDSet[np.argsort(-dis)[:self.MAXSIZE]]  # 根据拥挤距离选择符合个数限制的解保留在存档中
        return globalNDSet