def call(self, population): # mix genomes shuffled_population = B.copy(population) shuffled_population = B.shuffle(shuffled_population) # how many chromosomes to crossover num_crossovers = int(population.shape[0] * self.population_fraction) self.print_debug('num_crossovers', num_crossovers) # compute the shape needed for the mutation mutations_shape = [num_crossovers] for idx, frac in enumerate(self.max_crossover_probability): max_genes = int(population.shape[idx + 1] * frac + 1) if max_genes > 1: num_genes = B.randint(1, high=max_genes) else: num_genes = 1 mutations_shape.append(num_genes) self.print_debug("mutation_shape: %s" % mutations_shape) slices = [] for crossover_size in mutations_shape: slices.append(slice(0, crossover_size)) slices = tuple(slices) tslices = slices2array(slices) self.print_debug('slices', slices) # crossover cross_section = shuffled_population[slices] population = B.assign(population, cross_section, tslices) return population
def call(self, population): # mix genomes population_copy = B.copy(population) population_copy = B.shuffle(population_copy) # how many chromosomes to crossover? num_crossovers = int(population.shape[0] * self.population_fraction) self.print_debug("population size %s" % population.shape[0]) self.print_debug("num_crossovers %s" % num_crossovers) # crossover matrix x_matrix = B.zeros(population.shape, dtype=population.dtype) self.print_debug("Creating x_matrix and mutation_matrix") # We need to accounting for the fact that the population # can be of rank N which makes the fancy indexing painful. # we need a shape for the mutation which is this: # [num_crossover, num_mutation, ..., num_mutations] mutations_shape = [num_crossovers] for idx, frac in enumerate(self.max_crossover_probability): max_genes = int(population.shape[idx + 1] * frac + 1) if max_genes > 1: num_genes = B.randint(1, high=max_genes) else: num_genes = max_genes mutations_shape.append(num_genes) self.print_debug("mutation_shape: %s" % mutations_shape) # create tensor mutations = B.ones(mutations_shape, dtype=population.dtype) # compute the fancy indexing dynamically slices = [] for size in mutations_shape: slices.append(slice(0, size)) slices = tuple(slices) tslices = slices2array(slices) # injecting mutations x_matrix = B.assign(x_matrix, mutations, tslices) x_matrix = B.full_shuffle(x_matrix) # invert crossover matrix inv_x_matrix = B.abs((x_matrix) - 1) # copy chromosomes that stays the same population = population * inv_x_matrix # add the mutations population += (population_copy * x_matrix) return population
def call(self, population): if not self.debug: population = B.shuffle(population) # how many chromosomes to crossover num_reversed_chromosomes = int(population.shape[0] * self.population_fraction) self.print_debug('num chromosomes', num_reversed_chromosomes) # compute the shape needed for the mutation mutations_shape = [num_reversed_chromosomes] for idx, frac in enumerate(self.max_reverse_probability): max_genes = int(population.shape[idx + 1] * frac + 1) # ! not an error: reverse need at least 2 indices to make sense. if max_genes > 2: num_genes = B.randint(2, high=max_genes) else: num_genes = 2 mutations_shape.append(num_genes) self.print_debug(idx, 'num_genes', num_genes, 'max', max_genes) self.print_debug("population_shape:", population.shape) self.print_debug("mutation_shape:", mutations_shape) # compute the fancy indexing dynamlically # ! the start point must be randomized slices = [slice(0, num_reversed_chromosomes)] for idx, crossover_size in enumerate(mutations_shape[1:]): # ! making indexing explicit as its a huge pitfall mutation_dim = idx + 1 max_start = population.shape[mutation_dim] - crossover_size + 1 start = B.randint(0, max_start) # start = random.randint(0, max_start) slices.append(slice(start, crossover_size + start)) slices = tuple(slices) tslices = slices2array(slices) self.print_debug('slices', slices) # revesing reversed_population = population[slices] axis = B.tensor([x for x in range(1, len(reversed_population.shape))]) reversed_population = B.reverse(reversed_population, axis) self.print_debug('reversed population', reversed_population) # assigning population = B.assign(population, reversed_population, tslices) return population
def call(self, population): # shuffle to make sure don't hit the same everytime if not self.debug: population = B.shuffle(population) # how many chromosomes to shuffle num_shuffle = int(population.shape[0] * self.population_fraction) shuffled_population = population[:num_shuffle] shuffled_population = B.full_shuffle(shuffled_population) self.print_debug("shuffled population", shuffled_population.shape) # recompose with non shuffled population shuffled_population = B.concatenate( [shuffled_population, population[num_shuffle:]]) return shuffled_population
def call(self, population): # mix genomes shuffled_population = B.copy(population) shuffled_population = B.shuffle(shuffled_population) # how many chromosomes to crossover num_crossover_chromosomes = int(population.shape[0] * self.population_fraction) self.print_debug('num chromosomes', num_crossover_chromosomes) # compute the shape needed for the mutation mutations_shape = [num_crossover_chromosomes] for idx, frac in enumerate(self.max_crossover_probability): max_genes = int(population.shape[idx + 1] * frac + 1) if max_genes > 1: num_genes = B.randint(1, high=max_genes) else: num_genes = 1 mutations_shape.append(num_genes) mutations_shape = mutations_shape self.print_debug("population_shape:", population.shape) self.print_debug("mutation_shape:", mutations_shape) # compute the fancy indexing dynamlically # ! the start point must be randomized slices = [slice(0, num_crossover_chromosomes)] for idx, crossover_size in enumerate(mutations_shape[1:]): # ! making indexing explicit as its a huge pitfall mutation_dim = idx + 1 max_start = population.shape[mutation_dim] - crossover_size + 1 start = B.randint(0, max_start) slices.append(slice(start, crossover_size + start)) slices = tuple(slices) tslices = slices2array(slices) self.print_debug('slices', slices) # crossover cross_section = shuffled_population[slices] population = B.assign(population, cross_section, tslices) return population
def uniform_population(shape, dtype=B.intx()): """Generate a uniform population made of Integers. Uniform means that each chromosome contains only one time each value and each chromosome have them in different order. Args: (set of ints): shape of the population. Its of the form (num_chromosomes, chromosome size) dtype (str): tensor type Returns: Tensor: uniform population. """ population = [] chromosome = B.range(shape[1], dtype=dtype) for i in range(shape[0]): chromosome = B.shuffle(chromosome) population.append(chromosome) return B.tensor(population)