def test_updateGenomeFitness(self): genome = StorageGenome() genome.fitness = 1.0 self.genome_repository.get_genome_by_id = lambda x: genome self.genome_repository.update_genome = lambda x: x self.assertEqual(2.0, self.genome_repository.update_genome_fitness(genome._id, 2.0).fitness)
def test_disable_genome(self): g = StorageGenome() g.is_alive = True genome = Transformator.Transformator.encode_StorageGenome(g) self.db.find_one_by_id = MagicMock(return_value=genome) self.genome_repository.update_genome = lambda x: x self.assertFalse(self.genome_repository.disable_genome(g._id).is_alive)
def test_updateGenomesFitness(self): genomes = [] for i in range(0, 10): g = StorageGenome() g.fitness = float(1 / (i + 2)) genomes.append((g, 4.7)) self.genome_repository.get_genome_by_id = lambda x: x self.genome_repository.update_genomes = lambda x: x for i in self.genome_repository.update_genomes_fitness(genomes): self.assertEqual(4.7, i.fitness)
def test_eq(self): """ Tests, that the equality operator works. :return: """ s1 = StorageGenome() s2 = StorageGenome() s2._id = ObjectId(s1._id) s2.cluster = ObjectId(s1.cluster) self.assertEquals(s1, s2)
def test_getGenomesInCluster(self): genomes = [] genomes_in_tuple = [] for g in range(1, 10): genome = StorageGenome() genome.fitness = float(1/g) genomes.append(genome) genomes_in_tuple.append((genome, genome.fitness)) self.mock_genome_repository.get_genomes_in_cluster = MagicMock(return_value=genomes) self.assertListEqual(genomes_in_tuple, self.genome_selector.get_genomes_in_cluster(0))
def __init__(self): self.mock_population = [] genome_one = StorageGenome() genome_one._id = ObjectId("000000000000000000000000") genome_one.fitness = 0.5 genome_one.genes = [ (1, True, 0.5), (2, True, 0.5), (3, True, 0.5), (4, True, 0.5) ] genome_two = StorageGenome() genome_two._id = ObjectId("000000000000000000000001") genome_two.fitness = 0.7 genome_two.genes = [ (1, True, 0.5), (3, True, 1), (4, True, 0), (5, True, 0.5) ] self.mock_population.append(genome_one) self.mock_population.append(genome_two)
def analyze_and_insert(self, genome: StorageGenome): analysis_genome = AnalysisGenome(self.gene_repository, genome) analysis_result = self.analyst.analyze(analysis_genome) genome.analysis_result = analysis_result self.genome_repository.insert_genome(genome) self.clusterer.cluster_genome(genome)
def test_selectGenomesForDiscarding(self): """ checks if 20% of worst cluster or genomes were selected :return: """ cluster = [] genome = [] for i in range(0, 4): c = Cluster() c.offspring = i cluster.append(c) for i in range(0, 10): g = StorageGenome() g.fitness = float(1/(i+1)) genome.append(g) self.mock_cluster_repository.get_current_clusters = MagicMock(return_value=cluster) self.mock_genome_repository.get_genomes_in_cluster = MagicMock(return_value=genome) self.assertEqual(8, len(self.genome_selector.select_genomes_for_discarding()))
def decode_StorageGenome(document: dict) -> StorageGenome: """ decodes dictionary to StorageGenome :param document: dictionary to decode :return: StorageGenome """ try: document["genes"] = { ObjectId(gene_id_as_str): gene_tuple for gene_id_as_str, gene_tuple in document["genes"].items() } document.pop('_type') analysis_result = Transformator.decode_AnalysisResult(document['analysis_result']) document.__setitem__('analysis_result', analysis_result) storage_genome = StorageGenome() storage_genome.__dict__ = document return storage_genome except KeyError: return None
def test_selectGenomesForBreeding_and_selectGenomesForMutation(self): offspring = [10, 10, 10, 10] cluster = [] genome = [] for i in offspring: c = Cluster() c.offspring = i cluster.append(c) for i in range(0, 8): g = StorageGenome() g.fitness = float(1/(i+1)) genome.append(g) g = StorageGenome() self.mock_cluster_repository.get_current_clusters = MagicMock(return_value=cluster) self.mock_genome_repository.get_genomes_in_cluster = MagicMock(return_value=genome) self.assertEqual(8, len(self.genome_selector.select_genomes_for_breeding(0.2))) self.assertEqual(type(g), type(self.genome_selector.select_genomes_for_breeding(0.2)[0][0])) self.assertEqual(type(g), type(self.genome_selector.select_genomes_for_mutation(0.2)[0])) self.assertEqual(8, len(self.genome_selector.select_genomes_for_mutation(0.2)))
def mutate_add_edge( self, analysis_genome: AnalysisGenome, storage_genome: StorageGenome ) -> StorageGenome: random.seed() starting_vertex = random.choice(list(analysis_genome.nodes)) if starting_vertex not in analysis_genome.edges.keys(): # if the chosen vertex has no outgoing edges (i.e. is a sink), every # other vertex may be a possible endpoint possible_endpoints = list(analysis_genome.nodes) else: possible_endpoints = [] for node in analysis_genome.nodes: for target_node, _ in analysis_genome.edges[starting_vertex]: if node != target_node: # if there is no edge from the selected node to the cur- # rent node, it is a possible endpoint possible_endpoints.append(node) endpoint = random.choice(possible_endpoints) gene_id = self.gene_repository.get_gene_id_for_endpoints( starting_vertex, endpoint ) gene_weight = random.random() gene_enabled = ProbabilisticTools.weighted_choice( [ (True, self.mutation_parameters["new_gene_enabled_probability"]), (False, 1 - self.mutation_parameters["new_gene_enabled_probability"]) ] ) new_genome = StorageGenome(storage_genome) new_genome.genes[gene_id] = (gene_enabled, gene_weight) return new_genome
def test_selectClusterCombination(self): offspring = [10, 10] cluster = [] genome = [] for i in offspring: c = Cluster() c.offspring = i cluster.append(c) for i in range(0, 8): g = StorageGenome() g.fitness = float(1/(i+1)) genome.append(g) self.mock_genome_repository.get_genomes_in_cluster = MagicMock(return_value=genome) test_comb = self.genome_selector.select_cluster_combinations(cluster[0], cluster[1], 2) g = StorageGenome() g_type = (g, g) g_list = [g_type] self.assertEqual(2, len(test_comb)) self.assertEqual(type(g_list), type(test_comb)) self.assertEqual(2, len(test_comb[0])) self.assertEqual(type(g_type), type(test_comb[0]))
def mutate_perturb_weights(self, genome: StorageGenome) -> StorageGenome: random.seed() new_genome = StorageGenome(genome) for gid, gene in genome.genes.items(): perturb_weight = random.random() < self.mutation_parameters[ "perturb_gene_weight_probability" ] if perturb_weight: new_gene = self.perturb_weight(gene) genome.genes[gid] = new_gene return new_genome
def test_basicExampleWithCycles(self): genes = { 1: (1, 5), 2: (2, 5), 3: (1, 6), 4: (5, 6), 5: (6, 7), 6: (7, 5), 7: (6, 3), 8: (7, 4), } storage_genome = StorageGenome() analysis_result = AnalysisResult() storage_genome.inputs['input_1'] = 1 storage_genome.inputs['input_2'] = 2 storage_genome.outputs['output_1'] = 3 storage_genome.outputs['output_2'] = 4 storage_genome.genes[1] = (False, float(Fraction(7, 10))) storage_genome.genes[2] = (False, float(Fraction(3, 10))) storage_genome.genes[3] = (False, float(Fraction(6, 10))) storage_genome.genes[4] = (False, float(Fraction(4, 10))) storage_genome.genes[5] = (False, float(Fraction(3, 10))) storage_genome.genes[6] = (False, float(Fraction(6, 10))) storage_genome.genes[7] = (False, float(Fraction(7, 10))) storage_genome.genes[8] = (False, float(Fraction(5, 10))) analysis_result.topologically_sorted_nodes = [2, 1, 5, 6, 7, 4, 3] analysis_result.topologically_sorted_cycle_nodes = [7] analysis_result.gene_closes_cycle_map[6] = True storage_genome.analysis_result = analysis_result mock_gene_repository = MagicMock() mock_gene_repository.get_node_labels_by_gene_id =\ lambda node_id: genes[node_id] gen = SimulationGenome( mock_gene_repository, storage_genome ) result = gen.calculate_step({ 'input_1': float(Fraction(5, 10)), 'input_2': float(Fraction(5, 10)) }) self.assertEqual(float(Fraction(7, 20)), result['output_1']) self.assertEqual(float(Fraction(3, 40)), result['output_2'])
def mutate_add_node( self, analysis_genome: AnalysisGenome, storage_genome: StorageGenome ) -> StorageGenome: random.seed() starting_vertex = random.choice(list(analysis_genome.edges.keys())) endpoint, _ = random.choice(list(analysis_genome.edges[starting_vertex])) old_gene_id = self.gene_repository.get_gene_id_for_endpoints( starting_vertex, endpoint ) old_gene = storage_genome.genes[old_gene_id] # try to find an existing gene from the repository first # if a matching gene that connects start -> new vertex # and new_vertex -> end is not found, we'll ask gene repository for a new one. connecting_nodes = self.gene_repository.find_connecting_nodes( starting_vertex, endpoint ) connecting_node = None for node in connecting_nodes: if node not in analysis_genome.nodes: connecting_node = node break else: connecting_node = self.gene_repository.get_next_node_label() new_gene_one_id = self.gene_repository.get_gene_id_for_endpoints( starting_vertex, connecting_node ) new_gene_one_weight = old_gene[1] new_gene_one = (True, new_gene_one_weight) new_gene_two_id = self.gene_repository.get_gene_id_for_endpoints( connecting_node, endpoint ) new_gene_two = (True, 1.0) new_genome = StorageGenome(storage_genome) for gid, gene in new_genome.genes.items(): if gid == old_gene_id: new_genome.genes[gid] = (False, gene[1]) break new_genome.genes[new_gene_one_id] = new_gene_one new_genome.genes[new_gene_two_id] = new_gene_two return new_genome
def test_breed_genomes(self): fitter_genome = StorageGenome() fitter_genome.fitness = 22.74 fitter_genome.genes = { 0: (True, 0.21), 1: (True, -0.56), 2: (True, 0.354), 3: (True, 0.98), 7: (True, 0.47), 8: (True, -0.13) } other_genome = StorageGenome() other_genome.fitness = 19.233 other_genome.genes = { 0: (True, 0.1), 1: (True, 0.1), 2: (True, 0.1), 4: (True, 0.1), 5: (True, -0.1), 6: (True, -0.1) } similar_genome = StorageGenome() similar_genome.fitness = 21.83 similar_genome.genes = { 0: (True, 0.1), 1: (True, 0.1), 2: (True, 0.1), 4: (True, 0.1), 5: (True, -0.1), 6: (True, -0.1) } new_genome = self.breeder.breed_genomes( fitter_genome, other_genome ) new_genome_two = self.breeder.breed_genomes( fitter_genome, similar_genome ) # print(new_genome.genes) # TODO: proper testing # self.fail("Not implemented.") self.assertListEqual( list(new_genome.genes.keys()), [0, 1, 2, 3, 7, 8], "The wrong genes were inherited by breed_genomes()." ) self.assertEqual( new_genome.genes[3][1], 0.98, "The differing gene with id 3 wasn't inherited correctly by breed_genomes()." ) self.assertEqual( new_genome.genes[7][1], 0.47, "The differing gene with id 3 wasn't inherited correctly by breed_genomes()." ) self.assertEqual( new_genome.genes[8][1], -0.13, "The differing gene with id 3 wasn't inherited correctly by breed_genomes()." ) in_set = [(g in new_genome_two.genes.keys()) for g in [0, 1, 2]] self.assertTrue( lambda : not False in in_set ) differing_genes = [g for g in new_genome_two.genes.keys() if (g not in [0, 1, 2])] for gene_id in differing_genes: weight = new_genome_two.genes[gene_id][1] parent_genome = fitter_genome \ if gene_id in fitter_genome.genes.keys() \ else similar_genome original_weight = parent_genome.genes[gene_id][1] self.assertEqual( weight, original_weight )
def breed_genomes( self, genome_one: StorageGenome, genome_two: StorageGenome ) -> StorageGenome: """ Generates a new genome based on two input genomes. Matching genes are inherited randomly from one of the parents. Differing genes are inherited from the fitter parent. If the fitness value difference is below fitness_difference_threshold, the differing genes are inherited randomly as well. :param genome_one: :param genome_two: :return: """ # Distinction between bigger and smaller genome is made to # be able to distinguish between disjoint and excess genes # potentially needed for later approaches. random.seed() bigger_genome, smaller_genome = (genome_one, genome_two) \ if len(genome_one.genes) > len(genome_two.genes) \ else (genome_two, genome_one) bigger_genome_gene_ids = bigger_genome.genes.keys() smaller_genome_gene_ids = smaller_genome.genes.keys() all_gene_ids = list(smaller_genome_gene_ids) + list(bigger_genome_gene_ids) matching_gene_ids = [gene_id for gene_id in bigger_genome_gene_ids if gene_id in smaller_genome_gene_ids] differing_gene_ids = [gene_id for gene_id in all_gene_ids if gene_id not in matching_gene_ids] fitter_genome_table = genome_one.genes \ if genome_one.fitness > genome_two.fitness \ else genome_two.genes new_genome = StorageGenome() # Insert inherited matching genes. for gene_id in matching_gene_ids: parent_genome_table = random.choice( [ genome_one.genes, genome_two.genes ] ) gene_enabled = self.should_gene_be_enabled( genome_one.genes[gene_id], genome_two.genes[gene_id] ) gene_weight = parent_genome_table[gene_id][1] new_genome.genes[gene_id] = (gene_enabled, gene_weight) # Insert inherited differing genes. if abs(genome_one.fitness - genome_two.fitness) > \ self.breeding_parameters["fitness_difference_threshold"]: for gene_id in differing_gene_ids: if gene_id in fitter_genome_table.keys(): gene_enabled = self.should_gene_be_enabled( fitter_genome_table[gene_id] ) gene_weight = fitter_genome_table[gene_id][1] new_genome.genes[gene_id] = (gene_enabled, gene_weight) else: for gene_id in differing_gene_ids: inherit_gene = random.random() < self.breeding_parameters[ "inherit_randomly_if_same_fitness_probability" ] if inherit_gene: parent_genome_table = genome_one.genes \ if gene_id in genome_one.genes.keys() \ else genome_two.genes gene_enabled = self.should_gene_be_enabled( parent_genome_table[gene_id] ) gene_weight = parent_genome_table[gene_id][1] new_genome.genes[gene_id] = (gene_enabled, gene_weight) return new_genome
def test_copyConstruct(self): s1 = StorageGenome() s1.inputs['uiae'] = 1 s1.inputs['eaiu'] = 2 s1.outputs['nrtd'] = 3 s1.outputs['dtrn'] = 4 s1.genes[2] = (True, float(Fraction(15, 11))) s1.genes[5] = (True, float(Fraction(135, 9))) s1.genes[12] = (True, float(Fraction(17, 81))) s1.analysis_result.topologically_sorted_nodes = [1, 5, 7, 2, 3, 8] s1.analysis_result.topologically_sorted_cycle_nodes = [3, 2, 8, 1] s1.analysis_result.gene_closes_cycle_map[5] = True s2 = StorageGenome(s1) self.assertNotEqual(s1, s2) self.assertNotEqual(s1._id, s2._id) self.assertDictEqual(s1.inputs, s2.inputs) self.assertDictEqual(s1.outputs, s2.outputs) self.assertDictEqual(s1.genes, s2.genes) self.assertEqual(s1.cluster, s2.cluster) self.assertEqual(s1.analysis_result, s2.analysis_result) self.assertNotEqual(s1.__repr__(), s2.__repr__())