def test_crossover(): #use these 2 individuals for all sub tests individual_1 = individual.Ind(size=5, genes={ "a": 1, "b": 2, "c": 3, "d": 4, "e": 5 }, fitness=0) individual_2 = individual.Ind(size=5, genes={ "a": 6, "b": 7, "c": 8, "d": 9, "e": 10 }, fitness=0) ranges = [ individual.ParamRange("a", 0, 10, 1), individual.ParamRange("b", 0, 10, 1), individual.ParamRange("c", 0, 10, 1), individual.ParamRange("d", 0, 10, 1), individual.ParamRange("e", 0, 10, 1) ] isError = False print("--------\nTesting crossover for individuals", individual_1.genes, "and", individual_2.genes) for cross_point in range(1, 4): print("Testing crossover point ", cross_point, "...") ret_pop = [] #restart each time through individual.crossover(individual_1, individual_2, ret_pop, ranges, cross_point) #Test that the individuals are correct print(ret_pop[0], ret_pop[1]) for i in range( cross_point ): #check up to cross point in each individual in ret_pop for no change if (ret_pop[0].genes[ranges[i].name]!=individual_1.genes[ranges[i].name]) or \ (ret_pop[1].genes[ranges[i].name] != individual_2.genes[ranges[i].name]): isError = True print("Error at gene ", ranges[i].name, " using crossover point ", cross_point) for i in range(cross_point, len(ranges)): if (ret_pop[0].genes[ranges[i].name] != individual_2.genes[ranges[i].name]) or \ (ret_pop[1].genes[ranges[i].name] != individual_1.genes[ranges[i].name]): isError = True print("Error at gene ", ranges[i].name, " using crossover point ", cross_point) if not isError: print("Crossover test complete with no errors")
def testCrossover(self): (i3, i4) = crossover(self.i1, self.i2) union1 = self.i1.chromosome.union(self.i2.chromosome) union2 = i3.chromosome.union(i4.chromosome) self.assertEqual(union1, union2) self.assertEqual(len(i3.chromosome), self.p) self.assertEqual(len(i4.chromosome), self.p)
def testCrossoverDiffIndividuals(self): (i3, i4) = crossover(self.i1, self.i2, c=3) self.assertNotEqual(i3, i4) union1 = self.i1.chromosome.union(self.i2.chromosome) union2 = i3.chromosome.union(i4.chromosome) self.assertEqual(union1, union2) self.assertEqual(len(i3.chromosome), self.p) self.assertEqual(len(i4.chromosome), self.p)
def crossover(pop, ranges, keep, tournament_size): # Choose the parent pairs ret_pop = [] # this will hold the new population number_of_pairs = int((len(pop) - keep) / 2) pairs_for_crossover = choose_individuals( pop, "tournament", number_of_pairs, tournament_size) # holds indices of individuals as a list of pairs # ensures choose_individuals can't break this function if len(pairs_for_crossover) != int(number_of_pairs): print("Error. Incorrect number of pairs for crossover chosen:", len(pairs_for_crossover), number_of_pairs) sys.exit(-1) # crosses over two individuals at a time from the pair list for i in range(len(pairs_for_crossover)): # random point to cross over cross_point = random.randint( 1, len(ranges) - 1) # forces crosspoint to not be before or after end #print("Crossoverpoint:", cross_point) # get the random individuals individual_1 = pop[pairs_for_crossover[i][0]] individual_2 = pop[pairs_for_crossover[i][1]] #print(individual_1,individual_2) # send over individuals and crossover point. ret_pop will be modified to hold two new individuals individual.crossover(individual_1, individual_2, ret_pop, ranges, cross_point) #add elitism individuals to the new population elitism(pop, ret_pop, keep) assert ( len(pop) == len(ret_pop)), "new population is not the correct size!" return ret_pop
def run(): p_cross = 0.7 p_mutation = 0.01 config = read_file('data/had12.dat') distances = config['distances'] flows = config['flows'] individual_size = config['size'] new_population = [] population_size = 100 tour_size = 5 num_of_gen = 100 result_matrix = np.zeros((4, num_of_gen, 5)) print(result_matrix) for e in range(5): current_population = generate_init_population(population_size, individual_size) current_population_costs = calculate_population_cost( distances, flows, current_population) result_matrix[:, 0, e] = ([ 0, min(current_population_costs), np.average(current_population_costs), max(current_population_costs) ]) print('poczatek fora') for gen in range(1, num_of_gen): print('current' + str(current_population)) for _ in range(population_size): new_population.append( tournament(current_population, current_population_costs, tour_size)) print('after tournamtent' + str(new_population)) # new_population = roulette(current_population, current_population_costs) new_population = [ crossover(individual_parent, choice(new_population)) if random() <= p_cross else individual_parent for individual_parent in new_population ] print('after crossover: ' + str(new_population)) new_population = [ mutate_individual(indiv) if random() <= p_mutation else indiv for indiv in new_population ] current_population = new_population new_population = [] current_population_costs = calculate_population_cost( distances, flows, current_population) print('gen' + str(gen)) result_matrix[:, gen, e] = ([ gen, min(current_population_costs), np.average(current_population_costs), max(current_population_costs) ]) print('generation ' + str(gen)) plt.xlabel('Generations') plt.ylabel('Costs') plt.errorbar(np.arange(num_of_gen), np.average(result_matrix[1, :, :], axis=1), np.std(result_matrix[1, :, :], axis=1), fmt='-o', label="Best") plt.errorbar(np.arange(num_of_gen), np.average(result_matrix[2, :, :], axis=1), np.std(result_matrix[2, :, :], axis=1), fmt='-o', label="Avg") plt.errorbar(np.arange(num_of_gen), np.average(result_matrix[3, :, :], axis=1), np.std(result_matrix[3, :, :], axis=1), fmt='-o', label="Worst") plt.legend(bbox_to_anchor=(1.05, 1), loc=4, borderaxespad=0.) plt.show() random_search(num_of_gen, individual_size, distances, flows)
def evolve(G, p, popsize, gener, mutprob, coprob, tsize, elitism=None): nodes_ordered_by_demand = sorted(G.node.items(), key=lambda t: t[1]['demand'], reverse=True) t1 = clock() pop = [] # generating first population, which will be random for i in range(popsize): individual = Individual(p, G) individual.calculate_fitness(G, nodes_ordered_by_demand) pop.append(individual) rank_population(pop) report = { 'worst_i': pop[-1].fitness, 'best_i': pop[0].fitness, 'generation': 0, 'better_sons': 0, 'total_sons': 0, 'best_i_hist': [pop[0].fitness], 'mean_fitness_hist': [sum([i.fitness for i in pop]) / popsize], 'repeated_i_hist': [popsize - unique_individuals(pop)] } for generation in range(gener): # applying elitism if relevant if elitism: topelite = int(ceil(elitism * popsize)) new_pop = pop[0:topelite] else: # if no elitism specified, simply create a new population new_pop = [] # while the population is not complete while len(new_pop) < popsize: random_number = random() subpop = sample(pop, tsize) # tournament individuals if random_number < mutprob: # mutating new_pop.append(mutate(subpop[0], G)) new_pop[-1].calculate_fitness(G, nodes_ordered_by_demand) elif random_number < coprob: # doing crossover mean_fitness = (subpop[0].fitness + subpop[1].fitness) / 2.0 i1, i2 = crossover(subpop[0], subpop[1]) i1.calculate_fitness(G, nodes_ordered_by_demand) if i1.fitness > mean_fitness: report['better_sons'] += 1 report['total_sons'] += 1 new_pop.append(i1) if i2 is not None: i2.calculate_fitness(G, nodes_ordered_by_demand) if i2.fitness > mean_fitness: report['better_sons'] += 1 new_pop.append(i2) report['total_sons'] += 1 else: # if no mutation or crossover, insert the best individual new_pop.append(deepcopy(subpop[0])) if len(new_pop) > popsize: new_pop.pop() report['total_sons'] -= 1 pop = rank_population(new_pop) report['best_i_hist'].append(pop[0].fitness) report['mean_fitness_hist'].append(sum([i.fitness for i in pop]) / popsize) report['repeated_i_hist'].append(popsize - unique_individuals(pop)) if report['best_i'] > pop[0].fitness: report['best_i'] = pop[0].fitness report['generation'] = generation if report['worst_i'] < pop[-1].fitness: report['worst_i'] = pop[-1].fitness t2 = clock() report['time'] = round(t2 - t1, 3) report['gener_per_s'] = gener / report['time'] return report
def evolve(G, p, popsize, gener, mutprob, coprob, tsize, elitism=None): nodes_ordered_by_demand = sorted(G.node.items(), key=lambda t: t[1]['demand'], reverse=True) t1 = clock() pop = [] # generating first population, which will be random for i in range(popsize): individual = Individual(p, G) individual.calculate_fitness(G, nodes_ordered_by_demand) pop.append(individual) rank_population(pop) report = { 'worst_i': pop[-1].fitness, 'best_i': pop[0].fitness, 'generation': 0, 'better_sons': 0, 'total_sons': 0, 'best_i_hist': [pop[0].fitness], 'mean_fitness_hist': [sum([i.fitness for i in pop]) / popsize], 'repeated_i_hist': [popsize - unique_individuals(pop)] } for generation in range(gener): # applying elitism if relevant if elitism: topelite = int(ceil(elitism * popsize)) new_pop = pop[0:topelite] else: # if no elitism specified, simply create a new population new_pop = [] # while the population is not complete while len(new_pop) < popsize: random_number = random() subpop = sample(pop, tsize) # tournament individuals if random_number < mutprob: # mutating new_pop.append(mutate(subpop[0], G)) new_pop[-1].calculate_fitness(G, nodes_ordered_by_demand) elif random_number < coprob: # doing crossover mean_fitness = (subpop[0].fitness + subpop[1].fitness) / 2.0 i1, i2 = crossover(subpop[0], subpop[1]) i1.calculate_fitness(G, nodes_ordered_by_demand) if i1.fitness > mean_fitness: report['better_sons'] += 1 report['total_sons'] += 1 new_pop.append(i1) if i2 is not None: i2.calculate_fitness(G, nodes_ordered_by_demand) if i2.fitness > mean_fitness: report['better_sons'] += 1 new_pop.append(i2) report['total_sons'] += 1 else: # if no mutation or crossover, insert the best individual new_pop.append(deepcopy(subpop[0])) if len(new_pop) > popsize: new_pop.pop() report['total_sons'] -= 1 pop = rank_population(new_pop) report['best_i_hist'].append(pop[0].fitness) report['mean_fitness_hist'].append( sum([i.fitness for i in pop]) / popsize) report['repeated_i_hist'].append(popsize - unique_individuals(pop)) if report['best_i'] > pop[0].fitness: report['best_i'] = pop[0].fitness report['generation'] = generation if report['worst_i'] < pop[-1].fitness: report['worst_i'] = pop[-1].fitness t2 = clock() report['time'] = round(t2 - t1, 3) report['gener_per_s'] = gener / report['time'] return report
def testCrossoverSameIndividuals(self): (i3, i4) = crossover(self.i1, self.i1) self.assertEqual(i3, self.i1) self.assertEqual(i4, None)