API‐Reference - adylagad/CSCI-561_Genetic-Algorithm GitHub Wiki

API Reference

Complete API documentation for all classes and functions.

📦 Package Structure


genetic_algorithm/
├── core/
│ ├── algorithm.py # GeneticAlgorithm
│ ├── types.py # Type definitions
│ └── interfaces.py # Abstract base classes
├── operators/
│ ├── crossover.py # Crossover operators
│ ├── mutation.py # Mutation operators
│ └── selection.py # Selection operators
├── initialization/
│ └── population.py # Population initializers
├── evaluation/
│ └── fitness.py # Fitness evaluators
└── utils/
└── helpers.py # Utility functions


🧬 Core Module

GeneticAlgorithm

Location: genetic_algorithm/core/algorithm.py

Main orchestrator for the genetic algorithm.

Class Definition

class GeneticAlgorithm:
    """
    Genetic Algorithm for solving TSP.

    Orchestrates the evolutionary process using provided operators.
    """

Constructor

def __init__(
    self,
    config: GAConfig,
    crossover_operator: CrossoverOperator,
    mutation_operator: MutationOperator,
    fitness_evaluator: FitnessEvaluator,
    population_initializer: PopulationInitializer
)

Parameters:

  • config (GAConfig): Configuration object
  • crossover_operator (CrossoverOperator): Crossover strategy
  • mutation_operator (MutationOperator): Mutation strategy
  • fitness_evaluator (FitnessEvaluator): Fitness evaluation strategy
  • population_initializer (PopulationInitializer): Population initialization strategy

Example:

from genetic_algorithm.core import GeneticAlgorithm
from genetic_algorithm.operators import *
from genetic_algorithm.evaluation import DistanceBasedFitness
from genetic_algorithm.initialization import RandomInitializer
from config.config import GAConfig

config = GAConfig()
selection = RouletteWheelSelection()
crossover = OrderCrossover(selection)
mutation = SwapMutation(config.mutation_rate)
fitness = DistanceBasedFitness()
initializer = RandomInitializer()

ga = GeneticAlgorithm(
    config=config,
    crossover_operator=crossover,
    mutation_operator=mutation,
    fitness_evaluator=fitness,
    population_initializer=initializer
)

Methods

run(cities: CityList, tour_size: int) -> Tuple[Tour, float, float]

Execute the genetic algorithm.

Parameters:

  • cities (CityList): List of city coordinates
  • tour_size (int): Number of cities

Returns:

  • Tuple[Tour, float, float]: (optimal_tour, optimal_cost, optimal_probability)

Example:

optimal_tour, optimal_cost, optimal_probability = ga.run(cities, len(cities))
get_statistics() -> Statistics

Get algorithm statistics.

Returns:

  • Statistics: Dictionary containing:
    • total_generations (int): Total generations run
    • convergence_generation (int): Generation where best was found
    • best_fitness (float): Best fitness value
    • average_cost (float): Average tour cost in final population
    • worst_cost (float): Worst tour cost in final population
    • converged (bool): Whether algorithm converged

Example:

stats = ga.get_statistics()
print(f"Converged at generation: {stats['convergence_generation']}")

🎲 Type Definitions

Location: genetic_algorithm/core/types.py

Type Aliases

# Basic types
City = Tuple[int, int, int]           # 3D coordinates
CityList = List[City]                 # List of cities
Tour = List[int]                      # Tour as city indices
Population = List[Tour]               # Collection of tours

# Derived types
FloatList = List[float]               # Fitness values, probabilities
Parents = Tuple[Tour, Tour]           # Parent pair for crossover
Statistics = Dict[str, Any]           # Algorithm statistics
ConfigDict = Dict[str, Any]           # Configuration dictionary

Examples

# City: 3D coordinates
city: City = (100, 200, 150)

# CityList: Multiple cities
cities: CityList = [
    (100, 200, 150),
    (50, 75, 200),
    (300, 100, 50)
]

# Tour: Sequence of city indices
tour: Tour = [0, 2, 1]  # Visit city 0, then 2, then 1

# Population: Multiple tours
population: Population = [
    [0, 1, 2],
    [1, 0, 2],
    [2, 0, 1]
]

🔀 Operators Module

Crossover Operators

OrderCrossover

Location: genetic_algorithm/operators/crossover.py

Order Crossover (OX) operator that preserves relative city order.

