def test_create_initial_generation(self):
        config = NeatConfig(population_size=150,
                            connection_max_weight=10,
                            connection_min_weight=-10)

        generation1 = gs.create_initial_generation(
            10,
            3,
            step_activation,
            InnovationNumberGeneratorSingleCore(),
            SpeciesIDGeneratorSingleCore(),
            AgentIDGeneratorSingleCore(),
            config,
            seed=1)

        generation2 = gs.create_initial_generation(
            10,
            3,
            step_activation,
            InnovationNumberGeneratorSingleCore(),
            SpeciesIDGeneratorSingleCore(),
            AgentIDGeneratorSingleCore(),
            config,
            seed=1)

        self.assertEqual(0, generation1.number)
        self.assertEqual(0, generation2.number)
        self.assertEqual(150, len(generation1.agents))

        # Compare if generations and generated genomes are the same
        for agent1, agent2 in zip(generation1.agents, generation2.agents):
            self.assertEqual(agent1.genome.seed, agent2.genome.seed)

            for node1, node2, i in zip(agent1.genome.nodes,
                                       agent2.genome.nodes,
                                       range(len(agent1.genome.nodes))):
                self.assertEqual(node1.innovation_number,
                                 node2.innovation_number)
                self.assertEqual(i, node1.innovation_number)
                self.assertEqual(node1.bias, node2.bias)

                if node1.node_type != NodeType.INPUT:
                    self.assertNotAlmostEqual(0,
                                              node1.bias,
                                              delta=0.000000000001)

            # Check connection weights
            for connection1, connection2, i in zip(
                    agent1.genome.connections, agent2.genome.connections,
                    range(len(agent1.genome.connections))):
                self.assertEqual(connection1.weight, connection2.weight)
                self.assertEqual(connection1.innovation_number,
                                 connection2.innovation_number)
                self.assertEqual(i, connection1.innovation_number)
                self.assertNotAlmostEqual(0,
                                          connection1.weight,
                                          delta=0.000000000001)
예제 #2
0
    def test_create_offspring_pairs(self):
        agent_id_generator = AgentIDGeneratorSingleCore()
        config = NeatConfig()

        rnd = np.random.RandomState(1)
        # First 10 random values
        # rnd.randint(3) = 1
        # rnd.randint(3) = 0
        # rnd.randint(3) = 0
        # rnd.randint(3) = 1
        # rnd.randint(3) = 1
        # rnd.randint(3) = 0
        # rnd.randint(3) = 0
        # rnd.randint(3) = 1

        tuple_list = ss.create_offspring_pairs(self.species1, 4,
                                               agent_id_generator,
                                               self.generation, rnd, config)

        # Test tuples
        agent_id_generator = AgentIDGeneratorSingleCore()
        self.assertEqual(4, len(tuple_list))
        self.assertEqual((self.agent2.id, self.agent1.id,
                          agent_id_generator.get_agent_id()), tuple_list[0])
        self.assertEqual((self.agent1.id, self.agent2.id,
                          agent_id_generator.get_agent_id()), tuple_list[1])
        self.assertEqual((self.agent2.id, self.agent1.id,
                          agent_id_generator.get_agent_id()), tuple_list[2])
        self.assertEqual((self.agent1.id, self.agent2.id,
                          agent_id_generator.get_agent_id()), tuple_list[3])
    def evaluate(self, amount_input_nodes: int, amount_output_nodes,
                 activation_function, challenge: Challenge, config: NeatConfig,
                 seed: int) -> None:
        assert self.callback is not None

        # Initialize Parameters
        innovation_number_generator = InnovationNumberGeneratorSingleCore()
        species_id_generator = SpeciesIDGeneratorSingleCore()
        agent_id_generator = AgentIDGeneratorSingleCore()

        # Notify callback about starting evaluation
        self._notify_reporters_callback(lambda r: r.on_initialization())
        # Prepare challenge
        challenge.initialization()

        initial_generation = gs.create_initial_generation(amount_input_nodes, amount_output_nodes, activation_function,
                                                          innovation_number_generator, species_id_generator,
                                                          agent_id_generator, config, seed)

        finished_generation = self._evaluation_loop(initial_generation, challenge, innovation_number_generator,
                                                    species_id_generator, agent_id_generator, config)

        # Finish the evaluation and notify the callback
        self._cleanup(challenge)
        self._notify_reporters_callback(lambda r: r.on_finish(finished_generation, self.reporters))
