<filename>lab4/Exercises/ga_template.py<gh_stars>0
import random


p_mutation = 0.2
num_of_generations = 30


def genetic_algorithm(population, fitness_fn, minimal_fitness):
    for generation in range(num_of_generations):
        print("Generation {}:".format(generation))
        print_population(population, fitness_fn)

        new_population = set()

        for i in range(len(population)):
            mother, father = random_selection(population, fitness_fn)
            child = reproduce(mother, father)

            if random.uniform(0, 1) < p_mutation:
                child = mutate(child)

            new_population.add(child)

        # Add new population to population, use union to disregard
        # duplicate individuals
        population = population.union(new_population)

        fittest_individual = get_fittest_individual(population, fitness_fn)

        if minimal_fitness <= fitness_fn(fittest_individual):
            break

    print("Final generation {}:".format(generation))
    print_population(population, fitness_fn)

    return fittest_individual


def print_population(population, fitness_fn):
    for individual in population:
        fitness = fitness_fn(individual)
        print("{} - fitness: {}".format(individual, fitness))


def reproduce(mother, father):
    '''
    Reproduce two individuals with single-point crossover
    Return the child individual
    '''
    child = []
    crossover_bit = random.randint(0, 2)
    for i in range(0, crossover_bit):
        child.append(mother[i])
    for i in range(crossover_bit, 3):
        child.append(father[i])
    child = (child[0], child[1], child[2])
    return child


def mutate(individual):
    '''
    Mutate an individual by randomly assigning one of its bits
    Return the mutated individual
    '''
    mutation = []
    for i in individual:
        mutation.append(i)
    mutated = False
    while not mutated:
        randBit = random.randint(0,2)
        if mutation[randBit] == 0:
            mutation[randBit] = 1
            mutated = True
        elif individual == (1,1,1):
            mutated = True
    mutation = (mutation[0], mutation[1], mutation[2])
    return mutation


def random_selection(population, fitness_fn):
    """
    Compute fitness of each in population according to fitness_fn and add up
    the total. Then choose 2 from sequence based on percentage contribution to
    total fitness of population
    Return selected variable which holds two individuals that were chosen as
    the mother and the father
    """

    # Python sets are randomly ordered. Since we traverse the set twice, we
    # want to do it in the same order. So let's convert it temporarily to a
    # list.
    selected = []

    ordered_population = list(population)

    for ind in ordered_population:
        if len(selected) < 2:
            selected.insert(0, ind)
        elif fitness_fn(ind) >= fitness_fn(selected[0]):
            selected[1] = selected[0]
            selected[0] = ind
    selected = (selected[0], selected[1])
    return selected


def fitness_function(individual):
    '''
    Computes the decimal value of the individual
    Return the fitness level of the individual

    Explanation:
    enumerate(list) returns a list of pairs (position, element):

    enumerate((4, 6, 2, 8)) -> [(0, 4), (1, 6), (2, 2), (3, 8)]

    enumerate(reversed((1, 1, 0))) -> [(0, 0), (1, 1), (2, 1)]
    '''
    (1,1,0)
    fitness = 0
    fitness = individual[2]
    fitness += individual[1] * 2
    fitness += individual[0] * 4
    
    return fitness


def get_fittest_individual(iterable, func):
    return max(iterable, key=func)


def get_initial_population(n, count):
    '''
    Randomly generate count individuals of length n
    Note since its a set it disregards duplicate elements.
    '''
    return set([
        tuple(random.randint(0, 1) for _ in range(n))
        for _ in range(count)
    ])


def main():
    minimal_fitness = 7

    # Curly brackets also creates a set, if there isn't a colon to indicate a dictionary
    initial_population = {
        (1, 1, 0),
        (0, 0, 0),
        (0, 1, 0),
        (1, 0, 0)
    }
    #initial_population = get_initial_population(3, 4)

    fittest = genetic_algorithm(initial_population, fitness_function, minimal_fitness)
    print('Fittest Individual: ' + str(fittest))


if __name__ == '__main__':
    main()

<filename>lab4/Exercises/ga_template.py<gh_stars>0
import random


p_mutation = 0.2
num_of_generations = 30


def genetic_algorithm(population, fitness_fn, minimal_fitness):
    for generation in range(num_of_generations):
        print("Generation {}:".format(generation))
        print_population(population, fitness_fn)

        new_population = set()

        for i in range(len(population)):
            mother, father = random_selection(population, fitness_fn)
            child = reproduce(mother, father)

            if random.uniform(0, 1) < p_mutation:
                child = mutate(child)

            new_population.add(child)

        # Add new population to population, use union to disregard
        # duplicate individuals
        population = population.union(new_population)

        fittest_individual = get_fittest_individual(population, fitness_fn)

        if minimal_fitness <= fitness_fn(fittest_individual):
            break

    print("Final generation {}:".format(generation))
    print_population(population, fitness_fn)

    return fittest_individual


