def test_two_populations_can_use_same_logger(self, tmpdir, capsys): log_file = tmpdir.join('log.txt') logger = SummaryLogger(target=log_file, stdout=True) pop1 = Population(chromosomes=list(range(10)), eval_function=lambda x: x, logger=logger) pop2 = Population(chromosomes=list(range(10)), eval_function=lambda x: x, logger=logger) evo = (Evolution().survive(fraction=0.5).breed( parent_picker=pick_random, combiner=lambda mom, dad: (mom + dad) + 1, n_parents=2).log(foo="dino")) _ = pop1.evolve(evolution=evo, n=5) _ = pop2.evolve(evolution=evo, n=5) # two evolutions have now been applied, lets check the output! with open(log_file, "r") as f: read_file = [item.replace("\n", "") for item in f.readlines()] # print(read_file) # size of the log should be appropriate assert len(read_file) == 10 # dino needs to be in every single line assert all(['dino' in row for row in read_file]) # check characteristics of stoud read_stdout = [ line for line in capsys.readouterr().out.split('\n') if line != '' ] assert len(read_stdout) == 10 assert all(['dino' in row for row in read_stdout])
def test_baselogger_works_via_evolution(self, tmpdir, capsys): log_file = tmpdir.join('log.txt') logger = BaseLogger(target=log_file, stdout=True) pop = Population(chromosomes=range(10), eval_function=lambda x: x, logger=logger) evo = (Evolution().survive(fraction=0.5).breed( parent_picker=pick_random, combiner=lambda mom, dad: (mom + dad) / 2 + (random.random() - 0.5), n_parents=2).log(foo='bar')) pop.evolve(evolution=evo, n=2) # check characteristics of the file with open(log_file, "r") as f: read_file = [item.replace("\n", "") for item in f.readlines()] # size of the log should be appropriate assert len(read_file) == 2 * len(pop) # bar needs to be in every single line assert all(['bar' in row for row in read_file]) # check characteristics of stoud read_stdout = [ line for line in capsys.readouterr().out.split('\n') if line != '' ] assert len(read_stdout) == 2 * len(pop) assert all(['bar' in row for row in read_stdout])
def test_simple_counter_works_every(self, simple_chromosomes, simple_evaluation_function): counter = PopCounter() pop = Population(chromosomes=simple_chromosomes, eval_function=simple_evaluation_function) evo = (Evolution().mutate(lambda x: x).callback( lambda p: counter.add(p), every=2)) pop.evolve(evolution=evo, n=10) assert counter.count == len(simple_chromosomes) * 5 assert counter.sum == sum(simple_chromosomes) * 5
def test_every_mechanic_in_evolution_log(self, tmpdir, capsys): log_file = tmpdir.join('log.txt') logger = SummaryLogger(target=log_file, stdout=True) pop = Population(chromosomes=list(range(10)), eval_function=lambda x: x) evo = (Evolution() .survive(fraction=0.5) .breed(parent_picker=pick_random, combiner=lambda mom, dad: (mom + dad) + 1, n_parents=2) .evaluate() .callback(logger.log, every=2)) pop.evolve(evolution=evo, n=100) with open(log_file, "r") as f: read_file = [item.replace("\n", "") for item in f.readlines()] assert len(read_file) == 50 # check characteristics of stoud read_stdout = [line for line in capsys.readouterr().out.split('\n') if line != ''] assert len(read_stdout) == 50
def test_repeat_step_grouped(self, n_groups, grouping_function): calls = [] def callback(pop): calls.append(len(pop)) sub_evo = (Evolution().survive(fraction=0.5).breed( parent_picker=pick_random, combiner=lambda x, y: x + y).callback(callback_function=callback)) pop = Population([0 for _ in range(100)], lambda x: x) evo = (Evolution().evaluate(lazy=True).repeat( sub_evo, grouping_function=grouping_function, n_groups=n_groups)) assert len(pop.evolve(evo, n=2)) == 100 assert len(calls) == 2 * n_groups
def run_evolutionary(opt_value=1, population_size=100, n_parents=2, num_iter=200, survival=0.5, noise=0.1, seed=42): random.seed(seed) def init_func(): return (random.random() - 0.5) * 20 + 10 def eval_func(x, opt_value=opt_value): return -((x - opt_value)**2) + math.cos(x - opt_value) def random_parent_picker(pop, n_parents): return [random.choice(pop) for i in range(n_parents)] def mean_parents(*parents): return sum(parents) / len(parents) def add_noise(chromosome, sigma): return chromosome + (random.random() - 0.5) * sigma pop = Population(chromosomes=[init_func() for _ in range(population_size)], eval_function=eval_func, maximize=True).evaluate() evo = (Evolution().survive(fraction=survival).breed( parent_picker=random_parent_picker, combiner=mean_parents, n_parents=n_parents).mutate(mutate_function=add_noise, sigma=noise).evaluate()) print("will start the evolutionary program, will log progress every step") for i in range(num_iter): pop = pop.evolve(evo).log() print( f"iteration:{i} best: {pop.current_best.fitness} worst: {pop.current_worst.fitness}" )
print(f"the best score i={self.i} => {best}") if __name__ == "__main__": logger = MyLogger() random.seed(42) pop = Population(chromosomes=[random_start() for _ in range(200)], eval_function=func_to_optimise, maximize=True, concurrent_workers=2) evo1 = (Evolution() .survive(fraction=0.1) .breed(parent_picker=pick_random_parents, combiner=make_child) .mutate(mutate_function=add_noise, sigma=0.2) .evaluate() .callback(logger.log)) evo2 = (Evolution() .survive(n=10) .breed(parent_picker=pick_random_parents, combiner=make_child) .mutate(mutate_function=add_noise, sigma=0.1) .evaluate() .callback(logger.log)) evo3 = (Evolution() .repeat(evo1, n=20) .repeat(evo2, n=20)) pop = pop.evolve(evo3, n=3)
def run_evolutionary(num_towns=42, population_size=100, num_iter=200, seed=42): """ Runs a simple evolutionary algorithm against a simple TSP problem. The goal is to explain the `evol` library, this is not an algorithm that should perform well. """ # First we generate random towns as candidates with a seed random.seed(seed) coordinates = [(random.random(), random.random()) for i in range(num_towns)] # Next we define a few functions that we will need in order to create an algorithm. # Think of these functions as if they are lego blocks. def init_func(num_towns): """ This function generates an individual """ order = list(range(num_towns)) random.shuffle(order) return order def dist(t1, t2): """ Calculates the distance between two towns. """ return math.sqrt((t1[0] - t2[0])**2 + (t1[1] - t2[1])**2) def eval_func(order): """ Evaluates a candidate chromosome, which is a list that represents town orders. """ return sum([ dist(coordinates[order[i]], coordinates[order[i - 1]]) for i, t in enumerate(order) ]) def pick_random(parents): """ This function selects two parents """ return random.choice(parents), random.choice(parents) def partition(lst, n_crossover): division = len(lst) / n_crossover return [ lst[round(division * i):round(division * (i + 1))] for i in range(n_crossover) ] def crossover_ox(mom_order, dad_order, n_crossover): idx_split = partition(range(len(mom_order)), n_crossover=n_crossover) dad_idx = sum([list(d) for i, d in enumerate(idx_split) if i % 2 == 0], []) path = [-1 for _ in range(len(mom_order))] for idx in dad_idx: path[idx] = dad_order[idx] cities_visited = {p for p in path if p != -1} for i, d in enumerate(path): if d == -1: city = [p for p in mom_order if p not in cities_visited][0] path[i] = city cities_visited.add(city) return path def random_flip(chromosome): result = chromosome[:] idx1, idx2 = random.choices(list(range(len(chromosome))), k=2) result[idx1], result[idx2] = result[idx2], result[idx1] return result pop = Population( chromosomes=[init_func(num_towns) for _ in range(population_size)], eval_function=eval_func, maximize=False).evaluate() evo = (Evolution().survive(fraction=0.1).breed( parent_picker=pick_random, combiner=crossover_ox, n_crossover=2).mutate(random_flip).evaluate()) print("will start the evolutionary program") scores = [] iterations = [] for i in range(num_iter): print( f"iteration: {i} best score: {min([individual.fitness for individual in pop])}" ) for indiviual in pop: scores.append(indiviual.fitness) iterations.append(i) pop = pop.evolve(evo) try: import matplotlib.pylab as plt plt.scatter(iterations, scores, s=1, alpha=0.3) plt.title("population fitness vs. iteration") plt.show() except ImportError: print("If you install matplotlib you will get a pretty plot.")
return new # We start by defining a population with candidates. pop = Population(chromosomes=[random_start() for _ in range(5)], eval_function=func_to_optimise, maximize=False) # We define a sequence of steps to change these candidates evo1 = ( Evolution().survive(fraction=0.2).breed(parent_picker=pick_random_parents, combiner=make_child) # .mutate(mutate_function=add_noise, sigma=1)) .mutate(mutate_function=add_noise, sigma=1)) # We define another sequence of steps to change these candidates evo2 = ( Evolution().survive(n=1).breed(parent_picker=pick_random_parents, combiner=make_child) # .mutate(mutate_function=add_noise, sigma=0.2)) .mutate(mutate_function=add_noise, sigma=0.1)) # We are combining two evolutions into a third one. You don't have to # but this approach demonstrates the flexibility of the library. evo3 = (Evolution().repeat(evo1, n=10).evaluate()) # In this step we are telling evol to apply the evolutions # to the population of candidates. pop = pop.evolve(evo3, n=10000) print(f"the best score found: {max([i.fitness for i in pop])}")
def test_evolve(self, simple_evolution): # The initial population contains the optimal solution. pop = Population(list(range(100)), eval_function=lambda x: x**2, maximize=False) with MinimumProgress(window=10): pop = pop.evolve(simple_evolution, n=100) assert pop.generation == 10
combiner=mate, population_size=population_size).mutate( mutate_function=mutate_painting, rate=0.005, sigma=0.4).evaluate(lazy=False).callback( print_summary, img_template=image_template, checkpoint_path=checkpoint_path)) shrink_step = (Evolution().survive(n=1).breed( parent_picker=pick_best, combiner=clone, population_size=population_size).mutate( mutate_function=shrink_painting).evaluate(lazy=False).callback( print_summary, img_template=image_template, checkpoint_path=checkpoint_path)) # 250 points pop = pop.evolve(evo_step_1, n=999) pop = pop.evolve(genome_duplication, n=1) # 500 points pop = pop.evolve(evo_step_1, n=899) pop = pop.evolve(shrink_step, n=100) pop = pop.evolve(genome_duplication, n=1) # 800 points pop = pop.evolve(evo_step_2, n=900) pop = pop.evolve(shrink_step, n=100) pop = pop.evolve(evo_step_2, n=900) pop = pop.evolve(shrink_step, n=100) pop = pop.evolve(evo_step_3, n=1000)
if __name__ == "__main__": checkpoint_path = "./geneticArt/" image_template = os.path.join(checkpoint_path, "drawing_%05d.png") targetImage = Image.open("./img/unicorn.png").convert('RGBA') #targetImage.show() #size = targetImage.size numPolygons = 150 popSize: int = 200 pop = Population(chromosomes=[ DrawImage(numPolygons, targetImage, background_color=(255, 255, 255)) for _ in range(popSize) ], eval_function=score, maximize=False, concurrent_workers=6) evolution = (Evolution().survive(fraction=0.05).breed( parent_picker=selection, combiner=crossover, population_size=popSize).mutate(mutate_function=mutation, rate=0.05).evaluate(lazy=False).apply( final, img_template=image_template, checkpoint_path=checkpoint_path)) pop = pop.evolve(evolution, n=2000)
def test_repeat_step(self): pop = Population([0 for i in range(100)], lambda x: x) evo = Evolution().repeat(Evolution().survive(fraction=0.9), n=10) # Check whether an Evolution inside another Evolution is actually applied assert len(pop.evolve(evo, n=2)) < 50