def select_elite(self, population): scores_for_chromosomes = [] for i in range(0, len(population)): chromosome = population[i] result = brainfuck.evaluate(chromosome) score = self.fitness_score(result, self.target) if score == self.max_fitness_score: current_time = time.time() print("\nFOUND SOLUTION: " + chromosome + " for: " + repr(self.target) + " in: " + str(int((current_time-self.start_time)/60)) + " minutes") self.best_fitness_scores.append(self.max_fitness_score) self.update_fitness_plot() exit() scores_for_chromosomes.append((chromosome, score)) scores_for_chromosomes.sort(key=lambda x: x[1]) scores = [x[1] for x in scores_for_chromosomes] print("population: " + "(min: " + str(min(scores)) + ", avg: " + str(mean(scores)) + ", max: " + str(max(scores)) + ")") top_performers = scores_for_chromosomes[-TOP_PERFORMERS_COUNT:] top_scores = [x[1] for x in top_performers] print("elite " + str(round(1.0-SELECTION_RATE, 2)) + ": " + "(min: " + str(min(top_scores)) + ", avg: " + str(mean(top_scores)) + ", max: " + str(max(top_scores)) + ")") chromosome = top_performers[-1][0] result = brainfuck.evaluate(chromosome) best_fitness_score = self.fitness_score(result, self.target) print("best: " + chromosome + ", result: " + repr(result) + ", score: " + str(best_fitness_score) + "/" + str(self.max_fitness_score)) self.best_fitness_scores.append(best_fitness_score) self.update_fitness_plot() return top_performers
def genetic_evolution(self): self.population = self.generate_population(self.population) while True: print("\ngeneration: " + str(self.generation) + ", population: " + str(len(self.population)) + ", mutation_rate: " + str(MUTATION_RATE)) # 1. Selection elite = self.select_elite(self.population) # 2. Crossover (Roulette selection) pairs = self.generate_pairs(elite) selected_offsprings = [] for pair in pairs: offsprings = self.crossover(pair[0][0], pair[1][0]) selected_offsprings.append(offsprings[random.randint(0, 1)]) # 3. Mutation mutated_population = self.mutation(selected_offsprings) # 4. Validation (We don't want syntactically incorrect programs) valid_population = [] for chromosome in mutated_population: if brainfuck.evaluate(chromosome) is not None: valid_population.append(chromosome) print("propagated to next generation: " + str(len(valid_population))) self.population = self.generate_population(valid_population) self.generation += 1
def mutation(self, selected_offsprings): offsprings = [] for offspring in selected_offsprings: valid = False mutation_attempts = 0 offspring_mutation = copy.deepcopy(offspring) while not valid and mutation_attempts < MAX_MUTATION_ATTEMPTS: for i in range(0, len(offspring_mutation)): if np.random.choice([True, False], p=[MUTATION_RATE, 1 - MUTATION_RATE]): action_type = random.randint(0, 2) if action_type == 0 and len( offspring_mutation ) < PROGRAM_LENGTH_UPPER_BOUND: # Inserting random value at index offspring_mutation = offspring_mutation[:i] + random.choice( AVAILABLE_OPS) + offspring_mutation[i:] elif action_type == 1 and len( offspring_mutation ) > PROGRAM_LENGTH_LOWER_BOUND: # Removing value at index offspring_mutation = offspring_mutation[: i] + offspring_mutation[ i + 1:] else: # Setting random value at index offspring_mutation = self.set_value_at_index( offspring_mutation, random.choice(AVAILABLE_OPS), i) if brainfuck.evaluate(offspring_mutation) is not None: valid = True offsprings.append(offspring_mutation) mutation_attempts += 1 return offsprings
def generate_population(self, population): while len(population) < POPULATION: length = random.randint(PROGRAM_LENGTH_LOWER_BOUND, PROGRAM_LENGTH_UPPER_BOUND) chromosome = "" for i in range(0, length): chromosome += random.choice(AVAILABLE_OPS) if brainfuck.evaluate(chromosome) is not None: # We don't want programs that are syntactically incorrect print(chromosome) exit() population.append(chromosome) return population