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 ...
)