This is a memo on how to use deap. Here, the memo is described using deap \ examples \ onemax_numpy.py as an example.
deap https://deap.readthedocs.io/en/master/
deap github https://github.com/DEAP/deap
OneMax? This is a problem that maximizes the sum of a sequence of 0s and 1s, such as [1, 1, 1, 1, 0, 0, 0, 1, 1, 0]. ⇒ The solution to be obtained is [1, 1, 1, 1, 1, 1, 1, 1, 1, 1].
In the code below, the problem is a sequence of length 100.
Paste the code with notes.
my_onemax_numpy.py
import random
import numpy
from deap import algorithms
from deap import base
from deap import creator
from deap import tools
# parameter
n_gene = 100            #Number of genes per individual
n_individuals = 300     #Number of individuals per generation
n_generations = 1000    #Number of generations
p_cxpb = 0.5            #Crossover rate (number of crossing individuals)
p_mutpb = 0.2           #Mutation rate (number of individuals to mutate)
p_mutate = 0.05         #Mutation probability (gene mutation rate)
n_tournsize = 3         #Tournament size
def evalOneMax(individual):
    """Evaluation function onemax"""
    return sum(individual),
def init_creator():
    """Set the direction of the objective function"""
    #One objective function to evaluate, maximizing individual fitness
    creator.create("FitnessMax", base.Fitness, weights=(1.0,))
    # numpy.Inherit the ndarray class
    # fitness=creator.Create an Individual class with a member variable called FitnessMax
    creator.create("Individual", numpy.ndarray, fitness=creator.FitnessMax)
    return creator
def my_gene_generator(min, max):
    """Gene generation function"""
    return random.randint(min, max)
def init_generator(creator):
    """Setting of gene, individual, and generation generation methods"""
    toolbox = base.Toolbox()
    #Definition of the function that produces the gene
    toolbox.register("attr_bool", my_gene_generator, 0, 1)
    #Definition of a function to generate an individual
    toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_bool, n_gene)
    #Definition of the function that generates the generation
    toolbox.register("population", tools.initRepeat, list, toolbox.individual)
    return toolbox
def operator_registration(toolbox):
    """Evaluation function / strategy setting"""
    toolbox.register("evaluate", evalOneMax)                                # evaluate =Evaluation function
    toolbox.register("mate", tools.cxTwoPoint)                              # mate =Two-point crossing
    toolbox.register("mutate", tools.mutFlipBit, indpb=p_mutate)            # mutate =bit inversion
    toolbox.register("select", tools.selTournament, tournsize=n_tournsize)  # select = tournament(3)
def stats_register():
    """State definition settings"""
    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)
    return stats
def get_cxpoint(size):
    """2 point setting for 2 point crossing"""
    cxpoint1 = random.randint(1, size)
    cxpoint2 = random.randint(1, size - 1)
    if cxpoint2 >= cxpoint1:
        cxpoint2 += 1
    else: # Swap the two cx points
        cxpoint1, cxpoint2 = cxpoint2, cxpoint1
    return cxpoint1, cxpoint2
def cxTwoPointCopy(ind1, ind2):
    """2-point crossover for numpy"""
    size = min(len(ind1), len(ind2))
    cxpoint1, cxpoint2 = get_cxpoint(size)
    
    ind1[cxpoint1:cxpoint2], ind2[cxpoint1:cxpoint2] \
        = ind2[cxpoint1:cxpoint2].copy(), ind1[cxpoint1:cxpoint2].copy()
        
    return ind1, ind2
def set_seed(seed=42):
    random.seed(seed)
def main(toolbox):
    set_seed()
    #Generation of early generation
    pop = toolbox.population(n=n_individuals)
    #elite for numpy=1 Strategy
    hof = tools.HallOfFame(1, similar=numpy.array_equal)
    #stats definition
    stats = stats_register()
    # main loop
    algorithms.eaSimple(pop, toolbox, cxpb=p_cxpb, mutpb=p_mutpb, ngen=n_generations, stats=stats,
                        halloffame=hof)
    #Display of best individuals
    best_ind = tools.selBest(pop, 1)[0]
    print("Best individual is \n Eval:\n  %s, \n Gene:\n  %s" % (best_ind.fitness.values, best_ind))
    return pop, stats, hof
if __name__ == "__main__":
    #Set the direction of the objective function
    creator = init_creator()
    #Setting of gene, individual, and generation generation methods
    toolbox = init_generator(creator)
    #Evolution method setting
    operator_registration(toolbox)
    #Main routine
    main(toolbox)
Execution result
gen     nevals  avg     std     min     max
0       300     49.88   4.82344 36      64
1       172     54.27   3.60792 45      68
2       181     57.24   3.32    47      68 
・ ・ ・
987     183     98.9767 2.3642  89      100
988     171     99.1467 2.02941 89      100
989     192     99.0567 2.26424 90      100
990     176     99.1167 2.12047 88      100
991     183     99.2733 1.94901 90      100
992     164     98.97   2.30704 90      100
993     178     99.03   2.0581  90      100
994     188     98.9767 2.24264 89      100
995     174     98.95   2.3211  86      100
996     177     98.83   2.33833 90      100
997     186     99.0367 2.15453 89      100
998     177     98.9833 2.16095 91      100
999     175     98.9933 2.25683 90      100
1000    181     98.8967 2.23443 89      100
Best individual is
 Eval:
  (100.0,),
 Gene:
  [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
① I don't know how to determine the direction (maximization / minimization) of the evaluation function. -A negative weight is given when minimizing fitness, and a positive weight is given when maximizing fitness (any value is acceptable). ・ Weight must be tuple
creator.py
#One objective function to evaluate, maximizing individual fitness
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
#There are two objective functions to evaluate, the first is to minimize fitness and the second is to maximize.
creator.create("FitnessMulti", base.Fitness, weights=(-1.0, 1.0))
② How do you generate and evaluate genes? -Register the generated function in the toolbox Here, a function called my_gene_generator that randomly generates 0 or 1 is used. Register with the name "attr_bool" in the toolbox
gene_generator.py
def my_gene_generator(min, max):
    """Gene generation function"""
    return random.randint(min, max)
def init_generator(creator):
    """Setting of gene, individual, and generation generation methods"""
    toolbox = base.Toolbox()
    #Definition of the function that produces the gene
    toolbox.register("attr_bool", my_gene_generator, 0, 1)
・ Register the evaluation function in the toolbox Here, a function called evalOneMax Register with the name "evaluate" in the toolbox
gene_eval.py
def evalOneMax(individual):
    """Evaluation function onemax"""
    return sum(individual),
def operator_registration(toolbox):
    """Evaluation function / strategy setting"""
    toolbox.register("evaluate", evalOneMax) # evaluate =Evaluation function
③ Where is the main loop? ・ Here
algorithms.eaSimple(pop, toolbox, cxpb=p_cxpb, mutpb=p_mutpb, ngen=n_generations, stats=stats, halloffame=hof)