Genetic Algorithm

๐Ÿ”ฅ Vibe Prompt

"Use Genetic Algorithm to solve TSP with 20 cities. Population 100, 200 generations. Show the best route evolution."

import random, math

def genetic_algorithm(cities, pop_size=100, generations=200, mutation_rate=0.01):
    n = len(cities)
    def dist(i, j): return math.sqrt((cities[i][0]-cities[j][0])**2 + (cities[i][1]-cities[j][1])**2)
    def fitness(route): return -sum(dist(route[i], route[(i+1)%n]) for i in range(n))
    
    pop = [random.sample(range(n), n) for _ in range(pop_size)]
    
    for gen in range(generations):
        scored = [(fitness(ind), ind) for ind in pop]
        scored.sort(reverse=True)
        pop = [ind for _, ind in scored]
        
        next_pop = pop[:2]  # Elitism
        while len(next_pop) < pop_size:
            p1, p2 = random.choices(pop[:pop_size//2], k=2)
            a, b = sorted(random.sample(range(n), 2))
            child = [-1] * n
            child[a:b] = p1[a:b]
            remaining = [x for x in p2 if x not in child]
            for i in range(n):
                if child[i] == -1:
                    child[i] = remaining.pop(0)
            if random.random() < mutation_rate:
                i, j = random.sample(range(n), 2)
                child[i], child[j] = child[j], child[i]
            next_pop.append(child)
        pop = next_pop
    
    return pop[0], -fitness(pop[0])

Chapter Summary

  • Understand core concepts and principles
  • Master implementation methods and techniques
  • Familiar with common issues and solutions
  • Able to apply in real projects

Further Reading

  • Official documentation and API references
  • Open source examples on GitHub
  • Technical books and online courses
  • Community discussions and tech blogs

Implementation Example

Basic Example

# This section provides a complete implementation example

Steps

  1. Setup: Configure development environment
  2. Data: Prepare required data
  3. Implementation: Build core functionality
  4. Testing: Verify correctness
  5. Optimization: Improve performance

Common Errors

| Error Type | Cause | Solution | |------------|-------|----------| | Compilation | Syntax | Check code syntax | | Runtime | Environment | Verify dependencies installed | | Logic | Algorithm | Step-by-step debugging | | Performance | Efficiency | Use profilers |

Code Example

import sys

def main():
    print("Hello, World!")

if __name__ == "__main__":
    main()

References

  • Official documentation
  • API reference
  • Open source examples
  • Community discussions

What Is a Genetic Algorithm?

Genetic Algorithms (GA) are inspired by natural selection โ€” the fittest individuals survive and reproduce.

The GA Cycle

1. INITIALIZE โ†’ Create random population
       โ†“
2. EVALUATE โ†’ Calculate fitness for each individual
       โ†“
3. SELECT โ†’ Choose parents based on fitness
       โ†“
4. CROSSOVER โ†’ Combine parents to create offspring
       โ†“
5. MUTATE โ†’ Randomly modify offspring
       โ†“
6. REPLACE โ†’ New generation replaces old
       โ†“
   (repeat from step 2 until convergence)

Key Components

| Component | What It Does | Example | |-----------|-------------|---------| | Chromosome | Represents a solution | Binary string, permutation, real vector | | Gene | A single parameter | Bit, city index, weight value | | Fitness | How good the solution is | Cost function (lower = better) | | Population | Set of candidate solutions | 100 chromosomes | | Selection | Picks parents for breeding | Tournament, roulette wheel | | Crossover | Combines two parents | Single-point, uniform, PMX | | Mutation | Random changes to offspring | Bit flip, swap, Gaussian noise |

Python Implementation

import random

class GeneticAlgorithm:
    def __init__(self, pop_size=100, mutation_rate=0.01, crossover_rate=0.8):
        self.pop_size = pop_size
        self.mutation_rate = mutation_rate
        self.crossover_rate = crossover_rate
    
    def evolve(self, fitness_func, gene_pool, chrom_length, generations=100):
        """Evolve a population over multiple generations."""
        # Initialize random population
        population = [
            [random.choice(gene_pool) for _ in range(chrom_length)]
            for _ in range(self.pop_size)
        ]
        
        for gen in range(generations):
            # Evaluate fitness
            fitness = [fitness_func(ind) for ind in population]
            
            # Track best
            best_idx = fitness.index(min(fitness))
            best_fitness = fitness[best_idx]
            best_individual = population[best_idx].copy()
            
            if gen % 20 == 0:
                print(f"Generation {gen}: best fitness = {best_fitness:.4f}")
            
            # Create next generation
            new_population = []
            
            # Elitism: keep the best
            new_population.append(best_individual)
            
            while len(new_population) < self.pop_size:
                # Selection (tournament)
                parent1 = self._tournament_select(population, fitness)
                parent2 = self._tournament_select(population, fitness)
                
                # Crossover
                if random.random() < self.crossover_rate:
                    child1, child2 = self._crossover(parent1, parent2)
                else:
                    child1, child2 = parent1.copy(), parent2.copy()
                
                # Mutation
                self._mutate(child1)
                self._mutate(child2)
                
                new_population.extend([child1, child2])
            
            population = new_population[:self.pop_size]
        
        return best_individual, best_fitness
    
    def _tournament_select(self, pop, fitness, k=3):
        idx = random.sample(range(len(pop)), k)
        best = min(idx, key=lambda i: fitness[i])
        return pop[best].copy()
    
    def _crossover(self, p1, p2):
        """Single-point crossover."""
        point = random.randint(1, len(p1) - 1)
        c1 = p1[:point] + p2[point:]
        c2 = p2[:point] + p1[point:]
        return c1, c2
    
    def _mutate(self, chrom):
        """Bit-flip mutation."""
        for i in range(len(chrom)):
            if random.random() < self.mutation_rate:
                chrom[i] = 1 - chrom[i]

# Example: Maximize sum of bits (MAX-ONE problem)
def fitness_max_one(chrom):
    return -sum(chrom)

ga = GeneticAlgorithm(pop_size=100, mutation_rate=0.01)
best, best_fit = ga.evolve(
    fitness_func=fitness_max_one,
    gene_pool=[0, 1],
    chrom_length=50,
    generations=200
)

print(f"Best: {sum(best)} / 50 ones, Fitness: {best_fit}")

Selection Methods

| Method | How It Works | Best For | |--------|-------------|----------| | Tournament | Pick k random, keep the best | Simple, prevents premature convergence | | Roulette wheel | Probability proportional to fitness | When fitness is clearly ranked | | Rank-based | Probability based on rank, not raw fitness | Avoids domination by outliers |

Summary

Genetic Algorithms evolve solutions through selection, crossover, and mutation โ€” mimicking natural evolution.

Key takeaways: | GA cycle: initialize โ†’ evaluate โ†’ select โ†’ crossover โ†’ mutate โ†’ replace | | Chromosome = candidate solution; Fitness = how good it is | | Selection: tournament (k=3) is simple and effective | | Crossover (80% rate): combines two parents into two children | | Mutation (1% rate): random bit flips prevent premature convergence | | Elitism: keep the best individual from each generation | | MAX-ONE: maximize the number of 1s in a binary string | | GA works for any problem with a fitness function |

Next Chapter: Simulated Annealing

The next chapter covers Simulated Annealing for optimization.

Unlock Full Tutorial

This chapter is paid content. Join the project to unlock over 5000 words of deep analysis, including 10+ god-tier Prompts and real Source Code examples!