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 = 1571021768  #int(time.time())
    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
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(config_file,
                   maze_env,
                   trial_out_dir,
                   args=None,
                   n_generations=100,
                   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.
        trial_out_dir:  The directory to store outputs for this trial
        n_generations:  The number of generations to execute.
        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 = 1559231616  #int(time.time())#42#
    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 trialSim
    trialSim = MazeSimulationTrial(maze_env=maze_env, population=p)

    # Add a stdout reporter to show progress in the terminal.
    p.add_reporter(neat.StdOutReporter(True))
    stats = neat.StatisticsReporter()
    p.add_reporter(stats)
    p.add_reporter(
        neat.Checkpointer(5,
                          filename_prefix='%s/maze-neat-checkpoint-' %
                          trial_out_dir))

    # 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")
    trialSim.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
    if not silent or solution_found:
        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,
                           True,
                           node_names=node_names,
                           directory=trial_out_dir,
                           fmt='svg')
        if args is None:
            visualize.draw_maze_records(maze_env,
                                        trialSim.record_store.records,
                                        view=True)
        else:
            visualize.draw_maze_records(maze_env,
                                        trialSim.record_store.records,
                                        view=True,
                                        width=args.width,
                                        height=args.height,
                                        filename=os.path.join(
                                            trial_out_dir, 'maze_records.svg'))
        visualize.plot_stats(stats,
                             ylog=False,
                             view=True,
                             filename=os.path.join(trial_out_dir,
                                                   'avg_fitness.svg'))
        visualize.plot_species(stats,
                               view=True,
                               filename=os.path.join(trial_out_dir,
                                                     'speciation.svg'))

    return solution_found