Bingo Tutorial 1: One Max Problem#

Goal: Find a list with all 1 values through genetic optimization#

This example walks through the general steps needed to set up and run a bingo analysis. The example problem described here is the one max problem. In the one max problem individuals in a population are defined by a chromosome with a list of 0 or 1 values, e.g., [0, 1, 1, 0, 1]. The goal of the optimization is to evolve toward an optimum list containing all 1’s.

Chromosome#

The basic unit of bingo evolutionary analyses are Chromosomes. Bingo’s built-in MultipleValueChromosome is used here. Individuals of this type contain their genetic information in a list attribute named values

[1]:
from bingo.chromosomes.multiple_values import MultipleValueChromosome
chromosome = MultipleValueChromosome([0, 1, 1, 0, 1])
print(type(chromosome))
print(chromosome.values)
print(chromosome)
<class 'bingo.chromosomes.multiple_values.MultipleValueChromosome'>
[0, 1, 1, 0, 1]
[0, 1, 1, 0, 1]

Chromosome Generator#

A chromosome generator is used to generate members (Chromosomes) in a population. The MultipleValueChromosomeGenerator generates these individuals by populating the indivudual’s values from a given input function. The generate_0_or_1 function is defined for this purpose.

[2]:
import numpy as np
from bingo.chromosomes.multiple_values import MultipleValueChromosomeGenerator

def generate_0_or_1():
    return np.random.choice([0, 1])

generator = MultipleValueChromosomeGenerator(generate_0_or_1,
                                             values_per_chromosome=16)
[3]:
# Example of Generator
chromosome = generator()
print(chromosome)
[np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(0)]

The Evolutionary Algorithm#

Evolutionary algorithms have 3 phases in bingo: variation, evaluation and selection.

Variation

The variation phase is responsible for generating offspring of the population, usually through some combination of mutation and crossover. Single-point mutation and crossover are used for this example. Also in this example, VarOr is used which creates offspring through either mutation or crossover (never both).

[4]:
from bingo.chromosomes.multiple_values import SinglePointCrossover, SinglePointMutation
from bingo.variation.var_or import VarOr

crossover = SinglePointCrossover()
mutation = SinglePointMutation(generate_0_or_1)
variation_phase = VarOr(crossover, mutation,
                        crossover_probability=0.4,
                        mutation_probability=0.4)
[5]:
# Example of Single-point Mutation
np.random.seed(0)
before_mutation = MultipleValueChromosome([0, 0, 0, 0, 0, 0])
after_mutation = mutation(before_mutation)
print("Mutation")
print("before: ", before_mutation)
print("after:  ", after_mutation)
Mutation
before:  [0, 0, 0, 0, 0, 0]
after:   [0, 0, 0, 0, np.int64(1), 0]
[6]:
# Example of Single-point Crossover
parent_1 = MultipleValueChromosome([0, 0, 0, 0, 0, 0])
parent_2 = MultipleValueChromosome([1, 1, 1, 1, 1, 1])
child_1, child_2 = crossover(parent_1, parent_2)
print("Crossover")
print("parent 1: ", parent_1)
print("parent 1: ", parent_2)
print("child 1: ", child_1)
print("child 1: ", child_2)
Crossover
parent 1:  [0, 0, 0, 0, 0, 0]
parent 1:  [1, 1, 1, 1, 1, 1]
child 1:  [0, 0, 0, 0, 0, 1]
child 1:  [1, 1, 1, 1, 1, 0]

Evaluation

The evaluation phase is responsible for evaluating the fitness of new members of a population. It relies on the definition of a FitnessFunction class.

The goal of bingo analyses is to minimize fitness, so fitness functions should be constructed accordingly. In the one max problem fitness is defined as the number of 0’s in the individuals values.

[7]:
from bingo.evaluation.fitness_function import FitnessFunction
from bingo.evaluation.evaluation import Evaluation

class OneMaxFitnessFunction(FitnessFunction):
    """Callable class to calculate fitness"""
    def __call__(self, individual):
        return individual.values.count(0)

fitness = OneMaxFitnessFunction()
evaluation_phase = Evaluation(fitness)
[8]:
# Example fitness calculation
chromosome = MultipleValueChromosome([0, 1, 0, 1, 0, 0])
print("Values: ", chromosome)
print("Fitness:",fitness(chromosome))
Values:  [0, 1, 0, 1, 0, 0]
Fitness: 4

Selection

The selection phase is responsible for choosing which members of the population proceed to the next generation. An implementation of the common tournament selection algorithm is used here.

[9]:
from bingo.selection.tournament import Tournament

selection_phase = Tournament(tournament_size=2)

Based on the above 3 phases, an EvolutionaryAlgorithm can be defined. Note that several evolutionary algorithms are implemented in bingo, with only the simplest shown here. They all generally take the same form, but may have different requirements for instatiation.

[10]:
from bingo.evolutionary_algorithms.evolutionary_algorithm import EvolutionaryAlgorithm

ev_alg = EvolutionaryAlgorithm(variation_phase, evaluation_phase,
                               selection_phase)

Creating an island and Running the Analysis#

An Island is the fundamental unit for running bingo evolutionary analyses. It is responsible for generating and evolving a population (using a generator and evolutionary algorithm).

[11]:
from bingo.evolutionary_optimizers.island import Island

island = Island(ev_alg, generator, population_size=10)
print("Best individual at start: ", island.get_best_individual())
print("Best individual's fitness: ", island.get_best_fitness())
Best individual at start:  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(1)]
Best individual's fitness:  5

The island can be evolved directly using it’s evolve member function. In this case the population is evolved for 50 generations

[12]:
island.evolve(50)

print("Best individual at start: ", island.get_best_individual())
print("Best individual's fitness: ", island.get_best_fitness())
Best individual at start:  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual's fitness:  1

Seeing the Evolution: tracking the best individual#

We can track the best individual over the analysis to see the evolution take place.

[13]:
np.random.seed(0)
island = Island(ev_alg, generator, population_size=10)
for i in range(50):
    island.evolve(1)
    print("Best individual in generation", i, ": ", island.get_best_individual())
Best individual in generation 0 :  [np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(0), np.int64(0)]
Best individual in generation 1 :  [np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 2 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 3 :  [np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 4 :  [np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 5 :  [np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 6 :  [np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 7 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 8 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 9 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 10 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 11 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(0), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 12 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 13 :  [np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 14 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 15 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 16 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 17 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 18 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 19 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 20 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 21 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 22 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 23 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 24 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 25 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 26 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0), np.int64(1), np.int64(0)]
Best individual in generation 27 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0)]
Best individual in generation 28 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0)]
Best individual in generation 29 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0)]
Best individual in generation 30 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0)]
Best individual in generation 31 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(0)]
Best individual in generation 32 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 33 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 34 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 35 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 36 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 37 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 38 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 39 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 40 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 41 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 42 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 43 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 44 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 45 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 46 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 47 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 48 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]
Best individual in generation 49 :  [np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1), np.int64(1)]