Пример #1
0
def run_rock_paper_scissors(population_size: int = 100,
                            n_iterations: int = 200,
                            random_seed: int = 42,
                            survive_fraction: float = 0.8,
                            arbitrariness: float = 0.2,
                            concurrent_workers: int = 1,
                            lizard_spock: bool = False,
                            grouped: bool = False,
                            silent: bool = False):
    seed(random_seed)

    RockPaperScissorsPlayer.arbitrariness = arbitrariness

    player_class = RockPaperScissorsLizardSpockPlayer if lizard_spock else RockPaperScissorsPlayer
    pop = ContestPopulation(chromosomes=[player_class() for _ in range(population_size)],
                            eval_function=evaluate, maximize=True,
                            concurrent_workers=concurrent_workers).evaluate()
    history = History()

    evo = Evolution().repeat(
        evolution=(Evolution()
                   .survive(fraction=survive_fraction)
                   .breed(parent_picker=pick_random, combiner=lambda x, y: x.combine(y), n_parents=2)
                   .mutate(lambda x: x.mutate())
                   .evaluate()
                   .callback(history.log)),
        n=n_iterations // 4,
        grouping_function=group_duplicate if grouped else None
    )

    pop.evolve(evo, n=4)

    if not silent:
        history.plot()
    return history
Пример #2
0
 def test_repr(self):
     assert repr(Evolution()) == 'Evolution()'
     assert repr(
         Evolution().evaluate()) == 'Evolution(\n  EvaluationStep())'
     r = 'Evolution(\n  RepeatStep() with evolution (10x):\n    Evolution(\n' \
         '      EvaluationStep()\n      SurviveStep()))'
     assert repr(Evolution().repeat(Evolution().survive(fraction=0.9),
                                    n=10)) == r
Пример #3
0
def run_travelling_salesman(population_size: int = 100,
                            n_iterations: int = 10,
                            random_seed: int = 0,
                            n_destinations: int = 50,
                            concurrent_workers: Optional[int] = None,
                            n_groups: int = 4,
                            silent: bool = False):
    seed(random_seed)
    # Generate some destinations
    destinations = [(random(), random()) for _ in range(n_destinations)]

    # Given a list of destination indexes, this is our cost function
    def evaluate(ordered_destinations: List[int]) -> float:
        total = 0
        for x, y in zip(ordered_destinations, ordered_destinations[1:]):
            coordinates_x = destinations[x]
            coordinates_y = destinations[y]
            total += sqrt((coordinates_x[0] - coordinates_y[1])**2 +
                          (coordinates_x[1] - coordinates_y[1])**2)
        return total

    # This generates a random solution
    def generate_solution() -> List[int]:
        indexes = list(range(n_destinations))
        shuffle(indexes)
        return indexes

    def print_function(population: Population):
        if population.generation % 5000 == 0 and not silent:
            print(
                f'{population.generation}: {population.documented_best.fitness:1.2f} / '
                f'{population.current_best.fitness:1.2f}')

    pop = Population.generate(generate_solution,
                              eval_function=evaluate,
                              maximize=False,
                              size=population_size * n_groups,
                              concurrent_workers=concurrent_workers)

    island_evo = (Evolution().survive(fraction=0.5).breed(
        parent_picker=pick_random,
        combiner=cycle_crossover).mutate(swap_elements, elitist=True))

    evo = (Evolution().evaluate(lazy=True).callback(print_function).repeat(
        evolution=island_evo,
        n=100,
        grouping_function=group_stratified,
        n_groups=n_groups))

    result = pop.evolve(evolution=evo, n=n_iterations)

    if not silent:
        print(f'Shortest route: {result.documented_best.chromosome}')
        print(f'Route length: {result.documented_best.fitness}')
Пример #4
0
    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
