def create(genome):
     connections = [cg.key for cg in itervalues(genome.connections) if cg.enabled]
     layers = feed_forward_layers(genome.input_keys, genome.output_keys, connections)
     mapping_tuples = {}
     node_evals = []
     # Traverse layers
     for layer in layers:
         # For each node in each layer, collect all incoming connections to the node
         for node in layer:
             incoming_connections = []
             for conn_key in connections:
                 input_node, output_node = conn_key
                 if output_node == node:
                     cg = genome.connections[conn_key]
                     incoming_connections.append((input_node, cg.weight))
             # Gather node gene information
             node_gene = genome.nodes[node]
             activation_function = node_gene.activation
             node_evals.append((node, activation_function, sum, incoming_connections))
     # Gather mapping tuples
     for key in genome.output_keys:
         mapping_tuples[key] = genome.nodes[key].cppn_tuple
     for key in genome.bias_keys:
         mapping_tuples[key] = genome.nodes[key].cppn_tuple
     return FeedForwardCPPN(genome.input_keys, genome.output_keys, node_evals, genome.nodes, mapping_tuples)
예제 #2
0
def report_fitness(pop):
	'''
	Report average, min, and max fitness of a population

	pop -- population to be reported
	'''
	avg_fitness = 0
	# Find best genome in current generation and update avg fitness
	for genome in itervalues(pop.population):
		avg_fitness += genome.fitness
	print("\n=================================================")
	print("\t\tGeneration: {}".format(pop.current_gen))
	print("=================================================")
	print("Best Fitness \t Avg Fitness \t Champion")
	print("============ \t =========== \t ========")
	print("{:.2f} \t\t {:.2f} \t\t {}".format(pop.best_genome.fitness, 
		  avg_fitness/pop.size,pop.best_genome.key))
	print("=================================================")
	print("Max Complexity \t Avg Complexity")
	print("============ \t =========== \t ========")
	print("{} \t\t {}".format(None, pop.avg_complexity))
    def run(self, task, goal, generations=None):
        '''
		Run evolution on a given task for a number of generations or until
		a goal is reached.

		task -- the task to be solved
		goal -- the goal to reach for the given task that defines a solution
		generations -- the max number of generations to run evolution for
		'''
        self.current_gen = 0
        reached_goal = False
        # Plot data
        best_fitnesses = []
        max_complexity = []
        min_complexity = []
        avg_complexity = []
        while self.current_gen < generations and not reached_goal:
            # Assess fitness of current population
            task(list(iteritems(self.population)))
            # Find best genome in current generation and update avg fitness
            curr_best = None
            curr_max_complex = None
            curr_min_complex = None
            avg_complexities = 0
            for genome in itervalues(self.population):
                avg_complexities += genome.complexity()
                # Update generation's most fit
                if curr_best is None or genome.fitness > curr_best.fitness:
                    curr_best = genome
                # Update generation's most complex
                if curr_max_complex is None or genome.complexity(
                ) > curr_max_complex.complexity():
                    curr_max_complex = genome
                # Update generation's least complex
                if curr_min_complex is None or genome.complexity(
                ) < curr_min_complex.complexity():
                    curr_min_complex = genome

            # Update global best genome if possible
            if self.best_genome is None or curr_best.fitness > self.best_genome.fitness:
                self.best_genome = curr_best

            # Update global most and least complex genomes
            if self.max_complex_genome is None or curr_max_complex.complexity(
            ) > self.max_complex_genome.complexity():
                self.max_complex_genome = curr_max_complex
            if self.min_complex_genome is None or curr_min_complex.complexity(
            ) < self.min_complex_genome.complexity():
                self.min_complex_genome = curr_min_complex

            self.max_dict[self.current_gen] = self.max_complex_genome

            # Reporters
            report_fitness(self)
            report_species(self.species, self.current_gen)
            report_output(self)
            best_fitnesses.append(self.best_genome.fitness)
            max_complexity.append(self.max_complex_genome.complexity())
            min_complexity.append(self.min_complex_genome.complexity())
            avg_complexity.append(
                (avg_complexities + 0.0) / len(self.population))
            self.avg_complex = (avg_complexities + 0.0) / len(self.population)
            avg_complexities = 0

            # Reached fitness goal, we can stop
            if self.best_genome.fitness >= goal:
                reached_goal = True

            # Create new unspeciated popuation based on current population's fitness
            self.population = self.reproduction.reproduce_with_species(
                self.species, self.size, self.current_gen)
            # Check for species extinction (species did not perform well)
            if not self.species.species:
                print("!!! Species went extinct !!!")
                self.population = self.reproduction.create_new_population(
                    self.size)

            # Speciate new population
            self.species.speciate(self.population, self.current_gen)
            self.current_gen += 1

        generations = range(self.current_gen)
        plot_fitness(generations, best_fitnesses)
        return self.best_genome
	def get_fitnesses(self):
		return [m.fitness for m in itervalues(self.members)]
