def test_mutation_parent_selection():
    """ Tests mutation_parent_selection function """
    gp_par = gp.GpParameters()
    gp_par.n_population = 8
    gp_par.f_mutation = 0.5
    gp_par.parent_selection = gp.SelectionMethods.ELITISM
    gp_par.mutate_co_parents = True
    gp_par.mutate_co_offspring = True
    population = gp.create_population(gp_par.n_population, 5)
    crossover_parents = [5, 6, 7]
    crossover_offspring = gp.create_population(2, 5)
    fitness = [0, 1, 2, 1, 2, 1, 1, 2, 2, 0]
    parents = gp.mutation_parent_selection(population, fitness,
                                           crossover_parents,
                                           crossover_offspring, gp_par)
    assert parents == [8, 7, 4, 2]

    gp_par.mutate_co_parents = False
    gp_par.mutate_co_offspring = False
    parents = gp.mutation_parent_selection(population, fitness,
                                           crossover_parents,
                                           crossover_offspring, gp_par)
    assert parents == [4, 2, 3, 1]

    gp_par.n_population = 4
    gp_par.f_mutation = 0.1
    fitness = [0, 1, 2, 1]
    parents = gp.mutation_parent_selection(population, fitness, [], [], gp_par)
    assert parents == []
def test_mutation():
    """ Tests mutation function """
    gp_par = gp.GpParameters()
    gp_par.n_population = 5
    gp_par.n_offspring_mutation = 1
    gp_par.mutation_p_add = 0.3
    gp_par.mutation_p_delete = 0.3
    gp_par.allow_identical = False

    for _ in range(5):  #Test a number of random possibilities
        population = gp.create_population(gp_par.n_population, 5)
        mutated_population = gp.mutation(population, range(len(population)),
                                         gp_par)
        assert len(mutated_population
                   ) == gp_par.n_offspring_mutation * gp_par.n_population
        for i in range(len(mutated_population)):
            assert mutated_population[i] not in population
            for j in range(len(mutated_population)):
                if i != j:
                    assert mutated_population[i] != mutated_population[j]

    gp_par.n_offspring_mutation = 5 * gp_par.n_population + 1
    gp_par.allow_identical = True
    for _ in range(5):  #Test a number of random possibilities
        population = gp.create_population(gp_par.n_population, 5)
        mutated_population = gp.mutation(population, range(len(population)),
                                         gp_par)
        assert len(mutated_population
                   ) == gp_par.n_offspring_mutation * gp_par.n_population

    #Test with too limited mutation possibilities
    gp_par.n_population = 5
    gp_par.n_offspring_mutation = 1
    gp_par.mutation_p_add = 0.0
    gp_par.mutation_p_delete = 1.0
    gp_par.allow_identical = False
    parents = gp.create_population(gp_par.n_population, 2)
    blockers = gp.create_population(7, 1)
    population = parents + blockers
    mutated_population = gp.mutation(population, range(len(parents)), gp_par)
    assert len(mutated_population
               ) != gp_par.n_offspring_mutation * gp_par.n_population
    for i in range(len(mutated_population)):
        assert mutated_population[i] not in population
        for j in range(len(mutated_population)):
            if i != j:
                assert mutated_population[i] != mutated_population[j]
def test_crossover():
    """ Tests crossover function """
    pop_size = 10
    gp_par = gp.GpParameters()
    gp_par.n_population = pop_size
    gp_par.n_offspring_crossover = 1
    gp_par.allow_identical = False
    for _ in range(5):  #Test a number of random possibilities
        population = gp.create_population(pop_size, 5)
        crossover_population = gp.crossover(population, range(len(population)),
                                            gp_par)
        for i in range(len(crossover_population)):
            assert crossover_population[i] not in population
            for j in range(len(crossover_population)):
                if i != j:
                    assert crossover_population[i] != crossover_population[j]

    gp_par.n_offspring_crossover = 3 * pop_size
    gp_par.allow_identical = True
    for _ in range(5):  #Test a number of random possibilities
        population = gp.create_population(pop_size, 5)
        crossover_population = gp.crossover(population, range(len(population)),
                                            gp_par)
        assert len(crossover_population
                   ) == gp_par.n_offspring_crossover * gp_par.n_population

    #Test what happens if no valid crossovers can be found
    parents = [['s(', 'a0', ')'], ['s(', 'a1', ')']]
    gp_par.n_offspring_crossover = 1
    gp_par.allow_identical = False
    gp_par.n_population = 2
    blockers = [['s(', 'a1', 'a0', ')'], ['s(', 'a0', 'a1', ')']]
    population = parents + blockers
    crossover_population = gp.crossover(population, range(len(parents)),
                                        gp_par)
    assert len(crossover_population
               ) == gp_par.n_offspring_crossover * gp_par.n_population
    for i in range(len(crossover_population)):
        assert crossover_population[i] not in population
        for j in range(len(crossover_population)):
            if i != j:
                assert crossover_population[i] != crossover_population[j]

    #Number of parents not factor of two
    with pytest.raises(ValueError):
        crossover_population = gp.crossover(population, range(3), gp_par)
def test_create_population():
    """ Tests create_population function """
    pop_size = 5
    genome_length = 5
    for _ in range(5):  #Test a number of random possibilities
        population = gp.create_population(population_size=pop_size,
                                          genome_length=genome_length)
        for i in range(pop_size):
            assert len(population[i]) >= genome_length
            for j in range(genome_length):
                assert population[i][j] != []
def test_crossover_parent_selection():
    """ Tests crossover_parent_selection function """
    gp_par = gp.GpParameters()
    gp_par.n_population = 10
    gp_par.f_crossover = 0.4
    gp_par.parent_selection = gp.SelectionMethods.ELITISM
    population = gp.create_population(gp_par.n_population, 5)
    fitness = [0, 1, 2, 1, 2, 1, 1, 2, 2, 0]
    parents = gp.crossover_parent_selection(population, fitness, gp_par)
    assert parents == [8, 7, 4, 2]

    gp_par.n_population = 4
    gp_par.f_crossover = 0.1
    fitness = [0, 1, 2, 1]
    parents = gp.crossover_parent_selection(population, fitness, gp_par)
    assert parents == []