An Introduction to Genetic Algorithms | by Anh T. Dang | Towards Data Science

Genetic Algorithms (GAs) are a part of Evolutionary Computing (EC), which is a rapidly growing area of Artificial Intelligence (AI). It inspired by the process of biological evolution based on Charles Darwin’s theory of natural selection, where fitter individuals are more likely to pass on their genes to the next generation. We, as human beings, also are the result of thousands of years of evolution.
The GA, developed by John Holland and his collaborators in the 1960s and 1970s.
As early as 1962, John Holland’s work on adaptive systems1 laid the foundation for later developments.
By the 1975, the publication of the book “Adaptation in Natural and Artificial Systems”2, by Holland and his students and colleagues.
The GA got popular in the late 1980s by was being applied to a broad range of subjects that are not easy to solve using other techniques.
In 1992, John Koza has used genetic algorithm to evolve programs to perform certain tasks. He called his method “genetic programming” (GP)3.
For thousands of years, humans have acted as agents of genetic selection, by breeding offspring with desired traits. All our domesticated animals and food crops are the results. Let review the genetic terms in nature as follows.
Each cell of a living thing contains chromosomes — strings of DNA.
Each chromosome contains a set of genes — blocks of DNA
Each gene determines some aspect of the organism (like eye colour)
A collection of genes is sometimes called a genotype
A collection of aspects (like eye colour) is sometimes called a phenotype
Reproduction (crossover) involves recombination of genes from parents and then small amounts of mutation (errors) in copying
The fitness of an organism is how much it can reproduce before it dies
Evolution based on “survival of the fittest”
Genetic Algorithms are categorized as global search heuristics. A genetic algorithm is a search technique used in computing to find true or approximate solutions to optimization and search problems. It uses techniques inspired by biological evolution such as inheritance, mutation, selection, and crossover.
We look at the basic process behind a genetic algorithm as follows.
Initialize population: genetic algorithms begin by initializing a Population of candidate solutions. This is typically done randomly to provide even coverage of the entire search space. A candidate solution is a Chromosome that is characterized by a set of parameters known as Genes.
Evaluate: next, the population is evaluated by assigning a fitness value to each individual in the population. In this stage we would often want to take note of the current fittest solution, and the average fitness of the population.
After evaluation, the algorithm decides whether it should terminate the search depending on the termination conditions set. Usually this will be because the algorithm has reached a fixed number of generations or an adequate solution has been found.
When the termination condition is finally met, the algorithm will break out of the loop and typically return its finial search results back to the user.
Selection: if the termination condition is not met, the population goes through a selection stage in which individuals from the population are selected based on their fitness score, the higher the fitness, the better chance an individual has of being selected.
Two pairs of selected individuals called parents.
Crossover: the next stage is to apply crossover and mutation to the selected individuals. This stage is where new individuals (children) are created for the next generation.
Mutation: at this point the new population goes back to the evaluation step and the process starts again. We call each cycle of this loop a generation.
Now, let’s see how to crack a password using a genetic algorithm. Imagine that a friend asks you to solve the following challenge: “You must find the three-letter word I set up as a password in my computer”.
In my example, we’ll start with a password of length 3, with each digit in the password being a letter. An example of password would be: nkA. We will start with a randomly generated initial sequence of letters, then change one random letter at a time until the word is “Anh”.
At first, we guess any randomly generated words made of three letters, such as “Ink, aNj, cDh”. The word Ink and cDh have exactly one letter in common with Anh, the password. We say that they have a score of 1. The word aNj has a score of 0 since it has no any matching letters with the password.
Since we haven’t found the solution, we can produce a new generation of words by combing some of the word we already have. For example, they are “Inh, aDj". From these two new words, the word Inh has a score of 2 and is very close to the password. We say that this second generation is better than the first second since it is closer to the solution.
A third-generation can be formed in which the word Inh can produce the word Anh in which the I is randomly mutated into A. This example is pretty simple to understand GA.
_letters = [a..zA..Z]target = "Anh"guess = get 3 random letters from _letters while guess != target:     index = get random value from [0..length of target]      guess[index] = get 1 random letter from _letters
Now, we will implement the example in Python language. Each digit in the password would be considered a Gene. We need a gene set to use for building guesses. For this example that will be a generic set of letters.
geneSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
It also needs a target password to guess.
target = "Anh"
Next the algorithm needs a way to generate a random string from the gene set.
import randomdef generate_parent(length):    genes = []    while len(genes) < length:        sampleSize = min(length - len(genes), len(geneSet))        genes.extend(random.sample(geneSet, sampleSize))    return ''.join(genes)
The fitness value the genetic algorithm provides is the only feedback the engine gets to guide it toward a solution. In this project the fitness value is the total number of letters in the guess that match the letter in the same position of the password.
def get_fitness(guess):    return sum(1 for expected, actual in zip(target, guess)               if expected == actual)
Next, the engine needs a way to produce a new guess by mutating the current one.
def mutate(parent):    index = random.randrange(0, len(parent))    childGenes = list(parent)    newGene, alternate = random.sample(geneSet, 2)    childGenes[index] = alternate \        if newGene == childGenes[index] \        else newGene    return ''.join(childGenes)
We also need display function to show information. Normally the display function also outputs the fitness value and how much time has elapsed.
import datetimedef display(guess):    timeDiff = datetime.datetime.now() - startTime    fitness = get_fitness(guess)    print("{0}\t{1}\t{2}".format(guess, fitness, str(timeDiff)))
Finally, we will try to run this solution by using the above functions as following.
random.seed()geneSet = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"target = "Anh"startTime = datetime.datetime.now()bestParent = generate_parent(len(target))bestFitness = get_fitness(bestParent)display(bestParent)while True:    child = mutate(bestParent)    childFitness = get_fitness(child)    if bestFitness >= childFitness:        continue    display(child)    if childFitness >= len(bestParent):        break    bestFitness = childFitness    bestParent = child
Run the above code and we’ll see the following output.
It’s very easy to understand about genetic algorithms. Right?
[1] Outline for a Logical Theory of Adaptive Systems
[2] Adaptation in Natural and Artificial Systems
[3] Genetic Programming: On the Programming of Computers by Means of Natural Selection