A Genetic Algorithm (GA) is an Artificial Intelligence algorithm designed to mimic the process of natural evolution. It is largely inspired by Darwin's theory of evolution and the concept of "survival of the fittest."
Genetic algorithms excel at solving optimization problems and provide one of the fastest convergence rates when parameters are properly configured.
The algorithm creates a random population of N individuals and iteratively evolves them according to the needs of the optimization problem through:
- Selection: Choosing the fittest individuals
- Crossover: Combining genetic information from parents
- Mutation: Introducing random variations
- Elitism: Preserving the best solutions
For a comprehensive introduction, check out this article on Genetic Algorithms.
# Clone or download the project
cd genetic-algorithm-in-python-master
# Create virtual environment (recommended)
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txtgenetic-algorithm/
├── images/ # Example images
│ ├── cross.jpg
│ └── s.jpg
├── selection_algorithms/ # Main package
│ ├── __init__.py # Package initialization
│ ├── base.py # SelectionStrategy ABC
│ ├── chromosome.py # Chromosome class
│ ├── config.py # Configuration dataclass
│ ├── genetic_algorithm.py # Main GA engine
│ ├── roulette_wheel.py # Roulette wheel selection
│ └── image_reconstruction.py # Example application
├── requirements.txt # Project dependencies
├── .gitignore # Git ignore patterns
└── README.md # This file
Configuration dataclass that defines the basis of the algorithm. These can be modified at startup or during runtime.
@dataclass
class Config:
num_genes: int = 400
mutation_rate: float = 0.002
population_size: int = 600
ideal_fitness: float = 0.0
elite_count: int = 20
fitness_mode: str = "minimize" # "minimize" or "maximize"
crossover_rate: float = 0.95
gene_type: str = "binary"Represents an individual solution in the population.
Key Methods:
mutate(): Randomly mutates genes based onmutation_rateflip_bit(value): Flips a binary gene (0 → 1 or 1 → 0)
Attributes:
genes: List of binary values representing the solutionfitness: Transformed fitness value used for selectionraw_fitness: Original fitness value from fitness functionnormalized_fitness: Normalized fitness for probability calculationscumulative_prob: Cumulative probability for roulette wheel selection
Abstract base class for selection strategies. Makes it easy to implement new selection algorithms.
Implements Roulette Wheel Selection for parent selection.
Key Methods:
select(): Returns two different chromosomes based on their fitness probabilities
Fitter individuals have a higher probability of being selected for reproduction, ensuring better solutions propagate through generations.
The main evolution engine that orchestrates the genetic algorithm.
Key Methods:
def crossover(parent1, parent2):
"""
Performs single-point crossover between two parents.
Returns two children based on crossover_rate.
"""def fix_negative_fitness(population):
"""
Shifts all fitness values to positive if any are negative.
This ensures proper probability calculations in selection.
"""def evolve(generations, fitness_func, callback=None):
"""
Runs the genetic algorithm for the specified number of generations.
Args:
generations: Number of generations to evolve
fitness_func: User-defined function to evaluate chromosomes
callback: Optional callback function executed after each generation
Returns:
Best individual found during evolution
"""Using this library is straightforward. Check the selection_algorithms/image_reconstruction.py for a complete example.
Step 1: Import Required Modules
from selection_algorithms.genetic_algorithm import GeneticAlgorithm
from selection_algorithms.config import ConfigStep 2: Define Your Fitness Function
The fitness function evaluates how good a solution is. For minimization problems, return lower values for better solutions.
def fitness_func(chromosome):
# Calculate fitness based on chromosome.genes
# chromosome.genes is a list of 0s and 1s
fitness = 0
# Your fitness calculation logic here
# Example: count the number of 1s
fitness = sum(chromosome.genes)
return fitnessStep 3: (Optional) Define a Callback
This function is called after every generation. Useful for logging, visualization, or debugging.
def on_generation(generation, best):
"""
Called after each generation with the generation number
and the best individual found in that generation.
"""
print(f"Generation {generation}: Best Fitness = {best.raw_fitness}")Step 4: Create the GeneticAlgorithm Object and Run Evolution
# Use default config
ga = GeneticAlgorithm()
# Or create custom config
config = Config(
num_genes=200,
population_size=1000,
mutation_rate=0.01,
fitness_mode="maximize"
)
ga = GeneticAlgorithm(config)
# Run evolution
best = ga.evolve(
generations=300, # Run for 300 generations
fitness_func=fitness_func, # Your fitness function
callback=on_generation # Optional: your callback
)
# Access the best solution found
print("Best solution:", best.genes)
print("Best fitness:", best.raw_fitness)Access and modify the configuration:
ga = GeneticAlgorithm()
# Modify configuration for your specific problem
ga.config.num_genes = 200 # Adjust to your problem size
ga.config.population_size = 1000 # Larger population for complex problems
ga.config.mutation_rate = 0.01 # Higher mutation for more exploration
ga.config.elite_count = 50 # Preserve more top solutions
ga.config.fitness_mode = "maximize" # For maximization problems
# Run evolution
best = ga.evolve(500, fitness_func)The selection_algorithms/image_reconstruction.py example demonstrates the power of genetic algorithms.
What it does:
- Loads a 20×20 binary image
- Starts with random pixel patterns
- Evolves the pattern to match the target image
- Shows real-time visualization of the evolution
To run the example:
cd selection_algorithms
python3 image_reconstruction.pyThe genetic algorithm will evolve random noise into the target image over 300 generations!
| Class | Method | Description |
|---|---|---|
GeneticAlgorithm |
evolve(generations, fitness_func, callback=None) |
Main evolution loop |
GeneticAlgorithm |
crossover(parent1, parent2) |
Single-point crossover |
GeneticAlgorithm |
fix_negative_fitness(population) |
Normalize negative fitness values |
RouletteWheel |
select() |
Select two parents based on fitness |
Chromosome |
mutate() |
Mutate genes based on mutation rate |
Chromosome |
flip_bit(value) |
Flip a binary gene value |
| Parameter | Type | Default | Description |
|---|---|---|---|
num_genes |
int | 400 | Number of genes per chromosome |
mutation_rate |
float | 0.002 | Probability of gene mutation |
population_size |
int | 600 | Population size |
ideal_fitness |
float | 0.0 | Target fitness for early stopping |
elite_count |
int | 20 | Number of elites to preserve |
fitness_mode |
str | "minimize" | "minimize" or "maximize" |
crossover_rate |
float | 0.95 | Crossover probability |
gene_type |
str | "binary" | Gene type (only binary supported) |
- ✅ Type-Safe: Comprehensive type hints throughout
- ✅ Validated Config: Dataclass with automatic validation
- ✅ Extensible: Abstract base class for selection strategies
- ✅ Optimized: Set-based deduplication for better performance
- ✅ Professional: Clean code with magic methods (
__repr__,__hash__) - ✅ Well-Documented: Comprehensive docstrings
- ✅ Python 3.x: Modern Python with dataclasses and type hints
-
Minimize: Lower fitness values are better (e.g., error minimization)
- Set
fitness_mode = "minimize" - The algorithm internally inverts fitness values for selection
- Set
-
Maximize: Higher fitness values are better (e.g., reward maximization)
- Set
fitness_mode = "maximize" - Fitness values are used directly for selection
- Set
- Initialization: Create a random population of chromosomes
- For each generation:
- Evaluate fitness for all individuals using your fitness function
- Create Roulette Wheel based on fitness probabilities
- Select parents and perform crossover to create offspring
- Apply mutation to offspring
- Preserve elite individuals (best solutions)
- Replace old population with new generation
- Termination: Return the best individual found
The algorithm stops early if ideal_fitness is reached, otherwise runs for the specified number of generations.
- Python 3.x
- numpy>=2.0.0
- opencv-python>=4.0.0 (for examples)
Install with:
pip install -r requirements.txtContributions, issues, and feature requests are welcome! Feel free to improve the library or add new selection algorithms.
This project is open source and available for educational and research purposes.
Created to provide an easy-to-use, well-documented Genetic Algorithm library for Python 3 with minimal dependencies and a clean, Pythonic API.