예제 #4
0
    def _run_master(self, amount_input_nodes: int, amount_output_nodes,
                    activation_function, challenge: Challenge,
                    config: NeatConfig, seed: int):

        logger.info("Maser - Name: {}, Size: {}, Rank {}/{}", self.name,
                    self.size, self.rank, self.size - 1)
        logger.info("Waiting for workers to start...")
        with MPIPoolExecutor() as self.executor:
            self.executor.bootup(wait=True)
            logger.info("All Workers should have started")

            # Initialize Parameters
            innovation_number_generator = InnovationNumberGeneratorSingleCore()
            species_id_generator = SpeciesIDGeneratorSingleCore()
            agent_id_generator = AgentIDGeneratorSingleCore()

            # Notify callback about starting evaluation
            self._notify_reporters_callback(lambda r: r.on_initialization())

            initial_generation = gs.create_initial_generation(
                amount_input_nodes, amount_output_nodes, activation_function,
                innovation_number_generator, species_id_generator,
                agent_id_generator, config, seed)

            finished_generation = self._evaluation_loop(
                initial_generation, challenge, innovation_number_generator,
                species_id_generator, agent_id_generator, config)

            self._notify_reporters_callback(
                lambda r: r.on_finish(finished_generation, self.reporters))
    def test_evaluate_generation(self):
        generation = gs.create_initial_generation(
            2, 1, step_activation, InnovationNumberGeneratorSingleCore(),
            SpeciesIDGeneratorSingleCore(), AgentIDGeneratorSingleCore(),
            self.config, 1)

        self.optimizer_single._evaluate_generation(generation, self.challenge)

        # Check challenge
        self.assertEqual(self.config.population_size,
                         self.challenge.before_evaluation_count)
        self.assertEqual(self.config.population_size,
                         self.challenge.evaluate_count)
        self.assertEqual(self.config.population_size,
                         self.challenge.after_evaluation_count)

        # Check callback
        self.assertEqual(1, self.callback.on_generation_evaluation_start_count)
        self.assertEqual(self.config.population_size,
                         self.callback.on_agent_evaluation_start_count)
        self.assertEqual(self.config.population_size,
                         self.callback.on_agent_evaluation_end_count)
        self.assertEqual(1, self.callback.on_generation_evaluation_end_count)

        for expected_fitness, agent in zip(range(self.config.population_size),
                                           generation.agents):
            self.assertEqual(expected_fitness, agent.fitness)