class OrderCrossover(CrossoverOperator):
    """
    Order Crossover (OX) operator.

    Preserves relative order of cities from parents.
    """

    def __init__(self, selection: SelectionOperator):
        """Initialize with selection operator."""

    def cross(self, parent1: Tour, parent2: Tour) -> Tour:
        """
        Create offspring from two parents.

        Args:
            parent1: First parent tour
            parent2: Second parent tour

        Returns:
            Offspring tour
        """

Example:

selection = RouletteWheelSelection()
crossover = OrderCrossover(selection)

parent1 = [0, 1, 2, 3, 4]
parent2 = [4, 3, 2, 1, 0]
offspring = crossover.cross(parent1, parent2)
# offspring might be: [0, 1, 3, 4, 2]

PMXCrossover

Location: genetic_algorithm/operators/crossover.py

Partially Mapped Crossover that preserves position information.

class PMXCrossover(CrossoverOperator):
    """Partially Mapped Crossover (PMX) operator."""

    def cross(self, parent1: Tour, parent2: Tour) -> Tour:
        """Create offspring using PMX."""

Example:

crossover = PMXCrossover(selection)
offspring = crossover.cross(parent1, parent2)

Mutation Operators

SwapMutation

Location: genetic_algorithm/operators/mutation.py

Swaps two random cities in a tour.

class SwapMutation(MutationOperator):
    """
    Swap Mutation operator.

    Randomly swaps two cities in the tour.
    """

    def __init__(self, mutation_rate: float):
        """
        Initialize mutation operator.

        Args:
            mutation_rate: Probability of mutation (0.0 to 1.0)
        """

    def mutate(self, population: Population) -> Population:
        """
        Apply mutation to population.

        Args:
            population: Current population

        Returns:
            Mutated population
        """

Example:

mutation = SwapMutation(mutation_rate=0.02)
mutated_population = mutation.mutate(population)

Selection Operators

RouletteWheelSelection

Location: genetic_algorithm/operators/selection.py

Fitness-proportionate selection (roulette wheel).

class RouletteWheelSelection(SelectionOperator):
    """
    Roulette Wheel Selection.

    Higher fitness = higher selection probability.
    """

    def select(
        self,
        probabilities: FloatList,
        population: Population
    ) -> Parents:
        """
        Select two parents.

        Args:
            probabilities: Selection probabilities for each individual
            population: Current population

        Returns:
            Tuple of two selected parents
        """

Example:

selection = RouletteWheelSelection()

# probabilities calculated from fitness
probabilities = [0.15, 0.25, 0.20, 0.30, 0.10]
parent1, parent2 = selection.select(probabilities, population)

🌱 Initialization Module

RandomInitializer

Location: genetic_algorithm/initialization/population.py

Creates random permutations of cities.

class RandomInitializer(PopulationInitializer):
    """Random population initialization."""

    def initialize(self, cities: CityList, tour_size: int) -> Population:
        """
        Create initial population with random tours.

        Args:
            cities: List of city coordinates
            tour_size: Number of cities

        Returns:
            Initial population
        """

Example:

initializer = RandomInitializer()
population = initializer.initialize(cities, len(cities))

NearestNeighborInitializer

Location: genetic_algorithm/initialization/population.py

Creates tours using nearest neighbor heuristic.

class NearestNeighborInitializer(PopulationInitializer):
    """Nearest Neighbor initialization."""

    def initialize(self, cities: CityList, tour_size: int) -> Population:
        """Create population using nearest neighbor heuristic."""

Example:

initializer = NearestNeighborInitializer()
population = initializer.initialize(cities, len(cities))
# Creates better initial solutions than random

📊 Evaluation Module

DistanceBasedFitness

Location: genetic_algorithm/evaluation/fitness.py

Evaluates fitness based on tour distance.

class DistanceBasedFitness(FitnessEvaluator):
    """
    Distance-based fitness evaluation.

    Fitness = 1 / total_distance
    (Lower distance = Higher fitness)
    """

    def evaluate(self, tour: Tour, cities: CityList) -> float:
        """
        Calculate fitness of a tour.

        Args:
            tour: Tour to evaluate (list of city indices)
            cities: List of city coordinates

        Returns:
            Fitness value (higher is better)
        """

Example:

fitness_evaluator = DistanceBasedFitness()

tour = [0, 1, 2, 3, 0]  # Tour visiting cities in order
cities = [(0,0,0), (1,0,0), (1,1,0), (0,1,0)]

fitness = fitness_evaluator.evaluate(tour, cities)
# Returns: 1 / total_distance

