def test_evolution(self): p = Population(10, 3, 1) entire_population = [] for k, v in p.population.items(): if k != 's0': entire_population = entire_population + v pass p.evolve_species(p.population.get('s0'), entire_population, 2)
class NEATRunner(BaseTrainer): def __init__( self, config: Config, evaluator: GymEvaluator, reporters: Optional[Sequence[BaseReporter]] = None, num_workers: Optional[int] = multiprocessing.cpu_count(), ): self._evaluator = evaluator self._population = Population(config) reporters = reporters or [] for reporter in reporters: self._population.add_reporter(reporter) self._num_workers = num_workers def _train(self, num_frames: Optional[int], stop_time: Optional[int]) -> DefaultGenome: if self._num_workers is None: func = lambda g, c: self._evaluate_population_fitness( g, c, num_frames) else: parallel = ParallelEvaluator( num_workers=self._num_workers, evaluator=self._evaluator, max_num_frames=num_frames or float('inf'), ) func = parallel.evaluate if stop_time is not None: # it may not be 100% reliable but it's the best we can achieve without writing a custom # parallel executor func = _timeout_func(func, time(), stop_time) try: return self._population.run( fitness_function=func, n=float('inf'), ) except TimeoutError: return self._population.best_genome def _evaluate_population_fitness( self, genomes: Sequence[Tuple[int, DefaultGenome]], config: Config, max_num_frames: int, ): if self._evaluator.num_frames >= max_num_frames: raise TimeoutError() for _, genome in genomes: genome.fitness, num_frames = self._evaluator.evaluate( genome, config) self._evaluator.num_frames += num_frames
def __init__( self, config: Config, evaluator: GymEvaluator, reporters: Optional[Sequence[BaseReporter]] = None, num_workers: Optional[int] = multiprocessing.cpu_count(), ): self._evaluator = evaluator self._population = Population(config) reporters = reporters or [] for reporter in reporters: self._population.add_reporter(reporter) self._num_workers = num_workers
def test_evolution(self): p = Population(10, 3, 1) status = p.get_status() for s in status.keys(): output = [] for i in range(status.get(s, 0)): output.append(p.run(s, i, [1, 2, 3])) p.set_score(s, i, 1) p.evolve()
def learn_cartpole(config_path): env = gym.make('CartPole-v0') env._max_episode_steps = max_evaluation_steps # Load configuration. config = Config(StateMachineGenome, DefaultReproduction, DefaultSpeciesSet, DefaultStagnation, config_path) # Create the population, which is the top-level object for a NEAT run. p = Population(config) # Add a stdout reporter to show progress in the terminal. p.add_reporter(StdOutReporter(True)) stats = StatisticsReporter() p.add_reporter(stats) # Run for up for the given number of generations f = lambda genomes, config: eval_genomes(genomes, config, env=env) winner = p.run(f, num_generations) input("Press Enter to continue...") net = StateMachineNetwork.create(winner, config) eval_network(net, env, True)
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_align_genome(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['s0'] = [g1, g2] a1, a2 = Population.align_genome(g1, g2) self.assertEqual(1, a1[0].get_innovation()) self.assertEqual(2, a1[1].get_innovation()) self.assertEqual(3, a1[2].get_innovation()) self.assertEqual(4, a1[3].get_innovation()) self.assertEqual(5, a1[4].get_innovation()) self.assertEqual(None, a1[5]) self.assertEqual(None, a1[6]) self.assertEqual(8, a1[7].get_innovation()) self.assertEqual(None, a1[8]) self.assertEqual(None, a1[9]) self.assertEqual(1, a2[0].get_innovation()) self.assertEqual(2, a2[1].get_innovation()) self.assertEqual(3, a2[2].get_innovation()) self.assertEqual(4, a2[3].get_innovation()) self.assertEqual(5, a2[4].get_innovation()) self.assertEqual(6, a2[5].get_innovation()) self.assertEqual(7, a2[6].get_innovation()) self.assertEqual(None, a2[7]) self.assertEqual(9, a2[8].get_innovation()) self.assertEqual(10, a2[9].get_innovation())
def play(): env = gym.make('CartPole-v1') ob = env.reset() p = Population.load(FULLNAME) winner = p.get_winner() while True: action = winner.run(ob) ob, reward, done, info = env.step(np.argmax(action)) env.render() if done: ob = env.reset()
def test_flow(self): p = Population(10, 3, 1) for _ in range(100): status = p.get_status() for s in status.keys(): output = [] for i in range(status.get(s, 0)): out = p.run(s, i, [1, 2, 3])[0] output.append(out) p.set_score(s, i, random.randrange(1, 10)) print(s, output) p.evolve() # print a sample pr = Printer(p.population[next(iter(p.population))][0]) pr.print()
def play(): env = gym.make('LunarLanderContinuous-v2') ob = env.reset() p = Population.load(FULLNAME) winner = p.get_winner() while True: action = action_final_activation(winner.run(ob)) print('Action: {}'.format(action)) ob, reward, done, info = env.step(action) env.render() if done: ob = env.reset()
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))
def _epoch(self): if self.current_generation == 0: self.population = Population(self.configuration) else: # Create the next generation from the current generation. self.population.population = self.population.reproduction.reproduce( self.population.config, self.population.species, self.population.config.pop_size, self.population.generation) # Check for complete extinction. if not self.population.species.species: self.population.reporters.complete_extinction() # If requested by the user, create a completely new population, # otherwise raise an exception. if self.population.config.reset_on_extinction: self.population.population = self.population.reproduction.create_new( self.population.config.genome_type, self.population.config.genome_config, self.population.config.pop_size) else: raise CompleteExtinctionException() # Evaluate all genomes using the user-provided function. self._eval_genomes(list(iteritems(self.population.population)), self.population.config) # Gather and report statistics. best = None for g in itervalues(self.population.population): if best is None or g.fitness > best.fitness: best = g # Track the best genome ever seen. if self.population.best_genome is None or best.fitness > self.population.best_genome.fitness: self.population.best_genome = best self.champion = self.population.best_genome # Divide the new population into species. self.population.species.speciate(self.population.config, self.population.population, self.population.generation) return self.stopping_criterion.evaluate(self)
def print_population(): g = Population.load(FULLNAME).get_winner() Printer(g).print()
def ttt_test(config): gens = config['max_generations'] pop = None start_genome = None #//Hold records for each run evals = [ 0 for i in range(neatconfig.num_runs) ] genes = [ 0 for i in range(neatconfig.num_runs) ] nodes = [ 0 for i in range(neatconfig.num_runs) ] # Made as lists for pass-by-reference winnernum = [ 0 ] winnergenes = [ 0 ] winnernodes = [ 0 ] #//For averaging totalevals = 0 totalgenes = 0 totalnodes = 0 dprint(DEBUG_INFO, "START TTT TEST") if config['seed_with_start_genome']: gene_filename = neatconfig.genedir + "/" + config['start_genome_file'] iFile = open(gene_filename, "r") if not iFile: dprint(DEBUG_ERROR, "Unable to open starting genome file %s." % (gene_filename, )) return pop dprint(DEBUG_INFO, "Opened start genome file %s." % (gene_filename, )) #//Read in the start Genome dprint(DEBUG_INFO, "Reading in the start genome") line = iFile.readline() words = line.strip().split() curword = words[0] gid = int(words[1]) if curword != "genomestart": dprint(DEBUG_ERROR, "Bad starting genome file %s." % (gene_filename, )) return pop dprint(DEBUG_INFO, "Reading in Genome id %d." % (gid,)) start_genome = Genome() start_genome.SetFromFile(gid, iFile) iFile.close() dprint(DEBUG_INFO, "Verifying start_genome") if not start_genome.verify(): dprint(DEBUG_ERROR, "genome.verify() failed:", start_genome.deep_string()) #Complete a number of runs for expcount in range(neatconfig.num_runs): if config['seed_with_start_genome']: #//Spawn the Population dprint(DEBUG_INFO, "Spawning Population off Genome") pop = Population() pop.SetFromGenome(start_genome, neatconfig.pop_size) dprint(DEBUG_INFO, "Verifying Spawned Population[%d]" % (expcount, )) if not pop.verify(): dprint(DEBUG_ERROR, "Population[%d] verification failed" % (expcount, )) elif config['seed_with_previous_population']: population_filename = neatconfig.genedir + "/" + config['previous_population_file'] dprint(DEBUG_INFO, "Reading Population from %s" % (population_filename, )) pop = Population() pop.SetFromFilename(population_filename) dprint(DEBUG_INFO, "Verifying Start Population[%d]" % (expcount, )) if not pop.verify(): dprint(DEBUG_ERROR, "Population[%d] verification failed" % (expcount, )) #// evolve up to gens generations gen = 1 while gen <= gens: dprint(DEBUG_INFO, "Evaluating Spawned Population[%d] Epoch[%d]" % (expcount, gen)) # if not pop.verify(): # dprint(DEBUG_ERROR, "Population[%d] Epoch[%d] verification failed" % (expcount, gen)) #print "Epoch", gen generation_filename = neatconfig.generationdir + "/tttgen_%d" % (gen,) # Evaluate one generation, checking for a successful end #//Check for success if ttt_epoch(pop, gen, generation_filename, winnernum, winnergenes, winnernodes): evals[expcount] = neatconfig.pop_size * (gen-1) + winnernum[0] genes[expcount] = winnergenes[0] nodes[expcount] = winnernodes[0] break # in case we want to change after run has started config = ttt_read_config(neatconfig.configdir + '/ttt.config') gens = config['max_generations'] gen += 1 # end of generation loop if g_found_optimal: break # end of num_runs loop #//Average and print stats dprint(DEBUG_INFO, "Nodes: ") for expcount in range(neatconfig.num_runs): dprint(DEBUG_INFO, nodes[expcount]) totalnodes += nodes[expcount] dprint(DEBUG_INFO, "Genes: ") for expcount in range(neatconfig.num_runs): dprint(DEBUG_INFO, genes[expcount]) totalgenes += genes[expcount] dprint(DEBUG_INFO, "Evals ") samples = 0 for expcount in range(neatconfig.num_runs): dprint(DEBUG_INFO, evals[expcount]) if evals[expcount] > 0: totalevals += evals[expcount] samples += 1 if samples > 0: avgnodes = float(totalnodes)/samples avggenes = float(totalgenes)/samples avgevals = float(totalevals)/samples else: avgnodes = 0 avggenes = 0 avgevals = 0 dprint(DEBUG_INFO, "Failures:", (neatconfig.num_runs - samples), "out of", neatconfig.num_runs, "runs") dprint(DEBUG_INFO, "Average Nodes:", avgnodes) dprint(DEBUG_INFO, "Average Genes:", avggenes) dprint(DEBUG_INFO, "Average Evals:", avgevals) return pop
def xor_test(gens): gene_filename = neatconfig.genedir + "/xorstartgenes" pop = None start_genome = None #//Hold records for each run evals = [ 0 for i in range(neatconfig.num_runs) ] genes = [ 0 for i in range(neatconfig.num_runs) ] nodes = [ 0 for i in range(neatconfig.num_runs) ] # Made as lists for pass-by-reference winnernum = [ 0 ] winnergenes = [ 0 ] winnernodes = [ 0 ] #//For averaging totalevals = 0 totalgenes = 0 totalnodes = 0 iFile = open(gene_filename, "r") if not iFile: dprint(DEBUG_ERROR, "Unable to open starting genome file %s." % (gene_filename, )) return pop print "START XOR TEST" #//Read in the start Genome print "Reading in the start genome" line = iFile.readline() words = line.strip().split() curword = words[0] gid = int(words[1]) if curword != "genomestart": print "Bad starting genome file %s." % (gene_filename, ) return pop print "Reading in Genome id %d." % (gid,) start_genome = Genome() start_genome.SetFromFile(gid, iFile) iFile.close() print "Verifying start_genome" if not start_genome.verify(): dprint(DEBUG_ERROR, "genome.verify() failed:", start_genome.deep_string()) #Complete a number of runs for expcount in range(neatconfig.num_runs): #//Spawn the Population print "Spawning Population off Genome2" pop = Population() pop.SetFromGenome(start_genome, neatconfig.pop_size) print "Verifying Spawned Population[%d]" % (expcount, ) if not pop.verify(): dprint(DEBUG_ERROR, "Population[%d] verification failed" % (expcount, )) #// evolve up to gens generations for gen in range(1, gens+1): print "Verifying Spawned Population[%d] Epoch[%d]" % (expcount, gen) if not pop.verify(): dprint(DEBUG_ERROR, "Population[%d] Epoch[%d] verification failed" % (expcount, gen)) #print "Epoch", gen generation_filename = neatconfig.generationdir + "/gen_%d" % (gen,) # Evaluate one generation, checking for a successful end #//Check for success if xor_epoch(pop, gen, generation_filename, winnernum, winnergenes, winnernodes): evals[expcount] = neatconfig.pop_size * (gen-1) + winnernum[0] genes[expcount] = winnergenes[0] nodes[expcount] = winnernodes[0] break # end of generation loop if g_found_optimal: break # end of num_runs loop #//Average and print stats print "Nodes: " for expcount in range(neatconfig.num_runs): print nodes[expcount] totalnodes += nodes[expcount] print "Genes: " for expcount in range(neatconfig.num_runs): print genes[expcount] totalgenes += genes[expcount] print "Evals " samples = 0 for expcount in range(neatconfig.num_runs): print evals[expcount] if evals[expcount] > 0: totalevals += evals[expcount] samples += 1 if samples > 0: avgnodes = float(totalnodes)/samples avggenes = float(totalgenes)/samples avgevals = float(totalevals)/samples else: avgnodes = 0 avggenes = 0 avgevals = 0 print "Failures:", (neatconfig.num_runs - samples), "out of", neatconfig.num_runs, "runs" print "Average Nodes:", avgnodes print "Average Genes:", avggenes print "Average Evals:", avgevals return pop
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))
def __init__(self, network, populationsize): self.population = Population(populationsize, network) self.network = network
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
import gym import numpy as np from neat import Population, Printer env = gym.make('MountainCar-v0') done = False strain_count = 10 passing_score = 500 p = Population(1000, 2, 3) target_reward = 0.5 max_reward = -999999 winner = None max_position = -1.2 min_position = 0.6 while True: status = p.get_status() for s in status.keys(): output = [] for i in range(status.get(s, 0)): ob = env.reset() reward_sum = 200 while True: action = p.run(s, i, ob) ob, reward, done, info = env.step(np.argmax(action)) max_position = np.max([max_position, ob[0]]) min_position = np.min([min_position, ob[0]]) reward_sum = reward_sum + reward if done:
def test_status(self): p = Population(10, 3, 1) status = p.get_status() self.assertEqual({'s0': 10}, status)
def test_init(self): p = Population(10, 3, 1) self.assertEqual(10, len(p.population.get('s0'))) self.assertEqual(5, p.node_innovation) self.assertEqual(1, p.conn_innovation)
def train(): env = gym.make('CartPole-v1') try: p = Population.load(FULLNAME) print('Existing state loaded') except FileNotFoundError as e: print('Creating new state') p = Population(1000, env.observation_space.shape[0], env.action_space.n) max_reward = 0 while True: try: status = p.get_status() for s in status.keys(): for i in range(status.get(s, 0)): ob = env.reset() reward_sum = 0 while True: action = p.run(s, i, ob) ob, reward, done, info = env.step(np.argmax(action)) reward_sum = reward_sum + reward if done: break p.set_score(s, i, reward_sum) max_reward = np.max([reward_sum, max_reward]) print(p.generation, max_reward, p.population.keys()) p.evolve() except KeyboardInterrupt as e: try: print('\nsaving before exit') p.save(FULLNAME) sys.exit('Bye!') except RuntimeError as e: print('error saving: {}'.format(str(e)))
import sys sys.path.insert(0, 'H:\\Documents\\Coding_projects') sys.path.insert(1, 'H:\\Documents\\Coding_projects\\neat') from neat import Population from neat import Network from neat import DataConf import csv import pygame pop = Population(1000, 3, 1, False) nets = pop.get_pop() iterations = 100 pygame.init() win = pygame.display.set_mode((500,500)) data_handler = DataConf(win) with open('H:\\Documents\\Coding_projects\\xor\\data\\scores.csv', mode='w') as csv_file: csv_file = csv.writer(csv_file) csv_file.writerow(["Score"]) for i in range(iterations): fitness_tot = [] for n in nets: answer = n.feed_forward([0, 0, 1])[0] n.fitness += abs(0 - answer) answer = n.feed_forward([1, 0, 1])[0]