예제 #6
0
 def setUp(self) -> None:
     self.config = NeatConfig(population_size=10)
     self.generation = gs.create_initial_generation(
         3, 2, step_activation, InnovationNumberGeneratorSingleCore(),
         SpeciesIDGeneratorSingleCore(), AgentIDGeneratorSingleCore(),
         self.config, 1)
     for i, agent in zip(range(len(self.generation.agents)),
                         self.generation.agents):
         agent.fitness = i
    def setUp(self) -> None:
        self.config = NeatConfig(population_size=7)
        self.inno_num_generator = InnovationNumberGeneratorSingleCore()
        self.species_id_generator = SpeciesIDGeneratorSingleCore()
        self.agent_id_generator = AgentIDGeneratorSingleCore()

        self.genome1 = gs.create_genome_structure(2, 1, step_activation,
                                                  self.config,
                                                  self.inno_num_generator)
        self.genome2 = gs.create_genome_structure(2, 1, step_activation,
                                                  self.config,
                                                  self.inno_num_generator)
        self.genome3 = gs.create_genome_structure(2, 1, step_activation,
                                                  self.config,
                                                  self.inno_num_generator)
        self.genome4 = gs.create_genome_structure(2, 1, step_activation,
                                                  self.config,
                                                  self.inno_num_generator)
        self.genome5 = gs.create_genome_structure(2, 1, step_activation,
                                                  self.config,
                                                  self.inno_num_generator)
        self.genome6 = gs.create_genome_structure(2, 1, step_activation,
                                                  self.config,
                                                  self.inno_num_generator)
        self.genome7 = gs.create_genome_structure(2, 1, step_activation,
                                                  self.config,
                                                  self.inno_num_generator)

        self.agent1 = Agent(1, self.genome1)
        self.agent1.fitness = 1
        self.agent2 = Agent(2, self.genome2)
        self.agent2.fitness = 2
        self.agent3 = Agent(3, self.genome3)
        self.agent3.fitness = 3
        self.agent4 = Agent(4, self.genome4)
        self.agent4.fitness = 4
        self.agent5 = Agent(5, self.genome5)
        self.agent5.fitness = 5
        self.agent6 = Agent(6, self.genome6)
        self.agent6.fitness = 6
        self.agent7 = Agent(7, self.genome7)
        self.agent7.fitness = 7

        self.species1 = Species(
            self.species_id_generator.get_species_id(), self.agent1.genome,
            [self.agent1, self.agent1, self.agent2, self.agent3])
        self.species2 = Species(self.species_id_generator.get_species_id(),
                                self.agent4.genome, [self.agent4, self.agent5])
        self.species3 = Species(self.species_id_generator.get_species_id(),
                                self.agent6.genome, [self.agent6, self.agent7])
    def test_create_initial_generation_genome(self):
        genome = Genome(20, [
            Node("abc", NodeType.INPUT, 0.3, step_activation, 0),
            Node("def", NodeType.OUTPUT, 0.4, step_activation, 1)
        ], [
            Connection("x", "abc", "def", 1.0, True),
            Connection("y", "def", "abc", -5, True)
        ])

        generation = gs.create_initial_generation_genome(
            genome,
            InnovationNumberGeneratorSingleCore(),
            SpeciesIDGeneratorSingleCore(),
            AgentIDGeneratorSingleCore(),
            NeatConfig(population_size=3),
            seed=1)

        self.assertEqual(3, len(generation.agents))
        self.assertEqual(0, generation.number)
        self.assertEqual(1, len(generation.species_list))
        self.assertEqual(3, len(generation.species_list[0].members))
        self.assertEqual(1, generation.seed)

        # First three random numbers
        # 1 - 12710949
        # 2 - 4686059
        # 3 - 6762380
        self.assertEqual(12710949, generation.agents[0].genome.seed)
        self.assertEqual(4686059, generation.agents[1].genome.seed)
        self.assertEqual(6762380, generation.agents[2].genome.seed)

        for node1, node2, node3, i in zip(generation.agents[0].genome.nodes,
                                          generation.agents[1].genome.nodes,
                                          generation.agents[2].genome.nodes,
                                          range(3)):
            self.assertEqual(node1.innovation_number, node2.innovation_number)
            self.assertEqual(node2.innovation_number, node3.innovation_number)
            self.assertEqual(node3.innovation_number, i)

        for connection1, connection2, connection3, i in zip(
                generation.agents[0].genome.connections,
                generation.agents[1].genome.connections,
                generation.agents[2].genome.connections, range(3)):
            self.assertEqual(connection1.innovation_number,
                             connection2.innovation_number)
            self.assertEqual(connection2.innovation_number,
                             connection3.innovation_number)
            self.assertEqual(connection3.innovation_number, i)
    def test_evaluation_loop(self):
        inno_generator = InnovationNumberGeneratorSingleCore()
        species_id_generator = SpeciesIDGeneratorSingleCore()
        agent_id_generator = AgentIDGeneratorSingleCore()

        initial_generation = gs.create_initial_generation(
            2, 1, step_activation, inno_generator, species_id_generator,
            agent_id_generator, self.config, 1)
        final_generation = self.optimizer_single._evaluation_loop(
            initial_generation, self.challenge, inno_generator,
            species_id_generator, agent_id_generator, self.config)

        expected_generation_number = 10
        self.assertEqual(expected_generation_number, final_generation.number)
        self.assertEqual(self.config.population_size,
                         len(final_generation.agents))

        # Check genome fitness
        for i, agent in zip(range(len(final_generation.agents)),
                            final_generation.agents):
            self.assertEqual(
                expected_generation_number * self.config.population_size + i,
                agent.fitness)

        # Check challenge calls
        self.assertEqual(
            (1 + expected_generation_number) * self.config.population_size,
            self.challenge.before_evaluation_count)
        self.assertEqual(
            (1 + expected_generation_number) * self.config.population_size,
            self.challenge.evaluate_count)
        self.assertEqual(
            (1 + expected_generation_number) * self.config.population_size,
            self.challenge.after_evaluation_count)

        # Check callback calls
        self.assertEqual(expected_generation_number + 1,
                         self.callback.on_generation_evaluation_start_count)
        self.assertEqual(
            (1 + expected_generation_number) * self.config.population_size,
            self.callback.on_agent_evaluation_start_count)
        self.assertEqual(
            (1 + expected_generation_number) * self.config.population_size,
            self.callback.on_agent_evaluation_end_count)
        self.assertEqual(expected_generation_number + 1,
                         self.callback.on_generation_evaluation_end_count)
