示例#1
0
def evolutionary_run(gens, pop_size, output_path, run_num, numofjoints):
    """ Conduct an evolutionary run using the snake and muscle model. 
    """
    params = NEAT.Parameters()
    params.CompatTreshold = 5.0
    params.CompatTresholdModifier = 0.3
    params.YoungAgeTreshold = 15
    params.SpeciesMaxStagnation = 1000
    params.OldAgeTreshold = 35
    params.MinSpecies = 1
    params.MaxSpecies = 25
    params.RouletteWheelSelection = False
    params.RecurrentProb = 0.25
    params.OverallMutationRate = 0.33
    params.MutateWeightsProb = 0.90
    params.WeightMutationMaxPower = 1.0
    params.WeightReplacementMaxPower = 5.0
    params.MutateWeightsSevereProb = 0.5
    params.WeightMutationRate = 0.75
    params.MaxWeight = 20
    params.MutateAddNeuronProb = 0.4
    params.MutateAddLinkProb = 0.4
    params.MutateRemLinkProb = 0.05
    params.CrossoverRate = 0.4

    assert pop_size >= 0, "wrong population size argument! pop_size: %d" % pop_size
    params.PopulationSize = pop_size

    # worm has only one dof (turning around y-axis) per joint
    num_outputs = numofjoints
    # the inputs for the ANN are the 7 current joint positions and the amplitude of a sine wave as well as a bias
    num_inputs = numofjoints + 1 + 1

    # Initialize the population
    # Genome(ID, NumInputs, NumHidden, NumOutputs, ActivationFunction?, Output activation function, Hidden layer acitvation function, seed, params)
    genome = NEAT.Genome(0, num_inputs, 0, num_outputs, False,
                         NEAT.ActivationFunction.SIGNED_SIGMOID,
                         NEAT.ActivationFunction.SIGNED_SIGMOID, 0, params)
    # Population(Genome, params, randomizedweights?, randomrange)
    population = NEAT.Population(genome, params, True, 1.0)
    genome_list = NEAT.GetGenomeList(population)

    morph_pop = MorphGenomes(pop_size)
    for ind in genome_list:
        morph_pop.addIndividual(ind.GetID())
    morph_genomes = morph_pop.getGenomes()

    # ANN genome and morphology genome are zipped together
    # Zip the two genome components together for use in the parallel call.
    zip_args = [(ind, morph_genomes[ind.GetID()]) for ind in genome_list]

    mnlog.write_population_statistics_headers(output_path + str(run_num) +
                                              "_fitnesses.dat")

    # Setup multiprocessing
    cores = mpc.cpu_count()
    #cores = 1
    pool = mpc.Pool(initializer=initProcess,
                    initargs=(
                        GlobalVarWorkaround.args,
                        GlobalVarWorkaround.man,
                        GlobalVarWorkaround.worm,
                    ),
                    processes=cores)

    assert gens >= 0, "wrong number of generations as argument! gens: %d" % gens

    for gen in xrange(gens):
        print gen
        #fitnesses = map(evaluate_individual,zip_args) # serial execution
        fitnesses = pool.map(evaluate_individual, zip_args)

        replace_nanfitnesses(fitnesses)

        for g, f in zip(genome_list, fitnesses):
            g.SetFitness(f)

        print("Generation " + str(gen) + "\t: " + str(max(fitnesses)))

        # Write the best performing individual to a file.
        mnlog.write_best_individual(
            output_path + "best_individuals/Evo_NEAT_run_" + str(run_num) +
            "_best_gen_" + str(gen) + ".dat",
            genome_list[fitnesses.index(max(fitnesses))])
        morph_pop.logGenome(
            genome_list[fitnesses.index(max(fitnesses))].GetID(),
            "Evo_NEAT_run_" + str(run_num) + "_best_gen_" + str(gen),
            output_path)

        # Write information about the best individual we wrote.
        with open(
                output_path + "/" + str(run_num) +
                "_best_individuals_logging.dat", "a") as f:
            f.write("Generation: "+str(gen)+" Individual is: "+str(genome_list[fitnesses.index(max(fitnesses))].GetID())+\
                " Fitness is: "+str(max(fitnesses))+"\n")

        # Log the progress of the entire population.
        mnlog.write_population_statistics(
            output_path + str(run_num) + "_fitnesses.dat", genome_list,
            fitnesses, gen)

        # Log the final population for later evaluation.
        if gen == gens - 1:
            population.Save(output_path + "run_" + str(run_num) +
                            "_population_generation_" + str(gen) + ".dat")

        # Create the next generation
        population.Epoch()
        genome_list = NEAT.GetGenomeList(population)
        morph_pop.NextGen()
        zip_args = []
        for ind in genome_list:
            # PID .. parent ID
            pid1 = ind.GetPID1()

            # if pid2 is negative it means that no crossover happend!
            pid2 = ind.GetPID2()
            gid = ind.GetID()

            # Handle Crossover
            morph_pop.Crossover(gid, pid1, pid2)

        # Handle Mutation
        morph_pop.MutatePopulation()

        # Zip the arguments for calling the evolution function.
        morph_genomes = morph_pop.getGenomes()
        zip_args = [(ind, morph_genomes[ind.GetID()]) for ind in genome_list]
