This is classical evolutionary algorithm which generates new solutions by applying random changes to current ones.

It is based on Darwin’s theory of evolution. It makes slow and slight changes in order to find the best solution.

GA works on populations which include some solutions , the population is the number of solution,each solution is an individual. The chromosome representation is done by a set of parameters which also defines an individual.Chromosome has as set of genes each being represented can be represented as string of 0’s or 1’s.

**Implementation :**

In this tutorial we will implement the following equation .

**Y=w1x1+w2x2+w3x3+w4x4+w5x5+w6x6**

x1,x2,x3,x4,x5,x6 are input values

W1,w2,w3,w4,w5,w6 are weights.

We will be looking to find the weights that maximize the equation . From just looking at the equation we can tell that positive numbers should be multiplied by by the largest possible positive number and negative numbers by smallest possible negative numbers. But we need the GA to do all these on it’s own.

Now we will define initial population.The number genes each population will have depends on the number weights to be found. The number of solutions is not fixed **, **we can only chose the value that fits well with our problem. Solutions Per Population, population size and initial population will be held in variables.

When we print new_population it will generate new_population,since it’s random it will provide different result every time we run it .

The

The next step is find the best individuals for parent mating. We are going to have to use GA variants which helps produce the offspring of the later generations. This will lead to the creation of a new population. It will keep repeating the steps for several generations.

The GA is as follows .

Link : https://gist.githubusercontent.com/ahmedfgad/d5de9f103d2e5c6aded76cf9c4402a7c/raw/1eff64afeace1c08d4542d0abb6f8b2ccf55d1c2/GA.py , source GIT HUB

The next step is to call the function in GA to find new population , we will use pop_fitness – which calculates the value of each solution in the current population.

Mating_pool function selects the best individuals from the current generation for producing the offspring. Crossover points to crossover between parents and finally the mutation function changes a single gene in each offspring , this happens randomly.

The full source code :

‘ ”

#Inputs of the equation.

equation_weights =[3 – 5, 1.2, 3, -13, -2]

#Number of the weights we are looking to optimize.

weights = 6 import numpy sol_per_pop = 8

#Defining the population size.

pop_size = (sol_per_pop, weights)

#The population will have sol_per_pop chromosome where each chromosome has num_weights genes.

#Creating the initial population.

new_population = numpy.random.uniform (low = -4.0, high = 4.0, size =

pop_size) print (new_population)

def

cal_pop_fitness (equation_inputs, pop):

#Calculating the fitness value of each solution in the current population.

#The fitness function caulcuates the sum of products between each input and its corresponding weight.

fitness = numpy.sum (pop * equation_inputs, axis = 1) return fitness def select_mating_pool (pop, fitness, num_parents):

#Selecting the best individuals in the current generation as parents for producing the offspring of the next generation.

parents = numpy.empty ((num_parents, pop.shape[1]))

for parent_num

in range (num_parents):

max_fitness_idx = numpy.where (fitness == numpy.max (fitness)) max_fitness_idx = max_fitness_idx[0][0] parents[parent_num,: ] = pop[max_fitness_idx,: ]fitness[max_fitness_idx] = -99999999999 return parents def crossover (parents, offspring_size):

offspring =

numpy.empty (offspring_size)

#The point at which crossover takes place between two parents. Usually it is at the center.

crossover_point = numpy.uint8 (offspring_size[1] / 2) for k

in range (offspring_size[0]):

#Index of the first parent to mate.

parent1_idx = k % parents.shape[0]

#Index of the second parent to mate.

parent2_idx = (k + 1) % parents.shape[0]

#The new offspring will have its first half of its genes taken from the first parent.

offspring[k, 0: crossover_point] = parents[parent1_idx, 0:crossover_point]

#The new offspring will have its second half of its genes taken from the second parent.

offspring[k, crossover_point: ] = parents[parent2_idx, crossover_point: ]return offspring def mutation (offspring_crossover):

#Mutation changes a single gene in each offspring randomly.

for

idx

in range (offspring_crossover.shape[0]):

#The random value to be added to the gene.

random_value = numpy.random.uniform (-1.0, 1.0, 1)

offspring_crossover[idx, 4] =

offspring_crossover[idx,

4] +

random_value return offspring_crossover num_generations =

5 num_parents_mating = 4 for generation

in range (num_generations):

#Measuring the fitness of each chromosome in the population.

fitness = cal_pop_fitness (weights, new_population)

#Selecting the best parents in the population for mating.

parents = select_mating_pool (new_population, fitness,

num_parents_mating)

#Generating next generation using crossover.

offspring_crossover = crossover (parents,

offspring_size =

(pop_size[0] – parents.shape[0],

weights))

#Adding some variations to the offsrping using mutation.

offspring_mutation = mutation (offspring_crossover)

#Creating the new population based on the parents and offspring.

new_population[0: parents.shape[0],: ] = parents new_population[parents.shape[0]: ,:] = offspring_mutation

print (“New population”)

print (new_population)

Ref : https://towardsdatascience.com/genetic-algorithm-implementation-in-python-5ab67bb124a6

Written by Masud Imran