예제 #10
0
    def test_build_generation_from_genome(self):
        initial_genome = Genome(20, [
            Node(1, NodeType.INPUT, 0, step_activation, 0),
            Node(2, NodeType.OUTPUT, 0.4, step_activation, 1)
        ], [Connection(1, 1, 2, 1.0, True),
            Connection(2, 1, 2, -5, True)])

        rnd = np.random.RandomState(1)
        generation = gs._build_generation_from_genome(
            initial_genome, SpeciesIDGeneratorSingleCore(),
            AgentIDGeneratorSingleCore(), 19, rnd,
            NeatConfig(population_size=3))

        self.assertEqual(3, len(generation.agents))
        self.assertEqual(0, generation.number)
        self.assertEqual(1, len(generation.species_list))
        self.assertEqual(3, len(generation.species_list[0].members))
        self.assertEqual(19, generation.seed)

        # First three random numbers
        # 1 - 12710949
        # 2 - 4686059
        # 3 - 6762380
        self.assertEqual(12710949, generation.agents[0].genome.seed)
        self.assertEqual(4686059, generation.agents[1].genome.seed)
        self.assertEqual(6762380, generation.agents[2].genome.seed)

        # Check if every weight and bias is not equal to 0
        for agent, i in zip(generation.agents, range(len(generation.agents))):
            genome = agent.genome
            self.assertEqual(i, agent.id)
            for node in genome.nodes:
                # Input nodes can have bias 0
                if node.node_type == NodeType.INPUT:
                    continue
                self.assertNotAlmostEqual(0, node.bias, delta=0.00000000001)

            for conn in genome.connections:
                self.assertNotAlmostEqual(0, conn.weight, delta=0.00000000001)
    def _build_new_generation(self, generation: Generation,
                              innovation_number_generator: InnovationNumberGeneratorInterface,
                              species_id_generator: SpeciesIDGeneratorSingleCore,
                              agent_id_generator: AgentIDGeneratorSingleCore,
                              config: NeatConfig) -> Generation:
        # Notify callback
        self._notify_reporters_callback(lambda r: r.on_reproduction_start(generation))

        # Get the random generator for the new generation
        new_generation_seed = np.random.RandomState(generation.seed).randint(2 ** 24)
        rnd = np.random.RandomState(new_generation_seed)

        # Get the best agents, which will be copied later
        best_agents_genomes = gs.get_best_genomes_from_species(generation.species_list,
                                                               config.species_size_copy_best_genome)

        # Get allowed species for reproduction
        generation = ss.update_fitness_species(generation)
        species_list = ss.get_allowed_species_for_reproduction(generation,
                                                               config.species_stagnant_after_generations)

        # TODO handle error no species
        if len(species_list) <= 5:
            species_list = generation.species_list
        # assert len(species_list) >= 1

        # Calculate the adjusted fitness values
        min_fitness = min([a.fitness for a in generation.agents])
        max_fitness = max([a.fitness for a in generation.agents])
        species_list = ss.calculate_adjusted_fitness(species_list, min_fitness, max_fitness)

        # Remove the low performing genomes
        species_list = ss.remove_low_genomes(species_list, config.percentage_remove_low_genomes)

        # Calculate offspring for species
        off_spring_list = ss.calculate_amount_offspring(species_list, config.population_size - len(best_agents_genomes))

        # Calculate off spring combinations
        off_spring_pairs = []
        for species, amount_offspring in zip(species_list, off_spring_list):
            off_spring_pairs += ss.create_offspring_pairs(species, amount_offspring, agent_id_generator, generation,
                                                          rnd, config)

        # Notify innovation number generator, that a new generation is created
        innovation_number_generator.next_generation(generation.number)

        # Create a dictionary for easy access
        agent_dict = {agent.id: agent for agent in generation.agents}

        # Create new agents - fill initially with best agents
        new_agents = [Agent(agent_id_generator.get_agent_id(), genome) for genome in best_agents_genomes]

        # Create agents with crossover
        self._notify_reporters_callback(lambda r: r.on_compose_offsprings_start())
        for parent1_id, parent2_id, child_id in off_spring_pairs:
            parent1 = agent_dict[parent1_id]
            parent2 = agent_dict[parent2_id]

            child_seed = (parent1.genome.seed + parent2.genome.seed) % 2 ** 24
            rnd_child = np.random.RandomState(child_seed)

            # Perform crossover for to get the nodes and connections for the child
            if parent1.fitness > parent2.fitness:
                child_nodes, child_connections = rp.cross_over(parent1.genome, parent2.genome, rnd_child, config)
            else:
                child_nodes, child_connections = rp.cross_over(parent2.genome, parent1.genome, rnd_child, config)

            # Create child genome
            child_genome = Genome(child_seed, child_nodes, child_connections)

            # Mutate genome
            child_genome = rp.mutate_weights(child_genome, rnd_child, config)
            child_genome, _, _, _ = rp.mutate_add_node(child_genome, rnd_child, innovation_number_generator, config)
            child_genome, _ = rp.mutate_add_connection(child_genome, rnd_child, innovation_number_generator, config)

            child_agent = Agent(child_id, child_genome)
            new_agents.append(child_agent)

        # Notify callback end
        self._notify_reporters_callback(lambda r: r.on_compose_offsprings_end())

        # TODO convert back
        # Select new representative
        existing_species = [ss.select_new_representative(species, rnd) for species in generation.species_list]
        # Reset members and fitness
        existing_species = [ss.reset_species(species) for species in existing_species]
        # existing_species = [ss.reset_species(species) for species in generation.species_list]

        # Sort members into species
        new_species_list = ss.sort_agents_into_species(existing_species, new_agents, species_id_generator, config)
        logger.info("Species IDs: {}".format([s.id_ for s in new_species_list]))
        logger.info("Species Mem: {}".format([len(s.members) for s in new_species_list]))

        # Filter out empty species
        new_species_list = ss.get_species_with_members(new_species_list)

        # Create new generation, notify callback and return new generation
        new_generation = Generation(generation.number + 1, new_generation_seed, new_agents, new_species_list)
        self._notify_reporters_callback(lambda r: r.on_reproduction_end(new_generation))
        return new_generation