def step(individuals): """ Runs a single generation of the evolutionary algorithm process: Selection Variation Evaluation Replacement :param individuals: The current generation, upon which a single evolutionary generation will be imposed. :return: The next generation of the population. """ # Select parents from the original population. parents = selection(individuals) # Crossover parents and add to the new population. cross_pop = crossover(parents) # Mutate the new population. new_pop = mutation(cross_pop) # Evaluate the fitness of the new population. new_pop = evaluate_fitness(new_pop) # Replace the old population with the new population. individuals = replacement(new_pop, individuals) # Generate statistics for run so far params['STATISTICS'].get_stats(individuals) return individuals
def act(self): # Process the information if the agent has sense nearby agents if self.agents_found: # Combine the original individual and individuals found by interacting with nearby agents to form # a population individuals = self.individual + self.nearby_agents # Find out parents from the population parents = selection(individuals) # Crossover parents and add to the new population. cross_pop = crossover(parents) # Mutate the new population. new_pop = mutation(cross_pop) # Evaluate the fitness of the new population. new_pop = evaluate_fitness(new_pop) # Replace the old population with the new population. individuals = replacement(new_pop, individuals) # Generate statistics for run so far get_stats(individuals) # Sort the individuals list individuals.sort(reverse=True) # Get the highest performing individual from the sorted population self.new_individual = individuals[0]
def children(self): """Return a list of children from this population.""" children = [] while len(children) < self.cut_off_count: children.extend(crossover_inds(*self._get_parents_for_crossover())) return evaluate_fitness(mutation(children), current_generation=self.current_generation)
def step(individuals): """ Runs a single generation of the evolutionary algorithm process: Selection Variation Evaluation Replacement :param individuals: The current generation, upon which a single evolutionary generation will be imposed. :return: The next generation of the population. """ # Select parents from the original population. parents = selection(individuals) # Crossover parents and add to the new population. cross_pop = crossover(parents) # Mutate the new population. new_pop = mutation(cross_pop) # Evaluate the fitness of the new population. new_pop = evaluate_fitness(new_pop) # Replace the old population with the new population. individuals = replacement(new_pop, individuals) # Generate statistics for run so far get_stats(individuals) return individuals
def search_loop(): """ This is a standard search process for an evolutionary algorithm. Loop over a given number of generations. :return: The final population after the evolutionary process has run for the specified number of generations. """ # Initialise population individuals = params['INITIALISATION'](params['POPULATION_SIZE']) # Evaluate initial population individuals = evaluate_fitness(individuals) # Generate statistics for run so far get_stats(individuals) # Traditional GE for generation in range(1, (params['GENERATIONS'] + 1)): stats['gen'] = generation # New generation individuals = params['STEP'](individuals) # Generate statistics for run so far get_stats(individuals) return individuals
def weips_step(individuals, weight_matrix): """ Runs a single generation of the evolutionary algorithm process: Selection Variation Evaluation Replacement :param individuals: The current generation, upon which a single :param weight_matrix: The matrix of weights used by the selection method. :return: The next generation of the population. """ # Size of the population pop_size = params['GENERATION_SIZE'] # Select parents from the original population. parents = weips_selection(individuals, weight_matrix, pop_size) # Crossover parents and add to the new population. cross_pop = crossover(parents) # Mutate the new population. new_pop = mutation(cross_pop) # Evaluate the fitness of the new population (Q_t). new_pop = evaluate_fitness(new_pop) # Replace the old population with the new population. individuals = weips_replacement(new_pop, individuals, weight_matrix) # Generate statistics for run so far params['STATISTICS'].get_stats(individuals) return individuals
def act(self): # Process the information if the agent has sense nearby agents if self.agents_found: # Combine the original individual and individuals found by interacting with nearby agents to form # a population individuals = self.individual + self.nearby_agents # Find out parents from the population parents = selection(individuals) # Crossover parents and add to the new population. cross_pop = crossover(parents) # Mutate the new population. new_pop = mutation(cross_pop) # Evaluate the fitness of the new population. new_pop = evaluate_fitness(new_pop) # Replace the old population with the new population. individuals = replacement(new_pop, individuals) # Generate statistics for run so far get_stats(individuals) # Sort the individuals list individuals.sort(reverse=True) # Get the higest performing individual from the sorted population self.new_individual = individuals[0]
def weips_search_loop(weight_init_method): """ This is a standard search process for an evolutionary algorithm. Loop over a given number of generations. :param: weight_initialisation: Defines how the weights are initialized. :return: The final population after the evolutionary process has run for the specified number of generations. """ # Initialise population individuals = params['INITIALISATION'](params['POPULATION_SIZE']) # Evaluate initial population individuals = evaluate_fitness(individuals) # Generate statistics for run so far params['STATISTICS'].get_stats(individuals) # Generate the uniformly distributed weights weight_matrix = weight_init_method(individuals) # Traditional GE for generation in range(1, (params['GENERATIONS'] + 1)): stats['gen'] = generation # New generation individuals = weips_step(individuals, weight_matrix) return individuals
def search_loop(): """ This is a standard search process for an evolutionary algorithm. Loop over a given number of generations. :return: The final population after the evolutionary process has run for the specified number of generations. """ if params['MULTICORE']: # initialize pool once, if mutlicore is enabled params['POOL'] = Pool(processes=params['CORES'], initializer=pool_init, initargs=(params,)) # , maxtasksperchild=1) # Initialise population individuals = initialisation(params['POPULATION_SIZE']) # Evaluate initial population individuals = evaluate_fitness(individuals) # Generate statistics for run so far get_stats(individuals) # Traditional GE for generation in range(1, (params['GENERATIONS']+1)): stats['gen'] = generation # New generation individuals = params['STEP'](individuals) if params['MULTICORE']: # Close the workers pool (otherwise they'll live on forever). params['POOL'].close() return individuals
def __init__(self, selection_proportion): self.current_generation = 0 self.individuals = sorted( evaluate_fitness(initialisation(params['POPULATION_SIZE']), current_generation=self.current_generation)) self.cut_off_count = int(len(self) * (1 - selection_proportion)) self.update_fittest_individuals() self.update_probabilities()
def steady_state(individuals): """ Runs a single generation of the evolutionary algorithm process, using steady state replacement: Selection Variation Evaluation Replacement Steady state replacement uses the Genitor model (Whitley, 1989) whereby new individuals directly replace the worst individuals in the population regardless of whether or not the new individuals are fitter than those they replace. Note that traditional GP crossover generates only 1 child, whereas linear GE crossover (and thus all crossover functions used in PonyGE) generates cython_backup children from cython_backup parents. Thus, we use a deletion strategy of cython_backup. :param individuals: The current generation, upon which a single evolutionary generation will be imposed. :return: The next generation of the population. """ # Initialise counter for new individuals. ind_counter = 0 while ind_counter < params['POPULATION_SIZE']: # Select parents from the original population. parents = selection(individuals) # Perform crossover on selected parents. cross_pop = crossover_inds(parents[0], parents[1]) if cross_pop is None: # Crossover failed. pass else: # Mutate the new population. new_pop = mutation(cross_pop) # Evaluate the fitness of the new population. new_pop = evaluate_fitness(new_pop) # Sort the original population individuals.sort(reverse=True) # Combine both populations total_pop = individuals[:-len(new_pop)] + new_pop # Increment the ind counter ind_counter += params['GENERATION_SIZE'] # Return the combined population. return total_pop
def steady_state(individuals): """ Runs a single generation of the evolutionary algorithm process, using steady state replacement: Selection Variation Evaluation Replacement Steady state replacement uses the Genitor model (Whitley, 1989) whereby new individuals directly replace the worst individuals in the population regardless of whether or not the new individuals are fitter than those they replace. Note that traditional GP crossover generates only 1 child, whereas linear GE crossover (and thus all crossover functions used in PonyGE) generates 2 children from 2 parents. Thus, we use a deletion strategy of 2. :param individuals: The current generation, upon which a single evolutionary generation will be imposed. :return: The next generation of the population. """ # Initialise counter for new individuals. ind_counter = 0 while ind_counter < params['POPULATION_SIZE']: # Select parents from the original population. parents = selection(individuals) # Perform crossover on selected parents. cross_pop = crossover_inds(parents[0], parents[1]) if cross_pop is None: # Crossover failed. pass else: # Mutate the new population. new_pop = mutation(cross_pop) # Evaluate the fitness of the new population. new_pop = evaluate_fitness(new_pop) # Sort the original population individuals.sort(reverse=True) # Combine both populations total_pop = individuals[:-len(new_pop)] + new_pop # Increment the ind counter ind_counter += params['GENERATION_SIZE'] # Return the combined population. return total_pop
def __init__(self, ip): # Interaction probability received in constructor self.interaction_probability = ip # Only initialize singel individual. Single agent can only have single genetic information self.individual = initialisation(1) # Evaluate the fitness for the the individual self.individual = evaluate_fitness(self.individual) # Flag which store the boolean value for other nebouring agents found or not self.agents_found = False
def __init__(self, ip): # Interaction probability received in constructor self.interaction_probability = ip # Only initialize single individual. Single agent can only have single genetic information self.individual = initialisation(1) # Evaluate the fitness for the the individual self.individual = evaluate_fitness(self.individual) # Flag which store the boolean value for other neighbouring agents found or not self.agents_found = False
def search_loop(): """ This is a standard search process for an evolutionary algorithm. Loop over a given number of generations. :return: The final population after the evolutionary process has run for the specified number of generations. """ logf = open(params['FILE_PATH'] + "/log.csv", 'w') #190312: log set_M() #190307: our mod for learning multiplier if params['MULTICORE']: # initialize pool once, if mutlicore is enabled params['POOL'] = Pool(processes=params['CORES'], initializer=pool_init, initargs=(params, )) # , maxtasksperchild=1) # Initialise population individuals = initialisation(params['POPULATION_SIZE']) # Evaluate initial population individuals = evaluate_fitness(individuals) # Generate statistics for run so far get_stats(individuals) write_log(logf, 0, params['M'], individuals) #190312: log #write_best(0, params['M'], individuals) # Traditional GE for generation in range(1, (params['GENERATIONS'] + 1)): stats['gen'] = generation update_M(generation, individuals) # 190307: our mod for learning multiplier # New generation individuals = params['STEP'](individuals) write_log(logf, generation, params['M'], individuals) #190312: log #write_best(generation, params['M'], individuals) print("generation ", generation, "/", params['GENERATIONS'], " finished at ", datetime.datetime.now()) # 190313: timestamp if params['MULTICORE']: # Close the workers pool (otherwise they'll live on forever). params['POOL'].close() logf.close() return individuals
def search_loop(): """ This is a standard search process for an evolutionary algorithm. Loop over a given number of generations. :return: The final population after the evolutionary process has run for the specified number of generations. """ if params['MULTICORE']: # initialize pool once, if mutlicore is enabled params['POOL'] = ThreadPool( processes=params['CORES'], initializer=pool_init, initargs=(params, )) # , maxtasksperchild=1) Logger.log("Generation 0 starts. Initializing...") # Initialise population individuals = initialisation(params['POPULATION_SIZE']) # Evaluate initial population individuals = evaluate_fitness(individuals) # Generate statistics for run so far get_stats(individuals) # Cleanup after evaluation if 'cleanup' in dir(params['FITNESS_FUNCTION']): params['FITNESS_FUNCTION'].cleanup(individuals) # Traditional GE for generation in range(1, (params['GENERATIONS'] + 1)): stats['gen'] = generation params['CURRENT_EVALUATION'] = 0 params['CURRENT_GENERATION'] = generation Logger.log("Generation {0} starts...".format(generation)) # New generation individuals = params['STEP'](individuals) # Cleanup after evaluation if 'cleanup' in dir(params['FITNESS_FUNCTION']): params['FITNESS_FUNCTION'].cleanup(individuals) Logger.close_all() if params['MULTICORE']: # Close the workers pool (otherwise they'll live on forever). params['POOL'].close() return individuals
def LAHC_search_loop(): """ Search loop for Late Acceptance Hill Climbing. This is the LAHC pseudo-code from Bykov and Burke. Produce an initial solution s Calculate initial cost function C(s) Specify Lfa For all k in {0...Lfa-1} f_k := C(s) First iteration I=0; Do until a chosen stopping condition Construct a candidate solution s* Calculate its cost function C(s*) v := I mod Lfa If C(s*)<=fv or C(s*)<=C(s) Then accept the candidate (s:=s*) Else reject the candidate (s:=s) Insert the current cost into the fitness array fv:=C(s) Increment the iteration number I:=I+1 :return: The final population. """ maximise = params['FITNESS_FUNCTION'].maximise max_its = params['POPULATION_SIZE'] * params['GENERATIONS'] # Initialise population individuals = params['INITIALISATION'](params['POPULATION_SIZE']) # Evaluate initial population individuals = evaluate_fitness(individuals) # Generate statistics for run so far get_stats(individuals) Lfa = params['HILL_CLIMBING_HISTORY'] s = stats['best_ever'] Cs = s.fitness f = Cs * np.ones(Lfa) # history I = len(individuals) for generation in range(1, (params['GENERATIONS'] + 1)): this_gen = [] # even though there is no population, we will take account of # the pop size parameter: ie we'll save stats after every # "generation" for j in range(params['POPULATION_SIZE']): this_gen.append(s) # collect this "generation" s_ = params['MUTATION'](s) # mutate s to get candidate s* if not s_.invalid: s_.evaluate() Cs_ = s.fitness v = I % Lfa # ugly if ((maximise and (Cs_ >= f[v] or Cs_ >= Cs)) or (not maximise and (Cs_ <= f[v] or Cs_ <= Cs))): # accept the candidate s = s_ Cs = Cs_ else: pass # reject the candidate f[v] = Cs I += 1 # break from inner and outer if needed if I >= max_its: break # but get this get stats first stats['gen'] = generation get_stats(this_gen) if I >= max_its: break return individuals
def SCHC_search_loop(): """ Search Loop for Step-Counting Hill-Climbing. This is the SCHC pseudo-code from Bykov and Petrovic. Produce an initial solution s Calculate an initial cost function C(s) Initial cost bound Bc := C(s) Initial counter nc := 0 Specify Lc Do until a chosen stopping condition Construct a candidate solution s* Calculate the candidate cost function C(s*) If C(s*) < Bc or C(s*) <= C(s) Then accept the candidate s := s* Else reject the candidate s := s Increment the counter nc := nc + 1 If nc >= Lc Then update the bound Bc := C(s) reset the counter nc := 0 Two alternative counting methods (start at the first If): SCHC-acp counts only accepted moves: If C(s*) < Bc or C(s*) <= C(s) Then accept the candidate s := s* increment the counter nc := nc + 1 Else reject the candidate s := s If nc >= Lc Then update the bound Bc := C(s) reset the counter nc := 0 SCHC-imp counts only improving moves: If C(s*) < C(s) Then increment the counter nc := nc + 1 If C(s*) < Bc or C(s*) <= C(s) Then accept the candidate s := s* Else reject the candidate s := s If nc >= Lc Then update the bound Bc := C(s) reset the counter nc := 0 :return: The final population. """ maximise = params['FITNESS_FUNCTION'].maximise max_its = params['POPULATION_SIZE'] * params['GENERATIONS'] count_method = "all" # TODO accept_method = "bykov" # TODO # Initialise population individuals = params['INITIALISATION'](params['POPULATION_SIZE']) # Evaluate initial population individuals = evaluate_fitness(individuals) # Generate statistics for run so far get_stats(individuals) Lc = params['HILL_CLIMBING_HISTORY'] s = stats['best_ever'] Cs = s.fitness Bc = Cs # initial cost bound nc = 0 I = len(individuals) for generation in range(1, (params['GENERATIONS'] + 1)): this_gen = [] # even though there is no population, we will take account of # the pop size parameter: ie we'll save stats after every # "generation" for j in range(params['POPULATION_SIZE']): this_gen.append(s) # collect this "generation" s_ = params['MUTATION'](s) # mutate s to get candidate s* if not s_.invalid: s_.evaluate() Cs_ = s.fitness # count if count_method == "all": # we count all iterations (moves) nc += 1 # increment the counter elif count_method == "acp": # we count accepted moves only if ((maximise and (Cs_ > Bc or Cs_ >= Cs)) or ((not maximise) and (Cs_ < Bc or Cs_ <= Cs))): nc += 1 # increment the counter elif count_method == "imp": # we count improving moves only if ((maximise and Cs_ > Cs) or ((not maximise) and Cs_ < Cs)): nc += 1 # increment the counter else: raise ValueError("Unknown count method " + count_method) # accept if accept_method == "bykov": # standard accept method if ((maximise and (Cs_ > Bc or Cs_ >= Cs)) or ((not maximise) and (Cs_ < Bc or Cs_ <= Cs))): s = s_ # accept the candidate Cs = Cs_ else: pass # reject the candidate elif accept_method == "nicolau": # simpler alternative suggested by Nicolau, unpublished if ((maximise and Cs_ >= Bc) or ((not maximise) and (Cs_ <= Bc))): s = s_ # accept the candidate Cs = Cs_ else: pass # reject the candidate else: raise ValueError("Unknown accept method " + accept_method) if nc >= Lc: Bc = Cs # update the bound nc = 0 # reset the counter I += 1 # break from inner and outer if needed if I >= max_its: break # but get this gen stats first stats['gen'] = generation get_stats(this_gen) if I >= max_its: break return individuals
def search_loop(): """ This is a standard search process for an evolutionary algorithm. Loop over a given number of generations. :return: The final population after the evolutionary process has run for the specified number of generations. """ print(params['INITIALISATION'], params['POPULATION_SIZE']) # Added by me as a debug - REMOVE # Initialise population individuals = params['INITIALISATION'](params['POPULATION_SIZE']) # Evaluate initial population individuals = evaluate_fitness(individuals) # Generate statistics for run so far get_stats(individuals) # Traditional GE for generation in range(1, (params['GENERATIONS']+1)): stats['gen'] = generation # New generation individuals = params['STEP'](individuals) #ROISIN: To save phenotype of best individual run_no = int(params["EXTRA_PARAMETERS"]) print("RUN_NO: ", run_no) best=max(individuals) print("Best: ", best) ind=best.phenotype length = len(ind) i = 0 # Wrie best to file and play with midi instruments = ["kick", "hh", "hhOp", "snH", "Sin1", "Sin2"] bestfile = open("../results/ChucK/" + instruments[run_no] + ".ck", 'w') """ Separate individaul into lines and add to file""" while i < length: # print i try: end_line = ind.index(";") # print "ind: %s end: %d, i: %d"%(ind, end_line, i) line = ind[: end_line + 1] try: if line[0] == "L": bestfile.write("while (true) \n { \n") line = line[1:] except IndexError: pass bestfile.write(str(line)) bestfile.write("\n") ind = ind[end_line + 1:] except ValueError: pass i += end_line bestfile.write("}") bestfile.close() return individuals
def SCHC_search_loop(): """ Search Loop for Step-Counting Hill-Climbing. This is the SCHC pseudo-code from Bykov and Petrovic. Produce an initial solution best Calculate an initial cost function C(best) Initial cost bound cost_bound := C(best) Initial counter counter := 0 Specify history Do until a chosen stopping condition Construct a candidate solution best* Calculate the candidate cost function C(best*) If C(best*) < cost_bound or C(best*) <= C(best) Then accept the candidate best := best* Else reject the candidate best := best Increment the counter counter := counter + 1 If counter >= history Then update the bound cost_bound := C(best) reset the counter counter := 0 Two alternative counting methods (start at the first If): SCHC-acp counts only accepted moves: If C(best*) < cost_bound or C(best*) <= C(best) Then accept the candidate best := best* increment the counter counter := counter + 1 Else reject the candidate best := best If counter >= history Then update the bound cost_bound := C(best) reset the counter counter := 0 SCHC-imp counts only improving moves: If C(best*) < C(best) Then increment the counter counter := counter + 1 If C(best*) < cost_bound or C(best*) <= C(best) Then accept the candidate best := best* Else reject the candidate best := best If counter >= history Then update the bound cost_bound := C(best) reset the counter counter := 0 :return: The final population. """ # Calculate maximum number of evaluation iterations. max_its = params['POPULATION_SIZE'] * params['GENERATIONS'] count_method = params['SCHC_COUNT_METHOD'] # Initialise population individuals = params['INITIALISATION'](params['POPULATION_SIZE']) # Evaluate initial population individuals = evaluate_fitness(individuals) # Generate statistics for run so far get_stats(individuals) # Set best individual and initial cost bound. best = trackers.best_ever cost_bound = best.deep_copy() # Set history and counter. history = params['HILL_CLIMBING_HISTORY'] counter = 0 # iters is the number of individuals examined/iterations so far. iters = len(individuals) for generation in range(1, (params['GENERATIONS']+1)): this_gen = [] # even though there is no population, we will take account of # the pop size parameter: ie we'll save stats after every # "generation" for j in range(params['POPULATION_SIZE']): this_gen.append(best) # collect this "generation" # Mutate best to get candidate best. candidate_best = params['MUTATION'](best) if not candidate_best.invalid: candidate_best.evaluate() # count if count_method == "count_all": # we count all iterations (moves) counter += 1 # increment the counter elif count_method == "acp": # we count accepted moves only if candidate_best > cost_bound or candidate_best >= best: counter += 1 # increment the counter elif count_method == "imp": # we count improving moves only if candidate_best > best: counter += 1 # increment the counter else: s = "algorithm.hill_climbing.SCHC_search_loop\n" \ "Error: Unknown count method: %s" % (count_method) raise Exception(s) # accept if candidate_best > cost_bound or candidate_best >= best: best = candidate_best # accept the candidate else: pass # reject the candidate if counter >= history: cost_bound = best # update the bound counter = 0 # reset the counter # Increment iteration counter. iters += 1 if iters >= max_its: # We have completed the total number of iterations. break # Get stats for this "generation". stats['gen'] = generation get_stats(this_gen) if iters >= max_its: # We have completed the total number of iterations. break return individuals
def LAHC_search_loop(): """ Search loop for Late Acceptance Hill Climbing. This is the LAHC pseudo-code from Burke and Bykov: Produce an initial solution best Calculate initial cost function C(best) Specify Lfa For all k in {0...Lfa-1} f_k := C(best) First iteration iters=0; Do until a chosen stopping condition Construct a candidate solution best* Calculate its cost function C(best*) idx := iters mod Lfa If C(best*)<=f_idx or C(best*)<=C(best) Then accept the candidate (best:=best*) Else reject the candidate (best:=best) Insert the current cost into the fitness array f_idx:=C(best) Increment the iteration number iters:=iters+1 :return: The final population. """ max_its = params['POPULATION_SIZE'] * params['GENERATIONS'] # Initialise population individuals = params['INITIALISATION'](params['POPULATION_SIZE']) # Evaluate initial population individuals = evaluate_fitness(individuals) # Generate statistics for run so far get_stats(individuals) # Find the best individual so far. best = trackers.best_ever # Set history. Lfa = params['HILL_CLIMBING_HISTORY'] history = [best for _ in range(Lfa)] # iters is the number of individuals examined so far. iters = len(individuals) for generation in range(1, (params['GENERATIONS']+1)): this_gen = [] # even though there is no population, we will take account of # the pop size parameter: ie we'll save stats after every # "generation" for j in range(params['POPULATION_SIZE']): this_gen.append(best) # collect this "generation" # Mutate the best to get the candidate best candidate_best = params['MUTATION'](best) if not candidate_best.invalid: candidate_best.evaluate() # Find the index of the relevant individual from the late # acceptance history. idx = iters % Lfa if candidate_best >= history[idx]: best = candidate_best # Accept the candidate else: pass # reject the candidate # Set the new best into the history. history[idx] = best # Increment evaluation counter. iters += 1 if iters >= max_its: # We have completed the total number of iterations. break # Get stats for this "generation". stats['gen'] = generation get_stats(this_gen) if iters >= max_its: # We have completed the total number of iterations. break return individuals