Example #1
0
 def genome_seeder(n):
     count = 0
     while count < n:
         for seed_genome in seed_genomes:
             genome = copy(seed_genome)
             mutator(genome)
             yield genome
             count += 1
Example #2
0
def genome_pair_factory(weight_gen=default_gen(), bias_gen=default_gen()):
    Node.innov_iter = itertools.count()
    Edge.innov_iter = itertools.count()

    np.random.seed(1)

    g1 = minimal(input_size=2, output_size=3, depth=5)
    n1 = g1.add_node(4)
    g1.add_edge(g1.layers[0][0], n1)
    g1.add_edge(n1, g1.outputs[0])

    n2 = g1.add_node(3)
    g1.add_edge(g1.layers[0][1], n2)
    g1.add_edge(n2, g1.outputs[2])

    g2 = copy(g1)

    n4 = g2.add_node(2)
    g2.add_edge(g2.layers[0][1], n4)
    g2.add_edge(n4, g2.layers[3][0])

    n5 = g1.add_node(4)
    g1.add_edge(g1.layers[3][0], n5)
    g1.add_edge(n5, g1.outputs[0])

    n3 = g1.add_node(3)
    e1 = g1.add_edge(g1.layers[0][0], n3)
    e2 = g1.add_edge(n3, g1.outputs[2])
    g2.layers[3].append(Node.copy(n3))
    g2.nodes.append(Node.copy(n3))

    n6 = g1.add_node(3)
    g1.add_edge(g1.layers[0][0], n6)
    g1.add_edge(n6, g1.outputs[1])

    g2.add_edge(g2.layers[0][0], n3)
    e2 = g2.add_edge(n3, g2.outputs[2])

    for w, edge in zip(weight_gen, [*g1.edges, *g2.edges]):
        edge.weight = w
    for w, node in zip(bias_gen, [*g1.nodes, *g2.nodes]):
        node.weight = w

    return g1, g2
Example #3
0
    def call_on_population(self, population):
        """Takes population of speciated genomes and evolves them into the next generation of genomes.

        - First we compute the population proportion that each group is granted.
        - Then we keep only the top species_member_survival_rate of each generation.
        - for each group
            - we put the top performing genome into the new populations
            - randomly draw Genomes from the remaining top performing
                genomes and apply mutations/pairing until the rest of the
                groups population share is taken up.

        :param population: NEATPopulation object
        :return: None
        """
        total_group_fitness_sum = sum([item['group_fitness'] for key, item in population.species.items()])
        new_genomes = []
        for key, item in population.species.items():
            pop_prop = int(round(population.population_size * (item['group_fitness'] / total_group_fitness_sum)))
            survival_prop = int(len(item['group']) * self.species_member_survival_rate)
            survival_prop = 5 if survival_prop < 5 else survival_prop
            item['group'] = item['group'][:survival_prop]
            best_performer = copy(item['group'][0])
            new_genomes.append(best_performer)
            for _ in range(pop_prop - 1):
                selected_gene = choice(item['group'])
                new_genome = self.call_on_genome(selected_gene)
                if random() > self.mutation_without_crossover_rate:
                    other_genome = None
                    if random() < self.interspecies_mating_rate and len(population.species) > 1:
                        # select from other species
                        other_item = choice([item for _, item in population.species.items()])
                        if len(other_item['group']) > 2:
                            other_genome = choice([g for g in other_item['group'] if g is not selected_gene])
                    elif len(item['group']) > 2:
                        other_genome = choice([g for g in item['group'] if g is not selected_gene])
                    if other_genome:
                        secondary, primary = sorted([new_genome, other_genome], key=lambda g: g.fitness)
                        new_genome = self.crossover(primary, secondary)
                new_genomes.append(new_genome)
        population.generation += 1
        population.genomes = new_genomes
Example #4
0
    def test_genome_weight_mutation(self):
        new_uniform_weight = 0.5
        with patch('numpy.random.uniform',
                   side_effect=[
                       0.1, *[0.95, 0.4, 0.95, *[random() for _ in range(10)]],
                       new_uniform_weight, *[random() for _ in range(10)]
                   ]):
            with patch('numpy.random.normal',
                       side_effect=[[0.1], [0.4],
                                    [random() for _ in range(10)]]):
                g = minimal(input_size=2, output_size=3, depth=5)
                m_g = copy(g)
                mutate_weights = curry_weight_mutator(
                    weight_mutation_likelihood=0.8,
                    weight_mutation_rate_random=0.1,
                    weight_mutation_rate_uniform=0.9,
                    weight_mutation_variance=0.1)
                mutate_weights(m_g)

        self.assertEqual(m_g.edges[0].weight, new_uniform_weight)
        self.assertEqual(g.edges[1].weight + 0.1, m_g.edges[1].weight)
Example #5
0
    def test_copy_factory(self):
        g = minimal()
        n2 = g.add_node(3)
        g.add_edge(g.layers[0][0], n2)
        g.add_edge(n2, g.outputs[0])
        g_copy = copy(g)
        self.assertNotEqual(g_copy, g)
        for node_copy, node in zip(g_copy.nodes, g.nodes):
            self.assertEqual(node_copy.innov, node.innov)

        for layer_copy, layer in zip(g_copy.layers, g.layers):
            self.assertEqual(len(layer_copy), len(layer))
            for node_copy, node in zip(layer_copy, layer):
                self.assertNotEqual(node_copy, node)
                self.assertEqual(node_copy.innov, node.innov)
                self.assertEqual(len(node_copy.edges_in), len(node.edges_in))
                self.assertEqual(len(node_copy.edges_out), len(node.edges_out))

        for edge_copy, edge in zip(g_copy.edges, g.edges):
            self.assertNotEqual(edge_copy, edge)
            self.assertEqual(edge_copy.innov, edge.innov)
Example #6
0
    def call_on_population(self, population):
        """Mutate Population.

        sorts genomes by fitness, removes any past a certain cutoff.
        Randomly samples from the remaining genomes and mutates them
        until the population is compelte again.

        :param population: Population Object being mutated
        :return: None
        """
        genomes = sorted(population.genomes,
                         key=lambda g: g.fitness,
                         reverse=True)
        cutoff = int(self.survival_rate * population.population_size)
        genomes = genomes[0:cutoff]
        population.genomes = [*genomes]
        new_genomes = np.random.choice(genomes,
                                       population.population_size - cutoff)
        for genome in new_genomes:
            new_genome = copy(genome)
            self.call_on_genome(new_genome)
            population.genomes.append(new_genome)
        population.generation += 1
Example #7
0
    def call_on_genome(self, genome):
        """Action on genome.

        Only performs weight and topological mutations.

        :param genome: Genome to copy and mutate.
        :return: New genome.
        """
        new_genome = copy(genome)
        new_genome.fitness = genome.fitness

        for edge in new_genome.edges:
            self.weight_mutator(edge)
        for node in new_genome.nodes:
            self.weight_mutator(node)

        if np.random.uniform(0, 1, 1) < self.new_node_probability:
            add_node(new_genome)

        if np.random.uniform(0, 1, 1) < self.new_edge_probability:
            add_edge(new_genome)

        return new_genome