def order_one_crossover(parent1, parent2, parameters=None): """ :param parent1: First parent chromosome, Gene, np.array with shape = (1,len(parent)) :param parent2: Second parent chromosome, Gene, np.array with shape = (1,len(parent)) :return """ parent1 = parent1.genotype() parent2 = parent2.genotype() n = len(parent1.genotype) start_substr = random.randint(0, n - 2) end_substr = random.randint(start_substr + 1, n) child1 = parent1.copy() child2 = parent2.copy() j = end_substr i = end_substr while j != start_substr: if not parent1[i] in child2[start_substr:end_substr]: child2[j] = parent1[i] j = (j + 1) % n i = (i + 1) % n j = end_substr i = end_substr while j != start_substr: if not parent2[i] in child1[start_substr:end_substr]: child1[j] = parent2[i] j = (j + 1) % n i = (i + 1) % n return Chromosome(child1, 0), Chromosome(child2, 0)
def nwox_crossover(parent1, parent2, parameters=None): """ Non-Wrapping Order Crossover (NWOX) - (Cicirello 2006) :param parent1: First parent chromosome, Gene, np.array with len [n^2,1] :param parent2: Second parent chromosome, Gene, np.array with len [n^2,1] :return: return two chromosome for each children, Chromosome """ crossover_points = np.sort(np.random.choice(np.arange(len(parent1.genotype)), replace=False, size=2)) gen1, gen2 = np.copy(parent1.genotype), np.copy(parent2.genotype) # First, all those bits are left as hole which are presenting within the cut-points in other parent gen1 = np.setdiff1d(gen1, parent2.genotype[crossover_points[0]: crossover_points[1] + 1], assume_unique=True) gen2 = np.setdiff1d(gen2, parent1.genotype[crossover_points[0]: crossover_points[1] + 1], assume_unique=True) gen1 = np.concatenate((gen1[:crossover_points[0]], parent2.genotype[crossover_points[0]: crossover_points[1] + 1], gen1[crossover_points[0]:])) gen2 = np.concatenate((gen2[:crossover_points[0]], parent1.genotype[crossover_points[0]: crossover_points[1] + 1], gen2[crossover_points[0]:])) chromosome1, chromosome2 = Chromosome(gen1, 0), Chromosome(gen2, 0) return chromosome1, chromosome2
def masked_crossover(parent1, parent2, parameters=None): """ :param parameters: dictionary of parameters that key = parameter name and value = parameter value :param parent1: First parent chromosome, Gene, np.array with shape (1, _n) :param parent2: Second parent chromosome, Gene, np.array with shape (1, _n) :return: return two chromosome for each children, Chromosome """ mask1 = np.random.randint(2, size=len(parent1.genotype)) mask2 = np.random.randint(2, size=len(parent2.genotype)) child1, child2 = np.full(len(parent1.genotype), np.inf), np.full(len(parent2.genotype), np.inf) child1, child2 = Chromosome(child1, 0), Chromosome(child2, 0) for i in range(len(mask1)): if mask2[i] and not mask1[i]: child1.genotype[i] = parent2.genotype[i] if mask1[i] and not mask2[i]: child2.genotype[i] = parent1.genotype[i] for i in range(len(child1.genotype)): if child1.genotype[i] == np.inf and parent1.genotype[i] not in child1.genotype: child1.genotype[i] = parent1.genotype[i] if child2.genotype[i] == np.inf and parent2.genotype[i] not in child2.genotype: child2.genotype[i] = parent2.genotype[i] not_exist_genotype_in_child1 = list(set(np.array(range(0, len(parent1.genotype)))) - set(child1.genotype)) not_exist_genotype_in_child2 = list(set(np.array(range(0, len(parent2.genotype)))) - set(child2.genotype)) return Chromosome(np.array(not_exist_genotype_in_child1), 0), Chromosome(np.array(not_exist_genotype_in_child2), 0)
def doCrossover(self, generation, i, index): chromo = generation.chromosomes length = chromo[0].length cut = random.randint(1, length - 1) parent1 = chromo[index[i]] parent2 = chromo[index[i + 1]] genesChild1 = parent1.genes[0:cut] + parent2.genes[cut:length] genesChild2 = parent1.genes[cut:length] + parent2.genes[0:cut] child1 = Chromosome(genesChild1, len(genesChild1)) child2 = Chromosome(genesChild2, len(genesChild2)) # ----clustering---- clustering = Clustering(generation, self.data, self.kmax) child1 = clustering.calcChildFit(child1) child2 = clustering.calcChildFit(child2) # ------------------- listA = [] listA.append(parent1) listA.append(parent2) listA.append(child1) listA.append(child2) # sort parent and child by fitness / dec listA = sorted(listA, reverse=True, key=lambda elem: elem.fitness) generation.chromosomes[index[i]] = listA[0] generation.chromosomes[index[i + 1]] = listA[1] return generation
def test_crossover_at_given_index_longer_chromosomes( self, first_chromosome_seed: str, second_chromosome_seed: str, crossover_index: int, first_chromosome_crossed_seed: str, second_chromosome_crossed_seed: str): first_chromosome = Chromosome(first_chromosome_seed) second_chromosome = Chromosome(second_chromosome_seed) first_chromosome_crossed = CrossedChromosomes(first_chromosome, second_chromosome, crossover_index).first() second_chromosome_crossed = CrossedChromosomes( first_chromosome, second_chromosome, crossover_index).second() self.assertEqual( first_chromosome_crossed, Chromosome(first_chromosome_crossed_seed), f"crossed: {first_chromosome_crossed.to_string()}, seed: {first_chromosome_crossed_seed}" ) self.assertEqual( second_chromosome_crossed, Chromosome(second_chromosome_crossed_seed), f"crossed: {second_chromosome_crossed.to_string()}, seed: {second_chromosome_crossed_seed}" )
def random(): c = Chromosome(self._data.dimension) # Avoid duplicates while c in self._population: c = Chromosome(self._data.dimension) c.dist = self._data.tour_dist(c.tour) return c
def test_mutate(self, chromosome_seed: str, mutated_seed: str, injected_random_number: "List"): chromosome = Chromosome(chromosome_seed) chromosome_mutated = chromosome.mutate(injected_random_number) self.assertEqual(chromosome_mutated, Chromosome(mutated_seed))
def crossover(self, crossover_rate): temp_population = [] new_population = [] for i in range(len(self.population)): temp_population.append(self.selection()) for i in range(0, len(temp_population) - 1, 2): if uniform(0, 1) < crossover_rate: crossover_point = randint(1, self.n_genes) temp1 = temp_population[i].chromo_numb[:crossover_point] temp2 = temp_population[i + 1].chromo_numb[crossover_point:] son_chromo_numb1 = temp1 + temp2 temp1 = temp_population[i + 1].chromo_numb[:crossover_point] temp2 = temp_population[i].chromo_numb[crossover_point:] son_chromo_numb2 = temp1 + temp2 son_chromo1 = Chromosome(self.n_genes) son_chromo1.generate(son_chromo_numb1) son_chromo1.numbToExpr(self.max_loops, self.grammar) son_chromo1.calculateFitness(self.data_train) son_chromo2 = Chromosome(self.n_genes) son_chromo2.generate(son_chromo_numb2) son_chromo2.numbToExpr(self.max_loops, self.grammar) son_chromo2.calculateFitness(self.data_train) new_population.append(son_chromo1) new_population.append(son_chromo2) else: new_population.append(temp_population[i]) new_population.append(temp_population[i + 1]) if len(temp_population) % 2 == 1: new_population.append(temp_population[-1]) self.population = new_population.copy()
def gen_pop(size, dimension, data, method='random'): print "Creating population..." population = set() if method == 'random': # Populate with unique individuals for i in xrange(size): c = Chromosome(dimension, data) # Avoid duplicated while c in all_pop: c = Chromosome(dimension, data) # Calc dist c.dist = data.tour_dist(c.tour) population.add(c) all_pop.add(c) # Generate with 2opt (hard for small tsp) elif method == '2opt': for i in xrange(size): c = Chromosome(dimension, data) c.dist = data.tour_dist(c.tour) c = functions.two_opt(c, data) # Avoid duplicated while c in all_pop: c = Chromosome(dimension, data) c.dist = data.tour_dist(c.tour) c = functions.two_opt(c, data) population.add(c) all_pop.add(c) print "Done" # Return population return population
def _mate_one(pair): mother, father = pair n = len(mother) inv1 = inversion(list(mother.genes)) inv2 = inversion(list(father.genes)) line = randint(0, n - 1) new_inv1 = inv1[0:line] + inv2[line:n] new_inv2 = inv2[0:line] + inv1[line:n] # line1 = randint(0, n - 1) # line2 = randint(0, n - 1) # # if line1 > line2: # line1, line2 = line2, line1 # # new_inv1 = inv2[0:line1] + inv1[line1:line2] + inv2[line2:n] # new_inv2 = inv1[0:line1] + inv2[line1:line2] + inv1[line2:n] child1 = permutation(new_inv1) child2 = permutation(new_inv2) child1_chrome = Chromosome(child1) child2_chrome = Chromosome(child2) return child1_chrome, child2_chrome
def multi_points_crossover(parent1, parent2, parameters={'prob': 0.4, 'points_count': 'middle'}): """ :param parameters: dictionary of parameters that key = parameter name and value = parameter value :param parent1: First parent chromosome, Gene, np.array with len [n^2,1] :param parent2: Second parent chromosome, Gene, np.array with len [n^2,1] :return: return two chromosome for each children, Chromosome """ if str(parameters['points_count']) == 'middle': return default_cross_over(parent1, parent2) if parameters['points_count'] > len(parent1.genotype) or parameters['points_count'] <= 0: warnings.warn('points must be between 1 and size of genotype. parents will be returned', stacklevel=3) return parent1, parent2 crossover_points = np.sort( np.random.choice(np.arange(len(parent1.genotype)), replace=False, size=parameters['points_count'])) crossover_points = np.append(crossover_points, len(parent1.genotype)) # print('cross over points', crossover_points) first_idx = 0 gen1, gen2 = np.zeros(len(parent1.genotype)), np.zeros(len(parent1.genotype)) for last_idx in crossover_points: if np.random.random() <= parameters['prob']: gen2[first_idx: last_idx] = parent2.genotype[first_idx: last_idx] gen1[first_idx: last_idx] = parent1.genotype[first_idx: last_idx] # print('same') else: gen1[first_idx: last_idx] = parent2.genotype[first_idx: last_idx] gen2[first_idx: last_idx] = parent1.genotype[first_idx: last_idx] # print('not same') # print(gen1) # print(gen2) first_idx = last_idx chromosome1, chromosome2 = Chromosome(gen1, 0), Chromosome(gen2, 0) return chromosome1, chromosome2
def crossover(self, parent1, parent2, crossover_rate): """ Geni za novi hromozom se uzimaju od 2 roditelja, primenjujuci odgovarajuci tip ukrstanja """ child1 = Chromosome() child2 = Chromosome() # pravimo kopiju roditeljskih gena koje cemo koristiti da ne bi uticale na original child1.values = np.copy(parent1.values) child2.values = np.copy(parent2.values) r = random.random() # Perform crossover. if (r < crossover_rate): # Pick a crossover point. Crossover must have at least 1 row (and at most 8) rows. #biramo 2 tacke za crossover, koje moraju biti razlicite crossover_point1 = random.randint(0, 8) crossover_point2 = random.randint(1, 9) while (crossover_point1 == crossover_point2): crossover_point1 = random.randint(0, 8) crossover_point2 = random.randint(1, 9) if (crossover_point1 > crossover_point2): temp = crossover_point1 crossover_point1 = crossover_point2 crossover_point2 = temp for i in range(crossover_point1, crossover_point2): child1.values[i], child2.values[i] = self.crossover_rows(child1.values[i], child2.values[i]) return child1, child2
def crossover(first_parent, second_parent): crossover_point = np.random.randint(1, 3) first_parent = copy.deepcopy(first_parent.get_genes()) second_parent = copy.deepcopy(second_parent.get_genes()) first_child = Chromosome(first_parent[:crossover_point]+second_parent[crossover_point:]) second_child = Chromosome((second_parent[:crossover_point] + first_parent[crossover_point:])) return [first_child, second_child]
def single_point_crossover(first_parent, second_parent, crossover_point): first_parent = first_parent.get_genes() second_parent = second_parent.get_genes() first_child = Chromosome(first_parent[:crossover_point] + second_parent[crossover_point:]) second_child = Chromosome( (second_parent[:crossover_point] + first_parent[crossover_point:])) return [first_child, second_child]
def test_optional_threshold(self, chromosome_seed: str, mutated_seed: str, injected_random_number: "List", threshold: float): chromosome = Chromosome(chromosome_seed) chromosome_mutated = chromosome.mutate(injected_random_number, threshold=threshold) self.assertEqual(chromosome_mutated, Chromosome(mutated_seed))
def evolve(self): # create a new population new_population = Population(self.helper, pop=self.POPULATION_SIZE, tour=self.TOURNAMENT_SIZE, cross=self.CROSSOVER_RATE, mut=self.MUTATION_INVERSION_RATE) # the best fitting solution go to the next population automatically (ELITISM) best_fit = ga.get_best_fitness(self.chromosomes, self.helper) elit_chromosome = Chromosome() elit_chromosome.path = list(best_fit.path) elit_chromosome.trucks_used = list(best_fit.trucks_used) new_population.chromosomes.append(elit_chromosome) elit_unchanged = Chromosome() elit_unchanged.path = list(best_fit.path) elit_unchanged.trucks_used = list(best_fit.trucks_used) # crossover for _ in range((self.POPULATION_SIZE - 2) / 2): #print 'generating child ' + str(i) # must select parent 1 using TOURNAMENT SELECTION parent_1 = ga.tournament_selection(self.chromosomes, self.helper, self.TOURNAMENT_SIZE) # must select parent 2 using TOURNAMENT SELECTION parent_2 = ga.tournament_selection(self.chromosomes, self.helper, self.TOURNAMENT_SIZE) # crossover these chomosomes child = ga.crossover(parent_1, parent_2, self.helper, self.CROSSOVER_RATE) child.fitness = None # reset the fitness (it was calculated in the tournament and yet can mutate) child.deposit_distance = None new_population.chromosomes.append(child) child2 = ga.crossover(parent_2, parent_1, self.helper, self.CROSSOVER_RATE) child2.fitness = None # reset the fitness (it was calculated in the tournament and yet can mutate) child2.deposit_distance = None new_population.chromosomes.append(child2) # mutate ga.mutate(new_population.chromosomes, self.helper, self.MUTATION_INVERSION_RATE) # insert one unchanged elit (to keep the best if its the case) new_population.chromosomes.append(elit_unchanged) if len(new_population.chromosomes) != self.POPULATION_SIZE: print 'POPULATION WITH DFF SIZE' return new_population
def ga(pixel_arr, constraints, pop_size=100, g_max=40, p_c=0.6, p_m=0.4, verbose=True): start_time = time.time() num_rows, num_cols = pixel_arr.shape[0], pixel_arr.shape[1] population = [Chromosome(pixel_arr) for i in range(pop_size)] avg_fitness = sum(c.fitness for c in population) best_ind = max(population, key=lambda c: c.fitness) if verbose: print("Generation 0:") print("Best fitness:", best_ind.fitness, "Avg fitness:", avg_fitness) print("Number of segmentations:", max(best_ind.segments)) print("Edge value:", best_ind.edge_value) print("Connectivity:", best_ind.connectivity) print("Deviation:", best_ind.deviation) print(f"Initial generation time: {time.time() - start_time}\n", flush=True) for g in range(1, g_max+1): start_time = time.time() offspring = [] for i in range(pop_size//2): p1 = parent_selection(population) p2 = parent_selection(population) if random() < p_c: cutoff = randint(0, len(p1.genotype)-1) c1_geno = crossover(p1.genotype, p2.genotype, cutoff) c2_geno = crossover(p2.genotype, p1.genotype, cutoff) else: c1_geno = p1.genotype c2_geno = p2.genotype if random() < p_m: c1_geno = mutate(c1_geno, num_rows, num_cols, arr, constraints) if random() < p_m: c2_geno = mutate(c2_geno, num_rows, num_cols, arr, constraints) c1 = Chromosome(pixel_arr, c1_geno) c2 = Chromosome(pixel_arr, c2_geno) offspring.append(c1) offspring.append(c2) population = elitist_replacement(population, offspring) avg_fitness = sum(c.fitness for c in population) best_ind = max(population, key=lambda c: c.fitness) if verbose: print(f"Generation {g}:") print("Best fitness:", best_ind.fitness, "Avg fitness:", avg_fitness) print("Number of segmentations:", max(best_ind.segments)) print("Edge value:", best_ind.edge_value) print("Connectivity:", best_ind.connectivity) print("Deviation:", best_ind.deviation) print(f"Time elapsed: {time.time() - start_time}\n", flush=True) return best_ind
def position_based_crossover(parent1, parent2, parameters=None): """ :param parameters: dictionary of parameters that key = parameter name and value = parameter value :param parent1: First parent chromosome, Gene, np.array with size [1,n] :param parent2: Second parent chromosome, Gene, np.array with size [1,n] :return: return two chromosome for each children, Chromosome """ def find_cycle(parent1, parent2, cycle, first): ind = np.where(parent2 == cycle[-1])[0][0] cycle.append(parent1[ind]) if parent1[ind] == first: return cycle return find_cycle(parent1, parent2, cycle, first) par_size = len(parent1.genotype) points = np.random.choice(par_size, 3, replace=False) gen1, gen2 = np.zeros(par_size, dtype=np.int), np.zeros(par_size, dtype=np.int) for i in range(len(points)): gen1[points[i]], gen2[points[i]] = parent2.genotype[points[i]], parent1.genotype[points[i]] cycle_index = [] for i in range(par_size): if i not in points: cycle = [parent2.genotype[i]] cycle_index.append(find_cycle(parent1.genotype, parent2.genotype, cycle, parent2.genotype[i])) else: cycle_index.append([]) for i in range(par_size): if i not in points: cycle = cycle_index[i] for j in range(1, len(cycle)): if cycle[j] not in gen1: gen1[i] = cycle[j] break cycle_index = [] for i in range(par_size): if i not in points: cycle = [parent1.genotype[i]] cycle_index.append(find_cycle(parent2.genotype, parent1.genotype, cycle, parent1.genotype[i])) else: cycle_index.append([]) for i in range(par_size): if i not in points: cycle = cycle_index[i] for j in range(1, len(cycle)): if cycle[j] not in gen2: gen2[i] = cycle[j] break chromosome1, chromosome2 = Chromosome(gen1, 0), Chromosome(gen2, 0) return chromosome1, chromosome2
def tournament_pair(self): mother = self.getByTournament() father = self.getByTournament() # create larger population size = self.params["NumChromes"] mothers = [Chromosome(str(mother)) for i in range(0, size/2)] fathers = [Chromosome(str(father)) for i in range(0, size/2)] return zip(mothers, fathers)
def test_exe(self): p1 = Chromosome("111100111100120000000013") p2 = Chromosome("000012131313111112001112") crossover_point = 4 children = OnePoint().exe(p1, p2, crossover_point) expected_1 = Chromosome("111112131313111112001112") expected_2 = Chromosome("000000111100120000000013") self.assertEqual(children[0].solution, expected_1.solution) self.assertEqual(children[1].solution, expected_2.solution)
def test_chromosome(): for _ in range(10): p1 = Chromosome(gen_prob=0.1, mutation_prob=0) p2 = Chromosome(gen_prob=0.1, mutation_prob=0) print("{} {}".format(p1.root, p1.eval())) print("{} {}".format(p2.root, p2.eval())) p1.crossover(p2) print("{} {}".format(p1.root, p1.eval())) print("{} {}".format(p2.root, p2.eval())) print() print()
def testRecombinate(): first = Chromosome() second = Chromosome() print(first.dnArray) print(second.dnArray) print(first.arithmeticArray) print(second.arithmeticArray) first.recombinate(second) print(first.dnArray) print(second.dnArray) print(first.arithmeticArray)
def uniform_crossover(first_parent, second_parent): first_child = first_parent.get_genes() second_child = second_parent.get_genes() for i in range(len(first_child)): if np.random.randint(10) % 2 == 0: temp = first_child[i] first_child[i] = second_child[i] second_child[i] = temp return [Chromosome(first_child), Chromosome(second_child)]
def crossover(parent_one, parent_two): bin_one = parent_one.binary bin_two = parent_two.binary new_bin_one = bin_one[:2] + bin_two[2:] new_bin_two = bin_two[:2] + bin_one[2:] child_one = Chromosome('', new_bin_one) child_two = Chromosome('', new_bin_two) return child_one, child_two
def exe(self): for i in range(0, len(self.chromosome), 2): if choice(range(1, self.probabilty + 1)) == 1: if self.chromosome[i] == '1': return Chromosome(self.chromosome[:i] + '00' + self.chromosome[i + 2:]) elif self.chromosome[i] == '0': return Chromosome(self.chromosome[:i] + '1' + str(randint(1, RcParser().get_m())) + self.chromosome[i + 2:]) return self.chromosome
def double_point_crossover(first_parent, second_parent, start_point, end_point): first_parent = first_parent.get_genes() second_parent = second_parent.get_genes() first_child = Chromosome(first_parent[:start_point] + second_parent[start_point:end_point] + first_parent[end_point:]) second_child = Chromosome(second_parent[:start_point] + first_parent[start_point:end_point] + second_parent[end_point:]) return [first_child, second_child]
def crossover(p1, p2): split = math.floor(p1.data.__len__()/2)#random.randint(1, str(p1.data).__len__()) kid1 = Chromosome() kid2 = Chromosome() for i in range(0, str(p1.data).__len__()): if i < split: kid1.data = kid1.data + p1.data[i] kid2.data = kid2.data + p2.data[i] else: kid1.data = kid1.data + p2.data[i] kid2.data = kid2.data + p1.data[i] return (kid1, kid2)
def copy(self, chrom1, chrom2): crom_size = chrom1.getLarge() newRoute1 = chrom1.getRoute() newRoute2 = chrom2.getRoute() son1 = Chromosome(crom_size, None, newRoute1) son2 = Chromosome(crom_size, None, newRoute2) print() print("New Sons without CrossOver (Indentical): ") print(son1.getRoute()) print(son2.getRoute()) return son1, son2
def uniform_crossover(first, second): temp_first = copy.deepcopy(first.get_sudoku()) temp_second = copy.deepcopy(second.get_sudoku()) for i in range(first.sudoku_size): choose = np.random.randint(first.sudoku_size) if choose % 2 == 0: for j in range(first.sudoku_size): temp = temp_first[i][j] temp_first[i][j] = temp_second[i][j] temp_second[i][j] = temp return Chromosome(9, temp_first), Chromosome(9, temp_second)
def single_point_crossover(first, second): point = np.random.randint(first.sudoku_size) # print(point) temp_first = copy.deepcopy(first.get_sudoku()) temp_second = copy.deepcopy(second.get_sudoku()) for i in range(point, first.sudoku_size): for j in range(first.sudoku_size): temp = temp_first[i][j] temp_first[i][j] = temp_second[i][j] temp_second[i][j] = temp return Chromosome(9, temp_first), Chromosome(9, temp_second)