🛠️ Utility Functions

Location: genetic_algorithm/utils/helpers.py

euclidean_distance

Calculate 3D Euclidean distance between two cities.

def euclidean_distance(city1: City, city2: City) -> float:
    """
    Calculate Euclidean distance between two cities.

    Args:
        city1: First city (x, y, z)
        city2: Second city (x, y, z)

    Returns:
        Distance between cities
    """

Formula: $\sqrt{(x_2-x_1)^2 + (y_2-y_1)^2 + (z_2-z_1)^2}$

Example:

from genetic_algorithm.utils import euclidean_distance

city1 = (0, 0, 0)
city2 = (3, 4, 0)
distance = euclidean_distance(city1, city2)
# Returns: 5.0

read_input

Read TSP input file.

def read_input(filename: str) -> Tuple[int, CityList]:
    """
    Read input file containing city coordinates.

    Args:
        filename: Path to input file

    Returns:
        Tuple of (tour_size, cities)

    Raises:
        FileNotFoundError: If file doesn't exist
        ValueError: If file format is invalid
    """

Example:

from genetic_algorithm.utils import read_input

tour_size, cities = read_input("input/input1.txt")
print(f"Loaded {tour_size} cities")

calculate_total_distance

Calculate total tour distance.

def calculate_total_distance(tour: Tour, cities: CityList) -> float:
    """
    Calculate total distance of a tour.

    Args:
        tour: Tour as list of city indices
        cities: List of city coordinates

    Returns:
        Total tour distance
    """

Example:

from genetic_algorithm.utils import calculate_total_distance

tour = [0, 1, 2, 0]
cities = [(0,0,0), (1,0,0), (1,1,0)]
distance = calculate_total_distance(tour, cities)
# Returns: sum of all edge distances

⚙️ Configuration Module

GAConfig

Location: config/config.py

Configuration dataclass for GA parameters.

@dataclass
class GAConfig:
    """Genetic Algorithm Configuration."""

    # Population
    population_size_multiplier: float = 1.0

    # Evolution
    mutation_rate: float = 0.02
    number_of_generations: int = 3500
    convergence_threshold: int = 500

    # I/O
    input_file: str = "input/input1.txt"
    output_dir: str = "output"

    # Logging
    log_level: str = "INFO"
    verbose: bool = True
    log_interval: int = 100

Methods

from_json(filepath: str) -> GAConfig

Load configuration from JSON file.

@classmethod
def from_json(cls, filepath: str) -> 'GAConfig':
    """
    Load configuration from JSON file.

    Args:
        filepath: Path to JSON config file

    Returns:
        GAConfig instance
    """

Example:

config = GAConfig.from_json("config/my_config.json")
to_json(filepath: str) -> None

Save configuration to JSON file.

def to_json(self, filepath: str) -> None:
    """
    Save configuration to JSON file.

    Args:
        filepath: Path to save JSON config
    """

Example:

config = GAConfig(mutation_rate=0.05)
config.to_json("config/custom_config.json")

🧪 Complete Usage Example

"""Complete example using the API."""

from genetic_algorithm.core import GeneticAlgorithm
from genetic_algorithm.operators import (
    OrderCrossover,
    SwapMutation,
    RouletteWheelSelection
)
from genetic_algorithm.evaluation import DistanceBasedFitness
from genetic_algorithm.initialization import NearestNeighborInitializer
from genetic_algorithm.utils import read_input
from config.config import GAConfig

# 1. Load configuration
config = GAConfig(
    mutation_rate=0.03,
    number_of_generations=5000,
    population_size_multiplier=1.5
)

# 2. Read input
tour_size, cities = read_input("input/input1.txt")

# 3. Create operators
selection = RouletteWheelSelection()
crossover = OrderCrossover(selection)
mutation = SwapMutation(config.mutation_rate)
fitness = DistanceBasedFitness()
initializer = NearestNeighborInitializer()

# 4. Create GA
ga = GeneticAlgorithm(
    config=config,
    crossover_operator=crossover,
    mutation_operator=mutation,
    fitness_evaluator=fitness,
    population_initializer=initializer
)

# 5. Run algorithm
optimal_tour, optimal_cost, optimal_probability = ga.run(cities, tour_size)

# 6. Get statistics
stats = ga.get_statistics()

# 7. Display results
print(f"Best tour cost: {optimal_cost:.2f}")
print(f"Converged at generation: {stats['convergence_generation']}")

📚 See Also