示例#2
0
def evolutionary_run(**kwargs):
    """ Conduct an evolutionary run.  
    
    Args:
        gens: generations of evolution
        pop_size: population size
        mut_prob: mutation probability
    """
    global args, current_network, run_num, output_path, population_size, simulation

    params = NEAT.Parameters()
    params.CompatTreshold = 5.0
    params.CompatTresholdModifier = 0.3
    params.YoungAgeTreshold = 15
    params.SpeciesMaxStagnation = 50
    params.OldAgeTreshold = 35
    params.MinSpecies = 1
    params.MaxSpecies = 25
    params.RouletteWheelSelection = False
    params.RecurrentProb = 0.25
    params.OverallMutationRate = 0.33
    params.MutateWeightsProb = 0.90
    params.WeightMutationMaxPower = 1.0
    params.WeightReplacementMaxPower = 5.0
    params.MutateWeightsSevereProb = 0.5
    params.WeightMutationRate = 0.75
    params.MaxWeight = 20

    params.MutateAddNeuronProb = 0.04
    params.MutateAddLinkProb = 0.1
    params.MutateRemSimpleNeuronProb = 0.04
    params.MutateRemLinkProb = 0.1

    # Phased Searching
    # params.PhasedSearching = True;
    # params.SimplifyingPhaseMPCTreshold = 20;
    # params.SimplifyingPhaseStagnationTreshold = 20;
    # params.ComplexityFloorGenerations = 20;

    params.PopulationSize = kwargs['pop_size']

    params.Save(output_path + str(run_num) + "_NEAT_params.cfg")

    # Initialize the populations
    genome = NEAT.Genome(0, 22, 0, 16, False,
                         NEAT.ActivationFunction.SIGNED_SIGMOID,
                         NEAT.ActivationFunction.SIGNED_SIGMOID, 0, params)
    # If not including a periodic input.
    if args.no_periodic:
        genome = NEAT.Genome(0, 21, 0, 16, False,
                             NEAT.ActivationFunction.SIGNED_SIGMOID,
                             NEAT.ActivationFunction.SIGNED_SIGMOID, 0, params)
    population = NEAT.Population(genome, params, True, 1.0)
    genome_list = NEAT.GetGenomeList(population)

    mnlog.write_population_statistics_headers(
        output_path + str(run_num) + "_fitnesses.dat",
        optional_additions="Num_Neurons,Num_Connections")

    # Setup multiprocessing
    cores = mpc.cpu_count()
    pool = mpc.Pool(processes=cores - 2)

    for gen in xrange(kwargs['gens']):
        ind_descriptor = pool.map(
            evaluate_individual,
            genome_list)  # 0 - fit, 1 - # neurons, 2 - # connections
        fitnesses = []
        num_conns = []
        num_neurons = []
        for g, ind in zip(genome_list, ind_descriptor):
            g.SetFitness(ind[0])
            fitnesses.append(ind[0])
            num_neurons.append(ind[1])
            num_conns.append(ind[2])
        print("Generation " + str(gen) + "\t: " + str(max(fitnesses)))

        # Write the best performing individual to a file.
        mnlog.write_best_individual(
            output_path + "best_individuals/Evo_NEAT_Mus_run_" + str(run_num) +
            "_best_gen_" + str(gen) + ".dat",
            genome_list[fitnesses.index(max(fitnesses))])

        # Log the progress of the entire population.
        mnlog.write_population_statistics(
            output_path + str(run_num) + "_fitnesses.dat",
            genome_list,
            fitnesses,
            gen,
            optional_additions=zip(num_neurons, num_conns))

        # Log the final population for later evaluation.
        if gen == kwargs['gens'] - 1:
            population.Save(output_path + "run_" + str(run_num) +
                            "_population_generation_" + str(gen) + ".dat")

        # Create the next generation
        population.Epoch()

        # Get the genomes
        genome_list = NEAT.GetGenomeList(population)
