What are genetic algorithm phases?

Key takeaways:

  • Genetic algorithms (GAs) mimic natural selection to find optimal solutions to complex problems.

  • Step 1: The process starts with a random population of solutions in the initialization phase.

  • Step 2: Selection chooses the fittest individuals as parents for the next generation.

  • Step 3: Crossover combines genetic material from parents to create diverse offspring.

  • Step 4: Mutation introduces random changes to maintain diversity and avoid premature convergence.

  • Step 5: Replacement ensures the population evolves by retaining the best solutions.

  • GAs are applied in engineering, finance, machine learning, robotics, and other fields.

  • They iteratively refine solutions through exploration (mutation, crossover) and exploitation (selection).

Genetic algorithms (GAs) are powerful optimization and search techniques inspired by genetics and natural selection. The process is broken into distinct genetic algorithm phases, each designed to enhance the algorithm's efficiency and effectiveness. From initialization to replacement, these phases iteratively refine a population of solutions to tackle complex challenges across various domains like engineering, finance, and artificial intelligence.

If you want to learn more about genetic algorithms (GAs), look into this: What is a genetic algorithm?

Genetic algorithm phases

We will discuss the following phases one by one, along with the applications:

Genetic algorithm phases
Genetic algorithm phases

Step 1: Initialization

A population of viable solutions is generated during the initialization phase, the first stage of a genetic algorithm. Each solution represents a candidate solution to the problem, sometimes referred to as an individual or chromosome. Usually, these individuals are created at random somewhere in the solution space of the problem. One important factor affecting the algorithm's performance is the population size.

This part is notably useful in:

  • Engineering design: Generating initial designs for structures, circuits, or systems.

  • Finance: Creating diverse portfolios of financial instruments for investment strategies.

Sample code for initialization

Let’s have a look at how we can code initialization in Python to create an initial population of a certain population size and chromosome length.

# Sample initialization code
import random
def initialize_population(population_size, chromosome_length):
population = []
for _ in range(population_size):
chromosome = [random.choice([0, 1]) for _ in range(chromosome_length)]
population.append(chromosome)
return population
# Testing the function
pop = initialize_population(5, 5)
print(pop)

