def eaNigel(population, toolbox, ngen, goal=0, stats=None, halloffame=None, history=None, verbose=__debug__): """This algorithm is a simple evolutionary algorithm. :param population: A list of individuals. :param toolbox: A :class:`~deap.base.Toolbox` that contains the evolution operators. :param ngen: The number of generation. :param goal: Stop looking if the best score in the halloffame is less than this value :param stats: A :class:`~deap.tools.Statistics` object that is updated inplace, optional. :param halloffame: A :class:`~deap.tools.HallOfFame` object that will contain the best individuals, optional. :param verbose: Whether or not to log the statistics. :returns: The final population :returns: A class:`~deap.tools.Logbook` with the statistics of the evolution """ logbook = Logbook() logbook.header = ['gen', 'nevals'] + (stats.fields if stats else []) # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in population if not ind.fitness.valid] fitnesses = toolbox.map(toolbox.evaluate, invalid_ind) for ind, fit in zip(invalid_ind, fitnesses): ind.fitness.values = fit if halloffame is not None: halloffame.update(population) if history is not None: history.update(population) record = stats.compile(population) if stats else {} logbook.record(gen=0, nevals=len(invalid_ind), **record) # Begin the generational process gen = 0 while halloffame[0].fitness.values[0] > goal and gen < ngen: # Select the next generation individuals offspring = toolbox.procreate(population) # Replace the current population by the offspring population[:] = offspring # Update the hall of fame with the generated individuals if halloffame is not None: halloffame.update(population) # population[-1] = halloffame[0] # always include the best ever in the offspring if history is not None: history.update(population) # Append the current generation statistics to the logbook record = stats.compile(population) if stats else {} gen += 1 logbook.record(gen=gen, nevals=len(invalid_ind), **record) print(logbook.stream) return population, logbook
def test_consecutive_callback(): callback = ConsecutiveStopping(generations=3) assert check_callback(callback) == [callback] logbook = Logbook() logbook.record(fitness=0.9) logbook.record(fitness=0.8) logbook.record(fitness=0.83) # Not enough records to decide assert not callback(logbook=logbook) logbook.record(fitness=0.85) logbook.record(fitness=0.81) # Current record is better that at least of of the previous 3 records assert not callback(logbook=logbook) logbook.record(fitness=0.8) # Current record is worst that the 3 previous ones assert callback(logbook=logbook) assert callback(logbook=logbook, record={"fitness": 0.8}) with pytest.raises(Exception) as excinfo: callback() assert str(excinfo.value) == "logbook parameter must be provided"
def test_delta_callback(): callback = DeltaThreshold(0.001) assert check_callback(callback) == [callback] logbook = Logbook() logbook.record(fitness=0.9) # Not enough records to decide assert not callback(logbook=logbook) logbook.record(fitness=0.923) logbook.record(fitness=0.914) # Abs difference is not bigger than the threshold assert not callback(logbook=logbook) logbook.record(fitness=0.9141) # Abs difference is bigger than the threshold assert callback(logbook=logbook) assert callback(logbook=logbook, record={"fitness": 0.9141}) with pytest.raises(Exception) as excinfo: callback() assert str(excinfo.value) == "logbook parameter must be provided"
def test_threshold_callback(): callback = ThresholdStopping(threshold=0.8) assert check_callback(callback) == [callback] assert not callback(record={"fitness": 0.5}) assert callback(record={"fitness": 0.9}) # test callback using LogBook instead of a record logbook = Logbook() logbook.record(fitness=0.93) logbook.record(fitness=0.4) assert not callback(logbook=logbook) logbook.record(fitness=0.95) assert callback(logbook=logbook) with pytest.raises(Exception) as excinfo: callback() assert (str(excinfo.value) == "At least one of record or logbook parameters must be provided")
class Population(list): """ A collection of individuals """ INDIVIDUAL_CLASS = Individual POPULATION_SIZE = 100 CLONE_BEST = 5 MAX_MATE_ATTEMPTS = 10 MATE_MUTATE_CLONE = (80, 18, 2) def __init__(self, bset): self.bset = bset pop = [Population.INDIVIDUAL_CLASS(self.bset) for _ in range(self.POPULATION_SIZE)] super(Population, self).__init__(pop) self.stats = Statistics(lambda ind: ind.fitness.values) self.stats.register("avg", np.mean) self.stats.register("std", np.std) self.stats.register("min", np.min) self.stats.register("max", np.max) self.logbook = Logbook() self.logbook.header = ['gen'] + self.stats.fields self.hof = HallOfFame(1) self.generation = 0 # do an initial evaluation for ind in self: ind.fitness.values = ind.evaluate() def select(self, k): """Probablistic select *k* individuals among the input *individuals*. The list returned contains references to the input *individuals*. :param k: The number of individuals to select. :returns: A list containing k individuals. The individuals returned are randomly selected from individuals according to their fitness such that the more fit the individual the more likely that individual will be chosen. Less fit individuals are less likely, but still possibly, selected. """ # adjusted pop is a list of tuples (adjusted fitness, individual) adjusted_pop = [(1.0 / (1.0 + i.fitness.values[0]), i) for i in self] # normalised_pop is a list of tuples (float, individual) where the float indicates # a 'share' of 1.0 that the individual deserves based on it's fitness relative to # the other individuals. It is sorted so the best chances are at the front of the list. denom = sum([fit for fit, ind in adjusted_pop]) normalised_pop = [(fit / denom, ind) for fit, ind in adjusted_pop] normalised_pop = sorted(normalised_pop, key=lambda i: i[0], reverse=True) # randomly select with a fitness bias # FIXME: surely this can be optimized? selected = [] for x in range(k): rand = random.random() accumulator = 0.0 for share, ind in normalised_pop: accumulator += share if rand <= accumulator: selected.append(ind) break if len(selected) == 1: return selected[0] else: return selected def evolve(self): """ Evolve this population by one generation """ self.logbook.record(gen=self.generation, **self.stats.compile(self)) self.hof.update(self) print(self.logbook.stream) # the best x of the population are cloned directly into the next generation offspring = self[:self.CLONE_BEST] # rest of the population clone, mate, or mutate at random for idx in range(len(self) - self.CLONE_BEST): # decide how to alter this individual rand = random.randint(0,100) for _ in range(0, self.MAX_MATE_ATTEMPTS): try: if rand < self.MATE_MUTATE_CLONE[0]: # MATE/CROSSOVER receiver, contributor = self.select(2) child = receiver.clone() child.mate(contributor) break elif rand < (self.MATE_MUTATE_CLONE[0] + self.MATE_MUTATE_CLONE[1]): # MUTATE ind = self.select(1) child = ind.clone() child.mutate() break else: child = self.select(1).clone() break except BirthError: continue # generate new blood when reproduction fails so badly else: child = Population.INDIVIDUAL_CLASS(self.bset) offspring.append(child) self[:] = offspring self.generation += 1 # evaluate every individual and sort for ind in self: if not len(ind.fitness.values): ind.fitness.values = ind.evaluate() self.sort(key=lambda i: i.fitness.values[0])
def eaSimple(population, toolbox, cxpb, mutpb, ngen, stats=None, halloffame=None, verbose=__debug__, pset=None, store=True): """ Parameters ---------- population toolbox cxpb mutpb ngen stats halloffame verbose pset store Returns ------- """ rst = random.getstate() len_pop = len(population) logbook = Logbook() logbook.header = [] + (stats.fields if stats else []) data_all = {} random.setstate(rst) for gen in range(1, ngen + 1): "评价" rst = random.getstate() """score""" invalid_ind = [ind for ind in population if not ind.fitness.valid] fitnesses = toolbox.parallel(iterable=population) for ind, fit, in zip(invalid_ind, fitnesses): ind.fitness.values = fit[0], ind.expr = fit[1] ind.y_dim = fit[2] ind.withdim = fit[3] random.setstate(rst) rst = random.getstate() """elite""" add_ind = [] add_ind1 = toolbox.select_kbest_target_dim(population, K_best=0.05 * len_pop) add_ind += add_ind1 elite_size = len(add_ind) random.setstate(rst) rst = random.getstate() """score""" random.setstate(rst) rst = random.getstate() """record""" if halloffame is not None: halloffame.update(add_ind1) if len(halloffame.items ) > 0 and halloffame.items[-1].fitness.values[0] >= 0.9999: print(halloffame.items[-1]) print(halloffame.items[-1].fitness.values[0]) break random.setstate(rst) rst = random.getstate() """Dynamic output""" record = stats.compile_(population) if stats else {} logbook.record(gen=gen, pop=len(population), **record) if verbose: print(logbook.stream) random.setstate(rst) """crossover, mutate""" offspring = toolbox.select_gs(population, len_pop - elite_size) # Vary the pool of individuals offspring = varAnd(offspring, toolbox, cxpb, mutpb) rst = random.getstate() """re-run""" offspring.extend(add_ind) population[:] = offspring random.setstate(rst) store = Store() store.to_csv(data_all) return population, logbook
def eaSimple(population, toolbox, cxpb, mutpb, ngen, stats=None, halloffame=None, verbose=__debug__, pset=None, store=True): """ Parameters ---------- population toolbox cxpb mutpb ngen stats halloffame verbose pset store Returns ------- """ rst = random.getstate() len_pop = len(population) logbook = Logbook() logbook.header = ['gen', 'pop'] + (stats.fields if stats else []) # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in population if not ind.fitness.valid] # fitnesses = toolbox.map(toolbox.evaluate, invalid_ind) fitnesses = toolbox.parallel(iterable=population) for ind, fit, in zip(invalid_ind, fitnesses): ind.fitness.values = fit[0], ind.expr = fit[1] ind.dim = fit[2] ind.withdim = fit[3] add_ind = toolbox.select_kbest_target_dim(population, K_best=0.1 * len_pop) if halloffame is not None: halloffame.update(add_ind) record = stats.compile(population) if stats else {} logbook.record(gen=0, nevals=len(population), **record) if verbose: print(logbook.stream) data_all = {} # Begin the generational process random.setstate(rst) for gen in range(1, ngen + 1): rst = random.getstate() if store: rst = random.getstate() target_dim = toolbox.select_kbest_target_dim.keywords['dim_type'] subp = functools.partial(sub, subed=pset.rep_name_list, subs=pset.real_name_list) data = { "gen{}_pop{}".format(gen, n): { "gen": gen, "pop": n, "score": i.fitness.values[0], "expr": str(subp(i.expr)), "with_dim": 1 if i.withdim else 0, "dim_is_target_dim": 1 if i.dim in target_dim else 0, "gen_dim": "{}{}".format(gen, 1 if i.withdim else 0), "gen_target_dim": "{}{}".format(gen, 1 if i.dim in target_dim else 0), "socre_dim": i.fitness.values[0] if i.withdim else 0, "socre_target_dim": i.fitness.values[0] if i.dim in target_dim else 0, } for n, i in enumerate(population) if i is not None } data_all.update(data) random.setstate(rst) # select_gs the next generation individuals offspring = toolbox.select_gs(population, len_pop) # Vary the pool of individuals offspring = varAnd(offspring, toolbox, cxpb, mutpb) rst = random.getstate() # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in offspring if not ind.fitness.valid] # fitnesses = toolbox.map(toolbox.evaluate, invalid_ind) # fitnesses = parallelize(n_jobs=3, func=toolbox.evaluate, iterable=invalid_ind, respective=False) fitnesses = toolbox.parallel(iterable=invalid_ind) for ind, fit in zip(invalid_ind, fitnesses): ind.fitness.values = fit[0], ind.expr = fit[1] ind.dim = fit[2] ind.withdim = fit[3] add_ind = toolbox.select_kbest_target_dim(population, K_best=0.1 * len_pop) add_ind2 = toolbox.select_kbest_dimless(population, K_best=0.2 * len_pop) add_ind3 = toolbox.select_kbest(population, K_best=5) offspring += add_ind offspring += add_ind2 offspring += add_ind3 # Update the hall of fame with the generated individuals if halloffame is not None: halloffame.update(add_ind) if len(halloffame.items ) > 0 and halloffame.items[-1].fitness.values[0] >= 0.95: print(halloffame.items[-1]) print(halloffame.items[-1].fitness.values[0]) break # Replace the current population by the offspring population[:] = offspring # Append the current generation statistics to the logbook record = stats.compile(population) if stats else {} logbook.record(gen=gen, nevals=len(population), **record) if verbose: print(logbook.stream) random.setstate(rst) store = Store() store.to_csv(data_all) return population, logbook
def eaMuPlusLambda_hack(population, toolbox, mu, lambda_, cxpb, mutpb, ngen, stats=None, halloffame=None, verbose=__debug__): """This is the :math:`(\mu + \lambda)` evolutionary algorithm. :param population: A list of individuals. :param toolbox: A :class:`~deap.base.Toolbox` that contains the evolution operators. :param mu: The number of individuals to select for the next generation. :param lambda\_: The number of children to produce at each generation. :param cxpb: The probability that an offspring is produced by crossover. :param mutpb: The probability that an offspring is produced by mutation. :param ngen: The number of generation. :param stats: A :class:`~deap.tools.Statistics` object that is updated inplace, optional. :param halloffame: A :class:`~deap.tools.HallOfFame` object that will contain the best individuals, optional. :param verbose: Whether or not to log the statistics. :returns: The final population :returns: A class:`~deap.tools.Logbook` with the statistics of the evolution. The algorithm takes in a population and evolves it in place using the :func:`varOr` function. It returns the optimized population and a :class:`~deap.tools.Logbook` with the statistics of the evolution. The logbook will contain the generation number, the number of evaluations for each generation and the statistics if a :class:`~deap.tools.Statistics` is given as argument. The *cxpb* and *mutpb* arguments are passed to the :func:`varOr` function. The pseudocode goes as follow :: evaluate(population) for g in range(ngen): offspring = varOr(population, toolbox, lambda_, cxpb, mutpb) evaluate(offspring) population = select(population + offspring, mu) First, the individuals having an invalid fitness are evaluated. Second, the evolutionary loop begins by producing *lambda_* offspring from the population, the offspring are generated by the :func:`varOr` function. The offspring are then evaluated and the next generation population is selected from both the offspring **and** the population. Finally, when *ngen* generations are done, the algorithm returns a tuple with the final population and a :class:`~deap.tools.Logbook` of the evolution. This function expects :meth:`toolbox.mate`, :meth:`toolbox.mutate`, :meth:`toolbox.select` and :meth:`toolbox.evaluate` aliases to be registered in the toolbox. This algorithm uses the :func:`varOr` variation. """ logbook = Logbook() logbook.header = ['gen', 'nevals'] + (stats.fields if stats else []) # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in population if not ind.fitness.valid] fitnesses = toolbox.map(toolbox.evaluate, invalid_ind) for ind, fit in zip(invalid_ind, fitnesses): ind.fitness.values = fit if halloffame is not None: halloffame.update(population) record = stats.compile(population) if stats is not None else {} logbook.record(gen=0, nevals=len(invalid_ind), **record) if verbose: print(logbook.stream) # --- Hack --- all_generations = {} # ------------ # Begin the generational process for gen in range(1, ngen + 1): # Vary the population offspring = varOr(population, toolbox, lambda_, cxpb, mutpb) # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in offspring if not ind.fitness.valid] fitnesses = toolbox.map(toolbox.evaluate, invalid_ind) for ind, fit in zip(invalid_ind, fitnesses): ind.fitness.values = fit # Update the hall of fame with the generated individuals if halloffame is not None: halloffame.update(offspring) # --- Hack --- all_generations[gen] = population + offspring # ------------ # Select the next generation population population[:] = toolbox.select(population + offspring, mu) # Update the statistics with the new population record = stats.compile(population) if stats is not None else {} logbook.record(gen=gen, nevals=len(invalid_ind), **record) if verbose: print(logbook.stream) return population, logbook, all_generations
def eaSimple(population, toolbox, cxpb, mutpb, ngen, stats=None, halloffame=None, verbose=__debug__, pset=None, store=True): """ Parameters ---------- population toolbox cxpb mutpb ngen stats halloffame verbose pset store Returns ------- """ rst = random.getstate() len_pop = len(population) logbook = Logbook() logbook.header = [] + (stats.fields if stats else []) data_all = {} random.setstate(rst) for gen in range(1, ngen + 1): "评价" rst = random.getstate() """score""" invalid_ind = [ind for ind in population if not ind.fitness.valid] fitnesses = toolbox.parallel(iterable=population) for ind, fit, in zip(invalid_ind, fitnesses): ind.fitness.values = fit[0], ind.expr = fit[1] ind.dim = fit[2] ind.withdim = fit[3] random.setstate(rst) rst = random.getstate() """elite""" add_ind = [] add_ind1 = toolbox.select_kbest_target_dim(population, K_best=0.01 * len_pop) add_ind2 = toolbox.select_kbest_dimless(population, K_best=0.01 * len_pop) add_ind3 = toolbox.select_kbest(population, K_best=5) add_ind += add_ind1 add_ind += add_ind2 add_ind += add_ind3 elite_size = len(add_ind) random.setstate(rst) rst = random.getstate() """score""" if store: subp = functools.partial(sub, subed=pset.rep_name_list, subs=pset.real_name_list) data = { "gen{}_pop{}".format(gen, n): { "gen": gen, "pop": n, "score": i.fitness.values[0], "expr": str(subp(i.expr)), } for n, i in enumerate(population) if i is not None } data_all.update(data) random.setstate(rst) rst = random.getstate() """record""" if halloffame is not None: halloffame.update(add_ind3) if len(halloffame.items ) > 0 and halloffame.items[-1].fitness.values[0] >= 0.95: print(halloffame.items[-1]) print(halloffame.items[-1].fitness.values[0]) break random.setstate(rst) rst = random.getstate() """Dynamic output""" record = stats.compile(population) if stats else {} logbook.record(gen=gen, pop=len(population), **record) if verbose: print(logbook.stream) random.setstate(rst) """crossover, mutate""" offspring = toolbox.select_gs(population, len_pop - elite_size) # Vary the pool of individuals offspring = varAnd(offspring, toolbox, cxpb, mutpb) rst = random.getstate() """re-run""" offspring.extend(add_ind) population[:] = offspring random.setstate(rst) store = Store() store.to_csv(data_all) return population, logbook
def eaSimple(population, toolbox, cxpb, mutpb, ngen, stats=None, halloffame=None, verbose=__debug__, pset=None, store=True): """ Parameters ---------- population toolbox cxpb mutpb ngen stats halloffame verbose pset store Returns ------- """ len_pop = len(population) logbook = Logbook() logbook.header = ['gen', 'nevals'] + (stats.fields if stats else []) random_seed = random.randint(1, 1000) # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in population if not ind.fitness.valid] fitnesses = toolbox.map(toolbox.evaluate, invalid_ind) # fitnesses = parallelize(n_jobs=4, func=toolbox.evaluate, iterable=invalid_ind) for ind, fit in zip(invalid_ind, fitnesses): ind.fitness.values = fit[0], ind.expr = fit[1] if halloffame is not None: halloffame.update(population) random.seed(random_seed) record = stats.compile_(population) if stats else {} logbook.record(gen=0, nevals=len(invalid_ind), **record) if verbose: print(logbook.stream) data_all = {} # Begin the generational process for gen in range(1, ngen + 1): if store: if pset: subp = partial(sub, subed=pset.rep_name_list, subs=pset.name_list) data = [{"score": i.fitness.values[0], "expr": subp(i.expr)} for i in halloffame.items[-5:]] else: data = [{"score": i.fitness.values[0], "expr": i.expr} for i in halloffame.items[-5:]] data_all['gen%s' % gen] = data # select_gs the next generation individuals offspring = toolbox.select_gs(population, len_pop) # Vary the pool of individuals offspring = varAnd(offspring, toolbox, cxpb, mutpb) if halloffame is not None: offspring.extend(halloffame) random_seed = random.randint(1, 1000) # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in offspring if not ind.fitness.valid] fitnesses = toolbox.map(toolbox.evaluate, invalid_ind) # fitnesses = parallelize(n_jobs=4, func=toolbox.evaluate, iterable=invalid_ind) for ind, fit in zip(invalid_ind, fitnesses): ind.fitness.values = fit[0], ind.expr = fit[1] # Update the hall of fame with the generated individuals if halloffame is not None: halloffame.update(offspring) if halloffame.items[-1].fitness.values[0] >= 0.95: print(halloffame.items[-1]) print(halloffame.items[-1].fitness.values[0]) break random.seed(random_seed) # Replace the current population by the offspring population[:] = offspring # Append the current generation statistics to the logbook record = stats.compile_(population) if stats else {} logbook.record(gen=gen, nevals=len(invalid_ind), **record) if verbose: print(logbook.stream) store = Store() store.to_txt(data_all) return population, logbook
def multiEaSimple(population, toolbox, cxpb, mutpb, ngen, stats=None, halloffame=None, verbose=__debug__, pset=None, store=True, alpha=1): """ Parameters ---------- population toolbox cxpb mutpb ngen stats halloffame verbose pset store alpha Returns ------- """ logbook = Logbook() logbook.header = ['gen', 'nevals'] + (stats.fields if stats else []) # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in population if not ind.fitness.valid] random_seed = random.randint(1, 1000) # fitnesses = list(toolbox.map(toolbox.evaluate, [str(_) for _ in invalid_ind])) # fitnesses2 = toolbox.map(toolbox.evaluate2, [str(_) for _ in invalid_ind]) fitnesses = parallelize(n_jobs=6, func=toolbox.evaluate, iterable=[str(_) for _ in invalid_ind]) fitnesses2 = parallelize(n_jobs=6, func=toolbox.evaluate2, iterable=[str(_) for _ in invalid_ind]) def funcc(a, b): """ Parameters ---------- a b Returns ------- """ return (alpha * a + b) / 2 for ind, fit, fit2 in zip(invalid_ind, fitnesses, fitnesses2): ind.fitness.values = funcc(fit[0], fit2[0]), ind.values = (fit[0], fit2[0]) ind.expr = (fit[1], fit2[1]) if halloffame is not None: halloffame.update(population) random.seed(random_seed) record = stats.compile_(population) if stats else {} logbook.record(gen=0, nevals=len(invalid_ind), **record) if verbose: print(logbook.stream) data_all = {} # Begin the generational process for gen in range(1, ngen + 1): # select_gs the next generation individuals offspring = toolbox.select_gs(population, len(population)) # Vary the pool of individuals offspring = varAnd(offspring, toolbox, cxpb, mutpb) if halloffame is not None: offspring.extend(halloffame.items[-2:]) # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in offspring if not ind.fitness.valid] random_seed = random.randint(1, 1000) # fitnesses = toolbox.map(toolbox.evaluate, [str(_) for _ in invalid_ind]) # fitnesses2 = toolbox.map(toolbox.evaluate2, [str(_) for _ in invalid_ind]) fitnesses = parallelize(n_jobs=6, func=toolbox.evaluate, iterable=[str(_) for _ in invalid_ind]) fitnesses2 = parallelize(n_jobs=6, func=toolbox.evaluate2, iterable=[str(_) for _ in invalid_ind]) for ind, fit, fit2 in zip(invalid_ind, fitnesses, fitnesses2): ind.fitness.values = funcc(fit[0], fit2[0]), ind.values = (fit[0], fit2[0]) ind.expr = (fit[1], fit2[1]) # Update the hall of fame with the generated individuals if halloffame is not None: halloffame.update(offspring) if halloffame.items[-1].fitness.values[0] >= 0.95: print(halloffame.items[-1]) print(halloffame.items[-1].fitness.values[0]) print(halloffame.items[-1].values[0]) print(halloffame.items[-1].values[1]) break if store: if pset: subp = partial(sub, subed=pset.rep_name_list, subs=pset.name_list) data = [{"score": i.values[0], "expr": subp(i.expr[0])} for i in halloffame.items[-2:]] data2 = [{"score": i.values[1], "expr": subp(i.expr[1])} for i in halloffame.items[-2:]] else: data = [{"score": i.values[0], "expr": i.expr} for i in halloffame.items[-2:]] data2 = [{"score": i.values[1], "expr": i.expr[2]} for i in halloffame.items[-2:]] data_all['gen%s' % gen] = list(zip(data, data2)) random.seed(random_seed) # Replace the current population by the offspring population[:] = offspring # Append the current generation statistics to the logbook record = stats.compile_(population) if stats else {} logbook.record(gen=gen, nevals=len(invalid_ind), **record) if verbose: print(logbook.stream) if store: store1 = Store() store1.to_txt(data_all) return population, logbook