예제 #1
0
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
예제 #2
0
    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]
예제 #3
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)
예제 #4
0
파일: step.py 프로젝트: jmmcd/PonyGE2
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
예제 #5
0
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
예제 #6
0
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
예제 #7
0
파일: agent.py 프로젝트: jmmcd/PonyGE2
    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]
예제 #8
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
예제 #9
0
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
예제 #10
0
    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()
예제 #11
0
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
예제 #12
0
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
예제 #13
0
파일: agent.py 프로젝트: jmmcd/PonyGE2
    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
예제 #14
0
    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
예제 #15
0
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
예제 #16
0
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
예제 #17
0
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
예제 #18
0
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
예제 #19
0
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
예제 #20
0
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
예제 #21
0
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