def test_perform_crossover(self): chromosome1 = Chromosome( [Gene(2, 1, True), Gene(3, 1, True), Gene(4, 1, True)]) chromosome2 = Chromosome( [Gene(1, 2, True), Gene(3, 4, True), Gene(5, 6, True)]) pop = Population([chromosome1, chromosome2]) crossover_pop = pop._perform_crossover() expected_len = 3 self.assertTrue(len(crossover_pop) == expected_len)
def test_selection(self): chromosome2 = Chromosome( [Gene(2, 1, True), Gene(3, 1, True), Gene(4, 1, True)]) chromosome1 = Chromosome( [Gene(1, 2, True), Gene(3, 4, True), Gene(5, 6, True)]) chromosome3 = Chromosome( [Gene(5, 1, True), Gene(8, 2, True), Gene(3, 1, True)]) pop = Population([chromosome1, chromosome2, chromosome3]) self.assertEqual(pop, pop.selection())
def test_perform_crossover_with_seed(self): chromosome1 = Chromosome( [Gene(2, 1, True), Gene(3, 1, True), Gene(4, 1, True)]) chromosome2 = Chromosome( [Gene(1, 2, True), Gene(3, 4, True), Gene(5, 6, True)]) pop = Population([chromosome1, chromosome2]) crossover_chromosome = pop._perform_crossover(1) expected_crossover_chromosome = Chromosome( [Gene(2, 1, True), Gene(3, 4, True), Gene(5, 6, True)]) self.assertEqual(crossover_chromosome, expected_crossover_chromosome)
def test_selection_with_different_fitness_func(self): chromosome1 = Chromosome( [Gene(2, 1, True), Gene(3, 1, True), Gene(4, 1, True)]) chromosome2 = Chromosome( [Gene(1, 2, True), Gene(3, 4, True), Gene(5, 6, True)]) chromosome3 = Chromosome( [Gene(5, 1, True), Gene(8, 2, True), Gene(3, 1, True)]) pop = Population([chromosome1, chromosome2, chromosome3], max_weight=9) expected_pop = Population([chromosome3, chromosome1], max_weight=9) self.assertEqual(expected_pop, pop.selection(maximum_selection=2))
def test_selection_with_less_chromosomes(self): chromosome1 = Chromosome( [Gene(2, 1, True), Gene(3, 1, True), Gene(4, 1, True)]) chromosome2 = Chromosome( [Gene(1, 2, True), Gene(3, 4, True), Gene(5, 6, True)]) chromosome3 = Chromosome( [Gene(5, 1, True), Gene(8, 2, True), Gene(3, 1, True)]) pop = Population([chromosome1, chromosome2, chromosome3]) expected_pop = Population([chromosome3, chromosome1]) self.assertEqual(expected_pop, pop.selection(maximum_selection=2))
def _initialize_first_population(self, gene_pool: List[Gene]): """ Helper method that creates a new population with randomly generated gene states. :param gene_pool: The pool of genes that we can use for each chromosome. :return: A population of chromosomes composed of genes. """ from genetic_algorithm.Population import Population population = list() population.append(Chromosome(gene_pool)) for _ in range(self.pop_limit): new_chromosome = [] for gene in gene_pool: toss = bool(random.getrandbits(1)) new_chromosome.append(Gene(gene.value, gene.weight, toss)) population.append(Chromosome(new_chromosome)) return Population(population, population_limit=self.pop_limit)
def parameterized_fitness_func(chromosome: Chromosome) -> int: """ Fitness function that calculates the fitness for a given chromosome. :param chromosome: The given chromosome. :return: An integer denoting the fitness of the chromosome. """ profits, weights = chromosome.calculate_active_values_and_weights() return profits - weights if weights > MAX_WEIGHT else profits
def test_crossover_does_not_return_empty_chromosomes(self): population_limit = 10 chromosome1 = Chromosome( [Gene(2, 1, True), Gene(3, 1, True), Gene(4, 1, True)]) chromosome2 = Chromosome( [Gene(1, 2, True), Gene(3, 4, True), Gene(5, 6, True)]) chromosome3 = Chromosome( [Gene(5, 1, True), Gene(8, 2, True), Gene(3, 1, True)]) pop = Population([chromosome1, chromosome2, chromosome3], population_limit=population_limit) new_pop = pop.crossover() for chrom in new_pop.chromosomes: self.assertTrue(len(chrom.genes) > 0)
def test_mutation_does_not_alter_chromosome_length(self): population_limit = 10 chromosome1 = Chromosome( [Gene(2, 1, True), Gene(3, 1, True), Gene(4, 1, True)]) chromosome2 = Chromosome( [Gene(1, 2, True), Gene(3, 4, True), Gene(5, 6, True)]) chromosome3 = Chromosome( [Gene(5, 1, True), Gene(8, 2, True), Gene(3, 1, True)]) expected_chromosome_length = 3 pop = Population([chromosome1, chromosome2, chromosome3], population_limit=population_limit) pop.mutate(0.2) for chromosome in pop.chromosomes: self.assertTrue(len(chromosome.genes), expected_chromosome_length)
def test_crossover_returns_same_population_size(self): population_limit = 10 chromosome1 = Chromosome( [Gene(2, 1, True), Gene(3, 1, True), Gene(4, 1, True)]) chromosome2 = Chromosome( [Gene(1, 2, True), Gene(3, 4, True), Gene(5, 6, True)]) chromosome3 = Chromosome( [Gene(5, 1, True), Gene(8, 2, True), Gene(3, 1, True)]) pop = Population([chromosome1, chromosome2, chromosome3], population_limit=population_limit) new_pop = pop.crossover() expected_pop_size = population_limit for chrom in new_pop.chromosomes: self.assertTrue(len(chrom.genes) > 0) self.assertTrue(len(new_pop.chromosomes) == expected_pop_size)
def test_fitness_positive_fitness_high_values(self): genes = [Gene(6, 1, True), Gene(8, 2, True), Gene(4, 3, True)] chromosome = Chromosome(genes) score = chromosome.fitness_score( BoundedKnapsackGA.fitness_func(BoundedKnapsackGA.MAX_WEIGHT)) other_genes = [Gene(2, 1, True), Gene(3, 2, True), Gene(4, 3, True)] other_chromosome = Chromosome(other_genes) other_score = other_chromosome.fitness_score( BoundedKnapsackGA.fitness_func(BoundedKnapsackGA.MAX_WEIGHT)) self.assertTrue(score > 0 and score > other_score)
def _perform_crossover(self, random_seed=None): """ Helper function to perform crossover. Chooses randomly two chromosomes and mixes half and half of each. :param random_seed: An optional random seed to use. :return: A new chromosome resulting from the crossover of two parent chromosomes. """ if not random_seed: rng = random.Random() else: rng = random.Random(random_seed) # Choose two parents randomly chain = [] parents = rng.sample(self.chromosomes, 2) parent1 = parents[0] parent2 = parents[1] chromosome_length = len(parent1.genes) // 2 chain.extend(parent1.genes[:chromosome_length]) chain.extend(parent2.genes[chromosome_length:]) # Return unique genes. This is a 0-1 knapsack after all. return Chromosome(list(chain))
def test_mutation_alters_chromosome_length(self): genes = [Gene(6, 1, True), Gene(8, 2, True), Gene(4, 3, True)] expected_length = 3 chromosome = Chromosome(genes) chromosome.mutate(1) self.assertTrue(len(chromosome) == expected_length)
def initPopulation(self, size): for i in range(size): self.population.append(Chromosome(10))
def test_fitness_func_bad_fitness(self): genes = [Gene(1, 5, True), Gene(2, 8, True), Gene(3, 2, True)] chromosome = Chromosome(genes) score = chromosome.fitness_score( BoundedKnapsackGA.fitness_func(BoundedKnapsackGA.MAX_WEIGHT)) self.assertTrue(score == 0)
def test_fitness_func_with_reward(self): genes = [Gene(2, 1, True), Gene(3, 2, True), Gene(4, 3, True)] chromosome = Chromosome(genes) score = chromosome.fitness_score( BoundedKnapsackGA.fitness_func(BoundedKnapsackGA.MAX_WEIGHT)) self.assertTrue(score > 0)
def test_inequality_between_chromosomes(self): first_genes = [Gene(1, 2, True), Gene(3, 4, True)] second_genes = [Gene(3, 4, True), Gene(1, 2, True)] first_chromosome = Chromosome(first_genes) second_chromosome = Chromosome(second_genes) self.assertFalse(first_chromosome == second_chromosome)
def test_equality_between_chromosomes(self): genes = [Gene(1, 2, True), Gene(3, 4, True)] first_chromosome = Chromosome(genes) second_chromosome = Chromosome(genes) self.assertTrue(first_chromosome == second_chromosome)