Пример #5
0
 def test_every(self, tmpdir, simple_population):
     directory = tmpdir.mkdir('ckpt')
     evo = Evolution().mutate(lambda x: x+1).checkpoint(target=directory, method=self.method, every=10)
     simple_population.evolve(evolution=evo, n=9)
     assert len(listdir(directory)) == 0
     simple_population.evolve(evolution=evo, n=11)
     assert len(listdir(directory)) == 2
Пример #6
0
 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])
Пример #7
0
 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])
Пример #8
0
    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
Пример #9
0
 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
Пример #10
0
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}"
    )
Пример #11
0
def run_rock_paper_scissors(population_size=100,
                            n_iterations=200,
                            random_seed=42,
                            survive_fraction=0.90,
                            arbitrariness=0.0):
    seed(random_seed)

    RockPaperScissorsPlayer.arbitrariness = arbitrariness

    pop = ContestPopulation(chromosomes=[
        RockPaperScissorsPlayer() for _ in range(population_size)
    ],
                            eval_function=evaluation_func,
                            maximize=True).evaluate()

    evo = (Evolution().survive(fraction=survive_fraction).breed(
        parent_picker=pick_random,
        combiner=lambda x, y: x.combine(y),
        n_parents=2).mutate(lambda x: x.mutate()).evaluate())

    preferences_over_time = []
    for _ in range(n_iterations):
        preferences = Counter()
        for individual in pop:
            preferences.update([individual.chromosome.preference])
        pop = pop.evolve(evo)
        preferences_over_time.append(preferences)

    try:
        import matplotlib.pylab as plt
        import pandas as pd
    except ImportError:
        print(
            "If you install matplotlib and pandas you will get a pretty plot.")
        return
    ax = pd.DataFrame(preferences_over_time).fillna(0).plot(figsize=(10, 4))
    ax.set_ylim([0, population_size])
    ax.set_xlabel('iteration')
    ax.set_ylabel('# individuals with preference')
    plt.show()
Пример #12
0
        self.i += 1
        best = max([i.fitness for i in pop.evaluate()])
        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)
Пример #13
0
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.")
Пример #14
0

def add_noise(chromosome, sigma):
    new = chromosome + (np.random.rand(100) - 0.5) * sigma
    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.
Пример #15
0
                     maximize=False,
                     concurrent_workers=4)

    # Code to load a pickled/stored version, each 50 generation the population is written to disk
    # stored_pop = Population.load('./output/20200207-223736.187164.pkl', eval_function=score, maximize=False)
    # # Create new population from stored one, trick to get multiprocessing working after
    # pop = Population(chromosomes=[deepcopy(a) for a in stored_pop.chromosomes],
    #                  eval_function=score, maximize=False, concurrent_workers=4, generation=4550)

    print(f"Staring with {pop.concurrent_workers} workers")

    genome_duplication = (Evolution().survive(fraction=0.025).breed(
        parent_picker=pick_best_and_random,
        combiner=merge,
        population_size=population_size).mutate(
            mutate_function=mutate_painting, rate=0.05,
            sigma=0.5).evaluate(lazy=False).callback(
                print_summary,
                img_template=image_template,
                checkpoint_path=checkpoint_path))

    evo_step_1 = (Evolution().survive(fraction=0.025).breed(
        parent_picker=pick_best_and_random,
        combiner=mate,
        population_size=population_size).mutate(
            mutate_function=mutate_painting, rate=0.05,
            sigma=0.5).evaluate(lazy=False).callback(
                print_summary,
                img_template=image_template,
                checkpoint_path=checkpoint_path))
Пример #16
0
def simple_evolution():
    return (Evolution().survive(fraction=0.5).breed(
        parent_picker=pick_random, n_parents=2,
        combiner=lambda x, y: x + y).mutate(lambda x: x + 1, probability=0.1))
Пример #17
0
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)
Пример #18
0
 def test_add_step(self):
     evo = Evolution()
     assert len(evo.chain) == 0
     evo_step = evo._add_step('step')
     assert len(evo.chain) == 0  # original unchanged
     assert evo_step.chain == ['step']  # copy with extra step
Пример #19
0
 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