def print_population(population, fitness_fn):
    for individual in population:
        fitness = fitness_fn(individual)
        print("{} - fitness: {}".format(individual, fitness))


def reproduce(mother, father):
    '''
    Reproduce two individuals with single-point crossover
    Return the child individual
    '''
    child = []
    crossover_bit = random.randint(0, 2)
    for i in range(0, crossover_bit):
        child.append(mother[i])
    for i in range(crossover_bit, 3):
        child.append(father[i])
    child = (child[0], child[1], child[2])
    return child


def mutate(individual):
    '''
    Mutate an individual by randomly assigning one of its bits
    Return the mutated individual
    '''
    mutation = []
    for i in individual:
        mutation.append(i)
    mutated = False
    while not mutated:
        randBit = random.randint(0,2)
        if mutation[randBit] == 0:
            mutation[randBit] = 1
            mutated = True
        elif individual == (1,1,1):
            mutated = True
    mutation = (mutation[0], mutation[1], mutation[2])
    return mutation


def random_selection(population, fitness_fn):
    """
    Compute fitness of each in population according to fitness_fn and add up
    the total. Then choose 2 from sequence based on percentage contribution to
    total fitness of population
    Return selected variable which holds two individuals that were chosen as
    the mother and the father
    """

    # Python sets are randomly ordered. Since we traverse the set twice, we
    # want to do it in the same order. So let's convert it temporarily to a
    # list.
    selected = []

    ordered_population = list(population)

    for ind in ordered_population:
        if len(selected) < 2:
            selected.insert(0, ind)
        elif fitness_fn(ind) >= fitness_fn(selected[0]):
            selected[1] = selected[0]
            selected[0] = ind
    selected = (selected[0], selected[1])
    return selected


def fitness_function(individual):
    '''
    Computes the decimal value of the individual
    Return the fitness level of the individual

    Explanation:
    enumerate(list) returns a list of pairs (position, element):

    enumerate((4, 6, 2, 8)) -> [(0, 4), (1, 6), (2, 2), (3, 8)]

    enumerate(reversed((1, 1, 0))) -> [(0, 0), (1, 1), (2, 1)]
    '''
    (1,1,0)
    fitness = 0
    fitness = individual[2]
    fitness += individual[1] * 2
    fitness += individual[0] * 4
    
    return fitness


def get_fittest_individual(iterable, func):
    return max(iterable, key=func)


def get_initial_population(n, count):
    '''
    Randomly generate count individuals of length n
    Note since its a set it disregards duplicate elements.
    '''
    return set([
        tuple(random.randint(0, 1) for _ in range(n))
        for _ in range(count)
    ])


def main():
    minimal_fitness = 7

    # Curly brackets also creates a set, if there isn't a colon to indicate a dictionary
    initial_population = {
        (1, 1, 0),
        (0, 0, 0),
        (0, 1, 0),
        (1, 0, 0)
    }
    #initial_population = get_initial_population(3, 4)

    fittest = genetic_algorithm(initial_population, fitness_function, minimal_fitness)
    print('Fittest Individual: ' + str(fittest))


if __name__ == '__main__':
    main()

# Add new population to population, use union to disregard # duplicate individuals Reproduce two individuals with single-point crossover     Return the child individual Mutate an individual by randomly assigning one of its bits     Return the mutated individual Compute fitness of each in population according to fitness_fn and add up     the total. Then choose 2 from sequence based on percentage contribution to     total fitness of population     Return selected variable which holds two individuals that were chosen as     the mother and the father # Python sets are randomly ordered. Since we traverse the set twice, we # want to do it in the same order. So let's convert it temporarily to a # list. Computes the decimal value of the individual     Return the fitness level of the individual      Explanation:     enumerate(list) returns a list of pairs (position, element):      enumerate((4, 6, 2, 8)) -> [(0, 4), (1, 6), (2, 2), (3, 8)]      enumerate(reversed((1, 1, 0))) -> [(0, 0), (1, 1), (2, 1)] Randomly generate count individuals of length n     Note since its a set it disregards duplicate elements. # Curly brackets also creates a set, if there isn't a colon to indicate a dictionary #initial_population = get_initial_population(3, 4)