# How to Implement Genetic Algorithms in Python: A Beginner's Guide to AI Optimization

> Learn to implement genetic algorithms in Python with this AI for Beginners guide. Explore evolutionary optimization and visualize convergence using interactive Jupyter notebooks. Perfect for beginners.

- Repository: [Microsoft/AI-For-Beginners](https://github.com/microsoft/AI-For-Beginners)
- Tags: getting-started
- Published: 2026-08-01

---

**The microsoft/AI-For-Beginners repository provides a complete, NumPy-based genetic algorithm implementation in pure Python that teaches evolutionary optimization through interactive Jupyter notebooks covering the full pipeline from population generation to convergence visualization.**

The microsoft/AI-For-Beginners curriculum offers a hands-on approach to learning artificial intelligence concepts through executable code examples. When you want to implement genetic algorithms for Python optimization, the repository's dedicated lesson in `lessons/6-Other/21-GeneticAlgorithms/` delivers a modular, beginner-friendly framework using only standard library and NumPy dependencies.

## Genetic Algorithm Architecture in the AI-For-Beginners Repository

The genetic algorithm implementation follows a layered architecture that separates theoretical concepts from practical execution. According to the source code in `lessons/6-Other/21-GeneticAlgorithms/Genetic.ipynb`, the system consists of four tightly coupled functional layers: population generation, fitness evaluation, genetic operators, and evolutionary selection.

### Core Components and File Structure

The lesson organizes its resources across three primary files:

- [`lessons/6-Other/21-GeneticAlgorithms/README.md`](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/6-Other/21-GeneticAlgorithms/README.md) — Contains the narrative overview, theoretical background on evolutionary computation, and terminology definitions (genes, chromosomes, crossover, mutation).
- `lessons/6-Other/21-GeneticAlgorithms/Genetic.ipynb` — Houses the complete executable implementation, including the `genetic()` and `evolve()` driver functions, helper utilities, and matplotlib visualizations.
- `lessons/6-Other/21-GeneticAlgorithms/Diophantine.ipynb` — Provides an assignment applying the framework to solve Diophantine equations, demonstrating extensibility.

## Step-by-Step Implementation of the Genetic Algorithm Pipeline

The repository teaches genetic algorithms through six discrete stages that mirror biological evolution. Each stage maps to specific Python functions within the notebook.

### Population Initialization with `generate` and `generate_one`

The algorithm begins by creating random candidate solutions. The `generate_one(N)` function produces a random permutation of integers from 1 to N, serving as the gene sequence for problems like the N-Queens puzzle. The `generate(N)` utility creates multiple candidates by repeated invocation.

```python
import numpy as np, random

def generate_one(N):
    """Create a random permutation of 1..N."""
    x = np.arange(1, N + 1)
    np.random.shuffle(x)
    return x

```

### Fitness Evaluation Using `fit`

Every candidate requires a quantitative quality measure. The `fit(L)` function evaluates the N-Queens problem by counting attacking queen pairs, returning lower values for better solutions.

```python
def fit(L):
    """Count the number of attacking queen pairs."""
    attacks = 0
    for i1, j1 in enumerate(L, 1):
        for i2, j2 in enumerate(L, 1):
            if i2 > i1:
                if j2 == j1 or abs(j2 - j1) == i2 - i1:
                    attacks += 1
    return attacks

```

### Selection Strategies with `choose` and `choose_rand`

Selection pressure drives evolution toward optimal solutions. The repository implements two fitness-proportionate selectors that compute normalized weight vectors from inverse fitness values:

- **`choose_rand`** — Probability-weighted random selection
- **`choose`** — Deterministic fitness-proportionate selection

Both functions calculate selection probabilities using `[1 / (f + 1) for _, f in P]` to favor lower fitness scores (minimization problems).

### Genetic Operators: `mutate` and `xover`

Variation introduces genetic diversity. The `mutate(G)` function randomly replaces a single gene value, while `xover(G1, G2)` performs single-point crossover by concatenating slices from two parent chromosomes.

```python
def mutate(G):
    """Replace a random gene with a random value."""
    idx = random.randint(0, len(G) - 1)
    G[idx] = random.randint(1, len(G))
    return G

def xover(G1, G2):
    """Single-point crossover."""
    cut = random.randint(0, len(G1))
    return np.concatenate((G1[:cut], G2[cut:]))

```

### The Evolution Loop: `genetic`, `evolve`, and `nxgeneration`

The `genetic(N, pop_size=100)` function orchestrates the evolutionary process alongside the `evolve()` helper. It initializes the population, then iteratively applies selection, crossover, and mutation until reaching a fitness of zero or exhausting the generation limit. The `nxgeneration` helper manages population replacement between iterations.

```python
def genetic(N, pop_size=100):
    # initialise population

    P = [(generate_one(N), fit(generate_one(N))) for _ in range(pop_size)]
    while min(f for _, f in P) > 0:
        # create next generation

        new_pop = []
        for _ in range(pop_size):
            i, j = np.random.choice(len(P), 2, replace=False,
                                   p=[1 / (f + 1) for _, f in P])
            child = xover(P[i][0], P[j][0])
            if random.random() < 0.1:
                child = mutate(child)
            new_pop.append((child, fit(child)))
        P = new_pop
    # return the best solution

    return min(P, key=lambda x: x[1])

```

## Visualizing Convergence and Results

After execution, the notebook plots optimization progress using matplotlib. The history tracking reveals convergence speed and population diversity over time.

```python
import matplotlib.pyplot as plt

solution, history = genetic(8)
plt.plot(history)
plt.title('Best fitness per generation')
plt.xlabel('Generation')
plt.ylabel('Fitness')
plt.show()

```

## Extending the Framework for Custom Optimization Problems

The modular design in `Genetic.ipynb` allows beginners to adapt the engine for various domains. By swapping the fitness function in `fit()`, changing the gene representation in `generate_one()`, or adjusting the mutation probability (currently set to 0.1), learners can tackle scheduling problems, knapsack optimization, or Sudoku solving. The `Diophantine.ipynb` notebook demonstrates this extensibility by applying the same pipeline to find integer solutions to polynomial equations.

## Summary

- The microsoft/AI-For-Beginners repository provides a complete genetic algorithm implementation in `lessons/6-Other/21-GeneticAlgorithms/Genetic.ipynb` using pure Python and NumPy.
- The pipeline consists of six stages: **encoding** (`generate`, `generate_one`), **fitness evaluation** (`fit`), **selection** (`choose_rand`, `choose`), **crossover** (`xover`), **mutation** (`mutate`), and **replacement** (`nxgeneration`).
- The `genetic()` and `evolve()` functions serve as the main entry points, running the evolution loop until convergence or generation limits.
- Visualization utilities track fitness history to confirm optimization progress.
- The framework requires no external dependencies beyond NumPy, making it accessible for beginners experimenting with AI optimization.

## Frequently Asked Questions

### What makes the AI-For-Beginners genetic algorithm implementation suitable for beginners?

The implementation uses only Python standard library and NumPy, with explicit function names like `generate_one`, `mutate`, and `xover` that correspond directly to genetic algorithm theory. The Jupyter notebook format allows interactive execution and immediate visualization of results, while the modular structure lets learners modify individual components without breaking the entire pipeline.

### How does the selection mechanism work in this genetic algorithm?

The selection process uses fitness-proportionate probability calculated via inverse fitness values `[1 / (f + 1) for _, f in P]`. The `np.random.choice()` function samples parent indices based on these weights, ensuring higher-fitness (lower numerical value) individuals have greater reproductive probability while maintaining population diversity through probabilistic selection.

### Can this code solve optimization problems other than N-Queens?

Yes. The repository includes `Diophantine.ipynb` which adapts the same framework to solve Diophantine equations. By modifying the `fit()` function to return a different metric and adjusting `generate_one()` to produce valid candidate structures, you can apply this genetic algorithm to scheduling, routing, bin packing, or constraint satisfaction problems.

### What is the time complexity of the genetic algorithm implementation?

The complexity depends on the fitness function and population parameters. For the N-Queens implementation, each fitness evaluation runs in O(N²) time due to the pairwise comparison loop. With population size P and generation count G, the total complexity is O(G × P × N²). The algorithm terminates early if it finds a perfect solution (fitness = 0) before reaching the generation limit.