示例#3
0
def evolutionary_run(**kwargs):
    """ Conduct an evolutionary run using the snake and muscle model.  
    
    Args:
        gens: generations of evolution
        pop_size: population size
        mut_prob: mutation probability
    """
    global args, current_network, run_num, output_path, population_size, simulation

    params = NEAT.Parameters()  
    params.CompatTreshold = 5.0
    params.CompatTresholdModifier = 0.3
    params.YoungAgeTreshold = 15
    params.SpeciesMaxStagnation = 50
    params.OldAgeTreshold = 35
    params.MinSpecies = 1 
    params.MaxSpecies = 25
    params.RouletteWheelSelection = False
    params.RecurrentProb = 0.25
    params.OverallMutationRate = 0.33
    params.MutateWeightsProb = 0.90
    params.WeightMutationMaxPower = 1.0
    params.WeightReplacementMaxPower = 5.0
    params.MutateWeightsSevereProb = 0.5
    params.WeightMutationRate = 0.75
    params.MaxWeight = 20
    
    params.MutateAddNeuronProb = 0.04
    params.MutateAddLinkProb = 0.1
    params.MutateRemSimpleNeuronProb = 0.04
    params.MutateRemLinkProb = 0.1

    # Phased Searching
    # params.PhasedSearching = True;
    # params.SimplifyingPhaseMPCTreshold = 20;
    # params.SimplifyingPhaseStagnationTreshold = 20;
    # params.ComplexityFloorGenerations = 20;

    params.PopulationSize = kwargs['pop_size'] 

    params.Save(output_path+str(run_num)+"_NEAT_params.cfg")
   
    # Initialize the populations
    genome = NEAT.Genome(0, 22, 0, 8, False, NEAT.ActivationFunction.SIGNED_SIGMOID, NEAT.ActivationFunction.SIGNED_SIGMOID, 0, params)
    # If not including a periodic input.
    if args.no_periodic:
        genome = NEAT.Genome(0, 21, 0, 8, False, NEAT.ActivationFunction.SIGNED_SIGMOID, NEAT.ActivationFunction.SIGNED_SIGMOID, 0, params)
    population = NEAT.Population(genome, params, True, 1.0)
    genome_list = NEAT.GetGenomeList(population)

    # Initialize the muscle groups either symmetrically or not symmetrically.
    if args.sym_mus_groups:
        mus_networks = {ind.GetID(): MuscleNetwork(gid=ind.GetID(),num_groups=4,num_nodes=[4,4,4,4]) for ind in genome_list}
    else:
        mus_networks = {ind.GetID(): MuscleNetwork(gid=ind.GetID(),num_groups=8,num_nodes=[4,4,4,4,4,4,4,4]) for ind in genome_list}

    mnlog.write_population_statistics_headers(output_path+str(run_num)+"_fitnesses.dat",optional_additions="Num_Neurons,Num_Connections")

    # Setup multiprocessing
    cores = mpc.cpu_count()
    pool = mpc.Pool(processes=cores-2)

    # Zip the arguments for the evaluate wrapper function.
    zip_args = [(ind,mus_networks[ind.GetID()]) for ind in genome_list]

    for gen in xrange(kwargs['gens']):
        ind_descriptor = pool.map(evaluate_individual,zip_args)
        # fitnesses = pool.map(
        #     Simulation(log_frames=args.log_frames, run_num=args.run_num, eval_time=args.eval_time, dt=.02, n=4),
        #     zip_args
        #     )
        fitnesses = []
        num_conns = []
        num_neurons = []
        for g,ind in zip(genome_list,ind_descriptor):
            g.SetFitness(ind[0])
            fitnesses.append(ind[0])
            num_neurons.append(ind[1])
            num_conns.append(ind[2])
        print("Generation "+str(gen)+"\t: "+str(max(fitnesses)))

        # Write the best performing individual to a file.
        mnlog.write_best_individual(output_path+"best_individuals/Evo_NEAT_Mus_run_"+str(run_num)+"_best_gen_"+str(gen)+".dat", 
                genome_list[fitnesses.index(max(fitnesses))])
        muslog.write_network(output_path+"best_individuals/Evo_NEAT_Mus_run_"+str(run_num)+"_best_mn_gen_"+str(gen)+".dat",
                mus_networks[genome_list[fitnesses.index(max(fitnesses))].GetID()])

        # Log the progress of the entire population.
        mnlog.write_population_statistics(output_path+str(run_num)+"_fitnesses.dat", genome_list, fitnesses, gen, optional_additions=zip(num_neurons,num_conns))

        # Log the final population for later evaluation.
        if gen == kwargs['gens'] - 1:
            population.Save(output_path+"run_"+str(run_num)+"_population_generation_"+str(gen)+".dat")
            muslog.write_networks(output_path+"run_"+str(run_num)+"_population_generation_mus_nets_"+str(gen)+".dat",
                [mn for k, mn in mus_networks.iteritems()])       

        # Create the next generation
        population.Epoch()
        new_mus_nets = {}
        zip_args = []

        # Perform evolutionary development of the Muscle Networks.
        genome_list = NEAT.GetGenomeList(population)
        for ind in genome_list:
            pid1 = ind.GetPID1()
            pid2 = ind.GetPID2()
            gid = ind.GetID()

            # Handle Crossover
            if pid2 >= 0:
                new_mus_nets[gid] = mus_networks[pid1].crossover(mus_networks[pid2])
            else:
                new_mus_nets[gid] = mus_networks[pid1].copy()

            # Handle Mutation
            new_mus_nets[gid].mutate(kwargs['mut_prob'])

            # Set the Genome ID in the new muscle node.
            new_mus_nets[gid].gid = gid 

            zip_args.append((ind,new_mus_nets[gid]))

        mus_networks = new_mus_nets
