美文网首页
DEAP1.2.2(七) 约束操作

DEAP1.2.2(七) 约束操作

作者: B_Selmy | 来源:发表于2018-09-07 16:30 被阅读0次

    (七) 约束操作
    演化算法通常情况下是无约束的,在这部分中,我们提出了一些方法去约束你的进化算法,这个教程是基于Coello[Coello 2002]的文章展开的。

    1. Penalty Function
      罚函数是最基本的个体约束方法,当它们处于一个特定区间时,这些个体不可以被计算适应值或者在某些问题中会禁止它们的使用。罚函数根据约束变化的数量对这些个体给出了适应度的缺陷。例如,在一个变化的约束中计算个体适应度,可以对它的适应度指定一个期待的值。这个被指定的值可以是常数或者随着有效解的变化而变化。下面的图展示了一个个体属性的适应度函数g(x)(绿色)和一个罚函数h(x)(红色),约束条件为3< x < 7。连续的曲线代表个体真实的适应度


      f(x)
    constraints.png

    上图中,左边的那个在是当变量不服从约束时,使用了常量互补方法h(x)= \ Delta(简单粗暴,直接放入可行域?)。中间的使用欧氏距离与之前的h(x)相加,构成了一个碗形的function,h(x) = delta + sqrt((x-x_{0})^2)。最后一张图则使用了一个平方项来提升“碗”的深度,h(x) = delta + (x-x_{0})^2,x_0指的是可行域的中心。

    在DEAP中,一个罚函数可以被添加到任何适应度函数当中,使用在tools中的DeltaPenalty装饰符就可以实现这个目标。罚函数使用两个强制参数和一个可选参数。第一个参数是一个可以根据用户定义的界限返回有效个体的函数,第二个是无效个体和有效区域间的距离。最后一个参数则默认为0。在下面的例子中,我们将会展示如何获得上图中最右图的效果。

    from math import sin
    import random
    from deap import tools, base, creator
    
    #creating individuals
    IND_LEN = 2 #each individual's length
    #creating maxfit
    creator.create('MaxFit', base.Fitness, weights = (1.0,))
    #creating individual
    creator.create('Individual',list, fitness = creator.MaxFit)
    
    #called toolbox
    toolbox = base.Toolbox()
    #define generating style
    toolbox.register('fltrand', random.uniform, 0, 10)
    #define individual
    toolbox.register('individual',tools.initRepeat, creator.Individual, toolbox.fltrand ,n = IND_LEN)
    
    #define population
    toolbox.register('population', tools.initRepeat, list, toolbox.individual) 
    
    pop = toolbox.population(n = 200)
    
    #define evalute
    def evalFct(individual):
        """Evaluation function for the individual."""
        x = individual[0]
        return (x - 5)**2 * sin(x) * (x/3),
    
    def feasible(individual):
        """Feasibility function for the individual. Returns True if feasible False
        otherwise."""
        if 3 < individual[0] < 7:
            return True
        return False
    
    def distance(individual):
        """A distance function to the feasibility region."""
        return (individual[0] - 5.0)**2
    
    toolbox = base.Toolbox()
    toolbox.register("evaluate", evalFct)
    toolbox.decorate("evaluate", tools.DeltaPenalty(feasible, 7.0, distance))
    
    
    toolbox.register('crossover', tools.cxTwoPoint)
    toolbox.register('mutate', tools.mutFlipBit, indpb = 0.5)
    toolbox.register('select', tools.selTournament, tournsize = 3)
    
    def simpleEA():
        #paramenters
        CXPB = 0.1 #possiblity of crossover
        MUPB = 0.1 #possiblity of mutation
        GEN = 40   #iteration number
        GR_SIZE = 200 #population size
        # generating pop
        #pop = toolbox.population(n = GR_SIZE)
        '''BEGIN!!!'''
        print('Start Evo')
        #calculating original group's fitness
        fitnesses = list(map(toolbox.evaluate, pop))
        for ind, fit in zip(pop, fitnesses):
            ind.fitness.values = fit
        print("  Evaluated %i individuals" % len(pop))    
        
        '''Evolution!!!'''
        for g in range(0, GEN):
            print('--generation %i-- ' %g)
            #select
            offspring = toolbox.select(pop, len(pop))
            offspring = list(map(toolbox.clone, offspring))
            #crossover
            for child1, child2 in zip(offspring[::1], offspring[1::2]):
                if random.random() < CXPB:
                    toolbox.crossover(child1, child2)
                    
                    #delete fitness of those children
                    del child1.fitness.values
                    del child2.fitness.values
            
            #mutation
            for mutant in offspring:
                if random.random() < MUPB:
                    toolbox.mutate(mutant)
                    del mutant.fitness.values
            
            #evaluate those invalid individuals
            invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
            fitnesses = list(map(toolbox.evaluate, invalid_ind))
            for ind, fit in zip(invalid_ind, fitnesses):
               ind.fitness.values = fit
            print('Evaluated %i individuals' %len(invalid_ind))
             
            #refresh the group by offsprings
            pop[:] = offspring
            
            #gather all fitness in one list
    
            fits = [ind.fitness.values[0] for ind in pop] 
                   
            length = len(pop)
            mean = sum(fits) / length
            sum2 = sum(x*x for x in fits)
            std = abs(sum2 / length - mean**2)**0.5
            
            print("  Min %s" % min(fits))
            print("  Max %s" % max(fits))
            print("  Avg %s" % mean)
            print("  Std %s" % std)
        
        print("-- End of (successful) evolution --")
        
        best_ind = tools.selBest(pop, 1)[0]
        print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values))
    
    
    if __name__ == "__main__":
        simpleEA()
    

    上面是一个简单地使用罚函数限制x范围的方法,从结果中可以看出,无论如何计算,x均不会超出7。罚函数在解决有约束规划问题上可以有很好的效果,它根据不同的惩罚规则将越界的数据点的适应度进行修正。

    相关文章

      网友评论

          本文标题:DEAP1.2.2(七) 约束操作

          本文链接:https://www.haomeiwen.com/subject/vcucgftx.html