【问题标题】:DEAP: make fitness of an individual depend on entire populationDEAP:使个人的适应度取决于整个人口
【发布时间】:2020-03-03 20:40:03
【问题描述】:

要实施共享策略(描述为here),适应度函数需要依赖于群体中的其他个体。

def shared_fitness(individual, population):
    #compute
    return result

如何在工具箱中注册此函数以供遗传算法使用?为了做到这一点:

toolbox = base.Toolbox()
toolbox.register('evaluate', shared_fitness, population=pop)

我首先必须定义一个人口@9​​87654324@。但是在算法时期,我希望用当前人口而不是初始人口来评估适应度。

如何实现依赖于群体中其他个体的适应度函数?

【问题讨论】:

    标签: python mathematical-optimization genetic-algorithm deap


    【解决方案1】:

    请注意,在 99% 的情况下,我们的人口将是某种列表(或其他容器对象)。当我们将这些对象传递给函数时,我们传递的是指针而不是值。这意味着我们对总体所做的任何更改都会影响评估函数,该函数包含一个指向总体的指针。
    对于健全性测试,我使用了N-Queens example from DEAP 并对评估函数进行了小改动 - 只是为了打印当前排名前 5 的人口成员。当您运行它时,您可以看到输出发生了变化,即使评估函数接收到“初始总体”作为输入。

    如果由于某种原因您的人口是按值而不是指针传递的,那么始终包含当前人口的全局变量可能会有所帮助,尽管这当然不太可取。

    #    This file is part of DEAP.
    #
    #    DEAP is free software: you can redistribute it and/or modify
    #    it under the terms of the GNU Lesser General Public License as
    #    published by the Free Software Foundation, either version 3 of
    #    the License, or (at your option) any later version.
    #
    #    DEAP is distributed in the hope that it will be useful,
    #    but WITHOUT ANY WARRANTY; without even the implied warranty of
    #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    #    GNU Lesser General Public License for more details.
    #
    #    You should have received a copy of the GNU Lesser General Public
    #    License along with DEAP. If not, see <http://www.gnu.org/licenses/>.
    
    import random
    
    import numpy
    
    from deap import algorithms
    from deap import base
    from deap import creator
    from deap import tools
    
    # Problem parameter
    NB_QUEENS = 20
    INDIV_COUNT = 0
    
    
    def evalNQueens(individual, population):
        global INDIV_COUNT
        """Evaluation function for the n-queens problem.
        The problem is to determine a configuration of n queens
        on a nxn chessboard such that no queen can be taken by
        one another. In this version, each queens is assigned
        to one column, and only one queen can be on each line.
        The evaluation function therefore only counts the number
        of conflicts along the diagonals.
        """
        size = len(individual)
        # Count the number of conflicts with other queens.
        # The conflicts can only be diagonal, count on each diagonal line
        left_diagonal = [0] * (2 * size - 1)
        right_diagonal = [0] * (2 * size - 1)
    
        # Sum the number of queens on each diagonal:
        for i in range(size):
            left_diagonal[i + individual[i]] += 1
            right_diagonal[size - 1 - i + individual[i]] += 1
    
        # Count the number of conflicts on each diagonal
        sum_ = 0
        for i in range(2 * size - 1):
            if left_diagonal[i] > 1:
                sum_ += left_diagonal[i] - 1
            if right_diagonal[i] > 1:
                sum_ += right_diagonal[i] - 1
    
        if INDIV_COUNT % len(population) == 0:
            print(f'top 5 individuals @ generation {int(INDIV_COUNT / 300)}: {population[:5]}')
        INDIV_COUNT += 1
    
        return sum_,
    
    
    creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
    creator.create("Individual", list, fitness=creator.FitnessMin)
    
    # Since there is only one queen per line,
    # individual are represented by a permutation
    toolbox = base.Toolbox()
    toolbox.register("permutation", random.sample, range(NB_QUEENS), NB_QUEENS)
    
    # Structure initializers
    # An individual is a list that represents the position of each queen.
    # Only the line is stored, the column is the index of the number in the list.
    toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.permutation)
    toolbox.register("population", tools.initRepeat, list, toolbox.individual)
    
    toolbox.register("mate", tools.cxPartialyMatched)
    toolbox.register("mutate", tools.mutShuffleIndexes, indpb=2.0 / NB_QUEENS)
    toolbox.register("select", tools.selTournament, tournsize=3)
    
    
    def main(seed=0):
        random.seed(seed)
    
        pop = toolbox.population(n=300)
        toolbox.register("evaluate", evalNQueens, population=pop)
        hof = tools.HallOfFame(1)
        stats = tools.Statistics(lambda ind: ind.fitness.values)
        stats.register("Avg", numpy.mean)
        stats.register("Std", numpy.std)
        stats.register("Min", numpy.min)
        stats.register("Max", numpy.max)
    
        algorithms.eaSimple(pop, toolbox, cxpb=0.5, mutpb=0.2, ngen=100, stats=stats,
                            halloffame=hof, verbose=True)
    
        return pop, stats, hof
    
    
    if __name__ == "__main__":
        main()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多