0

I'm building a Genetic Algorithm to maximize this function: x^5 - 10x^3 + 30x - y^2 + 21y.

The code must be in binary and the bounds for x and y are [-2.5, 2.5]. To generate the initial population I made a 16 bit string for both x and y where:

  • The first bit represents the signal [0 or 1]
  • The the second and third bit represents the integer part [00, 01 or 10]
  • The rest represents the float part

This is the function that generates the initial population:

def generate_population(n_pop):
    population = list()
    for _ in range(n_pop):
        aux = list()
        for _ in range(2):
            signal = bin(randint(0, 1))[2:]
            int_part = bin(randint(0, 2))[2:].zfill(2)
            float_part = bin(randint(0, 5000))[2:].zfill(13)
            aux.append((signal+int_part+float_part))
        population.append(aux)
    return population

I also made a function that returns the binary number into float:

def convert_float(individual):
    float_num = list()
    for i in range(2):
        signal = int(individual[i][0])
        int_part = int(individual[i][1:3], 2)
        float_part = int(individual[i][3:], 2) * (10 ** -4)
        value = round(int_part + float_part, 4)
        if value > 2.5:
            value = 2.5
        if signal == 1:
            value = value * (-1)
        float_num.append(value)
    return float_num

And lastly this function that calculate the fitness of each individual:

def get_fitness(individual):
    x = individual[0]
    y = individual[1]
    return x ** 5 - 10 * x ** 3 + 30 * x - y ** 2 + 21 * y

This is my main function:

def ga(n_pop=10, n_iter=10):
    population = generate_population(n_pop)
    best_fitness_id, best_fitness = 0, get_fitness(convert_float(population[0]))
    for i in range(n_iter):
        float_population = [convert_float(x) for x in population]
        fitness_population = [get_fitness(x) for x in float_population]
        for j in range(n_pop):
            if fitness_population[j] > best_fitness:
                best_fitness_id, best_fitness = j, fitness_population[j]
                print(f'--> NEW BEST FOUND AT GENERATION {i}:')
                print(f'{float_population[j]} = {fitness_population[j]}')
        selected_parents = rank_selection()
        # childrens = list()
        # childrens = childrens + population[best_fitness_id]  # ELITE

After running the program I have something like this:

  • The population looks like: [['0000001100110111', '0000110111110101'], ['0010011111101110', '1000100101001001'], ...
  • The float population: [[0.0823, 0.3573], [1.203, -0.2377], ...
  • And the fitness values: [9.839066068044746, 16.15145434928624, ...

I need help to build the rank_selection() function, I've been stuck in this selection for 2 days. I know is something 1/N, 2/N etc and I've seen tons of examples in multiple languages but I could not apply any of them to this particular algorithm and it MUST be rank selecion.

I already know how to perform crossover and mutation.

  • 1
    Use a weighted random selection to select a parent, using the fitness as weight: https://stackoverflow.com/a/26196078/6273251 – Random Davis Nov 03 '22 at 15:36
  • You could try this genetic algorithm library: https://colab.research.google.com/drive/1MH5W08Jp4yUAv3Fx2qTO5Ds17XPfPFw4?usp=sharing – Dadu Khan Nov 09 '22 at 05:24

0 Answers0