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:
- Create a starting population of random candidates.
- Score every candidate with the fitness function.
- Select the best candidates as parents.
- Use crossover to combine parents into new children.
- Apply mutation to some of the children.
- Replace the old population with the new one, and go back to step 2.
- 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_populationOutput
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/5Explanation:
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.
| Concept | Word-Guessing Example |
|---|---|
| Population | A group of random 5-letter strings |
| Fitness Function | Count of letters in the correct position |
| Selection | Picking the top 2 strings each generation |
| Crossover | Splicing two strings together at a random point |
| Mutation | Randomly swapping a letter with a 10% chance |