OpenGeneticAlgorithm.NET
An extensible .NET genetic algorithm library for optimization and artificial intelligence - Evolutionary computation and complex problem solving made simple
Install / Use
/learn @asarnaout/OpenGeneticAlgorithm.NETREADME
🧬 OpenGeneticAlgorithm.NET
The most intuitive, powerful, and extensible genetic algorithm framework for .NET
OpenGA.Net is a high-performance, type-safe genetic algorithm library that makes evolutionary computation accessible to everyone. Whether you're solving complex optimization problems, researching machine learning, or just getting started with genetic algorithms, OpenGA.Net provides the tools you need with an elegant, fluent API.
🚀 Quick Start
Installation
dotnet add package OpenGA.Net
Your First Genetic Algorithm
A Chromosome in OpenGA.Net represents a potential solution to your optimization problem. It contains genes (the solution components) and defines how to evaluate, modify, and repair solutions.
Step 1: Create your chromosome by inheriting from the Chromosome<T> abstract class, the example below demonstrates how a Chromosome representing a potential solution to the traveling salesman problem could look like:
using OpenGA.Net;
// A chromosome for the Traveling Salesman Problem. Each chromosome represents a route through cities (genes = city sequence)
public class TspChromosome(IList<int> cities, double[,] distanceMatrix) : Chromosome<int>(cities)
{
// Calculate how "good" this route is (shorter distance = higher fitness)
public override async Task<double> CalculateFitnessAsync()
{
double totalDistance = CalculateTotalDistance();
return 1.0 / (1.0 + totalDistance);
}
// Randomly swap two cities in the route
public override async Task MutateAsync(Random random)
{
int index1 = random.Next(Genes.Count);
int index2 = random.Next(Genes.Count);
(Genes[index1], Genes[index2]) = (Genes[index2], Genes[index1]);
}
public override async Task<Chromosome<int>> DeepCopyAsync()
{
return new TspChromosome(new List<int>(Genes), distanceMatrix);
}
public override async Task GeneticRepairAsync()
{
// Ensure each city appears exactly once (fix any duplicates)
}
}
Step 2: Create your initial population:
// Generate initial population of random routes. The initial population represents a set of random solutions to the optimization problem.
var initialPopulation = new TspChromosome[100];
for (int i = 0; i < 100; i++)
{
var cities = Enumerable.Range(0, numberOfCities).OrderBy(x => _random.Next()).ToList();
initialPopulation[i] = new TspChromosome(cities, _distanceMatrix);
}
Step 3: Configure and run your genetic algorithm:
// Configure and run your genetic algorithm
var bestSolution = await OpenGARunner<int>
.Initialize(initialPopulation)
.RunToCompletionAsync();
// Get your optimized result
Console.WriteLine($"Best route: {string.Join(" → ", bestSolution.Genes)}");
That's it! 🎉 You just solved an optimization problem with a few lines of code.
🏗️ Architecture Overview
OpenGA.Net is built around four core concepts that work together seamlessly:
🧬 Chromosomes
Your solution candidates. Strongly typed and extensible. Each Chromosome<T> subclass defines how a solution is represented and evaluated. Implement:
- CalculateFitnessAsync() — return a higher-is-better score for the current Genes
- MutateAsync() — randomly perturb Genes to explore the search space
- DeepCopyAsync() — produce a full copy used during crossover
- GeneticRepairAsync() (optional) — fix invalid states after crossover/mutation
Tip: See the TSP chromosome in the Quick Start above for a concrete example. The pattern is the same for any problem: choose a gene representation, define a fitness function, add a simple mutation, and optionally repair to enforce constraints.
🎯 Parent Selection Strategies
Choose the chromosomes that will participate in mating/crossover:
| Strategy | When to Use | Problem Characteristics | Population Size | Fitness Landscape | |----------|-------------|------------------------|-----------------|-------------------| | Tournament (Default) | Default choice for most problems | Balanced exploration/exploitation needed | Any size | Noisy or multimodal landscapes | | Elitist | Need guaranteed convergence | High-quality solutions must be preserved | Medium to large (50+) | Clear fitness hierarchy | | Roulette Wheel | Fitness-proportionate diversity | Wide fitness range, avoid premature convergence | Large (100+) | Smooth, unimodal landscapes | | Boltzmann | Dynamic selection pressure | Need cooling schedule control | Medium to large | Complex, deceptive landscapes | | Rank Selection | Prevent fitness scaling issues | Similar fitness values across population | Any size | Flat or highly scaled fitness | | Random | Maximum diversity exploration | Early stages or highly exploratory search | Any size | Unknown or chaotic landscapes |
🧬 Crossover Strategies
Create offspring by combining parent chromosomes:
| Strategy | When to Use | Gene Representation | Problem Type | Preservation Needs | |----------|-------------|-------------------|--------------|-------------------| | One-Point (Default) | Fast, simple problems | Order doesn't matter critically | Optimization with independent variables | Preserve some gene clusters | | K-Point | Moderate complexity balance | Mixed dependencies between genes | Multi-dimensional optimization | Control disruption level | | Uniform | Maximum genetic diversity | Independent genes | Exploratory search, avoid local optima | No specific gene clustering | | Custom | Domain-specific requirements | Complex constraints or structures | Specialized problem domains | Domain-specific validation |
🔄 Survivor Selection Strategies
Manage population evolution over generations:
| Strategy | When to Use | Convergence Speed | Population Diversity | Resource Constraints | |----------|-------------|-------------------|---------------------|---------------------| | Elitist (Default) | Most optimization problems | Fast convergence | Moderate diversity loss | Low computational overhead | | Generational | Exploration-heavy search | Slower, thorough exploration | High diversity maintained | Higher memory usage | | Tournament | Balanced performance | Moderate convergence | Good diversity balance | Moderate computational cost | | Age-based | Long-running evolutionary systems | Very slow, stable | Excellent long-term diversity | Requires age tracking | | Boltzmann | Temperature-controlled evolution | Adaptive convergence | Dynamic diversity control | Higher computational complexity | | Random Elimination | Maintain population diversity | Slowest convergence | Maximum diversity | Minimal computational overhead |
🏁 Termination Strategies
Control when the genetic algorithm stops evolving:
| Strategy | When to Use | Stopping Condition | Best For | Predictability | |----------|-------------|-------------------|----------|----------------| | Maximum Epochs (Default) | Known iteration limits | Fixed number of generations | Time-constrained scenarios | Highly predictable runtime | | Maximum Duration | Real-time applications | Maximum execution duration | Production systems | Predictable time bounds | | Target Standard Deviation | Diversity monitoring | Low population diversity | Avoiding premature convergence | Adaptive stopping | | Target Fitness | Goal-oriented optimization | Specific fitness threshold reached | Known optimal solution value | Adaptive based on performance |
💡 Strategy Selection Examples
// High-performance optimization (fast convergence needed)
.ParentSelection(c => c.RegisterSingle(s => s.Tournament()))
.Crossover(c => c.RegisterSingle(s => s.OnePointCrossover()))
.SurvivorSelection(r => r.RegisterSingle(s => s.Elitist()))
.Termination(t => t.MaximumEpochs(100))
// Exploratory search (avoiding local optima)
.ParentSelection(c => c.RegisterSingle(s => s.Tournament()))
.Crossover(c => c.RegisterSingle(s => s.UniformCrossover()))
.SurvivorSelection(r => r.RegisterSingle(s => s.Generational()))
.Termination(t => t.TargetStandardDeviation(stdDev: 0.001))
// Production system (time-constrained)
.ParentSelection(c => c.RegisterSingle(s => s.Tournament()))
.Crossover(c => c.RegisterSingle(s => s.OnePointCrossover()))
.SurvivorSelection(r => r.RegisterSingle(s => s.Elitist()))
.Termination(t => t.MaximumDuration(TimeSpan.FromMinutes(5)))
// Quality-focused research (target fitness termination)
.ParentSelection(c => c.RegisterSingle(s => s.RouletteWheel()))
.Crossover(c => c.RegisterSingle(s => s.KPointCrossover(3)))
.SurvivorSelection(r => r.RegisterSingle(s => s.Elitist(0.2f)))
.Termination(t => t.TargetFitness(0.95).TargetStandardDeviation(stdDev: 0.001, window: 10))
🎯 Use Cases
🏭 Optimization Problems
- Scheduling: Job shop, vehicle routing, resource allocation
- Engineering Design: Antenna design, circuit optimization, structural engineering
- Financial: Portfolio optimization, trading strategies, risk management
🧠 Machine Learning
- Neural Architecture Search: Automatically design neural networks
- Hyperparameter Tuning: Optimize ML model parameters
- Feature Selection: Find optimal feature subsets
🎮 Game Development
- AI Behavior: Evolve intelligent game agents
- Level Generation: Create procedural game c
