Genetic Algorithms & Evolutionary Computation

Last Updated 17 Aug, 2026
Quick Answer

What is a genetic algorithm?

A genetic algorithm is a search and optimization method inspired by natural selection that evolves candidate solutions over successive generations to find optimal answers.

  • The five core components: population, fitness, selection, crossover, and mutation
  • How to implement a basic genetic algorithm in Python
  • Why elitism prevents top fitness scores from dropping across generations

A genetic algorithm (GA) is a way to solve problems by copying how evolution works in nature. You start with a group of rough guesses, and over many rounds you keep the better ones, combine them, and shake them up a little, until you end up with a good answer.

What Is a Genetic Algorithm? 

A genetic algorithm is a search method inspired by natural selection. Instead of solving a problem directly, it evolves a solution over time.

It starts with a group of random candidate solutions, called a population. Each candidate is scored on how good it is. The best candidates are more likely to be picked to create the next generation, and small random changes keep the population from getting stuck. Repeat this enough times, and the population tends to get better with each generation.

Core Concepts

Before walking through an example, here are the five building blocks every genetic algorithm uses.

Population

The population is the full set of candidate solutions the algorithm is working with at any one time. In a GA that tries to guess a word, one candidate might be KEMUB and another might be HELXO — each one is a guess, and together they form the population for that generation.

Fitness Function

The fitness function is how you score a candidate. It gives a number that says how close that candidate is to a good solution. A higher fitness score means a better candidate. For a word-guessing GA, fitness could simply be the number of letters that are already in the right place.

Selection 

Selection decides which candidates get to become parents for the next generation. Candidates with higher fitness are more likely to be chosen. This is the "survival of the fittest" part — weaker candidates are less likely to pass their traits on.

Crossover

Crossover combines two parent candidates to make a new child candidate. Part of the child comes from one parent, and the rest comes from the other. This lets good traits from two different parents mix together in one child.

Mutation

Mutation makes a small random change to a candidate, like swapping one letter for a random one. Without mutation, the population could get stuck if the right answer needs something that isn't in any current candidate. A little randomness keeps new possibilities coming in.

How a Genetic Algorithm Runs

With all five parts defined, here's how they fit together into one repeating loop.

A genetic algorithm repeats these steps:

  1. Create a starting population of random candidates.
  2. Score every candidate with the fitness function.
  3. Select the best candidates as parents.
  4. Use crossover to combine parents into new children.
  5. Apply mutation to some of the children.
  6. Replace the old population with the new one, and go back to step 2.
  7. Stop when a candidate is good enough, or after a set number of generations.

Example: Evolving the Word "HELLO"

Here is a simple genetic algorithm in Python. It starts with random 5-letter strings and evolves them toward the target word HELLO. Fitness counts how many letters are already in the correct position.

import random
random.seed(7)
TARGET = "HELLO"
GENES = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
POP_SIZE = 20
def random_individual():
    return "".join(random.choice(GENES) for _ in range(len(TARGET)))
def fitness(individual):
    return sum(1 for a, b in zip(individual, TARGET) if a == b)
def selection(population):
    scored = sorted(population, key=fitness, reverse=True)
    return scored[0], scored[1]  # top 2 parents
def crossover(parent1, parent2):
    point = random.randint(1, len(TARGET) - 1)
    return parent1[:point] + parent2[point:]
def mutate(individual, rate=0.1):
    chars = list(individual)
    for i in range(len(chars)):
        if random.random() < rate:
            chars[i] = random.choice(GENES)
    return "".join(chars)
population = [random_individual() for _ in range(POP_SIZE)]
for generation in range(1, 21):
    population.sort(key=fitness, reverse=True)
    best = population[0]
    print(f"Generation {generation}: best = {best}  fitness = {fitness(best)}/{len(TARGET)}")
    if fitness(best) == len(TARGET):
        break
    parent1, parent2 = selection(population)
    new_population = [parent1, parent2]  # keep best 2 (elitism)
    while len(new_population) < POP_SIZE:
        child = crossover(parent1, parent2)
        child = mutate(child)
        new_population.append(child)
    population = new_population

Output

Generation 1: best = KEMUB  fitness = 1/5
Generation 2: best = KEMLS  fitness = 2/5
Generation 3: best = KEMLS  fitness = 2/5
Generation 4: best = KEMLS  fitness = 2/5
Generation 5: best = KEMLS  fitness = 2/5
Generation 6: best = KEMLS  fitness = 2/5
Generation 7: best = HEMLS  fitness = 3/5
Generation 8: best = HEMLS  fitness = 3/5
Generation 9: best = HEMLS  fitness = 3/5
Generation 10: best = HEMLS  fitness = 3/5
Generation 11: best = HEMLS  fitness = 3/5
Generation 12: best = HEMLS  fitness = 3/5
Generation 13: best = HEMLS  fitness = 3/5
Generation 14: best = HEMLS  fitness = 3/5
Generation 15: best = HEMLS  fitness = 3/5
Generation 16: best = HEMLS  fitness = 3/5
Generation 17: best = HEMLS  fitness = 3/5
Generation 18: best = HEMLS  fitness = 3/5
Generation 19: best = HEMLS  fitness = 3/5
Generation 20: best = HELLW  fitness = 4/5

Explanation:

Fitness climbs from 1 to 4 out of 5, but not every generation — it often plateaus until a lucky mutation fixes another letter. Elitism (keeping the best 2 candidates) means fitness never drops, even during the plateaus.

Why Use a Genetic Algorithm?

The word-guessing example is small enough to solve by hand, but the same five steps work on much harder problems where there's no simple formula for the answer.

Genetic algorithms are useful when a problem has a huge number of possible solutions and no easy way to calculate the best one directly. They're commonly used for scheduling, route optimization, tuning parameters in other algorithms, and designing shapes or systems where trial and improvement works better than a fixed formula.

Quick Summary

Here's how the five core concepts map to the word-guessing example above.

ConceptWord-Guessing Example
PopulationA group of random 5-letter strings
Fitness FunctionCount of letters in the correct position
SelectionPicking the top 2 strings each generation
CrossoverSplicing two strings together at a random point
MutationRandomly swapping a letter with a 10% chance

Frequently Asked Questions

The fitness function scores each candidate solution to evaluate how close it is to an optimal answer, helping the algorithm select the best candidates to produce the next generation.

Mutation introduces small random changes to individuals, preventing the population from getting stuck when the optimal solution requires traits not present in existing candidates.

Elitism is the strategy of carrying the highest-scoring candidate solutions directly into the next generation, ensuring that the overall best fitness never decreases.

Genetic algorithms are useful for problems with massive search spaces where there is no simple direct formula, such as scheduling, route optimization, and parameter tuning.