def get_best_n_members(members, n): half_members = [] for gid, g in members.items(): half_members.append((gid, g)) half_members.sort(reverse=True, key=lambda x: x[1].fitness) return from_list_to_dict(half_members[:n])
def calculateDifferentRanks(self): dominated_dict = self.population flag = True current_rank = 0 dominated = [] while len(dominated_dict) != 0 and flag: flag = False self.computeRank(dominated_dict) for gid, g in dominated_dict.items(): if g.rank == 2: flag = True g.rank = current_rank else: g.rank = None dominated.append((gid, g)) dominated_dict = from_list_to_dict(dominated) dominated = [] current_rank += 1
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 reproduce(self, config, species, pop_size, generation): all_fitnesses = [] remaining_species = [] for stag_sid, stag_s, stagnant in self.stagnation.update( species, generation): if stagnant: self.reporters.species_stagnant(stag_sid, stag_s) else: all_fitnesses.extend(m.rank for m in itervalues(stag_s.members)) remaining_species.append(stag_s) if not remaining_species: species.species = {} return {} min_fitness = min(all_fitnesses) max_fitness = max(all_fitnesses) fitness_range = max(1.0, max_fitness - min_fitness) for afs in remaining_species: # Compute adjusted fitness. msf = mean([m.rank for m in itervalues(afs.members)]) af = (msf - min_fitness) / fitness_range afs.adjusted_fitness = af adjusted_fitnesses = [s.adjusted_fitness for s in remaining_species] avg_adjusted_fitness = mean(adjusted_fitnesses) # type: float self.reporters.info( "Average adjusted fitness: {:.3f}".format(avg_adjusted_fitness)) previous_sizes = [len(s.members) for s in remaining_species] min_species_size = self.reproduction_config.min_species_size min_species_size = max(min_species_size, self.reproduction_config.elitism) spawn_amounts = self.compute_spawn(adjusted_fitnesses, previous_sizes, pop_size, min_species_size) new_population = {} all_old_members = [] species.species = {} population = [] for s in remaining_species: population += list(iteritems(s.members)) for spawn, s in zip(spawn_amounts, remaining_species): spawn = max(spawn, self.reproduction_config.elitism) assert spawn > 0 old_members = list(iteritems(s.members)) all_old_members += old_members s.members = {} species.species[s.key] = s old_members.sort(reverse=False, key=lambda x: x[1].rank) if spawn <= 0: continue repro_cutoff = int( math.ceil(self.reproduction_config.survival_threshold * len(old_members))) repro_cutoff = max(repro_cutoff, 2) old_members = old_members[:repro_cutoff] while spawn > 0: spawn -= 1 if len(old_members) > 2: parent1_id, parent1, parent2_id, parent2 = self.tournament( old_members, self.tournament_threshold) else: parent1_id, parent1 = random.choice(old_members) parent2_id, parent2 = random.choice(old_members) gid = next(self.genome_indexer) child = config.genome_type(gid) child.configure_crossover(parent1, parent2, config.genome_config) child.mutate(config.genome_config) new_population[gid] = child self.ancestors[gid] = (parent1_id, parent2_id) all_old_members.sort(key=lambda x: x[0]) all_old_members = from_list_to_dict(all_old_members) new_population.update(all_old_members) return new_population
def reproduce(self, config, species, pop_size, generation): all_fitnesses = [] remaining_species = [] max_stagnation = self.stagnation.stagnation_config.max_stagnation # **************************** EXTINCTION STAGNANT SPECIES *************************** for stag_sid, stag_s, stagnant in self.stagnation.update( species, generation): if stagnant: self.reporters.species_stagnant(stag_sid, stag_s) else: all_fitnesses.extend(m.fitness for m in itervalues(stag_s.members)) remaining_species.append(stag_s) if not remaining_species: species.species = {} return {} # ********************************* ADJUSTED FITNESS ********************************* adjusted_fitnesses, avg_adjusted_fitness = self.compute_adjusted_fitness( all_fitnesses, remaining_species) self.reporters.info( "Average adjusted fitness: {:.3f}".format(avg_adjusted_fitness)) # Compute the number of new members for each species in the new generation. previous_sizes = [len(s.members) for s in remaining_species] min_species_size = self.reproduction_config.min_species_size min_species_size = max(min_species_size, self.reproduction_config.elitism) spawn_amounts = self.compute_spawn(adjusted_fitnesses, previous_sizes, pop_size, min_species_size) # 3 set new_population = {} all_old_members = [] species.species = {} re_spawn = False for spawn, s in zip(spawn_amounts, remaining_species): # If elitism is enabled, each species always at least gets to retain its elites. spawn = max(spawn, self.reproduction_config.elitism) assert spawn > 0 # The species has at least one member for the next generation, so retain it. old_members = list(iteritems(s.members)) all_old_members += old_members s.members = {} species.species[s.key] = s # Sort members in order of descending fitness. old_members.sort(reverse=True, key=lambda x: x[1].fitness) if spawn <= 0: continue # Only use the survival threshold fraction to use as parents for the next generation. repro_cutoff = int( math.ceil(self.reproduction_config.survival_threshold * len(old_members))) # Use at least two parents no matter what the threshold fraction result is. repro_cutoff = max(repro_cutoff, 2) old_members = old_members[:repro_cutoff] # **************************** CROSSOVER AND MUTATION **************************** while spawn > 0: spawn -= 1 if len(old_members) > 2: parent1_id, parent1, parent2_id, parent2 = self.tournament( old_members, self.tournament_threshold) else: parent1_id, parent1 = random.choice(old_members) parent2_id, parent2 = random.choice(old_members) gid = next(self.genome_indexer) child = config.genome_type(gid) child.configure_crossover(parent1, parent2, config.genome_config) child.mutate(config.genome_config) new_population[gid] = child self.ancestors[gid] = (parent1_id, parent2_id) all_old_members.sort(key=lambda x: x[0]) all_old_members = from_list_to_dict(all_old_members) new_population.update(all_old_members) return new_population