예제 #5
0
    def reproduce_with_species(self, species_set, pop_size, generation):
        '''
		Creates and speciates genomes.

		species_set -- set of current species
		pop_size    -- population size
		generation  -- current generation
		'''
        all_fitnesses = []
        remaining_species = []
        # Traverse species and grab fitnesses from non-stagnated species
        for sid, species, species_is_stagnant in self.stagnation.update(
                species_set, generation):
            if species_is_stagnant:
                print("!!! Species {} Stagnated !!!".format(sid))
                # self.reporters.species_stagnant(sid, species)
                pass
            else:
                # Add fitnesses of members of current species
                all_fitnesses.extend(member.fitness
                                     for member in itervalues(species.members))
                remaining_species.append(species)
        # No species
        if not remaining_species:
            species_set.species = {}
            return {}
        # Find min/max fitness across entire population
        min_population_fitness = min(all_fitnesses)
        max_population_fitness = max(all_fitnesses)
        # Do not allow the fitness range to be zero, as we divide by it below.
        population_fitness_range = max(
            1.0, max_population_fitness - min_population_fitness)
        # Compute adjusted fitness and record minimum species size
        for species in remaining_species:
            # Determine current species average fitness
            mean_species_fitness = mean(
                [member.fitness for member in itervalues(species.members)])
            max_species_fitness = max(
                [member.fitness for member in itervalues(species.members)])
            # Determine current species adjusted fitness and update it
            species_adjusted_fitness = (
                mean_species_fitness -
                min_population_fitness) / population_fitness_range
            species.adjusted_fitness = species_adjusted_fitness
            species.max_fitness = max_species_fitness
        adjusted_fitnesses = [
            species.adjusted_fitness for species in remaining_species
        ]
        avg_adjusted_fitness = mean(adjusted_fitnesses)
        # Compute the number of new members for each species in the new generation.
        previous_sizes = [
            len(species.members) for species in remaining_species
        ]
        min_species_size = max(2, self.species_elitism)
        spawn_amounts = self.compute_species_sizes(adjusted_fitnesses,
                                                   previous_sizes, pop_size,
                                                   min_species_size)
        new_population = {}
        species_set.species = {}
        for spawn, species in zip(spawn_amounts, remaining_species):
            # If elitism is enabled, each species always at least gets to retain its elites.
            spawn = max(spawn, self.species_elitism)
            assert spawn > 0
            # The species has at least one member for the next generation, so retain it.
            old_species_members = list(iteritems(species.members))
            # Update species with blank slate
            species.members = {}
            # Update species in species set accordingly
            species_set.species[species.key] = species
            # Sort old species members in order of descending fitness.
            old_species_members.sort(reverse=True, key=lambda x: x[1].fitness)
            # Clone elites to new generation.
            if self.species_elitism > 0:
                for member_key, member in old_species_members[:self.
                                                              species_elitism]:
                    new_population[member_key] = member
                    spawn -= 1
            # If the species only has room for the elites, move onto next species
            if spawn <= 0: continue
            # Only allow fraction of species members to reproduce
            reproduction_cutoff = int(
                ceil(self.species_reproduction_threshold *
                     len(old_species_members)))
            # Use at least two parents no matter what the threshold fraction result is.
            reproduction_cutoff = max(reproduction_cutoff, 2)
            old_species_members = old_species_members[:reproduction_cutoff]

            # Randomly choose parents and produce the number of offspring allotted to the species.
            # NOTE: Asexual reproduction for now
            while spawn > 0:
                spawn -= 1
                parent1_key, parent1 = random.choice(old_species_members)
                # parent2_key, parent2 = random.choice(old_species_members)
                child_key = next(self.genome_indexer)
                child = Genome(child_key)
                # child.crossover(parent1, parent2)
                child.copy(parent1, generation)
                child.mutate(generation)
                new_population[child_key] = child
        return new_population