示例#4
0
def evolutionary_run(**kwargs):
    """ Conduct an evolutionary run using the worm.  
    
    Args:
        gens: generations of evolution
        pop_size: population size
        mut_prob: mutation probability
    """
    global args, current_network, run_num, output_path, population_size, simulation

    params = NEAT.Parameters()
    params.CompatTreshold = 5.0
    params.CompatTresholdModifier = 0.3
    params.YoungAgeTreshold = 15
    params.SpeciesMaxStagnation = 1000
    params.OldAgeTreshold = 35
    params.MinSpecies = 1
    params.MaxSpecies = 25
    params.RouletteWheelSelection = False
    params.RecurrentProb = 0.25
    params.OverallMutationRate = 0.33
    params.MutateWeightsProb = 0.90
    params.WeightMutationMaxPower = 1.0
    params.WeightReplacementMaxPower = 5.0
    params.MutateWeightsSevereProb = 0.5
    params.WeightMutationRate = 0.75
    params.MaxWeight = 20
    params.MutateAddNeuronProb = 0.4
    params.MutateAddLinkProb = 0.4
    params.MutateRemLinkProb = 0.05

    params.PopulationSize = kwargs['pop_size']

    # Calculate the number of inputs (without bias and periodic signal) and outputs based on the number of joints.
    num_outputs = kwargs['num_joints'] * 2
    num_inputs = kwargs['num_joints'] * 2 + kwargs['num_joints'] + 1

    # Initialize the populations
    genome = NEAT.Genome(0, num_inputs + 2, 0, num_outputs, False,
                         NEAT.ActivationFunction.SIGNED_SIGMOID,
                         NEAT.ActivationFunction.SIGNED_SIGMOID, 0, params)
    # If not including a periodic input.
    if args.no_periodic:
        genome = NEAT.Genome(0, num_inputs + 1, 0, num_outputs, False,
                             NEAT.ActivationFunction.SIGNED_SIGMOID,
                             NEAT.ActivationFunction.SIGNED_SIGMOID, 0, params)
    population = NEAT.Population(genome, params, True, 1.0)

    mnlog.write_population_statistics_headers(output_path + str(run_num) +
                                              "_fitnesses.dat")

    # Setup multiprocessing
    cores = mpc.cpu_count()
    pool = mpc.Pool(processes=cores - 2)

    for gen in xrange(kwargs['gens']):
        genome_list = NEAT.GetGenomeList(population)

        fitnesses = pool.map(evaluate_individual, genome_list)
        #fitnesses = []
        #for g_l in genome_list:
        #    fitnesses.append(evaluate_individual(g_l))
        for g, f in zip(genome_list, fitnesses):
            g.SetFitness(f)
        print("Generation " + str(gen) + "\t: " + str(max(fitnesses)))

        # Write the best performing individual to a file.
        mnlog.write_best_individual(
            output_path + "best_individuals/Evo_NEAT_run_" + str(run_num) +
            "_best_gen_" + str(gen) + ".dat",
            genome_list[fitnesses.index(max(fitnesses))])

        # Log the progress of the entire population.
        mnlog.write_population_statistics(
            output_path + str(run_num) + "_fitnesses.dat", genome_list,
            fitnesses, gen)

        # Log the final population for later evaluation.
        if gen == kwargs['gens'] - 1:
            population.Save(output_path + "run_" + str(run_num) +
                            "_population_generation_" + str(gen) + ".dat")

        # Create the next generation
        population.Epoch()
