示例#1
0
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