예제 #1
0
    def iterate_generation(self):
        # Gather and report statistics.
        best = None
        for g in itervalues(self.population):
            if best is None or g.fitness > best.fitness:
                best = g
        self.reporters.post_evaluate(self.config, self.population, self.species, best)

        # Track the best genome ever seen.
        if self.best_genome is None or best.fitness > self.best_genome.fitness:
            self.best_genome = best

        # Create the next generation from the current generation.
        self.population = self.reproduction.reproduce(self.config, self.species,
                                                      self.config.pop_size, self.generation)

        # Check for complete extinction.
        if not self.species.species:
            self.reporters.complete_extinction()

            # If requested by the user, create a completely new population,
            # otherwise raise an exception.
            if self.config.reset_on_extinction:
                self.population = self.reproduction.create_new(self.config.genome_type,
                                                               self.config.genome_config,
                                                               self.config.pop_size)
            else:
                raise CompleteExtinctionException()

        # Divide the new population into species.
        self.species.speciate(self.config, self.population, self.generation)

        self.reporters.end_generation(self.config, self.population, self.species)

        self.generation += 1
예제 #2
0
    def run(self, fitness_function, ngen, maxtime):

        gen = 0
        start = time()

        while ((ngen is None or gen < ngen)
               and (maxtime is None or time() - start < maxtime)):

            self.config.gen = gen

            gen += 1

            self.config.current_evaluations = 0

            self.reporters.start_generation(self.generation)

            # Evaluate all genomes using the user-provided function.
            fitness_function(list(self.population.items()), self.config)

            # Gather and report statistics.
            best = None
            for g in self.population.values():

                if g.fitness is None:
                    raise RuntimeError('Fitness not assigned to genome %d' %
                                       g.key)

                # Break out fitness tuple into actual fitness, evaluations
                g.fitness, g.actual_fitness, evaluations = (self.parse_fitness(
                    g.fitness))

                # Accumulate evaluations
                self.config.current_evaluations += evaluations
                self.config.total_evaluations += evaluations

                if best is None:
                    best = g

                else:
                    if g.actual_fitness > best.actual_fitness:
                        best = g

            self.reporters.post_evaluate(self.config, self.population,
                                         self.species, best)

            # Track the best genome ever seen.
            if (self.best_genome is None
                    or best.actual_fitness > self.best_genome.actual_fitness):
                self.best_genome = best

            if not self.config.no_fitness_termination:
                # End if the fitness threshold is reached.
                fv = self.fitness_criterion(g.actual_fitness
                                            for g in self.population.values())
                if fv >= self.config.fitness_threshold:
                    self.reporters.found_solution(self.config, self.generation,
                                                  best)
                    break

            # Create the next generation from the current generation.
            self.reproduce()

            # Check for complete extinction.
            if not self.species.species:
                self.reporters.complete_extinction()

                # If requested by the user, create a completely new population,
                # otherwise raise an exception.
                if self.config.reset_on_extinction:
                    self.create_new_pop()
                else:
                    raise CompleteExtinctionException()

            # Divide the new population into species.
            self.species.speciate(self.config, self.population,
                                  self.generation)

            self.reporters.end_generation(self.config, self.population,
                                          self.species)

            self.generation += 1

        if self.config.no_fitness_termination:
            self.reporters.found_solution(self.config, self.generation,
                                          self.best_genome)

        self.plot_species()

        return self.best_genome
    def run(self, fitness_function, n=None):
        # Variables needed to save archive on each update
        winner_name_prefix = "front_" + self.winner_name

        if self.config.no_fitness_termination and (n is None):
            raise RuntimeError(
                "Cannot have no generational limit with no fitness termination"
            )

        k = 0
        while n is None or k < n:
            k += 1
            front = []
            self.reporters.start_generation(self.generation)

            not_evaluated = {}
            evaluated = []
            # len(population) = 2*pop_size
            for gid, g in self.population.items():
                g.rank = None
                if g.fitness is None:
                    not_evaluated[gid] = g
                else:
                    evaluated.append((gid, g))

            # Evaluate all genomes using the user-provided function.
            fitness_function(list(iteritems(not_evaluated)), self.config)
            start_time_gen = time.time()

            # calculate distance on 2*pop_size
            if self.use_archive:
                self.KNNdistances(self.population,
                                  self.n_neighbors,
                                  archive=self.novelty_archive)
            else:
                self.KNNdistances(self.population, self.n_neighbors)
            self.calculateDifferentRanks()

            for gid, g in self.population.items():
                if self.use_archive and g not in self.novelty_archive and g.dist is not None and g.dist > self.novelty_threshold:
                    self.novelty_archive.append(g)
                    self.n_add_archive += 1
                    self.last_archive_modified = self.generation
                    with open("archive_" + self.winner_name, "wb") as f:
                        pickle.dump(self.novelty_archive, f)

            # fig = plt.figure()
            # ax = fig.add_subplot(111, label='')
            for elem in self.population.items():
                if elem[1].rank == 0:
                    front.append(elem)
            #         ax.scatter(elem[1].fitness, elem[1].dist, color='orange')
            #         ax.annotate(elem[1].rank, (elem[1].fitness, elem[1].dist))
            #     else:
            #         ax.scatter(elem[1].fitness, elem[1].dist, color='blue')
            #         ax.annotate(elem[1].rank, (elem[1].fitness, elem[1].dist))
            #
            # ax.set_xlabel('Fitness')
            # # ax.set_ylabel('Mean Height Pelvis')
            # ax.set_ylabel('Mean Diversity')
            # plt.axis((0, plt.axis()[1], 0, plt.axis()[3]))
            # plt.title('MO_NS_FO: POP=' + str(len(self.population)))
            # plt.savefig('MO_NS_FO/Figures/Figure'+str(self.generation)+'.png')
            # plt.close(fig)

            population = []
            for gid, g in self.population.items():
                population.append((gid, g))
            population.sort(reverse=False, key=lambda x: x[1].rank)
            self.population = population[:self.config.pop_size]
            self.population = from_list_to_dict(self.population)
            self.species.speciate(self.config, self.population,
                                  self.generation)

            # Gather and report statistics.
            best = None
            for g in itervalues(self.population):
                if best is None or g.fitness > best.fitness:
                    best = g

            with open(winner_name_prefix, "wb") as f:
                pickle.dump(front, f)

            self.reporters.post_evaluate(self.config, self.population,
                                         self.species, best)

            # Check for complete extinction.
            if not self.species.species:
                self.reporters.complete_extinction()

                # If requested by the user, create a completely new population,
                # otherwise raise an exception.
                if self.config.reset_on_extinction:
                    self.population = self.reproduction.create_new(
                        self.config.genome_type, self.config.genome_config,
                        self.config.pop_size)
                else:
                    raise CompleteExtinctionException()

            if not self.config.no_fitness_termination:
                # End if the fitness threshold is reached.
                fv = self.fitness_criterion(
                    g.dist for g in itervalues(self.population))
                if fv >= self.config.fitness_threshold:
                    self.reporters.found_solution(self.config, self.generation,
                                                  best)
                    break

            self.reporters.end_generation(self.config, self.population,
                                          self.species)

            # Create the next generation from the current generation.
            self.population = self.reproduction.reproduce(
                self.config, self.species, self.config.pop_size,
                self.generation)

            # Check for complete extinction.
            if not self.species.species:
                self.reporters.complete_extinction()

                # If requested by the user, create a completely new population,
                # otherwise raise an exception.
                if self.config.reset_on_extinction:
                    self.population = self.reproduction.create_new(
                        self.config.genome_type, self.config.genome_config,
                        self.config.pop_size)
                else:
                    raise CompleteExtinctionException()

            if self.use_archive:
                time_diff = self.generation - self.last_archive_modified

                if time_diff > 60:
                    self.novelty_threshold -= self.novelty_threshold * 0.05

                if self.n_add_archive > 4 and time_diff <= 30:
                    self.novelty_threshold += self.novelty_threshold * 0.05
                    self.n_add_archive = 0

                if time_diff > 30:
                    self.n_add_archive = 0

                self.reporters.info("Novelty's archive size: {}\n".format(
                    len(self.novelty_archive)))
            self.reporters.info("Front size: {}\n".format(len(front)))
            self.generation += 1

            diff = round(time.time() - start_time_gen, 3)
            self.sum_times += diff
            self.reporters.info("\nGen: " + str(k) + " tempo: " + str(diff) +
                                " sec\n")

        if self.config.no_fitness_termination:
            self.reporters.found_solution(self.config, self.generation,
                                          self.best_genome)

        self.reporters.info("Computation mean time: " +
                            str(self.sum_times / (self.generation + 1)))

        return front
    def run(self, fitness_function, n=None):
        # Variables needed to save winner
        winner_interval = 10
        winner_name_prefix = "winner_checkpoint_"
        last_winner_checkpoint = 0

        if self.config.no_fitness_termination and (n is None):
            raise RuntimeError("Cannot have no generational limit with no fitness termination")

        k = 0
        while n is None or k < n:
            k += 1
            self.reporters.start_generation(self.generation)
            start_time_gen = time.time()

            # Evaluate all genomes using the user-provided function.
            not_evaluated = {}
            evaluated = []
            # len(population) = 2*pop_size
            for gid, g in self.population.items():
                if g.fitness is None:
                    not_evaluated[gid] = g
                else:
                    evaluated.append((gid, g))

            diff = round(time.time() - start_time_gen, 3)
            self.sum_times += diff

            fitness_function(list(iteritems(not_evaluated)), self.config)

            start_time_gen = time.time()
            if self.random_replace:
                i = 0
                self.population = {}
                for gid, g in not_evaluated.items():
                    if len(evaluated) <= i or g.fitness > evaluated[i][1].fitness:
                        self.population[gid] = g
                    else:
                        self.population[evaluated[i][0]] = evaluated[i][1]
                    i = i + 1
                self.species.speciate(self.config, self.population, self.generation)
            elif self.mu_lambda:
                self.population = []
                self.population += evaluated
                for key, v in not_evaluated.items():
                    self.population.append((key, v))
                self.population.sort(reverse=True, key=lambda x: x[1].fitness)
                self.population = from_list_to_dict(self.population[:self.config.pop_size])
                self.species.speciate(self.config, self.population, self.generation)
            else:
                self.species.speciate(self.config, self.population, self.generation)
                dim = 0
                max_spec_dim = 0
                max_sid = -1
                for sid, s in iteritems(self.species):
                    s.members = self.get_best_half_members(s.members)
                    d = len(s.members)
                    if d > max_spec_dim:
                        max_spec_dim = d
                        max_sid = sid
                    dim += d
                diff = dim - self.config.pop_size
                if diff > 0 and diff > max_spec_dim:
                    s = self.species[max_sid]
                    s.members = s.members[:len(s.members) - diff]

            # Check for complete extinction.
            if not self.species.species:
                self.reporters.complete_extinction()

                # If requested by the user, create a completely new population,
                # otherwise raise an exception.
                if self.config.reset_on_extinction:
                    self.population = self.reproduction.create_new(self.config.genome_type,
                                                                   self.config.genome_config,
                                                                   self.config.pop_size)
                else:
                    raise CompleteExtinctionException()

            # Gather and report statistics.
            best = None
            for g in itervalues(self.population):
                if best is None or g.fitness > best.fitness:
                    best = g
            self.reporters.post_evaluate(self.config, self.population, self.species, best)

            # Track the best genome ever seen.
            if self.best_genome is None or best.fitness > self.best_genome.fitness:
                self.best_genome = best
                # Code to save the best after winner_interval generations
                if self.overwrite:
                    filename = winner_name_prefix
                else:
                    filename = '{0}{1}'.format(winner_name_prefix, self.generation)
                last_winner_checkpoint = self.generation
                with open(filename, 'wb') as f:
                    pickle.dump(self.best_genome, f)

            if not self.config.no_fitness_termination:
                # End if the fitness threshold is reached.
                fv = self.fitness_criterion(g.fitness for g in itervalues(self.population))
                if fv >= self.config.fitness_threshold:
                    self.reporters.found_solution(self.config, self.generation, best)
                    break

            self.reporters.end_generation(self.config, self.population, self.species)

            # Create the next generation from the current generation.
            self.population = self.reproduction.reproduce(self.config, self.species,
                                                          self.config.pop_size, self.generation)

            self.generation += 1

            print_file("\nGen: " + str(k) + " tempo: " + str(round(time.time() - start_time_gen,3)) + " sec\n")
            diff = round(time.time() - start_time_gen, 3)
            self.sum_times += diff
            self.reporters.info("\nGen: " + str(k) + " tempo: " + str(diff) + " sec\n")

        if self.config.no_fitness_termination:
            self.reporters.found_solution(self.config, self.generation, self.best_genome)

        self.reporters.info("Computation mean time: " + str(self.sum_times / (self.generation + 1)))

        return self.best_genome
    def run(self, fitness_function, n=None):
        # Variables needed to save archive on each update
        winner_name_prefix = "archive_checkpoint_" + self.winner_name

        if self.config.no_fitness_termination and (n is None):
            raise RuntimeError(
                "Cannot have no generational limit with no fitness termination"
            )

        k = 0
        while n is None or k < n:
            k += 1

            self.reporters.start_generation(self.generation)

            # Evaluate all genomes using the user-provided function.
            fitness_function(list(iteritems(self.population)), self.config)
            self.KNNdistances(self.population, self.novelty_archive,
                              self.n_neighbors)

            # Gather and report statistics.
            best = None
            for g in itervalues(self.population):
                if best is None or g.dist > best.dist:
                    best = g
                if g.dist > self.novelty_threshold:
                    if g not in self.novelty_archive:
                        self.novelty_archive.append(g)
                        print("Distanza di aggiunta: ", g.dist)
                        self.n_add_archive += 1
                        self.last_archive_modified = self.generation
                        with open(winner_name_prefix, "wb") as f:
                            pickle.dump(self.novelty_archive, f)

            self.reporters.post_evaluate(self.config, self.population,
                                         self.species, best)

            # if self.last_genome_added is None:
            #     self.last_genome_added = best

            # Track the best genome ever seen.
            # if self.last_genome_added.fitness != best.fitness and best.dist > self.novelty_threshold:
            #     print("Distanza di aggiunta: ", best.dist)
            #     self.last_genome_added = best
            #     self.last_archive_modified = self.generation
            #     self.n_add_archive += 1
            #     self.novelty_archive.append(best)
            #     with open(winner_name_prefix, "wb") as f:
            #         pickle.dump(self.novelty_archive, f)

            if not self.config.no_fitness_termination:
                # End if the fitness threshold is reached.
                fv = self.fitness_criterion(
                    g.dist for g in itervalues(self.population))
                if fv >= self.config.fitness_threshold:
                    self.reporters.found_solution(self.config, self.generation,
                                                  best)
                    break

            # Create the next generation from the current generation.
            self.population = self.reproduction.reproduce(
                self.config, self.species, self.config.pop_size,
                self.generation)

            # Check for complete extinction.
            if not self.species.species:
                self.reporters.complete_extinction()

                # If requested by the user, create a completely new population,
                # otherwise raise an exception.
                if self.config.reset_on_extinction:
                    self.population = self.reproduction.create_new(
                        self.config.genome_type, self.config.genome_config,
                        self.config.pop_size)
                else:
                    raise CompleteExtinctionException()

            # Divide the new population into species.
            self.species.speciate(self.config, self.population,
                                  self.generation)

            self.reporters.end_generation(self.config, self.population,
                                          self.species)

            time_diff = self.generation - self.last_archive_modified

            if time_diff > 60:
                self.novelty_threshold -= self.novelty_threshold * 0.05

            if self.n_add_archive > 4 and time_diff <= 30:
                self.novelty_threshold += self.novelty_threshold * 0.05
                self.n_add_archive = 0

            if time_diff > 30:
                self.n_add_archive = 0

            self.reporters.info("Novelty's archive size: {}\n".format(
                len(self.novelty_archive)))
            self.generation += 1

        if self.config.no_fitness_termination:
            self.reporters.found_solution(self.config, self.generation,
                                          self.best_genome)

        return self.novelty_archive
    def run(self, fitness_function, n=None):
        # Variables needed to save archive on each update
        winner_name_prefix = "archive_checkpoint_" + self.winner_name

        if self.config.no_fitness_termination and (n is None):
            raise RuntimeError("Cannot have no generational limit with no fitness termination")

        k = 0
        while n is None or k < n:
            k += 1

            self.reporters.start_generation(self.generation)

            not_evaluated = {}
            evaluated = []
            # len(population) = 2*pop_size
            for gid, g in self.population.items():
                if g.fitness is None:
                    not_evaluated[gid] = g
                else:
                    evaluated.append((gid, g))

            # Evaluate all genomes using the user-provided function.
            fitness_function(list(iteritems(not_evaluated)), self.config)
            self.KNNdistances(self.population, self.novelty_archive, self.n_neighbors)

            if len(evaluated) != 0:
                self.species.speciate(self.config, self.population, self.generation)
                dim = 0
                max_spec_dim = 0
                max_sid = -1
                for sid, s in iteritems(self.species.species):

                    s.members = self.get_best_n_members(s.members, math.ceil(len(s.members) / 2))
                    d = len(s.members)
                    if d > max_spec_dim:
                        max_spec_dim = d
                        max_sid = sid
                    dim += d
                diff = dim - self.config.pop_size
                if diff > 0 and diff > max_spec_dim:
                    s = self.species.species[max_sid]
                    s.members = self.get_best_n_members(s.members, len(s.members) - diff)

                new_population = {}
                for sid, s in iteritems(self.species.species):
                    for gid, g in s.members.items():
                        new_population[gid] = g
                self.population = new_population

            self.species.speciate(self.config, self.population, self.generation)

            # Check for complete extinction.
            if not self.species.species:
                self.reporters.complete_extinction()

                # If requested by the user, create a completely new population,
                # otherwise raise an exception.
                if self.config.reset_on_extinction:
                    self.population = self.reproduction.create_new(self.config.genome_type,
                                                                   self.config.genome_config,
                                                                   self.config.pop_size)
                else:
                    raise CompleteExtinctionException()

            # Gather and report statistics.
            best = None
            for g in itervalues(self.population):
                if best is None or g.dist > best.dist:
                    best = g
                if g.dist > self.novelty_threshold:
                    if g not in self.novelty_archive:
                        self.novelty_archive.append(g)
                        print("Distanza di aggiunta: ", g.dist)
                        self.n_add_archive += 1
                        self.last_archive_modified = self.generation
                        with open(winner_name_prefix, "wb") as f:
                            pickle.dump(self.novelty_archive, f)

            self.reporters.post_evaluate(self.config, self.population, self.species, best)

            if not self.config.no_fitness_termination:
                # End if the fitness threshold is reached.
                fv = self.fitness_criterion(g.dist for g in itervalues(self.population))
                if fv >= self.config.fitness_threshold:
                    self.reporters.found_solution(self.config, self.generation, best)
                    break

            # Create the next generation from the current generation.
            self.population = self.reproduction.reproduce(self.config, self.species,
                                                          self.config.pop_size, self.generation)

            # Check for complete extinction.
            if not self.species.species:
                self.reporters.complete_extinction()

                # If requested by the user, create a completely new population,
                # otherwise raise an exception.
                if self.config.reset_on_extinction:
                    self.population = self.reproduction.create_new(self.config.genome_type,
                                                                   self.config.genome_config,
                                                                   self.config.pop_size)
                else:
                    raise CompleteExtinctionException()

            # Divide the new population into species.
            self.species.speciate(self.config, self.population, self.generation)

            self.reporters.end_generation(self.config, self.population, self.species)

            time_diff = self.generation - self.last_archive_modified

            if time_diff > 60:
                self.novelty_threshold -= self.novelty_threshold * 0.05

            if self.n_add_archive > 4 and time_diff <= 30:
                self.novelty_threshold += self.novelty_threshold * 0.05
                self.n_add_archive = 0

            if time_diff > 30:
                self.n_add_archive = 0

            self.reporters.info("Novelty's archive size: {}\n".format(len(self.novelty_archive)))
            if len(self.novelty_archive) > 0:
                self.reporters.info("Archive's best: {}".format(
                    max(self.novelty_archive, key=lambda x: x.fitness[0]).fitness[0]))
            else:
                self.reporters.info("Archive's best: 0")
            self.generation += 1

        if self.config.no_fitness_termination:
            self.reporters.found_solution(self.config, self.generation, self.best_genome)

        return self.novelty_archive
    def run(self, fitness_function, n=None):
        #Variables needed to save winner
        winner_interval = 10
        winnername_prefix = "winner_checkpoint_"
        last_winner_checkpoint = 0

        if self.config.no_fitness_termination and (n is None):
            raise RuntimeError(
                "Cannot have no generational limit with no fitness termination"
            )

        k = 0
        while n is None or k < n:
            k += 1
            start_time_gen = time.time()
            self.reporters.start_generation(self.generation)

            # Evaluate all genomes using the user-provided function.
            fitness_function(list(iteritems(self.population)), self.config)
            if self.initial_best:
                self.species.speciate(self.config, self.population,
                                      self.generation)

            with open("output.txt", "a") as f:
                f.write("Gen: " + str(k) + " tempo: " +
                        str(round(time.time() - start_time_gen, 3)) + " sec\n")

            start_time_gen = time.time()
            # Gather and report statistics.
            best = None
            for g in itervalues(self.population):
                if best is None or g.fitness > best.fitness:
                    best = g
            self.reporters.post_evaluate(self.config, self.population,
                                         self.species, best)

            # Track the best genome ever seen.
            if self.best_genome is None or best.fitness > self.best_genome.fitness:
                self.best_genome = best

            if not self.config.no_fitness_termination:
                # End if the fitness threshold is reached.
                fv = self.fitness_criterion(
                    g.fitness for g in itervalues(self.population))
                if fv >= self.config.fitness_threshold:
                    self.reporters.found_solution(self.config, self.generation,
                                                  best)
                    break

            # Create the next generation from the current generation.
            self.population = self.reproduction.reproduce(
                self.config, self.species, self.config.pop_size,
                self.generation)

            # Check for complete extinction.
            if not self.species.species:
                self.reporters.complete_extinction()

                # If requested by the user, create a completely new population,
                # otherwise raise an exception.
                if self.config.reset_on_extinction:
                    self.population = self.reproduction.create_new(
                        self.config.genome_type, self.config.genome_config,
                        self.config.pop_size)
                else:
                    raise CompleteExtinctionException()

            # Divide the new population into species.
            self.species.speciate(self.config, self.population,
                                  self.generation)

            self.reporters.end_generation(self.config, self.population,
                                          self.species)

            self.generation += 1
            #Code to save the best after winner_interval generations
            if winner_interval is not None:
                dg = self.generation - last_winner_checkpoint
                if dg >= winner_interval:
                    filename = '{0}{1}'.format(winnername_prefix,
                                               self.generation)
                    last_winner_checkpoint = self.generation
                    with open(filename, 'wb') as f:
                        pickle.dump(self.best_genome, f)

            with open("output.txt", "a") as f:
                f.write("Gen: " + str(k) + " tempo: " +
                        str(round(time.time() - start_time_gen, 3)) + " sec\n")

        if self.config.no_fitness_termination:
            self.reporters.found_solution(self.config, self.generation,
                                          self.best_genome)

        return self.best_genome
