def test_another_crossover(self): g1 = Genome(3, 1) g2 = Genome(3, 1) node_i = 4 conn_i = 0 for generation in range(10): conn_i = g1.mutate_connections(conn_i) node_i, conn_i = g1.mutate_nodes(node_i, conn_i) conn_i = g2.mutate_connections(conn_i) node_i, conn_i = g2.mutate_nodes(node_i, conn_i) a1, a2 = Population.align_genome(g1, g2) g1 = Population.crossover(a1, a2, g1.get_input_nodes(), g1.get_output_nodes()) g2 = Population.crossover(a1, a2, g1.get_input_nodes(), g1.get_output_nodes()) Printer(g1).print()
def test_crossover(self): g1 = Genome(3, 1) g1.create_node(Node.TYPE_HIDDEN, 5) g1.connect_nodes_by_id(1, 4, 1) g1.connect_nodes_by_id(2, 4, 2) g1.connect_nodes_by_id(3, 4, 3) g1.connect_nodes_by_id(2, 5, 4) g1.connect_nodes_by_id(5, 4, 5) g1.connect_nodes_by_id(1, 5, 8) g2 = Genome(3, 1) g2.create_node(Node.TYPE_HIDDEN, 5) g2.create_node(Node.TYPE_HIDDEN, 6) g2.connect_nodes_by_id(1, 4, 1) g2.connect_nodes_by_id(2, 4, 2) g2.connect_nodes_by_id(3, 4, 3) g2.connect_nodes_by_id(2, 5, 4) g2.connect_nodes_by_id(5, 4, 5) g2.connect_nodes_by_id(5, 6, 6) g2.connect_nodes_by_id(6, 4, 7) g2.connect_nodes_by_id(3, 5, 9) g2.connect_nodes_by_id(1, 6, 10) p = Population(2, 3, 1) p.population[0] = g1 p.population[1] = g2 a1, a2 = Population.align_genome(g1, g2) g3 = Population.crossover(a1, a2, g1.get_input_nodes(), g1.get_output_nodes()) self.assertEqual(10, len(g3.connections)) self.assertEqual(6, len(g3.nodes)) self.assertEqual(1, g3.select_connection_by_innovation(1).get_innovation()) self.assertEqual(2, g3.select_connection_by_innovation(2).get_innovation()) self.assertEqual(3, g3.select_connection_by_innovation(3).get_innovation()) self.assertEqual(4, g3.select_connection_by_innovation(4).get_innovation()) self.assertEqual(5, g3.select_connection_by_innovation(5).get_innovation()) self.assertEqual(6, g3.select_connection_by_innovation(6).get_innovation()) self.assertEqual(7, g3.select_connection_by_innovation(7).get_innovation()) self.assertEqual(8, g3.select_connection_by_innovation(8).get_innovation()) self.assertEqual(9, g3.select_connection_by_innovation(9).get_innovation()) self.assertEqual(10, g3.select_connection_by_innovation(10).get_innovation()) self.assertEqual((2, 3), Population.calculate_excess_disjoint(g1, g2)) self.assertEqual(5, species_distance(g1, g2))
class Trainer: def __init__(self, network, populationsize): self.population = Population(populationsize, network) self.network = network #The fitness function rewards based on how accurate the output is #Optimal fitness is reached if input[0] is substracted from input[1] #Iterations is the amount of training cycles #Mutationrate is the chance that offspring is mutated #Elitism is the amount of genomes that are put into the next generation without change def train(self, iterations, mutationrate, elitism): oldFitnessSum = 0 newFitnessSum = 0 for i in range(iterations): #EVALUATION for member in self.population.population: self.network.loadDNA(member) #repeat network evalutation 5 times for accuracy for _ in range(5): #two random inputs inputs = [] inputs.append(uniform(-5, 10)) inputs.append(uniform(-10, 20)) self.network.setInputs(inputs) result = self.network.run()[0] expectation = inputs[0] - inputs[1] #perfect fitness if there is no difference #we also square the difference because we want some dope ass inequality member.fitness += 100 - pow(abs(result - expectation), 2) #PRINT GENERATION PROGRESS if (i % 2 == 0): oldFitnessSum = sum(dna.fitness for dna in self.population.population) else: newFitnessSum = sum(dna.fitness for dna in self.population.population) if (oldFitnessSum != 0 and newFitnessSum != 0): print("Gen Nr: " + str(i)) print("Difference between Generation Fitness Sum: " + str(round(newFitnessSum - oldFitnessSum, 2))) percentage = (newFitnessSum - oldFitnessSum) / oldFitnessSum * 100 print("Percentage difference between generation: " + str(round(percentage, 2)) + "%") print("New Fitness Sum: " + str(round(newFitnessSum, 2))) print( "Highest Fitness: " + str(max(dna.fitness for dna in self.population.population))) #CREATE NEW POPULATION #best genomes at beginning of list, so we can include them easily (elitism) self.population.population.sort(key=lambda x: x.fitness, reverse=True) #dont make a new generation on last iteration, so we can #take the population as-is and evaluate it one more time in main.py if (i < iterations - 1): population2 = [] #add 5 best genomes unchanged for elitismIndex in range(elitism): self.population.population[elitismIndex].fitness = 0 population2.append( self.population.population[elitismIndex]) for _ in range(len(self.population.population) - elitism): parent1 = self.population.rouletteSelect() parent2 = self.population.rouletteSelect() child = self.population.crossover(parent1, parent2) if (uniform(0, 1) < mutationrate): child = self.population.mutate(child) child.fitness = 0 population2.append(child) self.population.population = population2 return self.population
def test_empty_crossover(self): g1 = Genome(3, 1) g2 = Genome(3, 1) a1, a2 = Population.align_genome(g1, g2) c = Population.crossover(a1, a2, g1.get_input_nodes(), g1.get_output_nodes()) self.assertGreaterEqual(4, len(c.nodes))