示例#5
0
def evolutionary_run(**kwargs):
    """ Conduct an evolutionary run using the snake and muscle model.  
    
    Args:
        gens: generations of evolution
        pop_size: population size
        mut_prob: mutation probability
    """
    global args, current_network, fitness_function, run_num, output_path, population_size, simulation

    params = NEAT.Parameters()
    params.CompatTreshold = 5.0
    params.CompatTresholdModifier = 0.3
    params.YoungAgeTreshold = 15
    params.SpeciesMaxStagnation = 1000
    params.OldAgeTreshold = 35
    params.MinSpecies = 1
    params.MaxSpecies = 25
    params.RouletteWheelSelection = False
    params.RecurrentProb = 0.25
    params.OverallMutationRate = 0.33
    params.MutateWeightsProb = 0.90
    params.WeightMutationMaxPower = 1.0
    params.WeightReplacementMaxPower = 5.0
    params.MutateWeightsSevereProb = 0.5
    params.WeightMutationRate = 0.75
    params.MaxWeight = 20
    params.MutateAddNeuronProb = 0.4
    params.MutateAddLinkProb = 0.4
    params.MutateRemLinkProb = 0.05

    params.PopulationSize = kwargs['pop_size']

    # Initialize the population
    if args.fixed_strength:
        genome = NEAT.Genome(0, 22, 0, 16, False,
                             NEAT.ActivationFunction.SIGNED_SIGMOID,
                             NEAT.ActivationFunction.SIGNED_SIGMOID, 0, params)
        # If not including a periodic input.
        if args.no_periodic:
            genome = NEAT.Genome(0, 21, 0, 16, False,
                                 NEAT.ActivationFunction.SIGNED_SIGMOID,
                                 NEAT.ActivationFunction.SIGNED_SIGMOID, 0,
                                 params)
    else:
        genome = NEAT.Genome(0, 22, 0, 24, False,
                             NEAT.ActivationFunction.SIGNED_SIGMOID,
                             NEAT.ActivationFunction.SIGNED_SIGMOID, 0, params)
        # If not including a periodic input.
        if args.no_periodic:
            genome = NEAT.Genome(0, 21, 0, 24, False,
                                 NEAT.ActivationFunction.SIGNED_SIGMOID,
                                 NEAT.ActivationFunction.SIGNED_SIGMOID, 0,
                                 params)
    population = NEAT.Population(genome, params, True, 1.0)
    genome_list = NEAT.GetGenomeList(population)

    morph_pop = MorphGenomes(kwargs['pop_size'])
    for ind in genome_list:
        morph_pop.addIndividual(ind.GetID())
    morph_genomes = morph_pop.getGenomes()

    # Zip the two genome components together for use in the parallel call.
    zip_args = [(ind, morph_genomes[ind.GetID()]) for ind in genome_list]

    mnlog.write_population_statistics_headers(
        output_path + str(run_num) + "_fitnesses.dat",
        optional_additions="Distance,Efficiency")

    # Setup multiprocessing
    cores = mpc.cpu_count()
    pool = mpc.Pool(processes=cores - 2)

    for gen in xrange(kwargs['gens']):
        #fitnesses = []
        #for z in zip_args:
        #    fitnesses.append(evaluate_individual(z))
        fitnesses = pool.map(evaluate_individual, zip_args)

        # Validate the fitnesses.
        fitnesses = check_valid_fitnesses(fitnesses)

        # Set the fitnesses appropriately.
        genome_list, fitnesses, dist_fit = set_sliding_window_fitnesses(
            genome_list, fitnesses, args.window_size, fitness_function)

        print("Generation " + str(gen) + "\t: " + str(max(zip(*fitnesses)[1])))

        # Write the best performing individual to a file.
        mnlog.write_best_individual(
            output_path + "best_individuals/Evo_NEAT_run_" + str(run_num) +
            "_best_gen_" + str(gen) + ".dat",
            genome_list[dist_fit.index(max(dist_fit))]
        )  #genome_list[fitnesses.index(max(zip(*fitnesses)[2]))]
        morph_pop.logGenome(
            genome_list[fitnesses.index(max(fitnesses))].GetID(),
            "Evo_NEAT_run_" + str(run_num) + "_best_gen_" + str(gen),
            output_path)

        # Write information about the best individual we wrote.
        with open(
                output_path + "/" + str(run_num) +
                "_best_individuals_logging.dat", "a") as f:
            f.write("Generation: "+str(gen)+" Individual is: "+str(genome_list[dist_fit.index(max(dist_fit))].GetID())+\
                " Fitness is: "+str(max(dist_fit))+"\n")

        # Log the progress of the entire population.
        mnlog.write_population_statistics_multi_component(
            output_path + str(run_num) + "_fitnesses.dat", genome_list,
            fitnesses, gen)

        # Log the final population for later evaluation.
        if gen == kwargs['gens'] - 1:
            population.Save(output_path + "run_" + str(run_num) +
                            "_population_generation_" + str(gen) + ".dat")

        # Create the next generation
        population.Epoch()
        morph_pop.NextGen()
        genome_list = NEAT.GetGenomeList(population)
        zip_args = []
        for ind in genome_list:
            pid1 = ind.GetPID1()
            pid2 = ind.GetPID2()
            gid = ind.GetID()

            # Handle Crossover
            morph_pop.Crossover(gid, pid1, pid2)

        # Handle Mutation
        morph_pop.MutatePopulation()

        # Zip the arguments for calling the evolution function.
        morph_genomes = morph_pop.getGenomes()
        zip_args = [(ind, morph_genomes[ind.GetID()]) for ind in genome_list]
