def test_generation(self): genome1 = create_genome_structure( 5, 2, modified_sigmoid_activation, NeatConfig(), InnovationNumberGeneratorSingleCore()) genome2 = create_genome_structure( 5, 2, modified_sigmoid_activation, NeatConfig(), InnovationNumberGeneratorSingleCore()) agent1 = Agent(1, genome1) agent2 = Agent(2, genome2) members = [agent1, agent2] species = [ Species(1, genome2, [agent1, agent2], max_species_fitness=10, generation_max_species_fitness=3, adjust_fitness=8) ] seed = 10 generation = Generation(2, seed, members, species) self.assertEqual(2, generation.number) self.assertEqual(species, generation.species_list) self.assertEqual(members, generation.agents) self.assertEqual(seed, generation.seed)
def test_agent(self): genome = create_genome_structure(5, 2, modified_sigmoid_activation, NeatConfig(), InnovationNumberGeneratorSingleCore()) agent = Agent(1, genome) self.assertEqual(1, agent.id) self.assertEqual(genome, agent.genome) self.assertIsNone(agent.neural_network) self.assertEqual(0, agent.fitness) self.assertEqual(0, agent.adjusted_fitness)
def setUp(self) -> None: self.agent1 = Agent(1, Genome(1, [], [])) self.agent2 = Agent(2, Genome(1, [], [])) self.agent3 = Agent(3, Genome(1, [], [])) self.agent4 = Agent(4, Genome(1, [], [])) self.agent5 = Agent(5, Genome(1, [], [])) self.agent6 = Agent(6, Genome(1, [], [])) self.agent7 = Agent(7, Genome(1, [], [])) self.species_reporter = sp.SpeciesReporter()
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_species(self): genome1 = create_genome_structure(5, 2, modified_sigmoid_activation, NeatConfig(), InnovationNumberGeneratorSingleCore()) genome2 = create_genome_structure(5, 2, modified_sigmoid_activation, NeatConfig(), InnovationNumberGeneratorSingleCore()) members = [Agent(1, genome1)] species = Species(1, genome2, members, max_species_fitness=10, generation_max_species_fitness=3, adjust_fitness=8) self.assertEqual(genome2, species.representative) self.assertEqual(8, species.adjusted_fitness) self.assertEqual(10, species.max_species_fitness) self.assertEqual(3, species.generation_max_species_fitness) self.assertEqual(members, species.members) self.assertEqual(1, species.id_)
def test_sort_agents_into_species(self): species_id_generator = SpeciesIDGeneratorSingleCore() species_list_new = ss.sort_agents_into_species( [], [self.agent1, self.agent2], species_id_generator, self.config) self.assertEqual(2, len(species_list_new)) # Test first species self.assertEqual(self.g1, species_list_new[0].representative) self.assertEqual(1, len(species_list_new[0].members)) self.assertEqual(self.agent1, species_list_new[0].members[0]) self.assertEqual(0, species_list_new[0].id_) # Test second species self.assertEqual(self.g2, species_list_new[1].representative) self.assertEqual(1, len(species_list_new[1].members)) self.assertEqual(self.agent2, species_list_new[1].members[0]) self.assertEqual(1, species_list_new[1].id_) # Insert one more matching genome genome_new = rs.deep_copy_genome(self.g1) agent_new = Agent(1, genome_new) species_list_new = ss.sort_agents_into_species(species_list_new, [agent_new], species_id_generator, self.config) self.assertEqual(2, len(species_list_new)) # Test first species self.assertEqual(self.g1, species_list_new[0].representative) self.assertEqual(2, len(species_list_new[0].members)) self.assertEqual(self.agent1, species_list_new[0].members[0]) self.assertEqual(agent_new, species_list_new[0].members[1]) self.assertEqual(0, species_list_new[0].id_) # Test second species self.assertEqual(self.g2, species_list_new[1].representative) self.assertEqual(1, len(species_list_new[1].members)) self.assertEqual(self.agent2, species_list_new[1].members[0]) self.assertEqual(1, species_list_new[1].id_)
def _build_generation_from_genome( initial_genome: Genome, species_id_generator: SpeciesIDGeneratorInterface, agent_id_generator: AgentIDGeneratorInterface, generation_seed: int, rnd: np.random.RandomState, config: NeatConfig) -> Generation: """ Build a generation from the given genome. The genome will be copied and the weight and biases will be randomized :param initial_genome: the genome as initial structure :param species_id_generator a generator to get species ids :param a generator to get agent ids :param generation_seed the seed for the generation :param rnd: a random generator to generate the seeds :param config: the neat config to specify the weights bounds :return: a new initialized generation with number 0, the created agents, and one species """ # Deep copy genome and set new weights genomes = [] for _ in range(config.population_size): seed = rnd.randint(2**24) rnd_generator_genome = np.random.RandomState(seed) # Copy genome, set new values and save seed copied_genome = rp.deep_copy_genome(initial_genome) copied_genome = _randomize_weight_bias(copied_genome, rnd_generator_genome, config) copied_genome.seed = seed genomes.append(copied_genome) agents = [ Agent(agent_id_generator.get_agent_id(), genome) for genome in genomes ] species = Species(id_=species_id_generator.get_species_id(), representative=genomes[0], members=agents) return Generation(0, generation_seed, agents, [species])
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
def setUp(self) -> None: self.config = NeatConfig(compatibility_factor_matching_genes=1, compatibility_factor_disjoint_genes=2, compatibility_threshold=2.5, compatibility_genome_size_threshold=0, population_size=8) self.g1_nodes = [ Node(1, NodeType.INPUT, 0, step_activation, 0), Node(2, NodeType.INPUT, 0, step_activation, 0), Node(3, NodeType.OUTPUT, 1.2, step_activation, 1), Node(4, NodeType.HIDDEN, 1.5, step_activation, 0.5), Node(6, NodeType.HIDDEN, 0.5, step_activation, 0.5), Node(7, NodeType.HIDDEN, 0.2, step_activation, 0.25) ] self.g1_connections = [ Connection(1, 1, 3, 1.2, True), Connection(2, 2, 3, 0.5, False), Connection(3, 1, 4, -1.2, True), Connection(4, 4, 3, 0.2, True), Connection(5, 2, 6, 2.0, True), Connection(6, 6, 3, -1.1, False) ] self.g1 = Genome(1, self.g1_nodes, self.g1_connections) self.g2_nodes = [ Node(1, NodeType.INPUT, 0, step_activation, 0), Node(2, NodeType.INPUT, 0, step_activation, 0), Node(3, NodeType.OUTPUT, 0.2, step_activation, 1), Node(4, NodeType.HIDDEN, 1.2, step_activation, 0.5), Node(5, NodeType.HIDDEN, 2.8, step_activation, 0.5) ] self.g2_connections = [ Connection(1, 1, 3, 0.8, True), Connection(2, 2, 3, 1.5, True), Connection(3, 1, 4, 1.2, True), Connection(4, 4, 3, 3.2, True), Connection(6, 6, 3, -1.1, False), Connection(7, 6, 3, -0.1, False), Connection(8, 1, 4, -1.1, False) ] self.g2 = Genome(2, self.g2_nodes, self.g2_connections) self.agent1 = Agent(1, self.g1) self.agent1.fitness = 1 self.agent2 = Agent(2, self.g2) self.agent2.fitness = 2 # Add some more agents, and complete species self.inno_num_generator = InnovationNumberGeneratorSingleCore() self.species_id_generator = SpeciesIDGeneratorSingleCore() 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.genome8 = gs.create_genome_structure(2, 1, step_activation, self.config, self.inno_num_generator) 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.agent8 = Agent(8, self.genome8) self.agent8.fitness = 8 self.species1 = Species(self.species_id_generator.get_species_id(), self.agent1.genome, [self.agent1, self.agent2, self.agent3], max_species_fitness=1.5, generation_max_species_fitness=10) self.species2 = Species(self.species_id_generator.get_species_id(), self.agent4.genome, [self.agent4, self.agent5, self.agent6], max_species_fitness=7, generation_max_species_fitness=5) self.species3 = Species(self.species_id_generator.get_species_id(), self.agent6.genome, [self.agent7, self.agent8], max_species_fitness=0, generation_max_species_fitness=6) self.generation = Generation( 21, 2, agents=[ self.agent1, self.agent2, self.agent3, self.agent4, self.agent5, self.agent6, self.agent7, self.agent8 ], species_list=[self.species1, self.species2, self.species3])