def test_uniform_distribution(): """check that every gene of the tensor are going to be flipped equally Note: # ! We need enough iterations and chromosomes to reduce collision # ! and ensure numerical stability """ NUM_ITERATIONS = 300 GENOME_SHAPE = (20, 4, 4) population = B.randint(0, 1024, GENOME_SHAPE) population_fraction = 1 crossover_probability = (0.5, 0.5) OP = RandomMutations2D(population_fraction, crossover_probability) # diff matrix previous_population = B.copy(population) population = OP(population) diff = B.clip(abs(population - previous_population), 0, 1) for _ in range(NUM_ITERATIONS - 1): previous_population = B.copy(population) population = OP(population) curr_diff = B.clip(abs(population - previous_population), 0, 1) # acumulating diff matrix diff += curr_diff print(curr_diff) for c in diff: print(c) print('mean', B.mean(c), 'min', B.min(c), 'max', B.max(c)) assert B.min(c) > NUM_ITERATIONS // 15 assert B.max(c) < NUM_ITERATIONS // 2 assert NUM_ITERATIONS // 8 < B.mean(c) < NUM_ITERATIONS // 2
def test_crossover1D_output_shape(): POPULATION_SHAPE = (8, 6) population = B.randint(0, 1024, POPULATION_SHAPE) population_fraction = 0.5 mutations_probability = 0.2 original_population = copy(population) population = DualCrossover1D(population_fraction, mutations_probability, debug=True)(population) cprint(population, 'cyan') cprint(original_population, 'yellow') assert population.shape == POPULATION_SHAPE # measuring mutation rate diff = B.clip(abs(population - original_population), 0, 1) # row test num_ones_in_row = 0 for col in diff: num_ones_in_row = max(list(col).count(1), num_ones_in_row) max_one_in_row = int(POPULATION_SHAPE[1] * mutations_probability) assert num_ones_in_row == max_one_in_row assert num_ones_in_row
def call(self, population): """ Create the mask use to generate mutations Args: population_shape (list): population tensor shape. Returns: tensor: mask Generation works by: 1. creating a slice that contains the mutation 2. Inserting it into the mask 3. Shuffle the mask in every dimension to distribute them """ affected_population = int(population.shape[0] * self.population_fraction) # Build sub tensors & slices by iterating through tensor dimensions sub_tensor_shape = [affected_population] slices = [slice(0, affected_population)] for idx, pop_size in enumerate(population.shape[1:]): midx = idx - 1 # recall dim1 are genes. max_genes = int(pop_size * self.mutations_probability[midx] + 1) num_genes = B.randint(1, high=max_genes) sub_tensor_shape.append(num_genes) slices.append(slice(0, num_genes)) slices = tuple(slices) tslices = slices2array(slices) self.print_debug("sub_tensor_shape", sub_tensor_shape) # drawing mutations mutations = B.randint(self.min_mutation_value, self.max_mutation_value + 1, shape=sub_tensor_shape) # blank mask mask = B.zeros(population.shape, dtype=mutations.dtype) # add mutations # print('mtuation', mutations.dtype) # print('mask', mask.dtype) mask = B.assign(mask, mutations, tslices) # shuffle mask every axis mask = B.full_shuffle(mask) # mutate population = population + mask # normalize if self.max_gene_value or self.min_gene_value: self.print_debug("min_gen_val", self.min_gene_value) self.print_debug("max_gen_val", self.max_gene_value) population = B.clip(population, min_val=self.min_gene_value, max_val=self.max_gene_value) return population
def test_shuffle(): SHAPES = [(2, 4), (2, 4, 4), (2, 4, 4, 4)] for shape in SHAPES: population = randint_population(shape, max_value=255) previous_population = B.copy(population) population = Shuffle(1, debug=True)(population) diff = B.clip(abs(population - previous_population), 0, 1) assert B.is_tensor(population) assert population.shape == shape sum_diff = B.sum(diff) shape_size = int(B.prod(shape) / 2) assert sum_diff >= shape_size
def test_1D_shape(): POPULATION_SHAPE = (64, 16) population = B.randint(0, 1024, POPULATION_SHAPE) population_fraction = 0.5 crossover_size_fraction = 0.2 original_population = copy(population) population = SingleCrossover1D(population_fraction, crossover_size_fraction, debug=1)(population) cprint(population, 'cyan') cprint(original_population, 'yellow') assert population.shape == POPULATION_SHAPE # measuring mutation rate diff = B.clip(abs(population - original_population), 0, 1) cprint('diff', 'cyan') cprint(diff, 'cyan') # row test num_ones_in_row = 0 for col in diff: num_ones = list(col).count(1) num_ones_in_row = max(num_ones, num_ones_in_row) max_one_in_row = POPULATION_SHAPE[1] * crossover_size_fraction assert num_ones_in_row <= max_one_in_row assert num_ones_in_row # col diff = B.transpose(diff) num_ones_in_col = 0 for col in diff: num_ones_in_col = max(list(col).count(1), num_ones_in_col) max_one_in_col = POPULATION_SHAPE[0] * population_fraction assert max_one_in_col - 3 <= num_ones_in_col <= max_one_in_col
def test_uniform_2Dcrossover_randomness_shape(): GENOME_SHAPE = (10, 4, 4) population = B.randint(0, 1024, GENOME_SHAPE) population_fraction = 0.5 crossover_probability = (0.5, 0.5) original_population = copy(population) OP = UniformCrossover2D(population_fraction, crossover_probability) population = OP(population) diff = B.clip(abs(population - original_population), 0, 1) print(diff) expected_mutations = original_population.shape[0] * population_fraction mutated_chromosomes = [] for c in diff: if B.max(c): mutated_chromosomes.append(c) num_mutations = len(mutated_chromosomes) # sometime we have a collision so we use a delta assert abs(num_mutations - expected_mutations) < 2 mutated_rows = crossover_probability[0] * GENOME_SHAPE[1] mutated_cells = crossover_probability[0] * GENOME_SHAPE[2] for cidx, c in enumerate(mutated_chromosomes): mr = 0.0 mc = 0.0 for r in c: s = B.cast(B.sum(r), B.floatx()) if s: mr += 1 mc += s assert abs(mutated_rows - mr) <= 2 assert abs(B.cast(mutated_cells, B.floatx()) - (mc / mutated_rows)) <= 3.0 # 2.5
from copy import copy from termcolor import cprint from evoflow.utils import op_optimization_benchmark NUM_RUNS = 3 # 100 # pop_shape = (100, 100, 100) pop_shape = (100, 100, 100) population = B.randint(0, 256, pop_shape) population_fraction = 0.5 max_reverse_probability = (0.5, 0.5) OP = Reverse2D(population_fraction, max_reverse_probability) op_optimization_benchmark(population, OP, NUM_RUNS).report() quit() GENOME_SHAPE = (6, 4) population = B.randint(0, 256, GENOME_SHAPE) population_fraction = 0.5 max_reverse_probability = 0.5 cprint(population, 'green') original_population = copy(population) # ! population will be shuffle if not debug population = Reverse1D(population_fraction, max_reverse_probability, debug=True)(population) cprint(population, 'blue') # diff matrix diff = B.clip(abs(population - original_population), 0, 1) print(diff)
op_optimization_benchmark(population, OP, NUM_RUNS).report() quit() GENOME_SHAPE = (6, 4, 4) population = B.randint(0, 100, GENOME_SHAPE) population_fraction = 0.5 crossover_probability = (0.5, 0.5) print(population.shape) # peforming crossover original_population = copy(population) population = UniformCrossover2D(population_fraction, crossover_probability)(population) print(population) # diff matrix diff = B.clip(abs(population - original_population), 0, 1) print(diff) quit() # expected mutated chromosomes expected_mutated = population.shape[0] * population_fraction cprint( "Expected mutated chromosome:%d (+/- 1 due to collision)" % (expected_mutated), 'cyan') # select mutated chromosomes mutated_chromosomes = [] for c in diff: if B.max(c): mutated_chromosomes.append(c) cprint("mutated chromosome:%d" % (len(mutated_chromosomes)), 'magenta') cprint("[example of mutated chromosome]", 'yellow')