def test_truncation_selection(): """ Basic truncation selection test""" pop = [ Individual([0, 0, 0], decoder=IdentityDecoder(), problem=MaxOnes()), Individual([0, 0, 1], decoder=IdentityDecoder(), problem=MaxOnes()), Individual([1, 1, 0], decoder=IdentityDecoder(), problem=MaxOnes()), Individual([1, 1, 1], decoder=IdentityDecoder(), problem=MaxOnes()) ] # We first need to evaluate all the individuals so that truncation selection has fitnesses to compare pop = Individual.evaluate_population(pop) truncated = ops.truncation_selection(pop, 2) assert len(truncated) == 2 # Just to make sure, check that the two best individuals from the original population are in the selected population assert pop[2] in truncated assert pop[3] in truncated
def test_naive_cyclic_selection(): """ Test of the naive deterministic cyclic selection """ pop = [ Individual(np.array([0, 0]), problem=MaxOnes()), Individual(np.array([0, 1]), problem=MaxOnes()) ] # This selection operator will deterministically cycle through the # given population selector = ops.naive_cyclic_selection(pop) selected = next(selector) assert np.all(selected.genome == [0, 0]) selected = next(selector) assert np.all(selected.genome == [0, 1]) # And now we cycle back to the first individual selected = next(selector) assert np.all(selected.genome == [0, 0])
def _build_test_pop(): """Construct a synthetic population for illustrating example operations.""" pop = [ Individual([1, 0, 1, 1, 0], IdentityDecoder(), MaxOnes()), Individual([0, 0, 1, 0, 0], IdentityDecoder(), MaxOnes()), Individual([0, 1, 1, 1, 1], IdentityDecoder(), MaxOnes()), Individual([1, 0, 0, 0, 1], IdentityDecoder(), MaxOnes()) ] pop = Individual.evaluate_population(pop) # Assign distinct values to an attribute on each individual attrs = [('foo', ['GREEN', 15, 'BLUE', 72.81]), ('bar', ['Colorless', 'green', 'ideas', 'sleep']), ('baz', [['a', 'b', 'c'], [1, 2, 3], [None, None, None], [0.1, 0.2, 0.3]])] for attr, vals in attrs: for (ind, val) in zip(pop, vals): ind.__dict__[attr] = val return pop
def test_proportional_selection_custom_key(): ''' Test of proportional selection with custom evaluation ''' pop = [ Individual(np.array([0, 0, 0]), problem=MaxOnes()), Individual(np.array([1, 1, 1]), problem=MaxOnes()) ] def custom_key(individual): ''' Returns fitness based on MaxZeros ''' return np.count_nonzero(individual.genome == 0) pop = Individual.evaluate_population(pop) selector = ops.proportional_selection(pop, key=custom_key) # we expect the first individual to always be selected # since its genome is all 0s selected = next(selector) assert np.all(selected.genome == [0, 0, 0]) selected = next(selector) assert np.all(selected.genome == [0, 0, 0])
def test_proportional_selection_pop_min(): ''' Test of proportional selection with pop-min offset ''' # Create a population of positive fitness individuals # scaling the fitness by the population minimum makes it so the # least fit member never gets selected. pop = [ Individual(np.array([0, 1, 0]), problem=MaxOnes()), Individual(np.array([1, 1, 1]), problem=MaxOnes()) ] pop = Individual.evaluate_population(pop) selector = ops.proportional_selection(pop, offset='pop-min') # we expect that the second individual is always selected # since the new zero point will be at the minimum fitness # of the population selected = next(selector) assert np.all(selected.genome == [1, 1, 1]) selected = next(selector) assert np.all(selected.genome == [1, 1, 1])
def test_mutate_bitflip(): # Create a very simple individual with two binary genes of all ones. ind = [Individual(np.array([1, 1]), problem=MaxOnes())] # Now mutate the individual such that we *expect both bits to bitflip* mutated_ind = next(ops.mutate_bitflip(iter(ind), expected_num_mutations=2)) assert np.all(mutated_ind.genome == [0, 0]) # Of course, since we didn't clone the original, well, that actually got # zapped, too. assert np.all(ind[0].genome == [0, 0])
def test_sus_selection_num_points(): ''' Test of SUS selection with varying `n` random points ''' # the second individual should always be selected pop = [ Individual(np.array([0, 0, 0]), problem=MaxOnes()), Individual(np.array([1, 1, 1]), problem=MaxOnes()) ] pop = Individual.evaluate_population(pop) # with negative points with pytest.raises(ValueError): selector = ops.sus_selection(pop, n=-1) selected = next(selector) # with n = None (default) selector = ops.sus_selection(pop, n=None) selected = next(selector) assert np.all(selected.genome == [1, 1, 1]) # with n less than len(population) selector = ops.sus_selection(pop, n=1) selected = next(selector) assert np.all(selected.genome == [1, 1, 1]) selected = next(selector) assert np.all(selected.genome == [1, 1, 1]) # with n greater than len(population) selector = ops.sus_selection(pop, n=3) selected = next(selector) assert np.all(selected.genome == [1, 1, 1]) selected = next(selector) assert np.all(selected.genome == [1, 1, 1]) selected = next(selector) assert np.all(selected.genome == [1, 1, 1]) selected = next(selector) assert np.all(selected.genome == [1, 1, 1]) selected = next(selector) assert np.all(selected.genome == [1, 1, 1])
def test_sus_selection1(): ''' Test of a deterministic case of stochastic universal sampling ''' # Make a population where sus_selection has an obvious # reproducible choice pop = [ Individual(np.array([0, 0, 0]), problem=MaxOnes()), Individual(np.array([1, 1, 1]), problem=MaxOnes()) ] pop = Individual.evaluate_population(pop) # This selection operator will always choose the [1, 1, 1] individual # since [0, 0, 0] has zero fitness selector = ops.sus_selection(pop) selected = next(selector) assert np.all(selected.genome == [1, 1, 1]) selected = next(selector) assert np.all(selected.genome == [1, 1, 1]) # run one more time to test shuffle selected = next(selector) assert np.all(selected.genome == [1, 1, 1])
def test_good_eval(): """ This is for testing a plain ole good individual to ensure that leap_ec.distrib.evaluate works for normal circumstances. """ # set up a basic dask local cluster with Client() as client: # hand craft an individual that should evaluate fine # Let's try evaluating a single individual individual = Individual(np.array([1, 1]), problem=MaxOnes()) future = client.submit(evaluate(context=context), individual) evaluated_individual = future.result() assert evaluated_individual.fitness == 2
def test_clone(): # We need an encoder and problem to ensure those float across during # clones. decoder = IdentityDecoder() problem = MaxOnes() original = Individual([1, 1], decoder=decoder, problem=problem) cloned = next(ops.clone(iter([original]))) assert original == cloned # Yes, but did the other state make it across OK? print(original.__dict__) print(cloned.__dict__) assert original.fitness == cloned.fitness assert original.decoder == cloned.decoder assert original.problem == cloned.problem # use this when comparing complex objects with arrays np.testing.assert_equal(original.__dict__, cloned.__dict__)
def test_lexical_maximization(): """ Tests the lexical_parsimony() for maximization problems """ problem = MaxOnes() # fitness=3, len(genome)=6 pop = [Individual(np.array([0, 0, 0, 1, 1, 1]), problem=problem)] # fitness=2, len(genome)=2 pop.append(Individual(np.array([1, 1]), problem=problem)) # fitness=3, len(genome)=3 pop.append(Individual(np.array([1, 1, 1]), problem=problem)) pop = Individual.evaluate_population(pop) best = ops.truncation_selection(pop, size=1, key=lexical_parsimony) # prefers the shorter of the 3 genomes assert np.all(best[0].genome == [1, 1, 1])
def test_truncation_selection_with_nan1(): """If truncation selection encounters a NaN and non-NaN fitness while maximizing, the non-NaN wins. """ # Make a population where binary tournament_selection has an obvious # reproducible choice problem = MaxOnes() pop = [ Individual(np.array([0, 0, 0]), problem=problem), Individual(np.array([1, 1, 1]), problem=problem) ] # We first need to evaluate all the individuals so that truncation # selection has fitnesses to compare pop = Individual.evaluate_population(pop) # Now set the "best" to NaN pop[1].fitness = nan best = ops.truncation_selection(pop, size=1) assert pop[0] == best[0]
from leap_ec.individual import Individual from leap_ec.decoder import IdentityDecoder from leap_ec.global_vars import context import leap_ec.ops as ops from leap_ec.binary_rep.problems import MaxOnes from leap_ec.binary_rep.initializers import create_binary_sequence from leap_ec.binary_rep.ops import mutate_bitflip from leap_ec import util # create initial rand population of 5 individuals parents = Individual.create_population(5, initialize=create_binary_sequence(4), decoder=IdentityDecoder(), problem=MaxOnes()) # Evaluate initial population parents = Individual.evaluate_population(parents) # print initial, random population util.print_population(parents, generation=0) # generation_counter is an optional convenience for generation tracking generation_counter = util.inc_generation(context=context) while generation_counter.generation() < 6: offspring = pipe(parents, ops.tournament_selection, ops.clone, mutate_bitflip(expected_num_mutations=1), ops.uniform_crossover(p_swap=0.2), ops.evaluate, ops.pool(size=len(parents))) # accumulate offspring