Code explanation

  • Line 2: We import the random module, allowing access to functions for generating random numbers.

  • Line 4: We define a function named initialize_population that takes two parameters: population_size (the number of individuals in the population) and chromosome_length (the length of each individual's chromosome).

  • Lines 6–8: We generate a chromosome for an individual by creating a list of length chromosome_length with random binary values (0 or 1).

  • Lines 11–12: We test the function by storing it in a pop variable, and then printing it.

Step 2: Selection

In the selection phase, individuals from the population are chosen to be parents for the next generation. Each individual's fitness level frequently determines the probability of selection; those who are more fit are more likely to be chosen. Various selection techniques, including tournament and roulette wheel selection, guide the population's evolution.

Selection is notably useful in:

  • Machine learning: Selecting promising models for the next generation in evolutionary algorithms.

  • Routing algorithms: Choosing routes with higher fitness in network optimization problems.

Sample code for selection

Let's look at how we can code selection in Python using a roulette wheel mechanism, in which the individuals with higher fitness are picked more frequently.

from numpy.random import choice
# Sample roulette wheel selection code
def roulette_wheel_selection(population, fitness_values):
total_fitness = sum(fitness_values)
probabilities = [fitness / total_fitness for fitness in fitness_values]
selected_index = choice(range(len(population)), p=probabilities)
return population[selected_index]
# Testing with dummy data
pop = [[1,0,0,1,0], [1,0,1,0,1], [1,1,1,1,0]]
fitness = [0.81, 0.22, 0.45]
parent = roulette_wheel_selection(pop, fitness)
print(parent)

Code explanation

  • Line 4: We define a function named roulette_wheel_selection that takes two parameters: population (a list of individuals) and fitness_values (a list of fitness values corresponding to each individual in the population).

  • Lines 5–8: We calculate the total fitness of the population by summing up all fitness values provided, the selection probability for each individual in the population based on its fitness value, and randomly selecting an index from the range of population indexes, with the probability distribution determined by the p parameter, which represents the selection probabilities computed earlier using total_fitness, probabilities and selected_index respectively.

  • Lines 11–15: We test the function by giving it some test values pop and fitness and storing it in a parent variable. Then we print the selected individual.

Step 3: Crossover (Recombination)

A crucial genetic operation called crossover occurs when parents exchange genetic material to have children. This stage mimics the way genetic recombination occurs naturally. Various crossover techniques, such as single-point or uniform crossover, create diverse offspring.

Crossover is notably useful in:

  • Scheduling problems: Combining schedules from different individuals to create better timetables.

  • Image processing: Blending features from different images creates new and diverse images.

Sample code for crossover

Let's examine how to code a single-point crossover in Python to create two children from two sample parents.

import random
# Sample single-point crossover code
def single_point_crossover(parent1, parent2):
crossover_point = random.randint(1, len(parent1) - 1)
child1 = parent1[:crossover_point] + parent2[crossover_point:]
child2 = parent2[:crossover_point] + parent1[crossover_point:]
return child1, child2
# Testing with dummy data
parent_A = [1, 0, 0, 1, 0, 1]
parent_B = [1, 1, 0, 0, 0, 1]
child_A, child_B = single_point_crossover(parent_A, parent_B)
print(child_A, child_B)

Code explanation

  • Line 4: We define a function named single_point_crossover that takes two parameters: parent1 and parent2, representing the chromosomes of two parents.

  • Line 5: We generate a random integer representing the crossover point. This value determines the position where the crossover will occur within the chromosomes.

  • Line 6: We create child1 by combining the genes of parent1 up to the crossover point with the genes of parent2 after the crossover point.

  • Line 7: We create child2 by combining the genes of parent2 up to the crossover point with the genes of parent1 after the crossover point.

  • Lines 11–15: We test the function by giving it some test values parent_A and parent_B and storing it in child_A and child_B variables. Then we print the newly generated individuals.

Step 4: Mutation

By introducing tiny, unpredictable changes to each individual, mutation keeps the algorithm from converging prematurely to a suboptimal solution. The individual's genetic variety is preserved in part by mutation. The nature of the problem and the algorithm's performance can be used to modify the mutation rates.

Mutation is notably useful in:

  • Robotics: Adjusting robot parameters to adapt to unforeseen environmental changes.

  • Chemical engineering: Modifying chemical reaction parameters for optimal outcomes.

Sample code for mutation

Let's have a look at how we can code a mutation in Python that randomly mutates an individual's chromosome depending on some mutation rate.

import random
# Sample bit flip mutation code
def bit_flip_mutation(individual, mutation_rate):
mutated_individual = [bit ^ (random.random() < mutation_rate) for bit in individual]
return mutated_individual
# Testing with dummy data
individual = [1, 0, 0, 0, 1]
mutate_probability = 0.5
mutated = bit_flip_mutation(individual, mutate_probability)
print(individual)
print(mutated)

Code explanation

  • Line 4: We define a function named bit_flip_mutation that takes two parameters: individual, representing the chromosome of an individual, and mutation_rate, indicating the probability of mutation for each bit.

  • Line 5: We apply bit flip mutation to the individual chromosome.

  • Lines 9–12: We test the function on an individual and a mutation rate of 0.5.

Note: You might need to run this several times to see the mutation in effect.

Step 5: Replacement

The next generation is generated by replacing some of the least fit members of the existing population after crossing over and mutating to create children. The replacement phase raises the general quality of the population by guaranteeing that only the fittest individuals make it to the following generation.

Replacement is notably useful in:

  • Optimization problems: Solving complex optimization problems in logistics and resource allocation.

  • Genomic studies: Identifying optimal gene combinations in genetic programming.

Sample code for replacement

Let's look at how we can code replacement in Python to replace the current generation with a mix of current and newly generated individuals based on their best fitness.

# Sample replacement code
def replace_population(current_population, offspring_population, fitness_values):
combined_population = list(zip(current_population, fitness_values)) + list(zip(offspring_population, [0] * len(offspring_population)))
combined_population.sort(key=lambda x: x[1], reverse=True)
new_population = [individual for individual, _ in combined_population[:len(current_population)]]
return new_population
# Testing with dummy data
pop = [[1,0,0,1,0], [1,0,1,0,1], [1,1,1,1,0]]
fitness = [0.81, 0.22, 0.45]
children = [[1,1,0,1,0], [1,0,1,1,0], [1,1,1,1,0]]
new_pop = replace_population(pop, children, fitness)
print(new_pop)

Code explanation

  • Line 2: We define a function named replace_population that takes three parameters: current_population (the current population of individuals), offspring_population (the offspring population produced through genetic operations), and fitness_values (the fitness values corresponding to individuals in the populations).

  • Line 3: We combine the current population with the offspring population into a single list combined_population.

  • Line 4: We sort the combined population based on fitness values in descending order.

  • Line 5: We select individuals for the new population by extracting the required number of individuals from the sorted combined population.

  • Lines 9–14: We test the function on a pop, their fitness, and their children to create a new population.

Conclusion

Understanding and effectively applying the genetic algorithm phases is key to optimizing solutions through a balance of exploration (mutation, crossover) and exploitation (selection). These phases enable genetic algorithms to iteratively refine a population of potential solutions, making them a powerful tool for solving complex problems across diverse fields such as engineering, finance, and artificial intelligence. By navigating each stage—selection, crossover, mutation, and replacement—genetic algorithms evolve robust and efficient solutions, demonstrating their versatility and effectiveness in addressing challenging optimization tasks.

If you want to know the detailed explanation about genetic algorithm, check out our course: Genetic Algorithms in Elixir.

Frequently asked questions

Haven’t found what you were looking for? Contact Us


What are the different phases of genetic algorithms?

The phases are initialization, selection, crossover, mutation, and replacement.


What is the most significant phase in a genetic algorithm?

Selection is the most significant phase as it determines the survival of the fittest solutions for the next generation.


What are four techniques used in genetic algorithms?

The techniques are uniform crossover, precedence preservative crossover (PPX), order crossover (OX), and cycle crossover.


What are the limitations of genetic algorithm?

Genetic algorithms can face challenges with intricate gene interactions and high computational costs, making them inefficient for large-scale problems and demanding substantial time and resources to identify optimal solutions.


What are the two main features of genetic algorithm?

Fitness function and crossover techniques are the two main features of the genetic algorithm.


Free Resources

Copyright ©2025 Educative, Inc. All rights reserved