def eaSimple(toolbox, population, cxpb, mutpb, ngen, halloffame=None): """This algorithm reproduce the simplest evolutionary algorithm as presented in chapter 7 of Back, Fogel and Michalewicz, "Evolutionary Computation 1 : Basic Algorithms and Operators", 2000. It uses :math:`\lambda = \kappa = \mu` and goes as follow. It first initializes the population (:math:`P(0)`) by evaluating every individual presenting an invalid fitness. Then, it enters the evolution loop that begins by the selection of the :math:`P(g+1)` population. Then the crossover operator is applied on a proportion of :math:`P(g+1)` according to the *cxpb* probability, the resulting and the untouched individuals are placed in :math:`P'(g+1)`. Thereafter, a proportion of :math:`P'(g+1)`, determined by *mutpb*, is mutated and placed in :math:`P''(g+1)`, the untouched individuals are transfered :math:`P''(g+1)`. Finally, those new individuals are evaluated and the evolution loop continues until *ngen* generations are completed. Briefly, the operators are applied in the following order :: evaluate(population) for i in range(ngen): offsprings = select(population) offsprings = mate(offsprings) offsprings = mutate(offsprings) evaluate(offsprings) population = offsprings """ _logger.info("Start of evolution") # 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 _logger.debug("Evaluated %i individuals", len(invalid_ind)) if halloffame is not None: halloffame.update(population) # Begin the generational process for gen in range(ngen): _logger.info("Evolving generation %i", gen) # Select the next generation individuals offsprings = toolbox.select(population, n=len(population)) # Clone the selected individuals offsprings = map(toolbox.clone, offsprings) # Apply crossover and mutation on the offsprings for ind1, ind2 in zip(offsprings[::2], offsprings[1::2]): if random.random() < cxpb: toolbox.mate(ind1, ind2) del ind1.fitness.values del ind2.fitness.values for ind in offsprings: if random.random() < mutpb: toolbox.mutate(ind) del ind.fitness.values # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in offsprings if not ind.fitness.valid] fitnesses = toolbox.map(toolbox.evaluate, invalid_ind) for ind, fit in zip(invalid_ind, fitnesses): ind.fitness.values = fit _logger.debug("Evaluated %i individuals", len(invalid_ind)) if halloffame is not None: halloffame.update(offsprings) # The population is entirely replaced by the offsprings population[:] = offsprings print toolbox.info(population) _logger.info("End of (successful) evolution") return population
def eaSimpleMany(toolbox, population, cxpb, mutpb, ngen, halloffame=None): """ This algorithm is based on the Simple algorithm above, but designed to return as many perfect individuals as possible, given an upper bound. """ _logger.info("Start of evolution") # 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 _logger.debug("Evaluated %i individuals", len(invalid_ind)) if halloffame is not None: halloffame.update(population) perfect = set() # Begin the generational process for gen in range(ngen): _logger.info("Evolving generation %i", gen) # Select the next generation individuals offsprings = toolbox.select(population, n=len(population)) # Clone the selected individuals offsprings = map(toolbox.clone, offsprings) # Apply crossover and mutation on the offsprings for ind1, ind2 in zip(offsprings[::2], offsprings[1::2]): if random.random() < cxpb: toolbox.mate(ind1, ind2) del ind1.fitness.values del ind2.fitness.values for ind in offsprings: if random.random() < mutpb: toolbox.mutate(ind) del ind.fitness.values # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in offsprings if not ind.fitness.valid] fitnesses = toolbox.map(toolbox.evaluate, invalid_ind) for ind, fit in zip(invalid_ind, fitnesses): ind.fitness.values = fit _logger.debug("Evaluated %i individuals", len(invalid_ind)) if halloffame is not None: halloffame.update(offsprings) # The population is entirely replaced by the offsprings population[:] = offsprings for ind in population: if ind.fitness.values[0] == toolbox.perfect(): perfect.add(ind) print toolbox.info(population) _logger.info("End of (successful) evolution") return population