From c9a1f6cbda44b97738ced26181db34f70115bcc6 Mon Sep 17 00:00:00 2001 From: Sepehr Madani <ssepehrmadani@gmail.com> Date: Sun, 26 Jul 2020 11:39:14 -0400 Subject: [PATCH] Implemented AM-GM crossover --- algorithms/genetic_bucket_algorithm.py | 55 +++++++++++++++----------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/algorithms/genetic_bucket_algorithm.py b/algorithms/genetic_bucket_algorithm.py index 87bc1e0..63e0558 100644 --- a/algorithms/genetic_bucket_algorithm.py +++ b/algorithms/genetic_bucket_algorithm.py @@ -18,7 +18,7 @@ class Chromosome: return random.randrange(0, 2 ** bit_count) -class GeneticAlgorithm(BaseAlgorithm): +class GeneticBucketAlgorithm(BaseAlgorithm): """ Finds nulls by running a genetic algorithm on all possible discrete values. """ @@ -32,11 +32,13 @@ class GeneticAlgorithm(BaseAlgorithm): self.bit_count = options.bit_count self.bit_resolution = options.bit_resolution self.mutation_factor = options.mutation_factor + self.buckets = [[]] * 8 self.check_parameters() def check_parameters(self): super().check_parameters() + assert len(self.null_degrees) == 1 def solve(self): self.intialize_sample() @@ -44,13 +46,15 @@ class GeneticAlgorithm(BaseAlgorithm): self.sort_fitness() for generation in range(self.gen_to_repeat): for ii in range(self.sample_size // 2, self.sample_size - 1, 2): - p1, p2 = random.sample(range(self.sample_size // 2), 2) + bucket_idx = random.randrange(4) + p1 = random.choice(self.buckets[bucket_idx]) + p2 = random.choice(self.buckets[bucket_idx + 4]) + self.crossover(p1, p2, ii, ii + 1) - self.mutate_sample() + # self.mutate_sample() self.update_fitness() self.sort_fitness() - # print(["{:.2f}".format(x.fitness) for x in self.chromosomes[:15]]) return self.make_weights(self.chromosomes[0]) def mutate_sample(self): @@ -61,36 +65,41 @@ class GeneticAlgorithm(BaseAlgorithm): def update_fitness(self, use_exact_angle=True): for chromosome in self.chromosomes: - values = [ - -20 * log10(abs(x)) - for x in compute_pattern( - N=self.N, - k=self.k, - weights=self.make_weights(chromosome), - degrees=self.null_degrees, + chromosome.fitness = -20 * log10( + abs( + compute_pattern( + N=self.N, + k=self.k, + weights=self.make_weights(chromosome), + degrees=self.null_degrees, + use_absolute_value=False, + )[0] ) - ] - chromosome.fitness = min(values) + ) + bucket_idx = int(((cmath.phase(chromosome.fitness) + pi) / (2 * pi)) * 8) % 8 + self.buckets[bucket_idx].append(chromosome) def sort_fitness(self): - self.chromosomes.sort(key=lambda x: x.fitness, reverse=True) + self.chromosomes.sort(key=lambda x: abs(x.fitness), reverse=True) def make_weights(self, chromosome): weights = [] for bits in chromosome.gene: - angle = (bits - (2 ** self.bit_count - 1) / 2) * 2 * pi / (2 ** self.bit_resolution) + angle = ( + (bits - (2 ** self.bit_count - 1) / 2) + * 2 + * pi + / (2 ** self.bit_resolution) + ) weights.append(cmath.exp(1j * angle)) return weights def crossover(self, p1, p2, c1, c2): - self.chromosomes[c1] = deepcopy(self.chromosomes[p1]) - self.chromosomes[c2] = deepcopy(self.chromosomes[p2]) - for i in range(self.N): - if random.random() >= 0.5: - self.chromosomes[c1].gene[i], self.chromosomes[c2].gene[i] = ( - self.chromosomes[c1].gene[i], - self.chromosomes[c2].gene[i], - ) + for ii in range(self.N): + g1 = p1.gene[ii] + g2 = p2.gene[ii] + self.chromosomes[c1].gene[ii] = (g1 + g2) // 2 + self.chromosomes[c2].gene[ii] = (g1 + g2 + 1) // 2 def intialize_sample(self): self.chromosomes = [ -- GitLab