DEAP: сделать физическую форму человека зависимым от всего населения - PullRequest
0 голосов
/ 07 ноября 2019

Для реализации стратегии совместного использования (описанной здесь ), функция пригодности должна зависеть от других людей в популяции.

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

Как зарегистрировать эту функцию в наборе инструментов, который будет использоваться генетическим алгоритмом? Чтобы сделать это:

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

Сначала я должен определить популяцию pop. Но в эпоху алгоритмов я хочу, чтобы пригодность оценивалась с текущей популяцией, а не с начальной.

Как я могу реализовать фитнес-функцию, которая зависит от других людей в популяции?

1 Ответ

1 голос
/ 08 ноября 2019

обратите внимание, что в 99% случаев наше население будет каким-то списком (или другим контейнерным объектом). Когда мы передаем эти объекты в функции, мы передаем указатель, а не значения. Это означает, что любые изменения, которые мы вносим в совокупность, будут влиять на функцию оценки, которая содержит указатель на совокупность.
Для проверки работоспособности я взял пример N-Queens из 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()
...