def reset_species(species: Species) -> Species: """ Reset the species members and the adjusted fitness value :param species: the species, that should be reset :return: the updated species """ species.members = [] species.adjusted_fitness = None return species
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_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 sort_agents_into_species(existing_species: List[Species], agents: List[Agent], species_id_generator: SpeciesIDGeneratorInterface, config: NeatConfig) -> List[Species]: """ Sort the given agents into the given list of species, according to the compatibility. If no matching species is found for an agent, a new species is created and the agent is placed inside it. Note: The existing members of a species are not deleted! :param existing_species: a list of existing species. :param agents: a list of agents that should be placed into species :param species_id_generator to generate new ids for species :param config: a neat config with the required compatibility parameters :return: the list of species with the sorted agents """ for agent in agents: for species in existing_species: compatibility = calculate_genetic_distance(agent.genome, species.representative, config) if compatibility <= config.compatibility_threshold: species.members.append(agent) break else: # Not found a matching element, new_species_id = species_id_generator.get_species_id() new_species = Species(new_species_id, agent.genome, [agent]) existing_species.append(new_species) return existing_species
def select_new_representative(species: Species, rnd: np.random.RandomState) -> Species: """ Assign a randomly selected genome from its members as new representative :param species: the species, with its members :param rnd: the random generator to select the representative :return: the updated species """ assert len(species.members) != 0 representative_index = rnd.randint(len(species.members)) species.representative = species.members[representative_index].genome return species
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_add_generation_fitness_reporter(self): self.assertIsNone(self.species_reporter.data.min_generation) self.assertIsNone(self.species_reporter.data.max_generation) self.assertEqual({}, self.species_reporter.data.species_size_dict) species1 = Species(1, None, [self.agent1, self.agent2, self.agent3, self.agent4, self.agent5, self.agent6, self.agent7]) # Add first generation generation1 = Generation(3, 1, [], [species1]) self.species_reporter.on_generation_evaluation_end(generation1, []) # Check after first generation self.assertEqual(3, self.species_reporter.data.min_generation) self.assertEqual(3, self.species_reporter.data.max_generation) self.assertEqual({1: ([3], [7])}, self.species_reporter.data.species_size_dict) # Add second generation with three species species1.members = [self.agent1, self.agent2, self.agent3] species2 = Species(2, None, [self.agent4, self.agent5, self.agent6]) species3 = Species(3, None, [self.agent7]) generation2 = Generation(4, 1, [], [species1, species2, species3]) self.species_reporter.on_generation_evaluation_end(generation2, []) # Check after second generation self.assertEqual(3, self.species_reporter.data.min_generation) self.assertEqual(4, self.species_reporter.data.max_generation) self.assertEqual({1: ([3, 4], [7, 3]), 2: ([4], [3]), 3: ([4], [1])}, self.species_reporter.data.species_size_dict) # Add third generation with two species species3.members = [self.agent4, self.agent5, self.agent6, self.agent7] generation3 = Generation(5, 1, [], [species1, species3]) self.species_reporter.on_generation_evaluation_end(generation3, []) # Check after third generation self.assertEqual(3, self.species_reporter.data.min_generation) self.assertEqual(5, self.species_reporter.data.max_generation) self.assertEqual({1: ([3, 4, 5], [7, 3, 3]), 2: ([4], [3]), 3: ([4, 5], [1, 4])}, self.species_reporter.data.species_size_dict)
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 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])
def test_get_species_id2(self): generator = SpeciesIDGeneratorSingleCore( [Species(4, None, None), Species(6, None, None)]) self.assertEqual(7, generator.get_species_id()) self.assertEqual(8, generator.get_species_id())