import random from typing import List import numpy as np import numpy.typing as npt from genome import Genome class Population: population: List[Genome] = [] # array to hold the current population mating_pool: List[Genome] = [] # array which we will use for our "mating pool" generations: int = 0 # number of generations finished: bool = False # are we finished evolving? mutation_rate: float perfect_score: int best_genome: Genome def __init__(self, mutation_rate, population_size, perfect_score=20): self.mutation_rate = mutation_rate self.perfect_score = perfect_score for i in range(0, population_size): new_genome = Genome() new_genome.calc_fitness() self.population.append(new_genome) # create a new generation def generate(self): max_fitness = 0 for genome in self.population: if genome.fitness > max_fitness: max_fitness = genome.fitness print("Max fitness of generation " + str(self.generations) + " = " + str(max_fitness)) # refill the population with children from the mating pool new_population = [] for genome in self.population: partner_a = self.accept_reject(max_fitness) partner_b = self.accept_reject(max_fitness) child = partner_a.crossover(partner_b) child.mutate(self.mutation_rate) new_population.append(child) self.population = new_population self.generations += 1 # select random with correct probability from population def accept_reject(self, max_fitness: int): safe_flag = 0 while safe_flag < 10000: partner = random.choice(self.population) r = random.randint(0, max_fitness) if r < partner.fitness: return partner safe_flag += 1 # compute the current "most fit" member of the population def evaluate(self): record = 0 best_index = 0 for index in range(len(self.population)): genome = self.population[index] if genome.fitness > record: record = genome.fitness best_index = index self.best_genome = self.population[best_index] if record >= self.perfect_score: self.finished = True return self.finished def calc_fitness(self): for genome in self.population: genome.calc_fitness()