Over billions of years, nature has developed a remarkably effective optimization process: evolution. Genetic algorithms (GA) transfer this principle into computer science and solve problems where classical algorithms fail.
The Basic Principle
Imagine you are searching for the best solution to a problem, but the solution space is enormous. Trying all possibilities would take years. Genetic algorithms take a different approach: they simulate evolution.
A Concrete Example
Our goal: Find a binary string where all bits are set to 1. Sounds trivial? It is. But this simple example demonstrates all the concepts that work the same way for more complex problems.
The Individual: An array of 5 bits, randomly initialized with 0 or 1.
The Fitness: Number of ones. Maximum is 5, then we have the perfect solution.
The Implementation in Java
The Individual
Each individual represents a possible solution:
public class Individual {
private int[] genes = new int[5];
private int fitness = 0;
// Random initialization
public Individual() {
Random rn = new Random();
for (int i = 0; i < genes.length; i++) {
genes[i] = rn.nextInt(2); // 0 or 1
}
}
// Fitness = number of ones
public void calcFitness() {
fitness = 0;
for (int gene : genes) {
if (gene == 1) fitness++;
}
}
}
The Population
A population manages multiple individuals:
public class Population {
private Individual[] individuals = new Individual[10];
private int fittest = 0; // Best fitness of the population
public Individual getFittest() {
int maxFit = Integer.MIN_VALUE;
Individual fittestIndividual = null;
for (Individual ind : individuals) {
if (ind.getFitness() > maxFit) {
maxFit = ind.getFitness();
fittestIndividual = ind;
}
}
return fittestIndividual;
}
public Individual getSecondFittest() {
// Similar, but second best
...
}
}
Selection
The two best individuals are selected as parents. There are various selection methods like tournament or roulette. Here we use elitist selection: simple and effective.
public void selection() {
fittest = population.getFittest();
secondFittest = population.getSecondFittest();
}
Crossover
The core mechanism: At a random point, the genes of both parents are swapped. The genes up to the crossover point are exchanged between the parents.
public void crossover() {
Random rn = new Random();
int crossOverPoint = rn.nextInt(fittest.genes.length);
for (int i = 0; i < crossOverPoint; i++) {
int temp = fittest.genes[i];
fittest.genes[i] = secondFittest.genes[i];
secondFittest.genes[i] = temp;
}
}
Mutation
Mutation prevents the algorithm from getting stuck in local optima. A random bit is flipped.
public void mutation() {
Random rn = new Random();
// 10% probability of mutation
if (rn.nextDouble() < 0.1) {
int mutationPoint = rn.nextInt(fittest.genes.length);
// Flip bit: 0 → 1 or 1 → 0
fittest.genes[mutationPoint] = 1 - fittest.genes[mutationPoint];
}
}
The Algorithm
Putting it all together: Iterate until the perfect solution is found.
public static void main(String[] args) {
GeneticAlgorithm ga = new GeneticAlgorithm();
// 1. Initialize population
ga.population.initializePopulation(10);
ga.population.calculateFitness();
int generation = 0;
// 2. Evolution loop
while (ga.population.fittest < 5) {
generation++;
// Selection
ga.selection();
// Crossover
ga.crossover();
// Mutation
ga.mutation();
// Replace weakest individual
ga.addFittestOffspring();
// Recalculate
ga.population.calculateFitness();
System.out.println("Generation: " + generation +
" Fitness: " + ga.population.fittest);
}
System.out.println("Solution found in generation " + generation);
}
Typical Output
Generation: 1 Fitness: 3
Generation: 2 Fitness: 3
Generation: 3 Fitness: 4
Generation: 4 Fitness: 4
Generation: 5 Fitness: 5
Solution found in generation 5
Genes: [1, 1, 1, 1, 1]
With only 5 generations and 10 individuals, the algorithm finds the perfect solution. For more complex problems it takes longer, but the principle remains identical.
Real-World Use Cases
This simple example can be applied to complex problems:
Traveling Salesman Problem
Genes = order of cities. Fitness = total distance (minimize). Crossover = combining route segments.
Neural Network Training
Genes = network weights. Fitness = prediction accuracy. Evolution finds optimal weights without backpropagation.
Feature Selection
Genes = which features to use (0/1). Fitness = model performance. Automatically finds the most important features.
Scheduling
Genes = assignment of tasks to time slots. Fitness = deadline compliance, resource utilization.
Key Learnings
"Genetic algorithms do not guarantee an optimal solution, but they often find a very good one in acceptable time."
1. Encoding is crucial
How you represent the problem as genes determines success. Binary is simple, but permutations, floats, or complex structures are often more suitable.
2. Balance between exploration and exploitation
Too much mutation = chaotic search. Too little = premature convergence. The right mutation rate is problem-specific.
3. The fitness function is key
A poor fitness function leads to poor solutions. Invest time in a precise evaluation function.
4. Maintain diversity
When all individuals become similar, evolution stagnates. Techniques like crowding or niching help.
Conclusion
Genetic algorithms are a powerful tool for optimization problems where the solution space is too large for exhaustive search. The implementation is surprisingly simple: population, fitness, selection, crossover, mutation. The art lies in the right encoding and the appropriate fitness function.
The beauty of it: You don't need to understand what the optimal solution looks like. You only need to be able to evaluate how good a solution is. Evolution takes care of the rest.
Technologies used:
Interested in optimization algorithms or AI-powered solutions? Get in touch, I look forward to the conversation.