Hello world

In the previous ones counting examples we made use of a binary alphabet to encode our genotypes.

Although a binary alphabet can encode virtually any problem with finite alphabets, sometimes more complex alphabets are more useful. In this example we will try to achieve a predefined phrase with an alphabet tailored to our problem.

The problem is as follows: Let’s assume we have an unknown sentence consisting of letters, numbers, punctuation marks and spaces, and we want to build an algorithm that finds that sentence.

We just need to program a new fitness function and provide a genotype initializer with our alphabet. But the

Fitness

Our target sentence will be in the TARGET variable, and will be of length TARGET_LEN. For the fitness we will compare the phenotype (i.e. the resulting sentence from the genotype) with the target sentence using the Hamming distance. The smaller the distance, the closer the sentence is to the best solution, thus the higher the fitness.

An implementation for this fitness could be as follows:

def fitness(phenotype):
    """The fitness will be based on the hamming distance error."""
    # Derive the phenotype from the genotype
    sentence = ''.join(str(x) for x in phenotype)
    # Compute the error of this solution
    error = len([i for i in filter(
    lambda x: x[0] != x[1], zip(sentence, TARGET)
    )])
    # Return the fitness according to that error
    return 1 / (1 + error)

This is not the only implementation, but it is simple enough to see what’s happening. We are assuming that our genotypes are composed of genes belonging to an specific alphabet. Let’s create the initializer that will generate those genotypes.

Alphabet and the genotype initializer

In the previous examples, we used the class AlphabetInitializer with a binary alphabet. Actually, this class works with any alphabet, provided that it consists of a finite number of elements.

We are going to use exactly the same object, but with a different alphabet, the one that encodes our solution:

alphabet = Alphabet(
    genes=string.ascii_letters + string.punctuation + ' '
)

Now we have an Alphabet that codifies our solutions. We can use it to create our initializer:

initializer = AlphabetInitializer(size=TARGET_LEN, alphabet=alphabet)

Being TARGET_LEN the length of the sentence we’ll try to discover and alphabet the alphabet that codifies our solutions.

Algorithm configuration

Let’s configure out algorithm. As we did before, it is enough to use the default operators.

ga = GeneticAlgorithm(
    # ... Stuff ...
    initializer=AlphabetInitializer(size=TARGET_LEN, alphabet=alphabet),
    # ... More stuff ...
    mutation=(RandomGene(alphabet), 1 / TARGET_LEN),
    # ... Even more stuff ...
)