def eval_fitness(genome_id, genome, config, time_steps=400): """ Evaluates fitness of the provided genome. Arguments: genome_id: The ID of genome. genome: The genome to evaluate. config: The NEAT configuration holder. time_steps: The number of time steps to execute for maze solver simulation. Returns: The phenotype fitness score in range (0, 1] """ # run the simulation maze_env = copy.deepcopy(trialSim.orig_maze_environment) control_net = neat.nn.FeedForwardNetwork.create(genome, config) fitness = maze.maze_simulation_evaluate(env=maze_env, net=control_net, time_steps=time_steps) # Store simulation results into the agent record record = agent.AgentRecord(generation=trialSim.population.generation, agent_id=genome_id) record.fitness = fitness record.x = maze_env.agent.location.x record.y = maze_env.agent.location.y record.hit_exit = maze_env.exit_found record.species_id = trialSim.population.species.get_species_id(genome_id) record.species_age = record.generation - trialSim.population.species.get_species( genome_id).created # add record to the store trialSim.record_store.add_record(record) return fitness
def eval_individual(genome_id, genome, genomes, n_items_map, config): """ Evaluates the individual represented by genome. Arguments: genome_id: The ID of genome. genome: The genome to evaluate. genomes: The genomes population for current generation. n_items_map: The map to hold novelty items for current generation. config: The NEAT configuration holder. Return: The True if successful solver found. """ # create NoveltyItem for genome and store it into map n_item = archive.NoveltyItem(generation=trial_sim.population.generation, genomeId=genome_id) n_items_map[genome_id] = n_item # run the simulation maze_env = copy.deepcopy(trial_sim.orig_maze_environment) control_net = neat.nn.FeedForwardNetwork.create(genome, config) goal_fitness = maze.maze_simulation_evaluate(env=maze_env, net=control_net, time_steps=SOLVER_TIME_STEPS, n_item=n_item, mcns=MCNS) if goal_fitness == -1: # The individual doesn't meet the minimal fitness criterion print("Individ with ID: %d marked for extiction, MCNS: %f" % (genome_id, MCNS)) return False # Store simulation results into the agent record record = agent.AgentRecord(generation=trial_sim.population.generation, agent_id=genome_id) record.fitness = goal_fitness record.x = maze_env.agent.location.x record.y = maze_env.agent.location.y record.hit_exit = maze_env.exit_found record.species_id = trial_sim.population.species \ .get_species_id(genome_id) record.species_age = record.generation - \ trial_sim.population.species.get_species(genome_id).created # add record to the store trial_sim.record_store.add_record(record) # Evaluate the novelty of a genome and add the novelty item to the archive of Novelty items if appropriate if not maze_env.exit_found: # evaluate genome novelty and add it to the archive if appropriate record.novelty = trial_sim.archive \ .evaluate_individual_novelty(genome=genome, genomes=genomes, n_items_map=n_items_map) # update fittest organisms list trial_sim.archive.update_fittest_with_genome(genome=genome, n_items_map=n_items_map) return maze_env.exit_found
def eval_individual(genome_id, genome, genomes, n_items_map, generation): """ Evaluates the individual represented by genome. Arguments: genome_id: The ID of genome. genome: The genome to evaluate. genomes: The genomes population for current generation. n_items_map: The map to hold novelty items for current generation. generation: The current generation. Return: The True if successful solver found. """ # create NoveltyItem for genome and store it into map n_item = archive.NoveltyItem(generation=generation, genomeId=genome_id) n_items_map[genome_id] = n_item # run the simulation maze_env = copy.deepcopy(trial_sim.orig_maze_environment) multi_net = NEAT.NeuralNetwork() genome.BuildPhenotype(multi_net) control_net = ANN(multi_net) goal_fitness = maze.maze_simulation_evaluate( env=maze_env, net=control_net, time_steps=SOLVER_TIME_STEPS, n_item=n_item) # Store simulation results into the agent record record = agent.AgenRecord(generation=generation, agent_id=genome_id) record.fitness = goal_fitness record.x = maze_env.agent.location.x record.y = maze_env.agent.location.y record.hit_exit = maze_env.exit_found #record.species_id = trial_sim.population.species.get_species_id(genome_id) #record.species_age = record.generation - trial_sim.population.species.get_species(genome_id).created # add record to the store trial_sim.record_store.add_record(record) # Evaluate the novelty of a genome and add the novelty item to the archive of Novelty items if appropriate if not maze_env.exit_found: # evaluate genome novelty and add it to the archive if appropriate record.novelty = trial_sim.archive.evaluate_individual_novelty(genome=Genome(genome), genomes=genomes, n_items_map=n_items_map) # update fittest organisms list trial_sim.archive.update_fittest_with_genome(genome=Genome(genome), n_items_map=n_items_map) return (maze_env.exit_found, goal_fitness)
def evaluate_individual_solution(genome, generation, robot): """ The function to evaluate individual solution against maze environment. Arguments: genome: The genome to evaluate. generation: The current generation. robot: The object encapsulating the robots population Return: The tuple specifying if solution was found and the distance from maze exit of final robot position. """ # create NoveltyItem for genome and store it into map genome_id = genome.GetID() n_item = archive.NoveltyItem(generation=generation, genomeId=genome_id) # run the simulation maze_env = copy.deepcopy(robot.orig_maze_environment) multi_net = NEAT.NeuralNetwork() genome.BuildPhenotype(multi_net) depth = 8 try: genome.CalculateDepth() depth = genome.GetDepth() except: pass control_net = ANN(multi_net, depth=depth) distance = maze.maze_simulation_evaluate(env=maze_env, net=control_net, time_steps=SOLVER_TIME_STEPS, n_item=n_item) # Store simulation results into the agent record record = agent.AgenRecord(generation=generation, agent_id=genome_id) record.distance = distance record.x = maze_env.agent.location.x record.y = maze_env.agent.location.y record.hit_exit = maze_env.exit_found record.species_id = robot.get_species_id(genome) robot.record_store.add_record(record) return (maze_env.exit_found, distance, n_item)
def run_experiment(params, maze_env, novelty_archive, trial_out_dir, args=None, n_generations=100, save_results=False, silent=False): """ The function to run the experiment against hyper-parameters defined in the provided configuration file. The winner genome will be rendered as a graph as well as the important statistics of neuroevolution process execution. Arguments: params: The NEAT parameters maze_env: The maze environment to use in simulation. novelty_archive: The archive to work with NoveltyItems. trial_out_dir: The directory to store outputs for this trial n_generations: The number of generations to execute. save_results: The flag to control if intermdiate results will be saved. silent: If True than no intermediary outputs will be presented until solution is found. args: The command line arguments holder. Returns: True if experiment finished with successful solver found. """ # set random seed seed = int(time.time())#1562938287#42#1563358622#1559231616# random.seed(seed) # Create Population genome = NEAT.Genome(0, 11, 0, 2, False, NEAT.ActivationFunction.UNSIGNED_SIGMOID, NEAT.ActivationFunction.UNSIGNED_SIGMOID, 0, params, 0) pop = NEAT.Population(genome, params, True, 1.0, seed) # Create the trial simulation global trial_sim trial_sim = MazeSimulationTrial(maze_env=maze_env, population=pop, archive=novelty_archive) # Run for up to N generations. start_time = time.time() best_genome_ser = None best_ever_goal_fitness = 0 best_id = -1 solution_found = False for generation in range(n_generations): gen_time = time.time() # get list of current genomes genomes = NEAT.GetGenomeList(pop) genomes_tuples = [] for genome in genomes: genomes_tuples.append((genome.GetID(), genome)) # evaluate genomes genome, solution_found, fitness = eval_genomes(genomes_tuples, generation) # store the best genome if solution_found or best_ever_goal_fitness < fitness: best_genome_ser = pickle.dumps(genome) best_ever_goal_fitness = fitness best_id = genome.GetID() if solution_found: print('Solution found at generation: %d, best fitness: %f, species count: %d' % (generation, fitness, len(pop.Species))) break # advance to the next generation pop.Epoch() # print statistics gen_elapsed_time = time.time() - gen_time print("\n****** Generation: %d ******\n" % generation) print("Best objective fitness: %f, genome ID: %d" % (fitness, best_id)) print("Species count: %d" % len(pop.Species)) print("Generation elapsed time: %.3f sec" % (gen_elapsed_time)) print("Best objective fitness ever: %f, genome ID: %d" % (best_ever_goal_fitness, best_id)) print("Best novelty score: %f, genome ID: %d\n" % (pop.GetBestFitnessEver(), pop.GetBestGenome().GetID())) elapsed_time = time.time() - start_time best_genome = pickle.loads(best_genome_ser) # write best genome to the file best_genome_file = os.path.join(trial_out_dir, "best_genome.pickle") with open(best_genome_file, 'wb') as genome_file: pickle.dump(best_genome, genome_file) # write the record store data rs_file = os.path.join(trial_out_dir, "data.pickle") trial_sim.record_store.dump(rs_file) print("Record store file: %s" % rs_file) print("Random seed:", seed) print("Trial elapsed time: %.3f sec" % (elapsed_time)) print("Best objective fitness: %f, genome ID: %d" % (best_ever_goal_fitness, best_genome.GetID())) print("Best novelty score: %f, genome ID: %d\n" % (pop.GetBestFitnessEver(), pop.GetBestGenome().GetID())) # Visualize the experiment results show_results = not silent if save_results or show_results: if args is None: visualize.draw_maze_records(maze_env, trial_sim.record_store.records, view=show_results) else: visualize.draw_maze_records(maze_env, trial_sim.record_store.records, view=show_results, width=args.width, height=args.height, filename=os.path.join(trial_out_dir, 'maze_records.svg')) # store NoveltyItems archive data trial_sim.archive.write_fittest_to_file(path=os.path.join(trial_out_dir, 'ns_items_fittest.txt')) trial_sim.archive.write_to_file(path=os.path.join(trial_out_dir, 'ns_items_all.txt')) # create the best genome simulation path and render maze_env = copy.deepcopy(trial_sim.orig_maze_environment) multi_net = NEAT.NeuralNetwork() best_genome.BuildPhenotype(multi_net) control_net = ANN(multi_net) path_points = [] evaluate_fitness = maze.maze_simulation_evaluate( env=maze_env, net=control_net, time_steps=SOLVER_TIME_STEPS, path_points=path_points) print("Evaluated fitness: %f, of best agent ID: %d" % (evaluate_fitness, best_genome.GetID())) visualize.draw_agent_path(trial_sim.orig_maze_environment, path_points, Genome(best_genome), view=show_results, width=args.width, height=args.height, filename=os.path.join(trial_out_dir, 'best_solver_path.svg')) return solution_found
def run_experiment(maze_env, trial_out_dir, args=None, n_generations=100, save_results=False, silent=False): """ The function to run the experiment against hyper-parameters defined in the provided configuration file. The winner genome will be rendered as a graph as well as the important statistics of neuroevolution process execution. Arguments: maze_env: The maze environment to use in simulation. trial_out_dir: The directory to store outputs for this trial n_generations: The number of generations to execute. save_results: The flag to control if intermdiate results will be saved. silent: If True than no intermediary outputs will be presented until solution is found. args: The command line arguments holder. Returns: True if experiment finished with successful solver found. """ # set random seed seed = int(time.time()) #1571021768# print("Random seed: %d" % seed) # Create Population of Robots and objective functions robot = create_robot(maze_env, seed=seed) obj_func = create_objective_fun(seed) # Run for up to N generations. start_time = time.time() best_robot_genome_ser = None best_robot_id = -1 solution_found = False best_obj_func_coeffs = None best_solution_novelty = 0 best_solution_distance = 0 stats = Statistics() for generation in range(n_generations): print("\n****** Generation: %d ******\n" % generation) gen_time = time.time() # evaluate objective function population obj_func_coeffs, max_obj_func_fitness = evaluate_obj_functions( obj_func, generation) # evaluate robots population robot_genome, solution_found, robot_fitness, distances, \ obj_coeffs, best_distance, best_novelty = evaluate_solutions( robot=robot, obj_func_coeffs=obj_func_coeffs, generation=generation) stats.post_evaluate(max_fitness=robot_fitness, errors=distances) # store the best genome if solution_found or robot.population.GetBestFitnessEver( ) < robot_fitness: best_robot_genome_ser = pickle.dumps(robot_genome) best_robot_id = robot_genome.GetID() best_obj_func_coeffs = obj_coeffs best_solution_novelty = best_novelty best_solution_distance = best_distance if solution_found: print( '\nSolution found at generation: %d, best fitness: %f, species count: %d\n' % (generation, robot_fitness, len(robot.population.Species))) break # advance to the next generation robot.population.Epoch() obj_func.population.Epoch() # print statistics gen_elapsed_time = time.time() - gen_time print("Generation fitness -> solution: %f, objective function: %f" % (robot_fitness, max_obj_func_fitness)) print( "Gen. species count -> solution: %d, objective function: %d" % (len(robot.population.Species), len(obj_func.population.Species))) print("Gen. archive size -> solution: %d, objective function: %d" % (robot.archive.size(), obj_func.archive.size())) print("Objective function coeffts: %s" % obj_coeffs) print( "Gen. best solution genome ID: %d, distance to exit: %f, novelty: %f" % (robot_genome.GetID(), best_distance, best_novelty)) print("->") print("Best fitness ever -> solution: %f, objective function: %f" % (robot.population.GetBestFitnessEver(), obj_func.population.GetBestFitnessEver())) print( "Best ever solution genome ID: %d, distance to exit: %f, novelty: %f" % (best_robot_id, best_solution_distance, best_solution_novelty)) print("------------------------------") print("Generation elapsed time: %.3f sec\n" % (gen_elapsed_time)) elapsed_time = time.time() - start_time # Load serialized best robot genome best_robot_genome = pickle.loads(best_robot_genome_ser) # write best genome to the file best_genome_file = os.path.join(trial_out_dir, "best_robot_genome.pickle") with open(best_genome_file, 'wb') as genome_file: pickle.dump(best_robot_genome, genome_file) # write the record store data rs_file = os.path.join(trial_out_dir, "data.pickle") robot.record_store.dump(rs_file) print("==================================") print("Record store file: %s" % rs_file) print("Random seed: %d" % seed) print("............") print("Best solution fitness: %f, genome ID: %d" % (robot.population.GetBestFitnessEver(), best_robot_genome.GetID())) print("Best objective func coefficients: %s" % best_obj_func_coeffs) print("------------------------------") # Visualize the experiment results show_results = not silent if save_results or show_results: if args is None: visualize.draw_maze_records(maze_env, robot.record_store.records, view=show_results) else: visualize.draw_maze_records(maze_env, robot.record_store.records, view=show_results, width=args.width, height=args.height, filename=os.path.join( trial_out_dir, 'maze_records.svg')) # store NoveltyItems archive data robot.archive.write_to_file( path=os.path.join(trial_out_dir, 'ns_items_all.txt')) # create the best genome simulation path and render maze_env = copy.deepcopy(robot.orig_maze_environment) multi_net = NEAT.NeuralNetwork() best_robot_genome.BuildPhenotype(multi_net) depth = 8 try: best_robot_genome.CalculateDepth() depth = genome.GetDepth() except: pass control_net = ANN(multi_net, depth=depth) path_points = [] distance = maze.maze_simulation_evaluate(env=maze_env, net=control_net, time_steps=SOLVER_TIME_STEPS, path_points=path_points) print("Best solution distance to maze exit: %.2f, novelty: %.2f" % (distance, best_solution_novelty)) visualize.draw_agent_path(robot.orig_maze_environment, path_points, best_robot_genome, view=show_results, width=args.width, height=args.height, filename=os.path.join( trial_out_dir, 'best_solver_path.svg')) # Draw the best agent phenotype ANN visualize.draw_net(multi_net, view=show_results, filename="best_solver_net", directory=trial_out_dir) # Visualize statistics visualize.plot_stats(stats, ylog=False, view=show_results, filename=os.path.join(trial_out_dir, 'avg_fitness.svg')) print("------------------------") print("Trial elapsed time: %.3f sec" % (elapsed_time)) print("==================================") return solution_found
def run_experiment(config_file, maze_env, novelty_archive, trial_out_dir, args=None, n_generations=100, save_results=False, silent=False): """ The function to run the experiment against hyper-parameters defined in the provided configuration file. The winner genome will be rendered as a graph as well as the important statistics of neuroevolution process execution. Arguments: config_file: The path to the file with experiment configuration maze_env: The maze environment to use in simulation. novelty_archive: The archive to work with NoveltyItems. trial_out_dir: The directory to store outputs for this trial n_generations: The number of generations to execute. save_results: The flag to control if intermdiate results will be saved. silent: If True than no intermediary outputs will be presented until solution is found. args: The command line arguments holder. Returns: True if experiment finished with successful solver found. """ # set random seed seed = int(time.time()) random.seed(seed) print("Selected random seed:", seed) # Load configuration. config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation, config_file) # Create the population, which is the top-level object for a NEAT run. p = neat.Population(config) # Create the trial simulation global trial_sim trial_sim = MazeSimulationTrial(maze_env=maze_env, population=p, archive=novelty_archive) # Add a stdout reporter to show progress in the terminal. p.add_reporter(neat.StdOutReporter(True)) stats = neat.StatisticsReporter() p.add_reporter(stats) # Run for up to N generations. start_time = time.time() best_genome = p.run(eval_genomes, n=n_generations) elapsed_time = time.time() - start_time # Display the best genome among generations. print('\nBest genome:\n%s' % (best_genome)) solution_found = \ (best_genome.fitness >= config.fitness_threshold) if solution_found: print("SUCCESS: The stable maze solver controller was found!!!") else: print("FAILURE: Failed to find the stable maze solver controller!!!") # write the record store data rs_file = os.path.join(trial_out_dir, "data.pickle") trial_sim.record_store.dump(rs_file) print("Record store file: %s" % rs_file) print("Random seed:", seed) print("Trial elapsed time: %.3f sec" % (elapsed_time)) # Visualize the experiment results show_results = solution_found or not silent if save_results or show_results: node_names = { -1: 'RF_R', -2: 'RF_FR', -3: 'RF_F', -4: 'RF_FL', -5: 'RF_L', -6: 'RF_B', -7: 'RAD_F', -8: 'RAD_L', -9: 'RAD_B', -10: 'RAD_R', 0: 'ANG_VEL', 1: 'VEL' } visualize.draw_net(config, best_genome, view=show_results, node_names=node_names, directory=trial_out_dir, fmt='svg') if args is None: visualize.draw_maze_records(maze_env, trial_sim.record_store.records, view=show_results) else: visualize.draw_maze_records(maze_env, trial_sim.record_store.records, view=show_results, width=args.width, height=args.height, filename=os.path.join( trial_out_dir, 'maze_records.svg')) visualize.plot_stats(stats, ylog=False, view=show_results, filename=os.path.join(trial_out_dir, 'avg_fitness.svg')) visualize.plot_species(stats, view=show_results, filename=os.path.join(trial_out_dir, 'speciation.svg')) # store NoveltyItems archive data trial_sim.archive.write_fittest_to_file( path=os.path.join(trial_out_dir, 'ns_items_fittest.txt')) trial_sim.archive.write_to_file( path=os.path.join(trial_out_dir, 'ns_items_all.txt')) # create the best genome simulation path and render maze_env = copy.deepcopy(trial_sim.orig_maze_environment) control_net = neat.nn.FeedForwardNetwork.create(best_genome, config) path_points = [] evaluate_fitness = maze.maze_simulation_evaluate( env=maze_env, net=control_net, time_steps=SOLVER_TIME_STEPS, path_points=path_points) print("Evaluated fitness of best agent: %f" % evaluate_fitness) visualize.draw_agent_path(trial_sim.orig_maze_environment, path_points, best_genome, view=show_results, width=args.width, height=args.height, filename=os.path.join( trial_out_dir, 'best_solver_path.svg')) return solution_found