示例#6
0
def evolutionary_run(**kwargs):
    """ Conduct an evolutionary run.  
    
    Args:
        gens: generations of evolution
        pop_size: population size
        mut_prob: mutation probability
    """
    global args, current_network, run_num, output_path, population_size, simulation

    params = NEAT.Parameters()  
    params.CompatTreshold = 5.0
    params.CompatTresholdModifier = 0.3
    params.YoungAgeTreshold = 15
    params.SpeciesMaxStagnation = 50
    params.OldAgeTreshold = 35
    params.MinSpecies = 1 
    params.MaxSpecies = 25
    params.RouletteWheelSelection = False
    params.RecurrentProb = 0.25
    params.OverallMutationRate = 0.33
    params.MutateWeightsProb = 0.90
    params.WeightMutationMaxPower = 1.0
    params.WeightReplacementMaxPower = 5.0
    params.MutateWeightsSevereProb = 0.5
    params.WeightMutationRate = 0.75
    params.MaxWeight = 20

    params.MutateAddNeuronProb = 0.04
    params.MutateAddLinkProb = 0.1
    params.MutateRemSimpleNeuronProb = 0.04
    params.MutateRemLinkProb = 0.1

    # Phased Searching
    # params.PhasedSearching = True;
    # params.SimplifyingPhaseMPCTreshold = 20;
    # params.SimplifyingPhaseStagnationTreshold = 20;
    # params.ComplexityFloorGenerations = 20;

    params.PopulationSize = kwargs['pop_size'] 

    params.Save(output_path+str(run_num)+"_NEAT_params.cfg")
   
    # Initialize the populations
    genome = NEAT.Genome(0, 22, 0, 16, False, NEAT.ActivationFunction.SIGNED_SIGMOID, NEAT.ActivationFunction.SIGNED_SIGMOID, 0, params)
    # If not including a periodic input.
    if args.no_periodic:
        genome = NEAT.Genome(0, 21, 0, 16, False, NEAT.ActivationFunction.SIGNED_SIGMOID, NEAT.ActivationFunction.SIGNED_SIGMOID, 0, params)
    population = NEAT.Population(genome, params, True, 1.0)
    genome_list = NEAT.GetGenomeList(population)

    mnlog.write_population_statistics_headers(output_path+str(run_num)+"_fitnesses.dat",optional_additions="Num_Neurons,Num_Connections")

    # Setup multiprocessing
    cores = mpc.cpu_count()
    pool = mpc.Pool(processes=cores-2)

    for gen in xrange(kwargs['gens']):
        ind_descriptor = pool.map(evaluate_individual,genome_list) # 0 - fit, 1 - # neurons, 2 - # connections
        fitnesses = []
        num_conns = []
        num_neurons = []
        for g,ind in zip(genome_list,ind_descriptor):
            g.SetFitness(ind[0])
            fitnesses.append(ind[0])
            num_neurons.append(ind[1])
            num_conns.append(ind[2])
        print("Generation "+str(gen)+"\t: "+str(max(fitnesses)))

        # Write the best performing individual to a file.
        mnlog.write_best_individual(output_path+"best_individuals/Evo_NEAT_Mus_run_"+str(run_num)+"_best_gen_"+str(gen)+".dat", 
                genome_list[fitnesses.index(max(fitnesses))])
    
        # Log the progress of the entire population.
        mnlog.write_population_statistics(output_path+str(run_num)+"_fitnesses.dat", genome_list, fitnesses, gen, optional_additions=zip(num_neurons,num_conns))

        # Log the final population for later evaluation.
        if gen == kwargs['gens'] - 1:
            population.Save(output_path+"run_"+str(run_num)+"_population_generation_"+str(gen)+".dat")

        # Create the next generation
        population.Epoch()

        # Get the genomes
        genome_list = NEAT.GetGenomeList(population)