예제 #8
0
    def run(self, fitness_function, n=None):

        k = 0

        while n is None or k < n:
            k += 1

            self.reporters.start_generation(self.generation)

            # Evaluate all genomes using the user-provided function.
            fitness_function(list(self.population.items()), self.config)

            # Gather and report statistics.
            best = None
            for g in self.population.values():
                if g.fitness is None:
                    raise RuntimeError(
                        "Fitness not assigned to genome {}".format(g.key))

                # Use actual_fitness to encode actual fitness, and replace genome's fitnss with its novelty
                behavior, g.actual_fitness = g.fitness
                g.fitness = self.config.novelty.add(behavior)

                if best is None or g.actual_fitness > best.actual_fitness:
                    best = g

            self.reporters.post_evaluate(self.config, self.population,
                                         self.species, best)

            # Track the best genome ever seen.
            if self.best_genome is None or best.actual_fitness > self.best_genome.actual_fitness:
                self.best_genome = best

            if not self.config.no_fitness_termination:
                # End if the fitness threshold is reached.
                fv = self.fitness_criterion(g.actual_fitness
                                            for g in self.population.values())
                if fv >= self.config.fitness_threshold:
                    self.reporters.found_solution(self.config, self.generation,
                                                  best)
                    break

            # Create the next generation from the current generation.
            self.population = self.reproduction.reproduce(
                self.config, self.species, self.config.pop_size,
                self.generation)

            # Check for complete extinction.
            if not self.species.species:
                self.reporters.complete_extinction()

                # If requested by the user, create a completely new population,
                # otherwise raise an exception.
                if self.config.reset_on_extinction:
                    self.population = self.reproduction.create_new(
                        self.config.genome_type, self.config.genome_config,
                        self.config.pop_size)
                else:
                    raise CompleteExtinctionException()

            # Divide the new population into species.
            self.species.speciate(self.config, self.population,
                                  self.generation)

            self.reporters.end_generation(self.config, self.population,
                                          self.species)

            self.generation += 1

        if self.config.no_fitness_termination:
            self.reporters.found_solution(self.config, self.generation,
                                          self.best_genome)

        return self.best_genome